Photo Gallery by Envira – Responsive Image Gallery for WordPress - Version 1.5.0

Version Description

  • Added: New UI
  • Added: WordPress native modal window for image upload, insertion from Media Library and edit
  • Added: Isotope / masonry layout on galleries
  • Added: Define Image Size for Gallery Images (either a WordPress registered size or your own dimensions)
Download this release

Release Info

Developer n7studios
Plugin Icon 128x128 Photo Gallery by Envira – Responsive Image Gallery for WordPress
Version 1.5.0
Comparing to
See all releases

Code changes from version 1.3.5.9 to 1.5.0

Files changed (90) hide show
  1. README.md +0 -4
  2. assets/css/admin.css +1 -0
  3. assets/css/attachment-details-modal-support.css +0 -1
  4. assets/css/editor.css +1 -0
  5. assets/css/envira.css +1 -1
  6. assets/css/images/delete-2x.png +0 -0
  7. assets/css/images/delete.png +0 -0
  8. assets/css/images/{envirabox_loading-2x.gif → envirabox_loading@2x.gif} +0 -0
  9. assets/css/images/envirabox_overlay.png +0 -0
  10. assets/css/images/{envirabox_sprite-2x.png → envirabox_sprite@2x.png} +0 -0
  11. assets/css/images/icons/breadcrumbs.svg +10 -0
  12. assets/css/images/icons/configuration.svg +18 -0
  13. assets/css/images/icons/downloads.svg +10 -0
  14. assets/css/images/icons/exif.svg +11 -0
  15. assets/css/images/icons/leaf.svg +8 -0
  16. assets/css/images/icons/lightbox.svg +9 -0
  17. assets/css/images/icons/misc.svg +11 -0
  18. assets/css/images/icons/mobile.svg +9 -0
  19. assets/css/images/icons/pagination.svg +8 -0
  20. assets/css/images/icons/pinterest.svg +12 -0
  21. assets/css/images/icons/printing.svg +9 -0
  22. assets/css/images/icons/proofing.svg +14 -0
  23. assets/css/images/icons/slideshow.svg +12 -0
  24. assets/css/images/icons/social.svg +9 -0
  25. assets/css/images/icons/tags.svg +10 -0
  26. assets/css/images/icons/video.svg +8 -0
  27. assets/css/images/icons/watermark.svg +9 -0
  28. assets/css/images/icons/woocommerce.svg +1 -0
  29. assets/css/images/menu-icon.png +0 -0
  30. assets/css/images/{menu-icon-2x.png → menu-icon@2x.png} +0 -0
  31. assets/css/images/meta-2x.png +0 -0
  32. assets/css/images/meta-active-2x.png +0 -0
  33. assets/css/images/meta-active.png +0 -0
  34. assets/css/images/meta.png +0 -0
  35. assets/css/images/modify-2x.png +0 -0
  36. assets/css/images/modify.png +0 -0
  37. assets/css/images/{preloader-2x.gif → preloader@2x.gif} +0 -0
  38. assets/css/images/social.png +0 -0
  39. assets/css/images/social@2x.png +0 -0
  40. assets/css/metabox.css +1 -1
  41. assets/css/settings.css +1 -0
  42. assets/css/table.css +1 -0
  43. assets/images/envira-logo.png +0 -0
  44. assets/js/admin.js +47 -0
  45. assets/js/clipboard.js +740 -0
  46. assets/js/conditional-fields.js +117 -0
  47. assets/js/editor.js +475 -120
  48. assets/js/envira.js +13 -71
  49. assets/js/gallery-help.js +56 -0
  50. assets/js/lib/fancybox.js +1 -1
  51. assets/js/lib/imagesloaded.js +892 -0
  52. assets/js/lib/isotope.js +4221 -915
  53. assets/js/lib/touchswipe.js +2038 -0
  54. assets/js/media-delete.js +98 -0
  55. assets/js/media-edit.js +535 -0
  56. assets/js/media-insert.js +105 -0
  57. assets/js/media-manage.js +91 -0
  58. assets/js/media-upload.js +93 -0
  59. assets/js/metabox.js +12 -636
  60. assets/js/min/admin-min.js +1 -0
  61. assets/js/min/clipboard-min.js +1 -0
  62. assets/js/min/editor-min.js +1 -1
  63. assets/js/min/envira-min.js +3 -2
  64. assets/js/min/metabox-min.js +1 -1
  65. assets/js/min/settings-min.js +1 -0
  66. assets/js/min/tabs-min.js +1 -0
  67. assets/js/settings.js +23 -0
  68. assets/js/tabs.js +99 -0
  69. assets/scss/attachment-details-modal-support.scss +0 -304
  70. assets/scss/envira.scss +0 -635
  71. assets/scss/metabox.scss +0 -805
  72. config.codekit +0 -1307
  73. envira-gallery-lite.php +430 -329
  74. includes/admin/ajax.php +576 -127
  75. includes/admin/common.php +349 -10
  76. includes/admin/editor.php +117 -120
  77. includes/admin/media-view.php +300 -0
  78. includes/admin/media.php +6 -184
  79. includes/admin/metaboxes.php +1098 -507
  80. includes/admin/notice.php +198 -0
  81. includes/admin/partials/header.php +15 -0
  82. includes/admin/partials/metabox-gallery-code.php +50 -0
  83. includes/admin/partials/metabox-gallery-settings.php +49 -0
  84. includes/admin/partials/metabox-gallery-type.php +54 -0
  85. includes/admin/posttype.php +36 -95
  86. includes/admin/settings.php +145 -0
  87. includes/admin/table.php +264 -0
  88. includes/admin/utils.php +0 -99
  89. includes/global/common.php +595 -41
  90. includes/global/posttype.php +3 -15
README.md DELETED
@@ -1,4 +0,0 @@
1
- Envira Gallery Lite
2
- ==============
3
-
4
- Envira Gallery Lite is the best responsive WordPress gallery plugin. Made lite and free.
 
 
 
 
assets/css/admin.css ADDED
@@ -0,0 +1 @@
 
1
+ body.post-type-envira #wpcontent,body.post-type-envira_album #wpcontent{padding-left:0}body.post-type-envira .update-nag,body.post-type-envira_album .update-nag{margin-left:20px;margin-bottom:20px}body.post-type-envira .subheading,body.post-type-envira_album .subheading{background-color:#fff;height:45px;margin-left:-20px}@media (max-width: 767px){body.post-type-envira .subheading,body.post-type-envira_album .subheading{height:auto;padding-bottom:20px}}body.post-type-envira .subheading h1,body.post-type-envira_album .subheading h1{font-size:20px;font-weight:400;line-height:45px;margin:0 0 0 20px;padding-left:20px}body.post-type-envira div.wrap,body.post-type-envira_album div.wrap{margin:0}body.post-type-envira div.wrap>h1,body.post-type-envira div.wrap>h2,body.post-type-envira_album div.wrap>h1,body.post-type-envira_album div.wrap>h2{margin:0 0 20px 0;padding:15px 20px 10px 20px;background:#fff;font-weight:600;font-size:20px}body.post-type-envira div.wrap>h1 a.page-title-action:hover,body.post-type-envira div.wrap>h2 a.page-title-action:hover,body.post-type-envira_album div.wrap>h1 a.page-title-action:hover,body.post-type-envira_album div.wrap>h2 a.page-title-action:hover{background:#95dc5e;border-color:#95dc5e;color:#fff}body.post-type-envira div.wrap>h1 span.subtitle,body.post-type-envira div.wrap>h2 span.subtitle,body.post-type-envira_album div.wrap>h1 span.subtitle,body.post-type-envira_album div.wrap>h2 span.subtitle{float:right}body.post-type-envira div.wrap .envira-tab,body.post-type-envira_album div.wrap .envira-tab{display:none}body.post-type-envira div.wrap .envira-tab.envira-active,body.post-type-envira_album div.wrap .envira-tab.envira-active{display:block}body.post-type-envira div.wrap div.envira-code,body.post-type-envira_album div.wrap div.envira-code{position:relative;margin:0 0 10px 0}body.post-type-envira div.wrap div.envira-code:after,body.post-type-envira_album div.wrap div.envira-code:after{content:"";display:table;clear:both}body.post-type-envira div.wrap div.envira-code code,body.post-type-envira_album div.wrap div.envira-code code{display:block;font-size:11px;padding:5px 20px 5px 5px}body.post-type-envira div.wrap div.envira-code a.envira-clipboard,body.post-type-envira_album div.wrap div.envira-code a.envira-clipboard{position:absolute;top:5px;right:5px;color:#23282d}body.post-type-envira div.wrap div.envira-code a.envira-clipboard span,body.post-type-envira_album div.wrap div.envira-code a.envira-clipboard span{display:block;text-indent:-9999px}body.post-type-envira .button,body.post-type-envira_album .button{-webkit-border-radius:2px;-moz-border-radius:2px;-o-border-radius:2px;border-radius:2px;padding:0 16px 1px;height:33px;line-height:30px;text-decoration:none;text-shadow:none;font-weight:600;-webkit-box-shadow:none;box-shadow:none}body.post-type-envira .button.button-small,body.post-type-envira_album .button.button-small{padding:0 8px 1px;line-height:22px;height:24px}@media (max-width: 767px){body.post-type-envira .button,body.post-type-envira_album .button{margin-top:10px}}body.post-type-envira .button.show-settings,body.post-type-envira_album .button.show-settings{height:auto}body.post-type-envira .button.button-primary,body.post-type-envira_album .button.button-primary{background:#7cc048;border-color:#7cc048;-webkit-box-shadow:none;box-shadow:none;color:#fff}body.post-type-envira .button.button-primary:hover,body.post-type-envira_album .button.button-primary:hover{background:#95dc5e;border-color:#95dc5e;color:#fff}body.post-type-envira .button.button-danger,body.post-type-envira_album .button.button-danger{background:#e02626;border-color:#e02626;-webkit-box-shadow:none;box-shadow:none;color:#fff}body.post-type-envira .button.button-danger:hover,body.post-type-envira_album .button.button-danger:hover{background:#f85959;border-color:#f85959;color:#fff}body.post-type-envira div#TB_window div.wrap,body.post-type-envira_album div#TB_window div.wrap{margin:10px 20px 0 2px}#envira-header{background-color:#7cc048;height:120px}#envira-header h1.envira-logo{margin:0;line-height:120px;margin-left:20px}#envira-header h1.envira-logo img{max-width:339px;height:auto}@media (max-width: 767px){#envira-header h1.envira-logo img{width:90%}}.envira-notice{position:relative;padding:20px;-webkit-border-radius:2px;-moz-border-radius:2px;-o-border-radius:2px;border-radius:2px;-webkit-box-shadow:none;box-shadow:none}.envira-notice p.envira-intro{border:none;margin:0 0 10px 0 !important;padding:0 0 10px 0 !important}.envira-notice .notice-dismiss{top:10px;right:10px;color:#fff}.envira-notice .notice-dismiss:before{color:#fff;width:26px;height:26px;font-size:22px}.envira-notice.updated{background:#7cc048;color:#fff;border:none}.envira-notice.warning{background:#fcf8e3;border:1px solid #faebcc}.envira-notice.warning .notice-dismiss{color:#000}.envira-notice.warning .notice-dismiss:before{color:#000}.envira-notice.error{border-top:1px solid #dc3232;border-right:1px solid #dc3232;border-bottom:1px solid #dc3232}body.post-type-envira.edit-php div.wrap,body.post-type-envira.post-new-php div.wrap,body.post-type-envira.post-php div.wrap,body.post-type-envira_album.edit-php div.wrap,body.post-type-envira_album.post-new-php div.wrap,body.post-type-envira_album.post-php div.wrap{margin:0}body.post-type-envira.edit-php div.wrap>div.error,body.post-type-envira.edit-php div.wrap>div.notice,body.post-type-envira.edit-php div.wrap>div.updated,body.post-type-envira.post-new-php div.wrap>div.error,body.post-type-envira.post-new-php div.wrap>div.notice,body.post-type-envira.post-new-php div.wrap>div.updated,body.post-type-envira.post-php div.wrap>div.error,body.post-type-envira.post-php div.wrap>div.notice,body.post-type-envira.post-php div.wrap>div.updated,body.post-type-envira_album.edit-php div.wrap>div.error,body.post-type-envira_album.edit-php div.wrap>div.notice,body.post-type-envira_album.edit-php div.wrap>div.updated,body.post-type-envira_album.post-new-php div.wrap>div.error,body.post-type-envira_album.post-new-php div.wrap>div.notice,body.post-type-envira_album.post-new-php div.wrap>div.updated,body.post-type-envira_album.post-php div.wrap>div.error,body.post-type-envira_album.post-php div.wrap>div.notice,body.post-type-envira_album.post-php div.wrap>div.updated{margin-left:20px;margin-right:20px}body.post-type-envira.edit-tags-php div.wrap,body.post-type-envira.taxonomy-envira-tag div.wrap{margin:0}body.post-type-envira.edit-tags-php div.wrap>div.error,body.post-type-envira.edit-tags-php div.wrap>div.notice,body.post-type-envira.edit-tags-php div.wrap>div.updated,body.post-type-envira.taxonomy-envira-tag div.wrap>div.error,body.post-type-envira.taxonomy-envira-tag div.wrap>div.notice,body.post-type-envira.taxonomy-envira-tag div.wrap>div.updated{margin-left:20px;margin-right:20px}body.post-type-envira.edit-tags-php div.wrap form.search-form,body.post-type-envira.edit-tags-php div.wrap form#edittag,body.post-type-envira.edit-tags-php div.wrap #col-container,body.post-type-envira.taxonomy-envira-tag div.wrap form.search-form,body.post-type-envira.taxonomy-envira-tag div.wrap form#edittag,body.post-type-envira.taxonomy-envira-tag div.wrap #col-container{margin:0 20px}body.post-type-envira.edit-tags-php div.wrap .button,body.post-type-envira.taxonomy-envira-tag div.wrap .button{height:28px;line-height:26px}body.post-type-envira div.wrap{margin:0 20px}@media screen and (max-width: 640px){body.post-type-envira div.wrap h1,body.post-type-envira_album div.wrap h1{padding-bottom:40px}body.post-type-envira div.wrap h1 span.subtitle,body.post-type-envira_album div.wrap h1 span.subtitle{clear:both;width:100%;padding:0}}@media screen and (max-width: 340px){body.post-type-envira div.wrap h1,body.post-type-envira_album div.wrap h1{text-align:center}body.post-type-envira div.wrap h1 a.page-title-action,body.post-type-envira_album div.wrap h1 a.page-title-action{display:block;text-align:center;margin:10px 0 0 0}}
assets/css/attachment-details-modal-support.css DELETED
@@ -1 +0,0 @@
1
- .media-sidebar .setting,.attachment-details .setting{display:block;float:left;width:100%;margin:1px 0}.media-sidebar .setting label,.attachment-details .setting label{display:block}.media-sidebar .setting .link-to-custom,.attachment-details .setting .link-to-custom{margin:3px 2px 0}.media-sidebar .setting span,.attachment-details .setting span{min-width:30%;margin-right:4%;font-size:12px;text-align:right}.media-sidebar .setting select,.attachment-details .setting select{max-width:65%}.media-sidebar .setting input[type="checkbox"],.media-sidebar .field input[type="checkbox"],.media-sidebar .setting input[type="radio"],.media-sidebar .field input[type="radio"],.attachment-details .setting input[type="checkbox"],.attachment-details .field input[type="checkbox"],.attachment-details .setting input[type="radio"],.attachment-details .field input[type="radio"]{float:none;margin:8px 3px 0;padding:0}.media-sidebar .setting span,.attachment-details .setting span,.compat-item label span{float:left;min-height:22px;padding-top:8px;line-height:16px;font-weight:normal;color:#666}.compat-item label span{text-align:right}.media-sidebar .setting input[type="text"],.media-sidebar .setting input[type="password"],.media-sidebar .setting input[type="email"],.media-sidebar .setting input[type="number"],.media-sidebar .setting input[type="search"],.media-sidebar .setting input[type="tel"],.media-sidebar .setting input[type="url"],.media-sidebar .setting textarea,.media-sidebar .setting .value,.attachment-details .setting input[type="text"],.attachment-details .setting input[type="password"],.attachment-details .setting input[type="email"],.attachment-details .setting input[type="number"],.attachment-details .setting input[type="search"],.attachment-details .setting input[type="tel"],.attachment-details .setting input[type="url"],.attachment-details .setting textarea,.attachment-details .setting .value{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:1px;width:65%;float:right}.media-sidebar .setting .value,.attachment-details .setting .value{margin:0 1px;text-align:left}.media-sidebar .setting textarea,.attachment-details .setting textarea,.compat-item .field textarea{height:62px;resize:vertical}.media-sidebar select,.attachment-details select{margin-top:3px}.edit-attachment-frame{display:block;height:100%;width:100%}.edit-attachment-frame .edit-media-header{overflow:hidden}.upload-php .media-modal-close .media-modal-icon:before{content:'\f335';font-size:22px}.upload-php .media-modal-close .media-modal-icon{margin:14px;width:22px}.upload-php .media-modal-close,.edit-attachment-frame .edit-media-header .left,.edit-attachment-frame .edit-media-header .right{cursor:pointer;color:#777;background-color:transparent;height:50px;width:50px;padding:0;position:absolute;text-align:center;border:0;border-left:1px solid #ddd;-webkit-transition:color .1s ease-in-out, background .1s ease-in-out;transition:color .1s ease-in-out, background .1s ease-in-out}.upload-php .media-modal-close{top:0;right:0}.edit-attachment-frame .edit-media-header .left{right:102px}.edit-attachment-frame .edit-media-header .right{right:51px}.edit-attachment-frame .media-frame-title{left:0;right:150px}.edit-attachment-frame .edit-media-header .right:before,.edit-attachment-frame .edit-media-header .left:before{font:normal 20px/50px 'dashicons' !important;display:inline;font-weight:300}.upload-php .media-modal-close:hover,.upload-php .media-modal-close:focus,.edit-attachment-frame .edit-media-header .left:hover,.edit-attachment-frame .edit-media-header .right:hover,.edit-attachment-frame .edit-media-header .left:focus,.edit-attachment-frame .edit-media-header .right:focus{background:#ddd;border-color:#ccc;color:#000;outline:none}.upload-php .media-modal-close:focus .media-modal-icon:before,.upload-php .media-modal-close:hover .media-modal-icon:before{color:#000}.edit-attachment-frame .edit-media-header .left:before,.rtl .edit-attachment-frame .edit-media-header .right:before{content:'\f341'}.edit-attachment-frame .edit-media-header .right:before,.rtl .edit-attachment-frame .edit-media-header .left:before{content:'\f345'}.edit-attachment-frame .edit-media-header .left.disabled,.edit-attachment-frame .edit-media-header .right.disabled,.edit-attachment-frame .edit-media-header .left.disabled:hover,.edit-attachment-frame .edit-media-header .right.disabled:hover{color:#ccc;background:inherit;cursor:default;pointer-events:none}.edit-attachment-frame .media-frame-content,.edit-attachment-frame .media-frame-router{left:0}.edit-attachment-frame .media-frame-content{border-bottom:none;bottom:0;top:50px}.edit-attachment-frame .attachment-details{position:absolute;overflow:auto;top:0;bottom:0;right:0;left:0;-webkit-box-shadow:inset 0px 4px 4px -4px rgba(0,0,0,0.1);box-shadow:inset 0px 4px 4px -4px rgba(0,0,0,0.1)}.edit-attachment-frame .attachment-media-view{float:left;width:65%;height:100%}.edit-attachment-frame .attachment-media-view .thumbnail{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:16px;height:100%}.edit-attachment-frame .attachment-media-view .details-image{display:block;margin-bottom:16px;max-width:100%;max-height:90%;max-height:-webkit-calc( 100% - 42px );max-height:calc( 100% - 42px )}.edit-attachment-frame .wp-media-wrapper{margin-bottom:12px}.edit-attachment-frame input,.edit-attachment-frame textarea{padding:6px 8px;line-height:16px}.edit-attachment-frame .attachment-info{overflow:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin-bottom:0;padding:12px 16px 0;width:35%;height:100%;-webkit-box-shadow:inset 0px 4px 4px -4px rgba(0,0,0,0.1);box-shadow:inset 0px 4px 4px -4px rgba(0,0,0,0.1);border-bottom:0;border-left:1px solid #ddd;background:#f3f3f3}.edit-attachment-frame .attachment-info .details,.edit-attachment-frame .attachment-info .settings{position:relative;overflow:hidden;float:none;margin-bottom:15px;padding-bottom:15px;border-bottom:1px solid #ddd}.edit-attachment-frame .attachment-info .filename{font-weight:normal;color:#666}.edit-attachment-frame .attachment-info .thumbnail{margin-bottom:12px}.attachment-info .actions{margin-bottom:16px}.attachment-info .actions a{display:inline;text-decoration:none}
 
assets/css/editor.css ADDED
@@ -0,0 +1 @@
 
1
+ .envira-gallery-choose-gallery,.envira-albums-choose-album{padding-left:.4em}.envira-gallery-choose-gallery span.envira-media-icon,.envira-albums-choose-album span.envira-media-icon{background:url(images/menu-icon.png) transparent no-repeat scroll 0 0;width:16px;height:16px;display:inline-block;vertical-align:text-top}.media-modal .media-modal-content .media-frame-content .attachments-browser.envira-gallery-editor div.envira-gallery-error{position:absolute;top:50px;left:0;right:300px}.media-modal .media-modal-content .media-frame-content .attachments-browser.envira-gallery-editor ul.attachments li.attachment{width:20%}.media-modal .media-modal-content .media-frame-content .attachments-browser.envira-gallery-editor ul.attachments li.attachment div.attachment-preview div.thumbnail img{position:absolute;z-index:1;top:0;left:0;width:100%;height:100%;opacity:0.2}.media-modal .media-modal-content .media-frame-content .attachments-browser.envira-gallery-editor ul.attachments li.attachment div.attachment-preview div.thumbnail strong{position:absolute;z-index:2;height:50%;top:0;left:0;right:0;padding:10px;text-align:center;overflow:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;vertical-align:bottom;background:rgba(0,0,0,0.07);text-shadow:1px 1px #ddd}.media-modal .media-modal-content .media-frame-content .attachments-browser.envira-gallery-editor ul.attachments li.attachment div.attachment-preview div.thumbnail strong span{display:block;position:absolute;bottom:10px;left:0;right:0;padding:0 10px;text-align:center}.media-modal .media-modal-content .media-frame-content .attachments-browser.envira-gallery-editor ul.attachments li.attachment div.attachment-preview div.thumbnail code{position:absolute;z-index:2;height:50%;bottom:0;left:0;right:0;padding:10px;text-align:center;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;vertical-align:middle;text-shadow:1px 1px #ddd}@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2 / 1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx){#envira-media-modal-button .envira-media-icon[style]{background-image:url(images/menu-icon@2x.png) !important;background-size:16px 16px !important}}
assets/css/envira.css CHANGED
@@ -1 +1 @@
1
- .envira-gallery-wrap,.envira-gallery-wrap *,.envira-tags-filter-list,.envira-tags-filter-list *{background:none;border:0 none;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;float:none;font-size:100%;height:auto;letter-spacing:normal;list-style:none;outline:none;position:static;text-decoration:none;text-indent:0;text-shadow:none;text-transform:none;width:auto;visibility:visible;overflow:visible;margin:0;padding:0;line-height:1;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-shadow:none;-moz-box-shadow:none;-ms-box-shadow:none;-o-box-shadow:none;box-shadow:none;-webkit-appearance:none;transition:none;-webkit-transition:none;-moz-transition:none;-o-transition:none;-ms-transition:none}.envira-gallery-wrap{width:100%;margin:0 auto 20px auto}.envira-gallery-wrap .envira-gallery-public{width:100%;margin:0 auto 20px auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.envira-gallery-wrap .envira-gallery-public.envira-clear{clear:both}.envira-gallery-wrap .envira-gallery-public.envira-clear:after{clear:both;content:'.';display:block;height:0;line-height:0;overflow:auto;visibility:hidden;zoom:1}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item{float:left}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item>.envira-gallery-link{display:block;outline:none;border:0 none;position:relative}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item img{display:block;margin:0 auto;max-width:100%}.envira-gallery-wrap.envira-gallery-rtl .envira-gallery-public .envira-gallery-item{float:right}/*! envirabox v2.1.5 fancyapps.com | fancyapps.com/envirabox/#license */.envirabox-wrap,.envirabox-skin,.envirabox-outer,.envirabox-inner,.envirabox-image,.envirabox-wrap iframe,.envirabox-wrap object,.envirabox-nav,.envirabox-nav span,.envirabox-tmp,.envirabox-buttons,.envirabox-thumbs,.envirabox-wrap *,.envirabox-thumbs *,.envirabox-buttons *{background:none;border:0 none;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;float:none;font-size:100%;height:auto;letter-spacing:normal;list-style:none;outline:none;position:static;text-decoration:none;text-indent:0;text-shadow:none;text-transform:none;width:auto;visibility:visible;overflow:visible;margin:0;padding:0;line-height:1;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-shadow:none;-moz-box-shadow:none;-ms-box-shadow:none;-o-box-shadow:none;box-shadow:none;-webkit-appearance:none;transition:none;-webkit-transition:none;-moz-transition:none;-o-transition:none;-ms-transition:none}.envirabox-wrap{position:absolute;top:0;left:0;z-index:988020}.envirabox-skin{position:relative;background:#f9f9f9;color:#444;text-shadow:none;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.envirabox-opened{z-index:988030}.envirabox-opened .envirabox-skin{-webkit-box-shadow:0 10px 25px rgba(0,0,0,0.5);-moz-box-shadow:0 10px 25px rgba(0,0,0,0.5);box-shadow:0 10px 25px rgba(0,0,0,0.5)}.envirabox-outer,.envirabox-inner{position:relative}.envirabox-inner{overflow:hidden}.envirabox-type-iframe .envirabox-inner{-webkit-overflow-scrolling:touch}.envirabox-error{color:#444;font:13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;margin:0;padding:15px;white-space:nowrap}.envirabox-image,.envirabox-iframe{display:block;width:100%;height:100%}.envirabox-image{max-width:100%;max-height:100%}#envirabox-loading,.envirabox-close,.envirabox-prev span,.envirabox-next span{background-image:url("images/envirabox_sprite.png")}#envirabox-loading{position:fixed;top:50%;left:50%;margin-top:-22px;margin-left:-22px;background-position:0 -108px;opacity:0.8;cursor:pointer;z-index:988060}#envirabox-loading div{width:44px;height:44px;background:url("images/envirabox_loading.gif") center center no-repeat}.envirabox-close{position:absolute;top:-18px;right:-18px;width:36px;height:36px;cursor:pointer;z-index:988040}.envirabox-nav{position:absolute;top:0;width:40%;height:100%;cursor:pointer;text-decoration:none;background:transparent url("images/blank.gif");-webkit-tap-highlight-color:transparent;z-index:988040}.envirabox-prev{left:0}.envirabox-next{right:0}.envirabox-nav span{position:absolute;top:50%;width:36px;height:34px;margin-top:-18px;cursor:pointer;z-index:988040;visibility:hidden}body.envira-touch .envirabox-nav span{visibility:visible}.envirabox-prev span{left:10px;background-position:0 -36px}.envirabox-next span{right:10px;background-position:0 -72px}.envirabox-nav:hover span{visibility:visible}.envirabox-tmp{position:absolute;top:-99999px;left:-99999px;max-width:99999px;max-height:99999px;overflow:visible !important}a.envirabox-close,a.envirabox-nav,a.fancy-close:hover,a.envirabox-nav:hover{border:0}.envirabox-lock{overflow:visible !important;width:auto}.envirabox-lock body{overflow:hidden !important}.envirabox-lock-test{overflow-y:hidden !important}.envirabox-overlay{position:absolute;top:0;left:0;overflow:hidden;display:none;z-index:988010;background:url("images/envirabox_overlay.png")}.envirabox-overlay-fixed{position:fixed;bottom:0;right:0}.envirabox-lock .envirabox-overlay{overflow:auto;overflow-y:scroll}.envirabox-title{visibility:hidden;font-size:13px;line-height:20px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;position:relative;text-shadow:none;z-index:988090}.envirabox-title a{color:#fff}.envirabox-opened .envirabox-title{visibility:visible}.envirabox-title-float-wrap{position:absolute;bottom:auto;right:50%;margin-top:20px;z-index:988050;text-align:center}.envirabox-title-float-wrap .child{display:inline-block;margin-right:-100%;padding:2px 20px;background:transparent;background:rgba(0,0,0,0.8);-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;text-shadow:0 1px 2px #222;color:#FFF;line-height:24px;white-space:nowrap}.envirabox-title-float-wrap.envirabox-title-text-wrap .child{white-space:normal}.envirabox-title-outside-wrap{position:relative;margin-top:10px;color:#fff}.envirabox-title-inside-wrap{padding-top:10px}.envirabox-title-over-wrap{position:absolute;bottom:0;left:0;color:#fff;padding:10px;background:#000;background:rgba(0,0,0,0.8)}#envirabox-buttons{position:fixed;left:0;width:100%;z-index:988050}#envirabox-buttons.top{top:10px}#envirabox-buttons.bottom{bottom:10px}#envirabox-buttons.bottom.has-padding{bottom:80px}#envirabox-buttons.top.has-padding{top:80px}#envirabox-buttons ul{display:block;width:auto;height:30px;margin:0 auto;padding:0;list-style:none;border:1px solid #111;border-radius:3px;-webkit-box-shadow:inset 0 0 0 1px rgba(255,255,255,0.05);-moz-box-shadow:inset 0 0 0 1px rgba(255,255,255,0.05);box-shadow:inset 0 0 0 1px rgba(255,255,255,0.05);background:#323232;background:-moz-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #444), color-stop(50%, #343434), color-stop(50%, #292929), color-stop(100%, #333));background:-webkit-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:-o-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:-ms-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#444444', endColorstr='#222222',GradientType=0 )}#envirabox-buttons ul li{float:left;margin:0;padding:0}#envirabox-buttons ul li#envirabox-buttons-title span{display:inline-block;padding:0 10px;color:#fff}#envirabox-buttons a{display:block;width:30px;height:30px;text-indent:-9999px;background-color:transparent;background-image:url("images/envirabox_buttons.png");background-repeat:no-repeat;outline:none;opacity:0.8}#envirabox-buttons a:hover{opacity:1}#envirabox-buttons a.btnPrev{background-position:5px 0}#envirabox-buttons a.btnNext{background-position:-33px 0;border-right:1px solid #3e3e3e}#envirabox-buttons a.btnPlay{background-position:0 -30px}#envirabox-buttons a.btnPlayOn{background-position:-30px -30px}#envirabox-buttons a.btnToggle,#envirabox-buttons a.btnFullscreen{background-position:3px -60px;border-left:1px solid #111;border-right:1px solid #3e3e3e;width:35px}#envirabox-buttons a.btnToggleOn,#envirabox-buttons a.btnFullscreenOn{background-position:-27px -60px}#envirabox-buttons a.btnClose{border-left:1px solid #111;width:35px;background-position:-56px 0px}#envirabox-buttons a.btnDisabled{opacity:0.4;cursor:default}#envirabox-thumbs{position:fixed;left:0;width:100%;overflow:hidden;z-index:988050}#envirabox-thumbs.bottom{bottom:2px}#envirabox-thumbs.top{top:2px}#envirabox-thumbs ul{position:relative;list-style:none;margin:0;padding:0}#envirabox-thumbs ul li{border:3px solid #fff;float:left;margin:5px;opacity:1}#envirabox-thumbs ul li.active{opacity:0.75;border:3px solid #888}#envirabox-thumbs ul li:hover{opacity:0.75}#envirabox-thumbs ul li a{display:block;position:relative;overflow:hidden;border:1px solid #222;background:#111;outline:none}#envirabox-thumbs ul li img{display:block;position:relative;border:0;padding:0;max-width:none}@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2 / 1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx){#envirabox-loading,.envirabox-close,.envirabox-prev span,.envirabox-next span{background-image:url("images/envirabox_sprite-2x.png");background-size:44px 152px}#envirabox-loading div{background-image:url("images/envirabox_loading-2x.gif");background-size:24px 24px}}
1
+ .envira-gallery-wrap,.envira-gallery-wrap *,.envira-tags-filter-list,.envira-tags-filter-list *{background:none;border:0 none;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;float:none;font-size:100%;height:auto;letter-spacing:normal;list-style:none;outline:none;position:static;text-decoration:none;text-indent:0;text-shadow:none;text-transform:none;width:auto;visibility:visible;overflow:visible;margin:0;padding:0;line-height:1;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-shadow:none;-moz-box-shadow:none;-ms-box-shadow:none;-o-box-shadow:none;box-shadow:none;-webkit-appearance:none;transition:none;-webkit-transition:none;-moz-transition:none;-o-transition:none;-ms-transition:none}.envira-tags-filter-list{clear:both;margin:0 0 10px 0}.envira-tags-filter-list li.envira-tags-filter,.envira-tags-filter-list li.envira-tag-filter{float:left;margin:0 20px 10px 0}.envira-tags-filter-list .envira-tag-filter-link{font-size:13px;font-weight:bold}.envira-breadcrumbs{display:block;margin:0 0 20px 0;padding:10px;background:#eee}.envira-breadcrumbs a{text-decoration:none}.envira-gallery-wrap{width:100%;margin:0 auto 20px auto}.envira-gallery-wrap .envira-pagination{margin:0 0 20px 0}.envira-gallery-wrap .envira-gallery-description{clear:both}.envira-gallery-wrap .envira-gallery-public{width:100%;margin:0 auto 20px auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.envira-gallery-wrap .envira-gallery-public.envira-clear{clear:both}.envira-gallery-wrap .envira-gallery-public.envira-clear:after{clear:both;content:'.';display:block;height:0;line-height:0;overflow:auto;visibility:hidden;zoom:1}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item-inner{position:relative}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item{float:left}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item>.envira-gallery-link{display:block;outline:none;border:0 none;position:relative}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item img{display:block;margin:0 auto;max-width:100%}.envira-gallery-wrap .envira-gallery-public .envira-gallery-item iframe,.envira-gallery-wrap .envira-gallery-public .envira-gallery-item video{display:block;margin:0 auto;width:100%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item{clear:both;width:100%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item{width:50%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(2n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item{width:33.33%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(3n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item{width:25%;margin:0;padding:0;box-sizing:border-box}.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(4n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item{width:20%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(5n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item{width:16.66%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(6n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.enviratope .envira-gallery-item{clear:none !important}.envira-gallery-wrap .envira-gallery-public.envira-gallery-css-animations .envira-gallery-item img{opacity:0;transition:all .2s ease-in-out}.envira-gallery-wrap .envira-gallery-public.envira-gallery-css-animations .envira-gallery-item a:hover img{opacity:1 !important}.envira-gallery-wrap.envira-gallery-rtl .envira-gallery-public .envira-gallery-item{float:right}@media only screen and (max-width: 768px){.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item{width:33%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(4n+1){clear:none}.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(3n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item{width:33%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(5n+1){clear:none}.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(3n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item{width:33%}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(6n+1){clear:none}.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(3n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.enviratope .envira-gallery-item{clear:none !important}}@media only screen and (max-width: 459px){.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item{width:50% !important}.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(6n+1){clear:none !important}.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(2n+1){clear:both !important}.envira-gallery-wrap .envira-gallery-public.enviratope .envira-gallery-item{clear:none !important}}@media only screen and (max-width: 320px){.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item,.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item{width:100% !important}.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-1-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-2-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-3-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-4-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-5-columns .envira-gallery-item:nth-child(6n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(2n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(3n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(4n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(5n+1),.envira-gallery-wrap .envira-gallery-public.envira-gallery-6-columns .envira-gallery-item:nth-child(6n+1){clear:both}.envira-gallery-wrap .envira-gallery-public.enviratope .envira-gallery-item{clear:none !important}}/*! envirabox v2.1.5 fancyapps.com | fancyapps.com/envirabox/#license */.envirabox-wrap,.envirabox-skin,.envirabox-outer,.envirabox-inner,.envirabox-image,.envirabox-wrap iframe,.envirabox-wrap object,.envirabox-nav,.envirabox-nav span,.envirabox-tmp,.envirabox-buttons,.envirabox-thumbs,.envirabox-wrap *,.envirabox-thumbs *,.envirabox-buttons *{background:none;border:0 none;border-radius:0;-webkit-border-radius:0;-moz-border-radius:0;float:none;font-size:100%;height:auto;letter-spacing:normal;list-style:none;outline:none;position:static;text-decoration:none;text-indent:0;text-shadow:none;text-transform:none;width:auto;visibility:visible;overflow:visible;margin:0;padding:0;line-height:1;box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-shadow:none;-moz-box-shadow:none;-ms-box-shadow:none;-o-box-shadow:none;box-shadow:none;-webkit-appearance:none;transition:none;-webkit-transition:none;-moz-transition:none;-o-transition:none;-ms-transition:none}.envirabox-wrap{position:absolute;top:0;left:0;z-index:988020}.envirabox-skin{position:relative;background:#f9f9f9;color:#444;text-shadow:none;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.envirabox-opened{z-index:988030}.envirabox-opened .envirabox-skin{-webkit-box-shadow:0 10px 25px rgba(0,0,0,0.5);-moz-box-shadow:0 10px 25px rgba(0,0,0,0.5);box-shadow:0 10px 25px rgba(0,0,0,0.5)}.envirabox-outer,.envirabox-inner{position:relative}.envirabox-inner{overflow:hidden}.envirabox-type-iframe .envirabox-inner{-webkit-overflow-scrolling:touch}.envirabox-error{color:#444;font:13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;margin:0;padding:15px;white-space:nowrap}.envirabox-image,.envirabox-iframe{display:block;width:100%;height:100%}.envirabox-image{max-width:100%;max-height:100%}#envirabox-loading,.envirabox-close,.envirabox-prev span,.envirabox-next span{background-image:url("images/envirabox_sprite.png")}#envirabox-loading{position:fixed;top:50%;left:50%;margin-top:-22px;margin-left:-22px;background-position:0 -108px;opacity:0.8;cursor:pointer;z-index:988060}#envirabox-loading div{width:44px;height:44px;background:url("images/envirabox_loading.gif") center center no-repeat}.envirabox-close{position:absolute;top:-18px;right:-18px;width:36px;height:36px;cursor:pointer;z-index:988040}.envirabox-nav{position:absolute;top:0;width:40%;height:100%;cursor:pointer;text-decoration:none;background:transparent url("images/blank.gif");-webkit-tap-highlight-color:transparent;z-index:988040}.envirabox-prev{left:0}.envirabox-next{right:0}.envirabox-prev.envirabox-arrows-outside{left:-100px}.envirabox-next.envirabox-arrows-outside{right:-100px}.envirabox-nav span{position:absolute;top:50%;width:36px;height:34px;margin-top:-18px;cursor:pointer;z-index:988040;visibility:hidden}body.envira-touch .envirabox-nav span{visibility:visible}.envirabox-prev span{left:10px;background-position:0 -36px}.envirabox-next span{right:10px;background-position:0 -72px}.envirabox-nav:hover span{visibility:visible}.envirabox-tmp{position:absolute;top:-99999px;left:-99999px;max-width:99999px;max-height:99999px;overflow:visible !important}a.envirabox-close,a.envirabox-nav,a.fancy-close:hover,a.envirabox-nav:hover{border:0}.envirabox-lock{overflow:visible !important;width:auto}.envirabox-lock body{overflow:hidden !important}.envirabox-lock-test{overflow-y:hidden !important}.envirabox-overlay{position:absolute;top:0;left:0;overflow:hidden;display:none;z-index:988010;background:url("images/envirabox_overlay.png")}.envirabox-overlay-fixed{position:fixed;bottom:0;right:0}.envirabox-lock .envirabox-overlay{overflow:auto;overflow-y:scroll}.envirabox-title{visibility:hidden;font-size:13px;line-height:20px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;position:relative;text-shadow:none;z-index:988090}.envirabox-opened .envirabox-title{visibility:visible}.envirabox-title-float-wrap{position:absolute;bottom:auto;right:50%;margin-top:20px;z-index:988050;text-align:center}.envirabox-title-float-wrap .child{display:inline-block;margin-right:-100%;padding:2px 20px;background:transparent;background:rgba(0,0,0,0.8);-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;text-shadow:0 1px 2px #222;color:#FFF;line-height:24px;white-space:nowrap}.envirabox-title-float-wrap.envirabox-title-text-wrap .child{white-space:normal}.envirabox-title-outside-wrap{position:relative;margin-top:10px;color:#fff}.envirabox-title-inside-wrap{padding-top:10px}.envirabox-title-over-wrap{position:absolute;bottom:0;left:0;color:#fff;padding:10px;background:#000;background:rgba(0,0,0,0.8)}#envirabox-buttons{position:fixed;left:0;width:100%;z-index:988050}#envirabox-buttons.top{top:10px}#envirabox-buttons.bottom{bottom:10px}#envirabox-buttons.bottom.has-padding{bottom:80px}#envirabox-buttons.top.has-padding{top:80px}#envirabox-buttons ul{display:block;width:auto;height:30px;margin:0 auto;padding:0;list-style:none;border:1px solid #111;border-radius:3px;-webkit-box-shadow:inset 0 0 0 1px rgba(255,255,255,0.05);-moz-box-shadow:inset 0 0 0 1px rgba(255,255,255,0.05);box-shadow:inset 0 0 0 1px rgba(255,255,255,0.05);background:#323232;background:-moz-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #444), color-stop(50%, #343434), color-stop(50%, #292929), color-stop(100%, #333));background:-webkit-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:-o-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:-ms-linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);background:linear-gradient(top, #444 0%, #343434 50%, #292929 50%, #333 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#444444', endColorstr='#222222',GradientType=0 )}#envirabox-buttons ul li{float:left;margin:0;padding:0}#envirabox-buttons ul li#envirabox-buttons-title span{display:inline-block;padding:0 10px;color:#fff}#envirabox-buttons a{display:block;width:30px;height:30px;text-indent:-9999px;background-color:transparent;background-image:url("images/envirabox_buttons.png");background-repeat:no-repeat;outline:none;opacity:0.8}#envirabox-buttons a:hover{opacity:1}#envirabox-buttons a.btnPrev{background-position:5px 0}#envirabox-buttons a.btnNext{background-position:-33px 0;border-right:1px solid #3e3e3e}#envirabox-buttons a.btnPlay{background-position:0 -30px}#envirabox-buttons a.btnPlayOn{background-position:-30px -30px}#envirabox-buttons a.btnToggle,#envirabox-buttons a.btnFullscreen{background-position:3px -60px;border-left:1px solid #111;border-right:1px solid #3e3e3e;width:35px}#envirabox-buttons a.btnToggleOn,#envirabox-buttons a.btnFullscreenOn{background-position:-27px -60px}#envirabox-buttons a.btnClose{border-left:1px solid #111;width:35px;background-position:-56px 0px}#envirabox-buttons a.btnDisabled{opacity:0.4;cursor:default}#envirabox-thumbs{position:fixed;left:0;width:100%;overflow:hidden;z-index:988050;box-sizing:border-box}#envirabox-thumbs *{box-sizing:border-box}#envirabox-thumbs.bottom{bottom:2px}#envirabox-thumbs.top{top:2px}#envirabox-thumbs ul{position:relative;list-style:none;margin:0;padding:0}#envirabox-thumbs ul li{border:3px solid #fff;float:left;margin:5px;opacity:1}#envirabox-thumbs ul li.active{opacity:0.75;border:3px solid #888}#envirabox-thumbs ul li:hover{opacity:0.75}#envirabox-thumbs ul li a{display:block;position:relative;overflow:hidden;border:1px solid #222;background:#111;outline:none}#envirabox-thumbs ul li img{display:block;position:relative;border:0;padding:0;max-width:none}@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2 / 1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx){#envirabox-loading,.envirabox-close,.envirabox-prev span,.envirabox-next span{background-image:url("images/envirabox_sprite@2x.png");background-size:44px 152px}#envirabox-loading div{background-image:url("images/envirabox_loading@2x.gif");background-size:24px 24px}}
assets/css/images/delete-2x.png DELETED
Binary file
assets/css/images/delete.png DELETED
Binary file
assets/css/images/{envirabox_loading-2x.gif → envirabox_loading@2x.gif} RENAMED
File without changes
assets/css/images/envirabox_overlay.png CHANGED
Binary file
assets/css/images/{envirabox_sprite-2x.png → envirabox_sprite@2x.png} RENAMED
File without changes
assets/css/images/icons/breadcrumbs.svg ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="breadcrumbs" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
4
+ y="0px" width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" fill-rule="evenodd" clip-rule="evenodd" d="M56,32.001l8,10L56,52H42v8c0,2.207-1.791,4-4,4H26.001C23.791,64,22,62.207,22,60
6
+ v-8h-9.999V32.001H22v-4H8L0,18L8,8h14V3.998C22,1.791,23.791,0,26.001,0H38c2.209,0,4,1.791,4,3.998V8h10v20.001H42v4H56z
7
+ M26.001,57.998c0,1.104,0.895,2.002,2,2.002H36c1.104,0,2-0.898,2-2.002V52H26.001V57.998z M38,6c0-1.104-0.896-2.002-2-2.002
8
+ h-7.999c-1.105,0-2,0.898-2,2.002v2H38V6z M48,24.001V11.998H10.001L4,18l6.001,6.001H48z M26.001,28.001v4H38v-4H26.001z
9
+ M16.001,35.997v12.001H54l6-5.997l-6-6.004H16.001z"/>
10
+ </svg>
assets/css/images/icons/configuration.svg ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="configuration" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" fill-rule="evenodd" clip-rule="evenodd" d="M60,38l-5.1,0.9c-0.5,1.6-1.1,3.1-1.9,4.5l3,4.2
6
+ c1.6,1.6,1.6,4.1,0,5.7L53.2,56c-1.6,1.6-4.1,1.6-5.7,0l-4.2-3c-1.4,0.8-2.9,1.4-4.5,1.9L38,60c0,2.2-1.8,4-4,4h-4c-2.2,0-4-1.8-4-4
7
+ l-0.9-5.1c-1.6-0.5-3.1-1.1-4.5-1.9l-4.2,3c-1.6,1.6-4.1,1.6-5.7,0L8,53.2c-1.6-1.6-1.6-4.1,0-5.7l3-4.2c-0.8-1.4-1.4-2.9-1.9-4.5
8
+ L4,38c-2.2,0-4-1.8-4-4v-4c0-2.2,1.8-4,4-4l5.1-0.9c0.5-1.6,1.1-3.1,1.9-4.5l-3-4.2c-1.6-1.6-1.6-4.1,0-5.7L10.8,8
9
+ c1.6-1.6,4.1-1.6,5.7,0l4.2,3c1.4-0.8,2.9-1.4,4.5-1.9L26,4c0-2.2,1.8-4,4-4h4c2.2,0,4,1.8,4,4l0.9,5.1c1.6,0.5,3.1,1.1,4.5,1.9
10
+ l4.2-3c1.6-1.6,4.1-1.6,5.7,0l2.8,2.8c1.6,1.6,1.6,4.1,0,5.7l-3,4.2c0.8,1.4,1.4,2.9,1.9,4.5L60,26c2.2,0,4,1.8,4,4v4
11
+ C64,36.2,62.2,38,60,38z M58,30l-6.3-1c-0.5-3.2-1.8-6.2-3.6-8.7l3.7-5.2c0.8-0.8,0.8-2,0-2.8c-0.8-0.8-2-0.8-2.8,0l-5.2,3.7
12
+ c-2.5-1.8-5.5-3.1-8.7-3.6L34,6c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2l-1.1,6.3c-3.2,0.5-6.2,1.8-8.7,3.6L15,12.2c-0.8-0.8-2-0.8-2.8,0
13
+ c-0.8,0.8-0.8,2,0,2.8l3.7,5.2c-1.9,2.5-3.1,5.5-3.6,8.7L6,30c-1.1,0-2,0.9-2,2s0.9,2,2,2l6.3,1c0.5,3.2,1.8,6.2,3.6,8.7L12.2,49
14
+ c-0.8,0.8-0.8,2,0,2.8c0.8,0.8,2,0.8,2.8,0l5.2-3.7c2.5,1.8,5.5,3.1,8.7,3.6L30,58c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2l1-6.3
15
+ c3.2-0.5,6.2-1.8,8.7-3.6l5.2,3.7c0.8,0.8,2,0.8,2.8,0c0.8-0.8,0.8-2,0-2.8l-3.7-5.2c1.9-2.5,3.1-5.5,3.6-8.7l6.3-1c1.1,0,2-0.9,2-2
16
+ S59.1,30,58,30z M32,42c-5.5,0-10-4.5-10-10c0-5.5,4.5-10,10-10c5.5,0,10,4.5,10,10C42,37.5,37.5,42,32,42z M32,26c-3.3,0-6,2.7-6,6
17
+ c0,3.3,2.7,6,6,6c3.3,0,6-2.7,6-6C38,28.7,35.3,26,32,26z"/>
18
+ </svg>
assets/css/images/icons/downloads.svg ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="download" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" fill="#3C4042" d="M51.2,7.9h-7.9v3.9h5.1l6.7,23.6H29.5c0.4,0,0.7-0.1,1-0.3c0.3-0.1,0.6-0.3,0.9-0.5l11.2-11.2
6
+ c0.9-0.9,0.9-2.3,0-3.2c-0.9-0.9-2.3-0.9-3.2,0L31.6,28V2c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2v26.2l-7.9-7.9c-0.9-0.9-2.3-0.9-3.2,0
7
+ c-0.9,0.9-0.9,2.3,0,3.2l11.2,11.2c0.3,0.3,0.7,0.5,1.1,0.6c0.3,0.1,0.6,0.2,0.9,0.2H3.9l6.8-23.6h5.1V7.9H7.9L0,35.4v23.6
8
+ C0,61.2,1.8,63,3.9,63h51.2c2.2,0,3.9-1.8,3.9-3.9V35.4L51.2,7.9z M19.7,35.4h19.7v7.9H19.7V35.4z M55.1,57.1c0,1.1-0.9,2-2,2H5.9
9
+ c-1.1,0-2-0.9-2-2V41.3c0-1.1,0.9-2,2-2h9.8v7.9h27.6v-7.9h9.8c1.1,0,2,0.9,2,2V57.1z"/>
10
+ </svg>
assets/css/images/icons/exif.svg ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="exif" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" d="M56,12h-6C47.5,7.3,43.2,0,40,0H24c-3.2,0-7.5,7.3-10,12H8c-4.4,0-8,3.6-8,8v36c0,4.4,3.6,8,8,8h48
6
+ c4.4,0,8-3.6,8-8V20C64,15.6,60.4,12,56,12z M24,4h16c1.5,0,4.2,4.5,6,8H18C19.8,8.5,22.5,4,24,4z M4,28h13
7
+ c-0.8,1.2-1.4,2.6-1.9,4H4V28z M60,56c0,2.2-1.8,4-4,4H8c-2.2,0-4-1.8-4-4V36h10.2c-0.1,0.7-0.2,1.3-0.2,2c0,9.9,8.1,18,18,18
8
+ c9.9,0,18-8.1,18-18c0-0.7-0.1-1.3-0.2-2H60V56z M18,38c0-7.7,6.3-14,14-14s14,6.3,14,14c0,7.7-6.3,14-14,14S18,45.7,18,38z
9
+ M60,32H48.9c-0.5-1.4-1.1-2.8-1.9-4h13V32z M60,24H43.2c-3.1-2.5-6.9-4-11.2-4s-8.1,1.5-11.2,4H4v-4c0-2.2,1.8-4,4-4h48
10
+ c2.2,0,4,1.8,4,4V24z"/>
11
+ </svg>
assets/css/images/icons/leaf.svg ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="leaf" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" d="M19.6,47.8c12.9,10.1,25.1,5.8,30.7,5.2l10,10H64L52.5,51.5C52.4,44.6,68.2,0,0,0
6
+ C7.4,25.7,6.7,37.7,19.6,47.8 M32,28.7C35.2,34.8,41,44,45,47c4,3,8.4,5.2-0.9,1.2C34.8,44.3,28,33.1,23.5,24.6
7
+ c-3.5-6.5-6.4-12.4-12.9-16.8c-6.5-4.4,0.8-1.3,0.8-1.3C23.2,12.3,27.5,20.2,32,28.7"/>
8
+ </svg>
assets/css/images/icons/lightbox.svg ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="lightbox" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" d="M4,56V12H0v44c0,4.4,3.8,8,8.5,8H56v-4H8.3C5.9,60,4,58.2,4,56z M54,8H18c-1.1,0-2,0.9-2,2v32
6
+ c0,1.1,0.9,2,2,2h36c1.1,0,2-0.9,2-2V10C56,8.9,55.1,8,54,8z M52,38c0,1.1-0.9,2-2,2H22c-1.1,0-2-0.9-2-2V14c0-1.1,0.9-2,2-2h28
7
+ c1.1,0,2,0.9,2,2V38z M60,0H12C9.8,0,8,1.8,8,4v48c0,2.2,1.8,4,4,4h48c2.2,0,4-1.8,4-4V4C64,1.8,62.2,0,60,0z M60,50
8
+ c0,1.1-0.9,2-2,2H14c-1.1,0-2-0.9-2-2V6c0-1.1,0.9-2,2-2h44c1.1,0,2,0.9,2,2V50z"/>
9
+ </svg>
assets/css/images/icons/misc.svg ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="misc" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" d="M62,11.8l-8.9,8.9L45,19l-1.6-8.1L52.2,2c-2.8-1.3-5.9-2-9-2C38,0,32.7,2,28.7,6c-5.7,5.7-7.3,14-4.9,21.2
6
+ L2.7,48.3c-3.6,3.6-3.6,9.4,0,13C4.5,63.1,6.8,64,9.2,64c2.4,0,4.7-0.9,6.5-2.7l21.1-21.1c2.2,0.7,4.4,1.1,6.7,1.1
7
+ c5.3,0,10.5-2,14.5-6C64.4,28.9,65.6,19.5,62,11.8z M54.8,32c-3,3-7,4.7-11.3,4.7c-1.8,0-3.5-0.3-5.2-0.8L35.6,35l-2,2L12.5,58.1
8
+ c-0.9,0.9-2,1.4-3.3,1.4c-1.2,0-2.4-0.5-3.3-1.4c-0.9-0.9-1.4-2-1.4-3.3c0-1.2,0.5-2.4,1.4-3.3L27,30.4l2-2l-0.9-2.7
9
+ c-2-5.9-0.5-12.2,3.8-16.5c3-3,7-4.7,11.3-4.7l-3.1,3.1l-1.7,1.7l0.5,2.4l1.6,8.1l0.6,3l3,0.6l8.1,1.6l2.4,0.5l1.7-1.7l3.1-3.1
10
+ C59.4,24.9,57.8,29,54.8,32z"/>
11
+ </svg>
assets/css/images/icons/mobile.svg ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="mobile" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+
6
+ <path class="envira-icon" d="M44,0H20c-4.4,0-8,3.6-8,8v48c0,4.4,3.6,8,8,8h24c4.4,0,8-3.6,8-8V8C52,3.6,48.4,0,44,0z M48,56
7
+ c0,2.2-1.8,4-4,4H20c-2.2,0-4-1.8-4-4V44h32V56z M48,40H16V16h32V40z M48,12H16V8c0-2.2,1.8-4,4-4h24c2.2,0,4,1.8,4,4V12z M32,56
8
+ c2.2,0,4-1.8,4-4c0-2.2-1.8-4-4-4c-2.2,0-4,1.8-4,4C28,54.2,29.8,56,32,56z"/>
9
+ </svg>
assets/css/images/icons/pagination.svg ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="pagination" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" d="M26,4V0h38v4H26L26,4z M40,19v-4h16v4H40L40,19z M40,27v-4h16v4H40L40,27z M40,35v-4h16v4H40L40,35z M38,50
6
+ v-4h26v4H38L38,50z M60,46V4h4v42H60L60,46z M26,14V4h4v10H26L26,14z M0,18v-4h38v4H0L0,18z M8,33v-4h22v4H8L8,33z M8,41v-4h22v4H8
7
+ L8,41z M8,49v-4h22v4H8L8,49z M0,64v-4h38v4H0L0,64z M34,60V18h4v42H34L34,60z M0,60V18h4v42H0L0,60z"/>
8
+ </svg>
assets/css/images/icons/pinterest.svg ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="pinterest" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path d="M33.587,0.534c11.815,0,22.577,8.128,22.577,20.583c0,11.702-5.982,24.685-19.303,24.685c-3.161,0-7.15-1.58-8.692-4.516
6
+ c-2.86,11.326-2.634,13.02-8.956,21.674l-0.527,0.188l-0.339-0.375c-0.226-2.371-0.564-4.705-0.564-7.074
7
+ c0-7.678,3.537-18.777,5.268-26.228c-0.941-1.919-1.204-4.252-1.204-6.359c0-3.801,2.634-8.617,6.923-8.617
8
+ c3.161,0,4.854,2.408,4.854,5.381c0,4.892-3.312,9.482-3.312,14.223c0,3.236,2.672,5.494,5.795,5.494
9
+ c8.654,0,11.326-12.493,11.326-19.153c0-8.918-6.321-13.772-14.863-13.772c-9.934,0-17.61,7.149-17.61,17.234
10
+ c0,4.854,2.972,7.337,2.972,8.504c0,0.978-0.715,4.441-1.957,4.441c-0.188,0-0.452-0.076-0.64-0.113
11
+ C9.957,35.113,8,27.927,8,22.998C8,9.113,20.718,0.534,33.587,0.534z"/>
12
+ </svg>
assets/css/images/icons/printing.svg ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="printing" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" fill="#3C4042" d="M24,20C24,20,24,20,24,20l-4,0v4c0,0,0,0,0,0c0,0,0,0,0,0v4h8v-8L24,20C24,20,24,20,24,20z M12,20
6
+ C12,20,12,20,12,20l-4,0v4c0,0,0,0,0,0l0,0v4h8v-8L12,20C12,20,12,20,12,20z M62,12H48V0H16v12H2c-1.1,0-2,0.9-2,2v36
7
+ c0,1.1,0.9,2,2,2h14v12h32V52h14c1.1,0,2-0.9,2-2V14C64,12.9,63.1,12,62,12z M20,4h24v8H20V4z M44,60H20V40h24V60z M60,46
8
+ c0,1.1-0.9,2-2,2H48V36H16v12H6c-1.1,0-2-0.9-2-2V18c0-1.1,0.9-2,2-2h52c1.1,0,2,0.9,2,2V46z"/>
9
+ </svg>
assets/css/images/icons/proofing.svg ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="proofing" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" fill-rule="evenodd" clip-rule="evenodd" d="M60.6,64H12.4C10.5,64,9,62.5,9,60.6V52c0-0.1,0-0.2,0-0.3V12.4
6
+ C9,10.5,10.5,9,12.4,9h48.1c1.9,0,3.4,1.5,3.4,3.4v48.1C64,62.5,62.5,64,60.6,64z M12.4,58.8c0,0.9,0.8,1.7,1.7,1.7h30.5L27.5,40.8
7
+ L12.4,53V58.8z M60.6,14.2c0-0.9-0.8-1.7-1.7-1.7H14.2c-0.9,0-1.7,0.8-1.7,1.7v34.1L26.3,37c0.3-0.2,0.6-0.3,0.9-0.4
8
+ c0.1,0,0.1,0,0.2-0.1c0.1,0,0.3-0.1,0.4-0.1c0.5-0.1,1.1,0.1,1.4,0.5l5.3,6.2l16.1-13.1c0.4-0.4,0.9-0.5,1.4-0.4
9
+ c0.6,0,1.1,0.1,1.6,0.4l7,7.6V14.2z M60.6,42.9C60.5,42.9,60.5,42.9,60.6,42.9l-8.8-9.4L36.7,45.8l12.8,14.8h9.3
10
+ c0.9,0,1.7-0.8,1.7-1.7V42.9z M22.8,29.6c-3.8,0-6.9-3.1-6.9-6.9c0-3.8,3.1-6.9,6.9-6.9s6.9,3.1,6.9,6.9
11
+ C29.6,26.5,26.6,29.6,22.8,29.6z M22.8,19.3c-1.9,0-3.4,1.5-3.4,3.4c0,1.9,1.5,3.4,3.4,3.4c1.9,0,3.4-1.5,3.4-3.4
12
+ C26.2,20.9,24.7,19.3,22.8,19.3z M16,4h-4V0h4V4z M28,4h-4V0h4V4z M40,4h-4V0h4V4z M52,4h-4V0h4V4z M64,4h-4V0h4V4z M4,4H0V0h4V4z
13
+ M4,16H0v-4h4V16z M4,28H0v-4h4V28z M4,40H0v-4h4V40z M4,52H0v-4h4V52z M4,64H0v-4h4V64z"/>
14
+ </svg>
assets/css/images/icons/slideshow.svg ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="slideshow" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" d="M62,4H2C0.9,4,0,4.9,0,6c0,1.1,0.9,2,2,2h2v36c0,2.2,1.8,4,4,4h17.3l-5,9.2c-0.6,0.9-0.2,2.1,0.8,2.6
6
+ c1.1,0.5,2.4,0.2,3-0.7l5.6-10.2c0.2-0.3,0.3-0.5,0.3-0.8H34c0,0.3,0.1,0.6,0.3,0.8l5.6,10.2c0.6,0.9,2,1.2,3,0.7
7
+ c1.1-0.5,1.4-1.7,0.8-2.6l-5-9.2H56c2.2,0,4-1.8,4-4V8h2c1.1,0,2-0.9,2-2C64,4.9,63.1,4,62,4z M56,12L56,12l0,30c0,1.1-0.9,2-2,2
8
+ H10c-1.1,0-2-0.9-2-2V10l0,0V8h2c0,0,0,0,0,0h44c0,0,0,0,0,0h2V12z M51,15.9c-1-0.6-2.2-0.2-2.7,0.7L35.9,27.9l-9.8-7
9
+ c-0.5-0.7-1.5-1.1-2.4-0.9c-0.2,0-0.3,0.1-0.5,0.1c0,0-0.1,0-0.1,0c0,0-0.1,0-0.1,0.1c-0.1,0.1-0.3,0.2-0.4,0.3
10
+ c-0.1,0.1-0.2,0.2-0.3,0.3c0,0,0,0-0.1,0.1l-10,12c-0.6,1-0.2,2.2,0.7,2.8s2.2,0.2,2.7-0.7l8.8-10.5l9.3,6.6
11
+ c0.2,0.3,0.5,0.5,0.9,0.7c0.1,0.1,0.1,0.3,0.3,0.4c1,0.5,2.2,0.2,2.7-0.7l14-12.8C52.3,17.6,52,16.4,51,15.9z"/>
12
+ </svg>
assets/css/images/icons/social.svg ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="social" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" d="M47.492,12.001H15.999C7.162,12.001,0,19.165,0,28c0,7.669,5.401,14.061,12.603,15.621L15.999,64l15.999-8l-3.001-12.001
6
+ h18.502l16.496,11.999V0L47.492,12.001z M19.054,58l-2.332-13.997h8.154l2.465,9.855L19.054,58z M43.995,39.998H31.998V40H15.999
7
+ C9.372,40,4,34.625,4,28c0-6.626,5.372-11.998,11.999-11.998h15.998v-0.004h11.998V39.998z M59.995,47.996l-11.998-8.57V16.569
8
+ l11.998-8.571V47.996z"/>
9
+ </svg>
assets/css/images/icons/tags.svg ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="tags" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" d="M12.3,37.7l14,14l2.8-2.8l-14-14L12.3,37.7z M33.3,0L1.2,32.1c-1.5,1.5-1.5,4,0,5.6l25.1,25.1
6
+ c1.5,1.5,4,1.5,5.6,0L64,30.7L64,0L33.3,0z M59.8,29.3L30.5,58.7c-0.8,0.8-2,0.8-2.8,0L5.3,36.3c-0.8-0.8-0.8-2,0-2.8L34.7,4.2
7
+ L60,4L59.8,29.3z M53.7,21.7c3.1-3.1,3.1-8.2,0-11.3c-3.1-3.1-8.2-3.1-11.3,0c-3.1,3.1-3.1,8.2,0,11.3
8
+ C45.4,24.8,50.5,24.8,53.7,21.7z M45.2,13.1c1.6-1.6,4.1-1.6,5.7,0c1.6,1.6,1.6,4.1,0,5.7c-1.6,1.6-4.1,1.6-5.7,0
9
+ C43.6,17.2,43.6,14.7,45.2,13.1z"/>
10
+ </svg>
assets/css/images/icons/video.svg ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="video" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" d="M62,16l-14,9.3V20c0-4.4-3.6-8-8-8H8c-4.4,0-8,3.6-8,8v24c0,4.4,3.6,8,8,8h32c4.4,0,8-3.6,8-8v-5.3L62,48
6
+ c1.1,0,2-0.9,2-2V18C64,16.9,63.1,16,62,16z M44,44c0,2.2-1.8,4-4,4H8c-2.2,0-4-1.8-4-4V20c0-2.2,1.8-4,4-4h32c2.2,0,4,1.8,4,4V44
7
+ z M60,41.9l-12-8v-3.7l12-8V41.9z"/>
8
+ </svg>
assets/css/images/icons/watermark.svg ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+ <svg version="1.1" id="watermark" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
5
+ <path class="envira-icon" d="M50,24v-6c0-9.9-8.1-18-18-18c-9.9,0-18,8.1-18,18v6h0c-4.4,0-8,3.6-8,8v24c0,4.4,3.6,8,8,8h36
6
+ c4.4,0,8-3.6,8-8V32C58,27.6,54.4,24,50,24z M18,18c0-7.7,6.3-14,14-14c7.7,0,14,6.3,14,14v6H18V18z M54,56c0,2.2-1.8,4-4,4H14
7
+ c-2.2,0-4-1.8-4-4V32c0-2.2,1.8-4,4-4h36c2.2,0,4,1.8,4,4V56z M32,36c-1.1,0-2,0.9-2,2v12c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2V38
8
+ C34,36.9,33.1,36,32,36z"/>
9
+ </svg>
assets/css/images/icons/woocommerce.svg ADDED
@@ -0,0 +1 @@
 
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?><svg width="256px" height="153px" viewBox="0 0 256 153" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid"><g><path d="M23.7586644,0 L232.137438,0 C245.324643,0 256,10.6753566 256,23.8625617 L256,103.404434 C256,116.591639 245.324643,127.266996 232.137438,127.266996 L157.409942,127.266996 L167.666657,152.385482 L122.558043,127.266996 L23.8633248,127.266996 C10.6761196,127.266996 0.000763038458,116.591639 0.000763038458,103.404434 L0.000763038458,23.8625617 C-0.10389732,10.7800169 10.5714592,0 23.7586644,0 L23.7586644,0 Z" fill="#9B5C8F"></path><path d="M14.5781994,21.7495935 C16.0351099,19.7723577 18.2204758,18.7317073 21.1342969,18.5235772 C26.441614,18.1073171 29.4595002,20.604878 30.1879555,26.0162602 C33.4139717,47.7658537 36.9521831,66.1853659 40.6985246,81.2747967 L63.4887685,37.8796748 C65.5700693,33.9252033 68.1716953,31.8439024 71.2936465,31.6357724 C75.8725083,31.3235772 78.6822644,34.2373984 79.8269798,40.3772358 C82.4286059,54.2178862 85.7586872,65.9772358 89.7131587,75.9674797 C92.4188498,49.5349593 96.9977116,30.4910569 103.449744,18.7317073 C105.01072,15.8178862 107.300151,14.3609756 110.318037,14.1528455 C112.711533,13.9447154 114.896899,14.6731707 116.874134,16.2341463 C118.85137,17.795122 119.89202,19.7723577 120.100151,22.1658537 C120.204216,24.0390244 119.89202,25.6 119.0595,27.1609756 C115.000964,34.6536585 111.670882,47.2455285 108.965191,64.7284553 C106.363565,81.6910569 105.42698,94.9073171 106.05137,104.377236 C106.2595,106.978862 105.84324,109.268293 104.80259,111.245528 C103.553809,113.534959 101.680638,114.78374 99.2871424,114.99187 C96.5814514,115.2 93.7716953,113.95122 91.0660042,111.141463 C81.3879555,101.255285 73.6871424,86.4780488 68.0676303,66.8097561 C61.3034026,80.1300813 56.3082807,90.1203252 53.0822644,96.7804878 C46.942427,108.539837 41.739175,114.57561 37.3684433,114.887805 C34.5586872,115.095935 32.1651912,112.702439 30.0838904,107.707317 C24.7765733,94.0747967 19.0529961,67.7463415 12.9131587,28.7219512 C12.4968985,26.0162602 13.1212888,23.6227642 14.5781994,21.7495935 Z M238.213972,38.0878049 C234.46763,31.5317073 228.952183,27.5772358 221.563565,26.0162602 C219.586329,25.6 217.713159,25.3918699 215.944053,25.3918699 C205.953809,25.3918699 197.836736,30.595122 191.488768,41.001626 C186.077386,49.8471545 183.371695,59.6292683 183.371695,70.3479675 C183.371695,78.3609756 185.036736,85.2292683 188.366817,90.9528455 C192.113159,97.5089431 197.628606,101.463415 205.017224,103.02439 C206.99446,103.44065 208.86763,103.64878 210.636736,103.64878 C220.731045,103.64878 228.848118,98.4455285 235.09202,88.0390244 C240.503403,79.0894309 243.209094,69.3073171 243.209094,58.5886179 C243.313159,50.4715447 241.544053,43.7073171 238.213972,38.0878049 Z M225.101777,66.9138211 C223.644866,73.7821138 221.04324,78.8813008 217.192834,82.3154472 C214.174947,85.0211382 211.365191,86.1658537 208.763565,85.6455285 C206.266004,85.1252033 204.184703,82.9398374 202.623728,78.8813008 C201.374947,75.6552846 200.750557,72.4292683 200.750557,69.4113821 C200.750557,66.8097561 200.958687,64.2081301 201.479012,61.8146341 C202.415598,57.5479675 204.184703,53.3853659 206.99446,49.4308943 C210.428606,44.3317073 214.070882,42.2504065 217.817224,42.9788618 C220.314785,43.499187 222.396086,45.6845528 223.957061,49.7430894 C225.205842,52.9691057 225.830232,56.195122 225.830232,59.2130081 C225.830232,61.9186992 225.622102,64.5203252 225.101777,66.9138211 Z M173.069256,38.0878049 C169.322915,31.5317073 163.703403,27.5772358 156.41885,26.0162602 C154.441614,25.6 152.568443,25.3918699 150.799338,25.3918699 C140.809094,25.3918699 132.69202,30.595122 126.344053,41.001626 C120.932671,49.8471545 118.22698,59.6292683 118.22698,70.3479675 C118.22698,78.3609756 119.89202,85.2292683 123.222102,90.9528455 C126.968443,97.5089431 132.48389,101.463415 139.872508,103.02439 C141.849744,103.44065 143.722915,103.64878 145.49202,103.64878 C155.586329,103.64878 163.703403,98.4455285 169.947305,88.0390244 C175.358687,79.0894309 178.064378,69.3073171 178.064378,58.5886179 C178.064378,50.4715447 176.399338,43.7073171 173.069256,38.0878049 Z M159.852996,66.9138211 C158.396086,73.7821138 155.79446,78.8813008 151.944053,82.3154472 C148.926167,85.0211382 146.116411,86.1658537 143.514785,85.6455285 C141.017224,85.1252033 138.935923,82.9398374 137.374947,78.8813008 C136.126167,75.6552846 135.501777,72.4292683 135.501777,69.4113821 C135.501777,66.8097561 135.709907,64.2081301 136.230232,61.8146341 C137.166817,57.5479675 138.935923,53.3853659 141.745679,49.4308943 C145.179825,44.3317073 148.822102,42.2504065 152.568443,42.9788618 C155.066004,43.499187 157.147305,45.6845528 158.708281,49.7430894 C159.957061,52.9691057 160.581451,56.195122 160.581451,59.2130081 C160.685516,61.9186992 160.373321,64.5203252 159.852996,66.9138211 L159.852996,66.9138211 L159.852996,66.9138211 Z" fill="#FFFFFF"></path></g></svg>
assets/css/images/menu-icon.png CHANGED
Binary file
assets/css/images/{menu-icon-2x.png → menu-icon@2x.png} RENAMED
Binary file
assets/css/images/meta-2x.png DELETED
Binary file
assets/css/images/meta-active-2x.png DELETED
Binary file
assets/css/images/meta-active.png DELETED
Binary file
assets/css/images/meta.png DELETED
Binary file
assets/css/images/modify-2x.png DELETED
Binary file
assets/css/images/modify.png DELETED
Binary file
assets/css/images/{preloader-2x.gif → preloader@2x.gif} RENAMED
File without changes
assets/css/images/social.png ADDED
Binary file
assets/css/images/social@2x.png ADDED
Binary file
assets/css/metabox.css CHANGED
@@ -1 +1 @@
1
- .envira-gallery-spinner{float:none;display:inline-block;margin-top:0}#envira-gallery{position:relative}#envira-gallery .envira-clear{clear:both}#envira-gallery .envira-clear:after{clear:both;content:'.';display:block;height:0;line-height:0;overflow:auto;visibility:hidden;zoom:1}#envira-gallery p.description{font-size:13px}#envira-gallery .inside{margin:10px 0;padding:0 10px}#envira-gallery #envira-tabs{position:relative}#envira-gallery #envira-tabs-nav{list-style:none;margin:0 0 10px;padding:0;border-bottom:1px solid #cecece}#envira-gallery #envira-tabs-nav li{float:left;margin:0 10px -1px 0}#envira-gallery #envira-tabs-nav li a{display:block;padding:7px 10px 5px;font-size:14px;color:#aaa;font-weight:300;text-decoration:none;outline:none}#envira-gallery #envira-tabs-nav li.envira-active a{border:1px solid #cecece;border-bottom-color:#fff;-moz-border-radius:3px 3px 0 0;-webkit-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;color:#21759b;padding-top:6px}#envira-gallery #envira-tabs-nav li a:hover{color:#21759b}#envira-gallery-types-nav{margin:10px 0;padding:10px 0;border-top:1px solid #eee;border-bottom:1px solid #eee}#envira-gallery-types-nav li{float:left;margin:0 10px 0 0}#envira-gallery-types-nav li.envira-gallery-type-label{margin-right:20px}#envira-gallery-types-nav li.envira-gallery-type-label span{font-weight:700;font-size:13px;vertical-align:middle}#envira-gallery .envira-meta-close-text{display:none;color:#fff;font-style:italic;font-size:11px;position:absolute;z-index:98;top:6px;right:27px}#envira-gallery .envira-helper-active .envira-meta-close-text{display:inline}#envira-gallery .envira-meta-icon{position:absolute;width:19px;height:16px;top:6px;right:0;background:url(images/meta.png) no-repeat scroll 0 0;display:block;outline:none;z-index:98}#envira-gallery .envira-helper-active .envira-meta-icon{background-image:url(images/meta-active.png)}#envira-gallery .envira-meta-information{display:none;padding:0 1em 1em;position:absolute;right:0;top:30px;width:278px;background:#fff;border:1px solid #e5e5e5;-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.7);box-shadow:0 5px 15px rgba(0,0,0,0.7);z-index:98}#envira-gallery .envira-helper-active .envira-meta-information{display:block}#envira-gallery .envira-meta-helper-overlay{position:absolute;z-index:97;background:#000;opacity:.7;filter:alpha(opacity=70);width:100%;height:100%}#envira-gallery .envira-tab{display:none}#envira-gallery .envira-tab.envira-active{display:block}#envira-gallery .envira-tab p.envira-intro{margin:1.5em 0 .5em}#envira-gallery .envira-tab th,#envira-gallery .envira-tab input[type="text"],#envira-gallery .envira-tab input[type="number"],#envira-gallery .envira-tab input[type="password"],#envira-gallery .envira-tab select{width:210px;padding-right:0}#envira-gallery .envira-tab tr td label{margin:0 10px 0 0}#envira-gallery .envira-progress-bar{display:none;width:100%;position:relative;height:10px;width:100%;margin:10px auto;border-radius:10px;background:#dfdfdf;background:rgba(0,0,0,0.1)}#envira-gallery .envira-progress-bar div{height:10px;min-width:20px;width:0;background:#aaa;background:rgba(0,0,0,0.2);border-radius:10px;-webkit-transition:width 300ms;-moz-transition:width 300ms;-ms-transition:width 300ms;-o-transition:width 300ms;transition:width 300ms}#envira-gallery .upload-flash-bypass{display:none}#envira-gallery .max-upload-size{display:block;margin:10px 0}#envira-gallery .envira-tab{min-height:320px}#envira-gallery #envira-gallery-output{margin:20px 0 10px;padding:0;list-style:none}#envira-gallery #envira-gallery-output li{background:#fff;display:block;float:left;margin:0 10px 10px 0;padding:4px;list-style:none;border:1px solid #cecece;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box;-moz-box-shadow:0 1px 2px rgba(0,0,0,0.06);-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.06);box-shadow:0 1px 2px rgba(0,0,0,0.06);cursor:move;position:relative;width:150px;height:150px}#envira-gallery #envira-gallery-output li a.check{display:none;position:absolute;right:5px;top:5px;width:24px;height:24px;background-color:#1e8cbe;-webkit-box-shadow:0 0 0 1px #fff,0 0 0 2px #1e8cbe;box-shadow:0 0 0 1px #fff,0 0 0 2px #1e8cbe}#envira-gallery #envira-gallery-output li a.check div.media-modal-icon{width:15px;height:15px;margin:5px 0 0 5px;background-position:-21px 0}#envira-gallery #envira-gallery-output li.selected{width:148px;height:148px;border:2px solid #1e8cbe;-webkit-box-shadow:inset 0 0 0 3px #fff,inset 0 0 0 7px #1e8cbe;box-shadow:inset 0 0 0 3px #fff,inset 0 0 0 7px #1e8cbe}#envira-gallery #envira-gallery-output li.selected a.check{display:block}#envira-gallery #envira-gallery-output li.envira-gallery-status-pending{background-color:#faebcc;border-color:#8a6d3b}#envira-gallery #envira-gallery-output li.envira-gallery-status-active{background-color:#dff0d8;border-color:#3c763d}#envira-gallery #envira-gallery-output li.dropzone{background:transparent;border:1px dashed #d5d5d5;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}#envira-gallery #envira-gallery-output li img{display:block;margin:auto;position:absolute;top:0;left:0;right:0;bottom:0;max-width:150px;max-height:150px}#envira-gallery #envira-gallery-output li .envira-gallery-remove-image{background:url(images/delete.png) no-repeat scroll 0 0;display:block;height:16px;left:-8px;outline:none;position:absolute;top:-8px;width:16px;z-index:20}#envira-gallery #envira-gallery-output li .envira-gallery-modify-image{background:url(images/modify.png) no-repeat scroll 0 0;display:block;height:16px;left:12px;outline:none;position:absolute;top:-8px;width:16px;z-index:20}#media-items .media-item .edit-attachment,.envira-gallery-media-frame .upload-flash-bypass{display:none !important}#media-items{margin:0 0 16px;overflow:hidden;width:100%}#media-items .media-item{width:auto;float:left;margin:0 8px 8px 0}#media-items .media-item img{max-width:164px;max-height:164px;float:none;margin:4px;display:block}.envira-gallery-gallery{padding-left:7px}.envira-gallery-gallery .attachment{margin:8px;max-width:164px}.envira-gallery-gallery .attachment-preview,.envira-gallery-gallery .attachment-preview .thumbnail{max-width:164px;max-height:164px}.envira-gallery-media-frame .max-upload-size{display:block;margin:1em 0}.envira-gallery-media-frame .envira-gallery-library-toolbar{top:5px}.envira-gallery-media-frame .attachment.envira-gallery-in-gallery{box-shadow:inset 0 0 0 3px #fff, inset 0 0 0 7px #519e0c}.envira-gallery-media-frame .attachment.envira-gallery-in-gallery .attachment-preview,.envira-gallery-media-frame .attachment.envira-gallery-in-gallery .attachment-preview .check{cursor:default}.envira-gallery-media-frame .attachment.envira-gallery-in-gallery .check{box-shadow:0 0 0 1px #519e0c;background:#519e0c;background-image:-webkit-gradient(linear, left top, left bottom, from(#519e0c), to(#519e0c));background-image:-webkit-linear-gradient(top, #519e0c, #407f08);background-image:-moz-linear-gradient(top, #519e0c, #407f08);background-image:-o-linear-gradient(top, #519e0c, #407f08);background-image:linear-gradient(to bottom, #519e0c, #407f08)}.envira-gallery-media-frame .attachment.envira-gallery-in-gallery .check div,.envira-gallery-media-frame .attachment.envira-gallery-in-gallery .check:hover div{background-position:-21px 0}.envira-gallery-meta-wrap .envira-gallery-meta-sidebar{overflow:auto;position:relative}.envira-gallery-media-frame .media-sidebar h3{margin:1.1em 0 1em}.envira-gallery-media-frame .media-sidebar p{margin:0 0 1.5em}.envira-gallery-meta{overflow:auto;padding:0 16px}.media-frame.envira-gallery-media-frame input:focus,.media-frame.envira-gallery-media-frame textarea:focus,.media-frame.envira-gallery-media-frame select:focus{border-color:#aaa}.envira-gallery-meta-wrap .envira-gallery-meta.attachments{top:0}.envira-gallery-meta.attachments .attachment{width:200px;height:200px;border:none !important}.envira-gallery-meta.attachments .attachment.selected{width:200px;height:200px}.envira-gallery-meta.attachments .attachment .attachment-preview{width:100%;height:100%;border:none !important}.envira-gallery-meta.attachments .attachment .attachment-preview:before{padding-top:0;border:none !important}.envira-gallery-meta.attachments .attachment .attachment-preview .thumbnail{display:table;position:relative;top:auto;right:auto;bottom:auto;left:auto;border:none !important}.envira-gallery-meta.attachments .attachment .attachment-preview .thumbnail:after{box-shadow:none;-webkit-box-shadow:none;-moz-box-shadow:none}.envira-gallery-meta.attachments .attachment .attachment-preview .thumbnail .inside{display:table-cell;width:200px;height:200px;text-align:center;vertical-align:middle;border:none !important}.envira-gallery-ui-content{top:16px !important}.envira-gallery-meta-wrap .form-table{margin:0}.envira-gallery-meta-wrap .form-table input[type=text],.envira-gallery-meta-wrap .form-table textarea{width:100%}#envira-gallery .envira-gallery-import-form{margin-bottom:20px;padding-bottom:20px;border-bottom:1px solid #ddd}#envira-gallery .envira-unit{font-style:normal;font-weight:700;font-size:13px}#envira-gallery textarea{width:100%}.envira-alert{padding:15px;margin-bottom:20px;border:1px solid #faebcc;border-radius:4px;background-color:#fcf8e3;color:#8a6d3b}#envira-gallery-plupload-upload-ui{position:relative}#envira-gallery-drag-drop-area{border:4px dashed #bbb;height:200px}#envira-gallery-plupload-upload-ui.drag-over #envira-gallery-drag-drop-area{border-color:#83b4d8}#envira-gallery .envira-gallery-progress-bar{display:none;width:100%;position:relative;height:10px;width:100%;margin:10px auto;border-radius:10px;background:#dfdfdf;background:rgba(0,0,0,0.1)}#envira-gallery .envira-gallery-progress-bar div{height:10px;min-width:20px;width:0;background:#aaa;background:rgba(0,0,0,0.2);border-radius:10px;-webkit-transition:width 300ms;-moz-transition:width 300ms;-ms-transition:width 300ms;-o-transition:width 300ms;transition:width 300ms}#envira-gallery .upload-flash-bypass{display:none}#envira-gallery .max-upload-size{display:block;margin:10px 0}body.branch-4-3 div.media-modal a.media-modal-close,body.branch-4-4 div.media-modal a.media-modal-close,body.branch-4-5 div.media-modal a.media-modal-close{text-align:center;text-decoration:none;display:inline-block}body.branch-4-3 div.media-modal a.media-modal-close span,body.branch-4-4 div.media-modal a.media-modal-close span,body.branch-4-5 div.media-modal a.media-modal-close span{display:inline-block;margin-top:17px}.envira-gallery-meta-container button.right{border-right:1px solid #ddd !important}.envira-gallery-meta-container .setting span.name{min-width:20%;text-align:left}.envira-gallery-meta-container .setting input[type=text]{width:75%}.envira-gallery-meta-container .setting textarea{height:150px}.envira-gallery-meta-container .setting .wp-editor-wrap{float:right;width:75%}.envira-gallery-meta-container #wp-link{float:left;width:100%}.envira-gallery-meta-container #wp-link #search-panel{display:block;float:left;width:100%}.envira-gallery-meta-container #wp-link #search-panel .link-search-wrapper{float:left;width:100%;margin:0}.envira-gallery-meta-container #wp-link #search-panel .link-search-wrapper label{display:block;float:left;width:100%;margin:1px 0}.envira-gallery-meta-container #wp-link #search-panel .link-search-wrapper label span.name{display:none}.envira-gallery-meta-container #wp-link #search-panel .link-search-wrapper label input{float:right;width:75%;max-width:75%}.envira-gallery-meta-container #wp-link #search-panel #search-results{position:relative;float:right;width:75%;max-width:75%;margin:-2px 0 0 0;display:block;top:0;left:0;right:0;bottom:0;border:none;border-left:1px solid #dfdfdf;border-bottom:1px solid #dfdfdf;border-right:1px solid #dfdfdf}.envira-gallery-meta-container #wp-link #search-panel #most-recent-results{display:none}.envira-gallery-meta-container div.actions a.button{display:inline-block}@media only screen and (max-width: 959px){.envira-gallery-meta-container .setting span.name{width:100%;max-width:100%;min-width:100%}.envira-gallery-meta-container .setting input[type=text]{width:100%}.envira-gallery-meta-container .setting input[type=checkbox]{clear:both}.envira-gallery-meta-container .setting .wp-editor-wrap{float:left;width:100%}}@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min--moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2 / 1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx){#envira-gallery .envira-meta-icon{background-image:url(images/meta-2x.png);background-size:19px 16px}#envira-gallery .envira-helper-active .envira-meta-icon{background-image:url(images/meta-active-2x.png);background-size:19px 16px}#envira-gallery #envira-gallery-output li .envira-gallery-remove-image{background-image:url(images/delete-2x.png);background-size:16px 16px}#envira-gallery #envira-gallery-output li .envira-gallery-modify-image{background-image:url(images/modify-2x.png);background-size:16px 16px}}
1
+ body.post-type-envira #message,body.post-type-envira_album #message{margin:5px 20px 15px 20px}form#post.envira-gallery{margin:0 20px}form#post.envira-gallery #poststuff p.envira-intro{margin:0;padding:0 0 30px 0;border-bottom:1px solid #ddd;font-size:16px;font-weight:700}form#post.envira-gallery #poststuff p.envira-intro small{margin:5px 0 0 0;display:block;font-weight:400}form#post.envira-gallery #poststuff p.envira-intro small a{text-decoration:none;font-weight:600}form#post.envira-gallery #poststuff div.envira-video-help{position:relative;z-index:1;width:100%;margin:20px 0 0 0}form#post.envira-gallery #poststuff div.envira-video-help iframe{position:relative;z-index:1;width:100%;height:auto;min-height:300px}form#post.envira-gallery #poststuff div.envira-video-help a.envira-video-close{position:absolute;z-index:2;top:-12px;right:-12px;width:24px;height:24px;line-height:24px;-webkit-border-radius:50%;-moz-border-radius:50%;-o-border-radius:50%;border-radius:50%;background:#f5f5f5;color:#000;text-align:center;text-decoration:none}form#post.envira-gallery #poststuff ul.envira-gallery-images-output{width:100%}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li{position:relative;display:inline-block;width:150px;margin:0 20px 20px 0;padding:0;list-style:none;vertical-align:top;-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box;background:#f7f7f7}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li img{display:block;width:150px;height:150px}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li div.placeholder-image{display:block;width:148px;height:149px;background:url(images/icons/leaf.svg) center no-repeat;background-size:64px 64px;border-left:1px solid #dfdfdf;border-top:1px solid #dfdfdf;border-right:1px solid #dfdfdf}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li div.meta{width:148px;overflow:hidden;text-align:center;border-left:1px solid #dfdfdf;border-bottom:1px solid #dfdfdf;border-right:1px solid #dfdfdf}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li div.meta div.title{font-size:12px;font-weight:700;width:138px;height:18px;line-height:18px;margin:8px 5px;overflow:hidden}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li div.meta div.title a.hint{position:absolute;display:inline-block;bottom:10px;right:10px;width:16px;height:16px;background:#f7f7f7}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li div.meta div.title a.hint.hidden{display:none}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li div.meta div.additional{display:none;margin:5px 0 0 0;font-weight:400}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li a.check{display:none;position:absolute;right:5px;top:5px;width:24px;height:24px;background-color:#eee;-webkit-box-shadow:0 0 0 1px #fff,0 0 0 2px rgba(0,0,0,0.15);box-shadow:0 0 0 1px #fff,0 0 0 2px rgba(0,0,0,0.15)}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li a.check div.media-modal-icon{display:none;width:15px;height:15px;margin:5px 0 0 5px;background-position:-21px 0}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li a.dashicons{position:absolute;display:block;top:5px;left:5px;width:25px;height:25px;line-height:25px;font-size:18px;outline:none;z-index:20;border-radius:2px;-moz-border-radius:2px;-webkit-border-radius:2px}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li a.dashicons.envira-gallery-modify-image{background:#0085ba;color:#fff}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li a.dashicons.envira-gallery-remove-image{left:35px;background:#e02626;color:#fff}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li.selected{width:148px;border:2px solid #7cc048 !important}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li.selected a.check{display:block;background-color:#7cc048;-webkit-box-shadow:0 0 0 1px #fff,0 0 0 2px #7cc048;box-shadow:0 0 0 1px #fff,0 0 0 2px #7cc048}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li.selected a.check div.media-modal-icon{display:block}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li.selected div.meta{width:146px}form#post.envira-gallery #poststuff ul.envira-gallery-images-output li.ui-sortable-helper li{position:absolute;top:0;left:0}form#post.envira-gallery #poststuff ul.envira-gallery-images-output.list li{position:relative;z-index:2;display:block;width:100%;margin:0 0 10px 0;padding:10px 15px;background:#fff;border:1px solid #ddd;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:2px;-moz-border-radius:2px;-webkit-border-radius:2px}form#post.envira-gallery #poststuff ul.envira-gallery-images-output.list li img{display:inline-block;width:75px;margin-left:45px}form#post.envira-gallery #poststuff ul.envira-gallery-images-output.list li div.meta{position:absolute;z-index:1;left:0;display:inline-block;width:100%;padding:0 80px 0 150px;border:none;font-weight:700;text-align:left;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}form#post.envira-gallery #poststuff ul.envira-gallery-images-output.list li div.meta div.title{display:block;width:100%;height:auto;font-size:16px;margin:0;padding:0}form#post.envira-gallery #poststuff ul.envira-gallery-images-output.list li div.meta div.title a.hint{display:none}form#post.envira-gallery #poststuff ul.envira-gallery-images-output.list li div.meta div.additional{display:block}form#post.envira-gallery #poststuff ul.envira-gallery-images-output.list li a.check{display:block;position:absolute;left:15px;top:35px}form#post.envira-gallery #poststuff ul.envira-gallery-images-output.list li a.envira-gallery-remove-image{left:auto;top:10px;right:10px}form#post.envira-gallery #poststuff ul.envira-gallery-images-output.list li a.envira-gallery-modify-image{left:auto;top:10px;right:40px}form#post.envira-gallery #poststuff #envira-gallery{margin:60px 0 20px 0}form#post.envira-gallery #poststuff #envira-gallery .handlediv,form#post.envira-gallery #poststuff #envira-albums .handlediv{display:none}form#post.envira-gallery #poststuff #envira-gallery .hndle,form#post.envira-gallery #poststuff #envira-albums .hndle{display:none}form#post.envira-gallery #poststuff #envira-gallery h2.nav-tab-wrapper,form#post.envira-gallery #poststuff #envira-albums h2.nav-tab-wrapper{margin:-56px 0 0 -1px;padding:0;border-bottom:none}form#post.envira-gallery #poststuff #envira-gallery h2.nav-tab-wrapper .nav-tab,form#post.envira-gallery #poststuff #envira-albums h2.nav-tab-wrapper .nav-tab{display:inline-block;width:49%;margin:0;padding:15px 0;text-align:center;font-size:16px;border-color:#e5e5e5;background:#f5f5f5}form#post.envira-gallery #poststuff #envira-gallery h2.nav-tab-wrapper .nav-tab.nav-tab-native-envira-gallery span,form#post.envira-gallery #poststuff #envira-albums h2.nav-tab-wrapper .nav-tab.nav-tab-native-envira-gallery span{display:inline-block;background:url(images/icons/leaf.svg) 0 5px no-repeat;background-size:14px 14px;text-indent:20px}form#post.envira-gallery #poststuff #envira-gallery h2.nav-tab-wrapper .nav-tab.nav-tab-external-gallery,form#post.envira-gallery #poststuff #envira-albums h2.nav-tab-wrapper .nav-tab.nav-tab-external-gallery{margin-right:-1px}form#post.envira-gallery #poststuff #envira-gallery h2.nav-tab-wrapper .nav-tab:hover,form#post.envira-gallery #poststuff #envira-gallery h2.nav-tab-wrapper .nav-tab.envira-active,form#post.envira-gallery #poststuff #envira-albums h2.nav-tab-wrapper .nav-tab:hover,form#post.envira-gallery #poststuff #envira-albums h2.nav-tab-wrapper .nav-tab.envira-active{background:#fff;border-bottom:1px solid #fff}form#post.envira-gallery #poststuff #envira-gallery h2.nav-tab-wrapper .nav-tab:focus,form#post.envira-gallery #poststuff #envira-albums h2.nav-tab-wrapper .nav-tab:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}form#post.envira-gallery #poststuff #envira-gallery h2.nav-tab-wrapper .nav-tab:last-child,form#post.envira-gallery #poststuff #envira-albums h2.nav-tab-wrapper .nav-tab:last-child{float:right}form#post.envira-gallery #poststuff #envira-gallery h2.nav-tab-wrapper .nav-tab input[type=radio],form#post.envira-gallery #poststuff #envira-albums h2.nav-tab-wrapper .nav-tab input[type=radio]{display:none}form#post.envira-gallery #poststuff #envira-gallery .inside,form#post.envira-gallery #poststuff #envira-albums .inside{margin:0;padding:0}form#post.envira-gallery #poststuff #envira-gallery .inside #envira-gallery-native #plupload-upload-ui,form#post.envira-gallery #poststuff #envira-albums .inside #envira-gallery-native #plupload-upload-ui{display:none}form#post.envira-gallery #poststuff #envira-gallery .inside #envira-gallery-native #plupload-upload-ui.drag-drop,form#post.envira-gallery #poststuff #envira-albums .inside #envira-gallery-native #plupload-upload-ui.drag-drop{display:block}form#post.envira-gallery #poststuff #envira-gallery .inside #envira-gallery-native #plupload-upload-ui.drag-drop .drag-drop-inside,form#post.envira-gallery #poststuff #envira-albums .inside #envira-gallery-native #plupload-upload-ui.drag-drop .drag-drop-inside{width:520px;margin-top:50px}form#post.envira-gallery #poststuff #envira-gallery .inside #envira-gallery-native #plupload-upload-ui.drag-drop .drag-drop-inside p.drag-drop-buttons,form#post.envira-gallery #poststuff #envira-albums .inside #envira-gallery-native #plupload-upload-ui.drag-drop .drag-drop-inside p.drag-drop-buttons{text-align:left}form#post.envira-gallery #poststuff #envira-gallery .inside #envira-gallery-native #plupload-upload-ui.drag-drop .drag-drop-inside .envira-progress-bar,form#post.envira-gallery #poststuff #envira-albums .inside #envira-gallery-native #plupload-upload-ui.drag-drop .drag-drop-inside .envira-progress-bar{display:none;width:100%;position:relative;height:10px;width:100%;margin:10px auto;border-radius:10px;background:#dfdfdf;background:rgba(0,0,0,0.1)}form#post.envira-gallery #poststuff #envira-gallery .inside #envira-gallery-native #plupload-upload-ui.drag-drop .drag-drop-inside .envira-progress-bar div,form#post.envira-gallery #poststuff #envira-albums .inside #envira-gallery-native #plupload-upload-ui.drag-drop .drag-drop-inside .envira-progress-bar div{height:10px;min-width:20px;width:0;background:#aaa;background:rgba(0,0,0,0.2);border-radius:10px;-webkit-transition:width 300ms;-moz-transition:width 300ms;-ms-transition:width 300ms;-o-transition:width 300ms;transition:width 300ms}form#post.envira-gallery #poststuff #envira-gallery .inside #envira-gallery-native #plupload-upload-ui a.envira-media-library.button,form#post.envira-gallery #poststuff #envira-albums .inside #envira-gallery-native #plupload-upload-ui a.envira-media-library.button{display:block;position:absolute;margin:0 auto;left:280px;right:0;width:230px;top:115px;text-align:center}form#post.envira-gallery #poststuff #envira-gallery .inside #envira-gallery-native #plupload-upload-ui p.upload-flash-bypass,form#post.envira-gallery #poststuff #envira-albums .inside #envira-gallery-native #plupload-upload-ui p.upload-flash-bypass{display:none}form#post.envira-gallery #poststuff #envira-gallery .inside div.envira-tab,form#post.envira-gallery #poststuff #envira-albums .inside div.envira-tab{padding:20px}form#post.envira-gallery #poststuff #envira-gallery .inside div.envira-tab ul#envira-gallery-types-nav,form#post.envira-gallery #poststuff #envira-albums .inside div.envira-tab ul#envira-gallery-types-nav{text-align:center}form#post.envira-gallery #poststuff #envira-gallery .inside div.envira-tab ul#envira-gallery-types-nav li,form#post.envira-gallery #poststuff #envira-albums .inside div.envira-tab ul#envira-gallery-types-nav li{display:inline-block;margin:0 20px 0 0;vertical-align:top}form#post.envira-gallery #poststuff #envira-gallery .inside div.envira-tab ul#envira-gallery-types-nav li:last-child,form#post.envira-gallery #poststuff #envira-albums .inside div.envira-tab ul#envira-gallery-types-nav li:last-child{margin:0}form#post.envira-gallery #poststuff #envira-gallery .inside div.envira-tab ul#envira-gallery-types-nav li label,form#post.envira-gallery #poststuff #envira-albums .inside div.envira-tab ul#envira-gallery-types-nav li label{float:left;width:110px}form#post.envira-gallery #poststuff #envira-gallery .inside div.envira-tab ul#envira-gallery-types-nav li label input,form#post.envira-gallery #poststuff #envira-albums .inside div.envira-tab ul#envira-gallery-types-nav li label input{display:none}form#post.envira-gallery #poststuff #envira-gallery .inside div.envira-tab ul#envira-gallery-types-nav li label div.icon,form#post.envira-gallery #poststuff #envira-albums .inside div.envira-tab ul#envira-gallery-types-nav li label div.icon{width:110px;height:110px;margin:0 0 10px 0;border:1px solid #ddd;background-size:64px 64px;background-position:center;background-repeat:no-repeat}form#post.envira-gallery #poststuff #envira-gallery .inside div.envira-tab ul#envira-gallery-types-nav li label div.title,form#post.envira-gallery #poststuff #envira-albums .inside div.envira-tab ul#envira-gallery-types-nav li label div.title{font-weight:700}form#post.envira-gallery #poststuff #envira-gallery .inside div.envira-tab ul#envira-gallery-types-nav li:hover label div.icon,form#post.envira-gallery #poststuff #envira-gallery .inside div.envira-tab ul#envira-gallery-types-nav li.envira-active label div.icon,form#post.envira-gallery #poststuff #envira-albums .inside div.envira-tab ul#envira-gallery-types-nav li:hover label div.icon,form#post.envira-gallery #poststuff #envira-albums .inside div.envira-tab ul#envira-gallery-types-nav li.envira-active label div.icon{background-color:#f7fcf3;border-color:#7cc048}form#post.envira-gallery #poststuff #envira-gallery .inside div.envira-tab ul#envira-gallery-types-nav li#envira-gallery-type-fc label div.icon,form#post.envira-gallery #poststuff #envira-albums .inside div.envira-tab ul#envira-gallery-types-nav li#envira-gallery-type-fc label div.icon{background-image:url(../images/types/fc.png)}form#post.envira-gallery #poststuff #envira-gallery .inside div.envira-tab ul#envira-gallery-types-nav li#envira-gallery-type-instagram label div.icon,form#post.envira-gallery #poststuff #envira-albums .inside div.envira-tab ul#envira-gallery-types-nav li#envira-gallery-type-instagram label div.icon{background-image:url(../images/types/instagram.png)}form#post.envira-gallery #poststuff #envira-albums .inside #envira-types #envira-album-native{position:relative}form#post.envira-gallery #poststuff #envira-albums .inside #envira-types #envira-album-native ul#envira-album-drag-drop-area{z-index:2;min-height:200px;margin:0;padding:20px;border:4px dashed #b4b9be;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}form#post.envira-gallery #poststuff #envira-albums .inside #envira-types #envira-album-native ul#envira-album-drag-drop-area li{cursor:move}form#post.envira-gallery #poststuff #envira-albums .inside #envira-types #envira-album-native p.drag-drop-info{position:absolute;top:80px;z-index:1;margin:0 auto;left:0;right:0;text-align:center;color:#a0a5aa;font-size:20px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}form#post.envira-gallery #poststuff #envira-albums .inside #envira-types #envira-album-native p.drag-drop-info span{display:block}form#post.envira-gallery #poststuff #envira-albums .inside #envira-types #envira-album-native p.drag-drop-info span.click{font-size:18px}form#post.envira-gallery #poststuff #envira-albums .inside #envira-types #envira-album-native p.drag-drop-info small{display:block;margin:5px 0;font-size:14px}form#post.envira-gallery #poststuff #envira-gallery-settings,form#post.envira-gallery #poststuff #envira-albums-settings{background:#f7f7f7}form#post.envira-gallery #poststuff #envira-gallery-settings:after,form#post.envira-gallery #poststuff #envira-albums-settings:after{content:"";display:table;clear:both}form#post.envira-gallery #poststuff #envira-gallery-settings .handlediv,form#post.envira-gallery #poststuff #envira-albums-settings .handlediv{display:none}form#post.envira-gallery #poststuff #envira-gallery-settings .hndle,form#post.envira-gallery #poststuff #envira-albums-settings .hndle{display:none}form#post.envira-gallery #poststuff #envira-gallery-settings .inside,form#post.envira-gallery #poststuff #envira-albums-settings .inside{margin:0;padding:0}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav{width:160px;margin:0;padding:0;border-right:1px solid #ddd}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li{float:left;width:100%;margin:0;padding:0}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li a{float:left;width:120px;margin:0 20px;padding:20px 0 20px 25px;text-decoration:none;color:#999;border-bottom:1px solid #ddd;background-position:left center;background-repeat:no-repeat;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;transition:none;-webkit-transition:none}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li a:hover,form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li a.envira-active,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li a:hover,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li a.envira-active{width:161px;margin:-1px 0 0 0;padding:20px 20px 20px 45px;text-decoration:none;color:#444;border-top:1px solid #ddd;border-bottom:1px solid #ddd;border-right:1px solid #fff;background-color:#fff;background-position:20px center}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li a:focus,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li a:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li:last-child a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li:last-child a{border-bottom:none}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li:last-child a:hover,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li:last-child a:hover{border-bottom:none}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-images a,form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-galleries a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-images a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-galleries a{background-image:url(images/icons/leaf.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-config a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-config a{background-image:url(images/icons/configuration.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-lightbox a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-lightbox a{background-image:url(images/icons/lightbox.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-mobile a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-mobile a{background-image:url(images/icons/mobile.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-downloads a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-downloads a{background-image:url(images/icons/downloads.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-exif a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-exif a{background-image:url(images/icons/exif.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-pagination a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-pagination a{background-image:url(images/icons/pagination.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-pinterest a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-pinterest a{background-image:url(images/icons/pinterest.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-proofing a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-proofing a{background-image:url(images/icons/proofing.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-printing a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-printing a{background-image:url(images/icons/printing.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-slideshow a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-slideshow a{background-image:url(images/icons/slideshow.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-social a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-social a{background-image:url(images/icons/social.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-tags a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-tags a{background-image:url(images/icons/tags.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-videos a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-videos a{background-image:url(images/icons/video.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-watermarking a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-watermarking a{background-image:url(images/icons/watermark.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-woocommerce a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-woocommerce a{background-image:url(images/icons/woocommerce.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li.envira-misc a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li.envira-misc a{background-image:url(images/icons/misc.svg);background-size:16px 16px}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs{margin:0 0 0 160px;padding:20px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;background:#fff;border-left:1px solid #ddd}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs h2,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs h2{clear:none}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs table.form-table,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs table.form-table{clear:none;margin:0 0 40px 0}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs table.form-table.no-margin,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs table.form-table.no-margin{margin:0}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs table.form-table th,form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs table.form-table td,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs table.form-table th,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs table.form-table td{padding-top:30px;padding-bottom:30px}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs table.form-table label.full-width,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs table.form-table label.full-width{display:block;margin:0 0 5px 0}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs table.form-table label.full-width:first-child,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs table.form-table label.full-width:first-child{margin-top:5px}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs table.form-table textarea,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs table.form-table textarea{width:100%}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs table.form-table input[type=checkbox],form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs table.form-table input[type=checkbox]{margin-bottom:2px}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs table.form-table p.description,form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs table.form-table span.description,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs table.form-table p.description,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs table.form-table span.description{font-size:13px;font-style:italic;color:#666}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-images nav,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-images nav{width:100%}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-images nav.envira-tab-options,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-images nav.envira-tab-options{margin:20px 0}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-images nav a.dashicons,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-images nav a.dashicons{position:absolute;color:#999}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-images nav a.dashicons.dashicons-grid-view,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-images nav a.dashicons.dashicons-grid-view{right:20px}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-images nav a.dashicons.dashicons-list-view,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-images nav a.dashicons.dashicons-list-view{right:50px}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-images nav a.dashicons.selected,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-images nav a.dashicons.selected{color:#23282d}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-images nav a.dashicons span,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-images nav a.dashicons span{display:inline-block;text-indent:-9999px}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-images nav.envira-select-options,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-images nav.envira-select-options{display:none}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-images ul#envira-gallery-output li,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-images ul#envira-gallery-output li{cursor:move}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-galleries nav,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-galleries nav{width:100%}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-galleries nav.envira-tab-options,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-galleries nav.envira-tab-options{height:40px;margin:20px 0;position:relative}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-galleries nav.envira-tab-options a.envira-galleries-add,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-galleries nav.envira-tab-options a.envira-galleries-add{display:none;position:absolute;top:0;left:0}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-galleries nav.envira-tab-options input#envira-albums-gallery-search,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-galleries nav.envira-tab-options input#envira-albums-gallery-search{position:absolute;top:0;right:0}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-galleries nav.envira-select-options,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-galleries nav.envira-select-options{display:none}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-galleries ul.envira-gallery-images-output li,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-galleries ul.envira-gallery-images-output li{cursor:move}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-galleries ul.envira-gallery-images-output li a.envira-gallery-remove-image,form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs #envira-tab-galleries ul.envira-gallery-images-output li a.envira-gallery-modify-image,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-galleries ul.envira-gallery-images-output li a.envira-gallery-remove-image,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs #envira-tab-galleries ul.envira-gallery-images-output li a.envira-gallery-modify-image{display:none}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs:after,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs:after{content:"";display:table;clear:both}form#post.envira-gallery #poststuff #envira-gallery-preview:after{content:"";display:table;clear:both}form#post.envira-gallery #poststuff #envira-gallery-preview button.handlediv{display:none}form#post.envira-gallery #poststuff #envira-gallery-preview h2.hndle{display:none}form#post.envira-gallery #poststuff #envira-gallery-preview .inside{margin:0;padding:20px}.media-modal .edit-attachment-frame .edit-media-header button.right{border-right:1px solid #ddd}.media-modal .uploader-inline a.envira-media-library.button{display:none}.media-modal .attachment.details{-webkit-box-shadow:inset 0 0 0 3px #fff,inset 0 0 0 7px #7cc048;box-shadow:inset 0 0 0 3px #fff,inset 0 0 0 7px #7cc048}.media-modal .attachment.details .check{background-color:#7cc048;-webkit-box-shadow:0 0 0 1px #fff,0 0 0 2px #7cc048;box-shadow:0 0 0 1px #fff,0 0 0 2px #7cc048}.media-modal ul.attachments.envira-albums-gallery-cover-image{padding:10px}.media-modal ul.attachments.envira-bulk-edit li.attachment{cursor:default}.media-modal ul.attachments.envira-bulk-edit li.attachment .attachment-preview{cursor:default}.media-modal .attachment-details .attachment-info{padding:16px}.media-modal .attachment-details .attachment-info .settings{margin:0;padding:0;border:none}.media-modal .attachment-details .attachment-info .settings .setting{margin:0 0 20px 0;padding:0 0 20px 0;border-bottom:1px solid #ddd}.media-modal .attachment-details .attachment-info .settings .setting input[type="text"],.media-modal .attachment-details .attachment-info .settings .setting textarea{display:block;width:100%;min-width:100%;margin:0}.media-modal .attachment-details .attachment-info .settings .setting input[type="checkbox"]{float:left;margin:7px 3px 0 0}.media-modal .attachment-details .attachment-info .settings .setting select{margin:0}.media-modal .attachment-details .attachment-info .settings .setting span.name{display:block;width:100%;min-width:100%;margin:0;padding:0;text-align:left;font-weight:700;font-size:14px}.media-modal .attachment-details .attachment-info .settings .setting span.description{text-align:left;font-style:normal;font-size:13px;font-style:italic;color:#666}.media-modal .attachment-details .attachment-info .settings .setting div.description{clear:both;float:left;margin:5px 0 0 0;text-align:left;font-size:13px;font-style:italic;color:#666}.media-modal .attachment-details .attachment-info div.actions a.button{display:inline-block}@media (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi){.wp-core-ui a.check .media-modal-icon{background-image:url(../../../../../wp-includes/images/uploader-icons-2x.png) !important;-webkit-background-size:134px 15px;background-size:134px 15px}}@media screen and (max-width: 1100px){form#post.envira-gallery #poststuff #envira-gallery .inside #envira-gallery-native #plupload-upload-ui.drag-drop #drag-drop-area,form#post.envira-gallery #poststuff #envira-albums .inside #envira-gallery-native #plupload-upload-ui.drag-drop #drag-drop-area{border-color:#d5d5d5}form#post.envira-gallery #poststuff #envira-gallery .inside #envira-gallery-native #plupload-upload-ui.drag-drop .drag-drop-inside,form#post.envira-gallery #poststuff #envira-albums .inside #envira-gallery-native #plupload-upload-ui.drag-drop .drag-drop-inside{width:100%;margin-top:20px}form#post.envira-gallery #poststuff #envira-gallery .inside #envira-gallery-native #plupload-upload-ui.drag-drop .drag-drop-inside p.drag-drop-buttons,form#post.envira-gallery #poststuff #envira-albums .inside #envira-gallery-native #plupload-upload-ui.drag-drop .drag-drop-inside p.drag-drop-buttons{text-align:center}form#post.envira-gallery #poststuff #envira-gallery .inside #envira-gallery-native #plupload-upload-ui a.envira-media-library.button,form#post.envira-gallery #poststuff #envira-albums .inside #envira-gallery-native #plupload-upload-ui a.envira-media-library.button{left:0;right:0;width:235px;top:145px}}@media screen and (max-width: 768px){form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav{width:60px}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li a,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li a{width:60px;height:60px;margin:0;padding:0;text-indent:-9999px;background-position:center}form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li a:hover,form#post.envira-gallery #poststuff #envira-gallery-settings ul#envira-tabs-nav li a.envira-active,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li a:hover,form#post.envira-gallery #poststuff #envira-albums-settings ul#envira-tabs-nav li a.envira-active{width:60px;height:60px;margin:0;padding:0;text-indent:-9999px;background-position:center}form#post.envira-gallery #poststuff #envira-gallery-settings #envira-tabs,form#post.envira-gallery #poststuff #envira-albums-settings #envira-tabs{margin:0 0 0 60px}}
assets/css/settings.css ADDED
@@ -0,0 +1 @@
 
1
+ .envira-tab label{margin-top:7px;display:block}.nav-tab{float:left}#envira-gallery-settings{padding:20px 0}#envira-gallery-settings #envira-gallery-refresh-submit{margin-left:10px}#envira-gallery-settings .envira-hideme{display:none}#envira-gallery-settings .envira-clear{clear:both}#envira-gallery-settings .envira-clear:after{clear:both;content:'.';display:block;height:0;line-height:0;overflow:auto;visibility:hidden;zoom:1}#envira-gallery-settings .envira-gallery{margin:15px 0 20px}#envira-gallery-settings .envira-tab{display:none}#envira-gallery-settings .envira-tab.envira-active{display:block}#envira-gallery-settings .envira-tab th{width:170px;padding-right:40px}@media (max-width: 767px){#envira-gallery-settings .envira-tab th{width:auto}}#envira-gallery-settings .envira-tab input[type="text"],#envira-gallery-settings .envira-tab input[type="number"],#envira-gallery-settings .envira-tab input[type="password"],#envira-gallery-settings .envira-tab select,#envira-gallery-settings .envira-tab textarea{width:350px;padding-right:0;font-size:13px}@media (max-width: 767px){#envira-gallery-settings .envira-tab input[type="text"],#envira-gallery-settings .envira-tab input[type="number"],#envira-gallery-settings .envira-tab input[type="password"],#envira-gallery-settings .envira-tab select,#envira-gallery-settings .envira-tab textarea{width:100%}}#envira-gallery-settings .envira-tab input[type="text"],#envira-gallery-settings .envira-tab input[type="number"],#envira-gallery-settings .envira-tab input[type="password"]{height:32px}@media (max-width: 767px){#envira-gallery-settings .envira-tab input[type="text"],#envira-gallery-settings .envira-tab input[type="number"],#envira-gallery-settings .envira-tab input[type="password"]{height:auto}}#envira-gallery-settings .envira-tab #envira-gallery-settings-submit{margin:40px 0 0 0px}#envira-gallery-settings #envira-gallery-refresh-submit{vertical-align:baseline}#envira-tabs .form-table th,#envira-tabs .form-table td{padding-top:40px;padding-bottom:40px}@media (min-width: 768px) and (max-width: 991px){#envira-tabs .form-table th{padding-top:40px;padding-bottom:10px;padding-right:0px !important}}@media (max-width: 767px){#envira-tabs .form-table th{padding-top:40px;padding-bottom:10px;padding-right:0px !important}}@media (min-width: 768px) and (max-width: 991px){#envira-tabs .form-table tr#envira-settings-key-box th{padding-top:20px}}@media (max-width: 767px){#envira-tabs .form-table tr#envira-settings-key-box th{padding-top:20px}}@media (min-width: 768px) and (max-width: 991px){#envira-tabs .form-table td{padding-top:0;padding-right:0px}}@media (max-width: 767px){#envira-tabs .form-table td{padding-top:0;padding-right:0px}}#envira-tabs .form-table tr{border-bottom:1px solid #ddd}#envira-tabs .form-table tr.no-bottom-border{border-bottom:0}#envira-tabs .description{color:#666;font-size:13px;margin-top:10px}#envira-tabs-nav{border-bottom:0 !important;background-color:#fff;height:50px;padding-left:20px;margin:0 0 0 -20px;display:table;width:100%}@media (max-width: 767px){#envira-tabs-nav{height:auto;background-color:transparent;margin:5px 0 0 0;padding:0 10px;display:table}}#envira-tabs-nav a{float:left;border-left:1px solid #f1f1f1;border-right:1px solid #f1f1f1;border-top:0;color:#6b6e72;background:none;line-height:50px;font-size:13px;padding:0 15px;margin:0}@media (max-width: 767px){#envira-tabs-nav a{-webkit-border-radius:5px;-moz-border-radius:5px;-o-border-radius:5px;border-radius:5px;background-color:#f7f7f7;padding:0px 20px;margin:5px 5px 0px 0;border:1px solid #ddd;line-height:35px;min-height:30px}}#envira-tabs-nav .envira-active{background-color:#f1f1f1;border-left:0;border-right:0;border-top:0;color:#000}@media (max-width: 767px){#envira-tabs-nav .envira-active{background-color:#6b6e72;color:#fff}}@media (max-width: 767px){#envira-tabs-nav a:hover{background-color:#6b6e72;color:#fff}}@media only screen and (max-width: 770px){#envira-gallery-settings #envira-gallery-settings-submit{margin:40px 0 0 0}}
assets/css/table.css ADDED
@@ -0,0 +1 @@
 
1
+ body.post-type-envira ul.subsubsub,body.post-type-envira_album ul.subsubsub{margin:0 0 20px 0;padding-left:20px}body.post-type-envira form#posts-filter,body.post-type-envira_album form#posts-filter{margin:0 20px}body.post-type-envira form#posts-filter div.tablenav.top,body.post-type-envira_album form#posts-filter div.tablenav.top{margin:0 0 8px 0}body.post-type-envira form#posts-filter .button,body.post-type-envira_album form#posts-filter .button{height:28px;line-height:26px}body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-col-left,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-col-left{width:40%}body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-col-left fieldset.inline-edit-date,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-col-left fieldset.inline-edit-date{display:none}body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-col-left div.inline-edit-group:last-child,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-col-left div.inline-edit-group:last-child{display:none}body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-col-center.inline-edit-categories,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-col-center.inline-edit-categories{display:none}body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-col-right,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-col-right{margin:30px 0 0 0}body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-col-right label.inline-edit-status.alignleft,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-col-right label.inline-edit-status.alignleft{width:100%}body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-col-right,body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-col-right,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery{width:60%}body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-col-right .inline-edit-group,body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery .inline-edit-group,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-col-right .inline-edit-group,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery .inline-edit-group{clear:none;float:left;width:50%}body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-col-right .inline-edit-group span.title,body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery .inline-edit-group span.title,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-col-right .inline-edit-group span.title,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery .inline-edit-group span.title{width:40%;padding-right:0.5em}body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-col-right .inline-edit-group input[type=number],body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery .inline-edit-group input[type=number],body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-col-right .inline-edit-group input[type=number],body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery .inline-edit-group input[type=number]{width:60px;line-height:normal}body.post-type-envira #wpbody-content td.colspanchange p.submit.inline-edit-save,body.post-type-envira_album #wpbody-content td.colspanchange p.submit.inline-edit-save{margin-bottom:20px}@media screen and (max-width: 940px){body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-col-left fieldset.inline-edit-col-right,body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-col-left fieldset.inline-edit-col-right,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery{clear:both;width:100%}body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-col-left fieldset.inline-edit-col-right .inline-edit-group,body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery .inline-edit-group,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-col-left fieldset.inline-edit-col-right .inline-edit-group,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery .inline-edit-group{clear:both;float:left;width:100%}body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-col-left fieldset.inline-edit-col-right .inline-edit-group span.title,body.post-type-envira #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery .inline-edit-group span.title,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-col-left fieldset.inline-edit-col-right .inline-edit-group span.title,body.post-type-envira_album #wpbody-content td.colspanchange fieldset.inline-edit-envira-gallery .inline-edit-group span.title{width:100%}body.post-type-envira p.search-box,body.post-type-envira_album p.search-box{width:94%}}
assets/images/envira-logo.png ADDED
Binary file
assets/js/admin.js ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Handles:
3
+ * - Copy to Clipboard functionality
4
+ * - Dismissable Notices
5
+ *
6
+ * @since 1.5.0
7
+ */
8
+ jQuery( document ).ready( function( $ ) {
9
+
10
+ /**
11
+ * Copy to Clipboard
12
+ */
13
+ if ( typeof Clipboard !== 'undefined' ) {
14
+ var envira_clipboard = new Clipboard( '.envira-clipboard' );
15
+ $( document ).on( 'click', '.envira-clipboard', function( e ) {
16
+ e.preventDefault();
17
+ } );
18
+ }
19
+
20
+ /**
21
+ * Dismissable Notices
22
+ * - Sends an AJAX request to mark the notice as dismissed
23
+ */
24
+ $( 'div.envira-notice' ).on( 'click', '.notice-dismiss', function( e ) {
25
+
26
+ e.preventDefault();
27
+
28
+ $( this ).closest( 'div.envira-notice' ).fadeOut();
29
+
30
+ // If this is a dismissible notice, it means we need to send an AJAX request
31
+ if ( $( this ).hasClass( 'is-dismissible' ) ) {
32
+ $.post(
33
+ envira_gallery_admin.ajax,
34
+ {
35
+ action: 'envira_gallery_ajax_dismiss_notice',
36
+ nonce: envira_gallery_admin.dismiss_notice_nonce,
37
+ notice: $( this ).parent().data( 'notice' )
38
+ },
39
+ function( response ) {
40
+ },
41
+ 'json'
42
+ );
43
+ }
44
+
45
+ } );
46
+
47
+ });
assets/js/clipboard.js ADDED
@@ -0,0 +1,740 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * clipboard.js v1.5.10
3
+ * https://zenorocha.github.io/clipboard.js
4
+ *
5
+ * Licensed MIT © Zeno Rocha
6
+ */
7
+ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Clipboard = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
8
+ var matches = require('matches-selector')
9
+
10
+ module.exports = function (element, selector, checkYoSelf) {
11
+ var parent = checkYoSelf ? element : element.parentNode
12
+
13
+ while (parent && parent !== document) {
14
+ if (matches(parent, selector)) return parent;
15
+ parent = parent.parentNode
16
+ }
17
+ }
18
+
19
+ },{"matches-selector":5}],2:[function(require,module,exports){
20
+ var closest = require('closest');
21
+
22
+ /**
23
+ * Delegates event to a selector.
24
+ *
25
+ * @param {Element} element
26
+ * @param {String} selector
27
+ * @param {String} type
28
+ * @param {Function} callback
29
+ * @param {Boolean} useCapture
30
+ * @return {Object}
31
+ */
32
+ function delegate(element, selector, type, callback, useCapture) {
33
+ var listenerFn = listener.apply(this, arguments);
34
+
35
+ element.addEventListener(type, listenerFn, useCapture);
36
+
37
+ return {
38
+ destroy: function() {
39
+ element.removeEventListener(type, listenerFn, useCapture);
40
+ }
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Finds closest match and invokes callback.
46
+ *
47
+ * @param {Element} element
48
+ * @param {String} selector
49
+ * @param {String} type
50
+ * @param {Function} callback
51
+ * @return {Function}
52
+ */
53
+ function listener(element, selector, type, callback) {
54
+ return function(e) {
55
+ e.delegateTarget = closest(e.target, selector, true);
56
+
57
+ if (e.delegateTarget) {
58
+ callback.call(element, e);
59
+ }
60
+ }
61
+ }
62
+
63
+ module.exports = delegate;
64
+
65
+ },{"closest":1}],3:[function(require,module,exports){
66
+ /**
67
+ * Check if argument is a HTML element.
68
+ *
69
+ * @param {Object} value
70
+ * @return {Boolean}
71
+ */
72
+ exports.node = function(value) {
73
+ return value !== undefined
74
+ && value instanceof HTMLElement
75
+ && value.nodeType === 1;
76
+ };
77
+
78
+ /**
79
+ * Check if argument is a list of HTML elements.
80
+ *
81
+ * @param {Object} value
82
+ * @return {Boolean}
83
+ */
84
+ exports.nodeList = function(value) {
85
+ var type = Object.prototype.toString.call(value);
86
+
87
+ return value !== undefined
88
+ && (type === '[object NodeList]' || type === '[object HTMLCollection]')
89
+ && ('length' in value)
90
+ && (value.length === 0 || exports.node(value[0]));
91
+ };
92
+
93
+ /**
94
+ * Check if argument is a string.
95
+ *
96
+ * @param {Object} value
97
+ * @return {Boolean}
98
+ */
99
+ exports.string = function(value) {
100
+ return typeof value === 'string'
101
+ || value instanceof String;
102
+ };
103
+
104
+ /**
105
+ * Check if argument is a function.
106
+ *
107
+ * @param {Object} value
108
+ * @return {Boolean}
109
+ */
110
+ exports.fn = function(value) {
111
+ var type = Object.prototype.toString.call(value);
112
+
113
+ return type === '[object Function]';
114
+ };
115
+
116
+ },{}],4:[function(require,module,exports){
117
+ var is = require('./is');
118
+ var delegate = require('delegate');
119
+
120
+ /**
121
+ * Validates all params and calls the right
122
+ * listener function based on its target type.
123
+ *
124
+ * @param {String|HTMLElement|HTMLCollection|NodeList} target
125
+ * @param {String} type
126
+ * @param {Function} callback
127
+ * @return {Object}
128
+ */
129
+ function listen(target, type, callback) {
130
+ if (!target && !type && !callback) {
131
+ throw new Error('Missing required arguments');
132
+ }
133
+
134
+ if (!is.string(type)) {
135
+ throw new TypeError('Second argument must be a String');
136
+ }
137
+
138
+ if (!is.fn(callback)) {
139
+ throw new TypeError('Third argument must be a Function');
140
+ }
141
+
142
+ if (is.node(target)) {
143
+ return listenNode(target, type, callback);
144
+ }
145
+ else if (is.nodeList(target)) {
146
+ return listenNodeList(target, type, callback);
147
+ }
148
+ else if (is.string(target)) {
149
+ return listenSelector(target, type, callback);
150
+ }
151
+ else {
152
+ throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Adds an event listener to a HTML element
158
+ * and returns a remove listener function.
159
+ *
160
+ * @param {HTMLElement} node
161
+ * @param {String} type
162
+ * @param {Function} callback
163
+ * @return {Object}
164
+ */
165
+ function listenNode(node, type, callback) {
166
+ node.addEventListener(type, callback);
167
+
168
+ return {
169
+ destroy: function() {
170
+ node.removeEventListener(type, callback);
171
+ }
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Add an event listener to a list of HTML elements
177
+ * and returns a remove listener function.
178
+ *
179
+ * @param {NodeList|HTMLCollection} nodeList
180
+ * @param {String} type
181
+ * @param {Function} callback
182
+ * @return {Object}
183
+ */
184
+ function listenNodeList(nodeList, type, callback) {
185
+ Array.prototype.forEach.call(nodeList, function(node) {
186
+ node.addEventListener(type, callback);
187
+ });
188
+
189
+ return {
190
+ destroy: function() {
191
+ Array.prototype.forEach.call(nodeList, function(node) {
192
+ node.removeEventListener(type, callback);
193
+ });
194
+ }
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Add an event listener to a selector
200
+ * and returns a remove listener function.
201
+ *
202
+ * @param {String} selector
203
+ * @param {String} type
204
+ * @param {Function} callback
205
+ * @return {Object}
206
+ */
207
+ function listenSelector(selector, type, callback) {
208
+ return delegate(document.body, selector, type, callback);
209
+ }
210
+
211
+ module.exports = listen;
212
+
213
+ },{"./is":3,"delegate":2}],5:[function(require,module,exports){
214
+
215
+ /**
216
+ * Element prototype.
217
+ */
218
+
219
+ var proto = Element.prototype;
220
+
221
+ /**
222
+ * Vendor function.
223
+ */
224
+
225
+ var vendor = proto.matchesSelector
226
+ || proto.webkitMatchesSelector
227
+ || proto.mozMatchesSelector
228
+ || proto.msMatchesSelector
229
+ || proto.oMatchesSelector;
230
+
231
+ /**
232
+ * Expose `match()`.
233
+ */
234
+
235
+ module.exports = match;
236
+
237
+ /**
238
+ * Match `el` to `selector`.
239
+ *
240
+ * @param {Element} el
241
+ * @param {String} selector
242
+ * @return {Boolean}
243
+ * @api public
244
+ */
245
+
246
+ function match(el, selector) {
247
+ if (vendor) return vendor.call(el, selector);
248
+ var nodes = el.parentNode.querySelectorAll(selector);
249
+ for (var i = 0; i < nodes.length; ++i) {
250
+ if (nodes[i] == el) return true;
251
+ }
252
+ return false;
253
+ }
254
+ },{}],6:[function(require,module,exports){
255
+ function select(element) {
256
+ var selectedText;
257
+
258
+ if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
259
+ element.focus();
260
+ element.setSelectionRange(0, element.value.length);
261
+
262
+ selectedText = element.value;
263
+ }
264
+ else {
265
+ if (element.hasAttribute('contenteditable')) {
266
+ element.focus();
267
+ }
268
+
269
+ var selection = window.getSelection();
270
+ var range = document.createRange();
271
+
272
+ range.selectNodeContents(element);
273
+ selection.removeAllRanges();
274
+ selection.addRange(range);
275
+
276
+ selectedText = selection.toString();
277
+ }
278
+
279
+ return selectedText;
280
+ }
281
+
282
+ module.exports = select;
283
+
284
+ },{}],7:[function(require,module,exports){
285
+ function E () {
286
+ // Keep this empty so it's easier to inherit from
287
+ // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
288
+ }
289
+
290
+ E.prototype = {
291
+ on: function (name, callback, ctx) {
292
+ var e = this.e || (this.e = {});
293
+
294
+ (e[name] || (e[name] = [])).push({
295
+ fn: callback,
296
+ ctx: ctx
297
+ });
298
+
299
+ return this;
300
+ },
301
+
302
+ once: function (name, callback, ctx) {
303
+ var self = this;
304
+ function listener () {
305
+ self.off(name, listener);
306
+ callback.apply(ctx, arguments);
307
+ };
308
+
309
+ listener._ = callback
310
+ return this.on(name, listener, ctx);
311
+ },
312
+
313
+ emit: function (name) {
314
+ var data = [].slice.call(arguments, 1);
315
+ var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
316
+ var i = 0;
317
+ var len = evtArr.length;
318
+
319
+ for (i; i < len; i++) {
320
+ evtArr[i].fn.apply(evtArr[i].ctx, data);
321
+ }
322
+
323
+ return this;
324
+ },
325
+
326
+ off: function (name, callback) {
327
+ var e = this.e || (this.e = {});
328
+ var evts = e[name];
329
+ var liveEvents = [];
330
+
331
+ if (evts && callback) {
332
+ for (var i = 0, len = evts.length; i < len; i++) {
333
+ if (evts[i].fn !== callback && evts[i].fn._ !== callback)
334
+ liveEvents.push(evts[i]);
335
+ }
336
+ }
337
+
338
+ // Remove event from queue to prevent memory leak
339
+ // Suggested by https://github.com/lazd
340
+ // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910
341
+
342
+ (liveEvents.length)
343
+ ? e[name] = liveEvents
344
+ : delete e[name];
345
+
346
+ return this;
347
+ }
348
+ };
349
+
350
+ module.exports = E;
351
+
352
+ },{}],8:[function(require,module,exports){
353
+ (function (global, factory) {
354
+ if (typeof define === "function" && define.amd) {
355
+ define(['module', 'select'], factory);
356
+ } else if (typeof exports !== "undefined") {
357
+ factory(module, require('select'));
358
+ } else {
359
+ var mod = {
360
+ exports: {}
361
+ };
362
+ factory(mod, global.select);
363
+ global.clipboardAction = mod.exports;
364
+ }
365
+ })(this, function (module, _select) {
366
+ 'use strict';
367
+
368
+ var _select2 = _interopRequireDefault(_select);
369
+
370
+ function _interopRequireDefault(obj) {
371
+ return obj && obj.__esModule ? obj : {
372
+ default: obj
373
+ };
374
+ }
375
+
376
+ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
377
+ return typeof obj;
378
+ } : function (obj) {
379
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;
380
+ };
381
+
382
+ function _classCallCheck(instance, Constructor) {
383
+ if (!(instance instanceof Constructor)) {
384
+ throw new TypeError("Cannot call a class as a function");
385
+ }
386
+ }
387
+
388
+ var _createClass = function () {
389
+ function defineProperties(target, props) {
390
+ for (var i = 0; i < props.length; i++) {
391
+ var descriptor = props[i];
392
+ descriptor.enumerable = descriptor.enumerable || false;
393
+ descriptor.configurable = true;
394
+ if ("value" in descriptor) descriptor.writable = true;
395
+ Object.defineProperty(target, descriptor.key, descriptor);
396
+ }
397
+ }
398
+
399
+ return function (Constructor, protoProps, staticProps) {
400
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
401
+ if (staticProps) defineProperties(Constructor, staticProps);
402
+ return Constructor;
403
+ };
404
+ }();
405
+
406
+ var ClipboardAction = function () {
407
+ /**
408
+ * @param {Object} options
409
+ */
410
+
411
+ function ClipboardAction(options) {
412
+ _classCallCheck(this, ClipboardAction);
413
+
414
+ this.resolveOptions(options);
415
+ this.initSelection();
416
+ }
417
+
418
+ /**
419
+ * Defines base properties passed from constructor.
420
+ * @param {Object} options
421
+ */
422
+
423
+
424
+ ClipboardAction.prototype.resolveOptions = function resolveOptions() {
425
+ var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
426
+
427
+ this.action = options.action;
428
+ this.emitter = options.emitter;
429
+ this.target = options.target;
430
+ this.text = options.text;
431
+ this.trigger = options.trigger;
432
+
433
+ this.selectedText = '';
434
+ };
435
+
436
+ ClipboardAction.prototype.initSelection = function initSelection() {
437
+ if (this.text) {
438
+ this.selectFake();
439
+ } else if (this.target) {
440
+ this.selectTarget();
441
+ }
442
+ };
443
+
444
+ ClipboardAction.prototype.selectFake = function selectFake() {
445
+ var _this = this;
446
+
447
+ var isRTL = document.documentElement.getAttribute('dir') == 'rtl';
448
+
449
+ this.removeFake();
450
+
451
+ this.fakeHandler = document.body.addEventListener('click', function () {
452
+ return _this.removeFake();
453
+ });
454
+
455
+ this.fakeElem = document.createElement('textarea');
456
+ // Prevent zooming on iOS
457
+ this.fakeElem.style.fontSize = '12pt';
458
+ // Reset box model
459
+ this.fakeElem.style.border = '0';
460
+ this.fakeElem.style.padding = '0';
461
+ this.fakeElem.style.margin = '0';
462
+ // Move element out of screen horizontally
463
+ this.fakeElem.style.position = 'fixed';
464
+ this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';
465
+ // Move element to the same position vertically
466
+ this.fakeElem.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px';
467
+ this.fakeElem.setAttribute('readonly', '');
468
+ this.fakeElem.value = this.text;
469
+
470
+ document.body.appendChild(this.fakeElem);
471
+
472
+ this.selectedText = (0, _select2.default)(this.fakeElem);
473
+ this.copyText();
474
+ };
475
+
476
+ ClipboardAction.prototype.removeFake = function removeFake() {
477
+ if (this.fakeHandler) {
478
+ document.body.removeEventListener('click');
479
+ this.fakeHandler = null;
480
+ }
481
+
482
+ if (this.fakeElem) {
483
+ document.body.removeChild(this.fakeElem);
484
+ this.fakeElem = null;
485
+ }
486
+ };
487
+
488
+ ClipboardAction.prototype.selectTarget = function selectTarget() {
489
+ this.selectedText = (0, _select2.default)(this.target);
490
+ this.copyText();
491
+ };
492
+
493
+ ClipboardAction.prototype.copyText = function copyText() {
494
+ var succeeded = undefined;
495
+
496
+ try {
497
+ succeeded = document.execCommand(this.action);
498
+ } catch (err) {
499
+ succeeded = false;
500
+ }
501
+
502
+ this.handleResult(succeeded);
503
+ };
504
+
505
+ ClipboardAction.prototype.handleResult = function handleResult(succeeded) {
506
+ if (succeeded) {
507
+ this.emitter.emit('success', {
508
+ action: this.action,
509
+ text: this.selectedText,
510
+ trigger: this.trigger,
511
+ clearSelection: this.clearSelection.bind(this)
512
+ });
513
+ } else {
514
+ this.emitter.emit('error', {
515
+ action: this.action,
516
+ trigger: this.trigger,
517
+ clearSelection: this.clearSelection.bind(this)
518
+ });
519
+ }
520
+ };
521
+
522
+ ClipboardAction.prototype.clearSelection = function clearSelection() {
523
+ if (this.target) {
524
+ this.target.blur();
525
+ }
526
+
527
+ window.getSelection().removeAllRanges();
528
+ };
529
+
530
+ ClipboardAction.prototype.destroy = function destroy() {
531
+ this.removeFake();
532
+ };
533
+
534
+ _createClass(ClipboardAction, [{
535
+ key: 'action',
536
+ set: function set() {
537
+ var action = arguments.length <= 0 || arguments[0] === undefined ? 'copy' : arguments[0];
538
+
539
+ this._action = action;
540
+
541
+ if (this._action !== 'copy' && this._action !== 'cut') {
542
+ throw new Error('Invalid "action" value, use either "copy" or "cut"');
543
+ }
544
+ },
545
+ get: function get() {
546
+ return this._action;
547
+ }
548
+ }, {
549
+ key: 'target',
550
+ set: function set(target) {
551
+ if (target !== undefined) {
552
+ if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && target.nodeType === 1) {
553
+ if (this.action === 'copy' && target.hasAttribute('disabled')) {
554
+ throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');
555
+ }
556
+
557
+ if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {
558
+ throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');
559
+ }
560
+
561
+ this._target = target;
562
+ } else {
563
+ throw new Error('Invalid "target" value, use a valid Element');
564
+ }
565
+ }
566
+ },
567
+ get: function get() {
568
+ return this._target;
569
+ }
570
+ }]);
571
+
572
+ return ClipboardAction;
573
+ }();
574
+
575
+ module.exports = ClipboardAction;
576
+ });
577
+
578
+ },{"select":6}],9:[function(require,module,exports){
579
+ (function (global, factory) {
580
+ if (typeof define === "function" && define.amd) {
581
+ define(['module', './clipboard-action', 'tiny-emitter', 'good-listener'], factory);
582
+ } else if (typeof exports !== "undefined") {
583
+ factory(module, require('./clipboard-action'), require('tiny-emitter'), require('good-listener'));
584
+ } else {
585
+ var mod = {
586
+ exports: {}
587
+ };
588
+ factory(mod, global.clipboardAction, global.tinyEmitter, global.goodListener);
589
+ global.clipboard = mod.exports;
590
+ }
591
+ })(this, function (module, _clipboardAction, _tinyEmitter, _goodListener) {
592
+ 'use strict';
593
+
594
+ var _clipboardAction2 = _interopRequireDefault(_clipboardAction);
595
+
596
+ var _tinyEmitter2 = _interopRequireDefault(_tinyEmitter);
597
+
598
+ var _goodListener2 = _interopRequireDefault(_goodListener);
599
+
600
+ function _interopRequireDefault(obj) {
601
+ return obj && obj.__esModule ? obj : {
602
+ default: obj
603
+ };
604
+ }
605
+
606
+ function _classCallCheck(instance, Constructor) {
607
+ if (!(instance instanceof Constructor)) {
608
+ throw new TypeError("Cannot call a class as a function");
609
+ }
610
+ }
611
+
612
+ function _possibleConstructorReturn(self, call) {
613
+ if (!self) {
614
+ throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
615
+ }
616
+
617
+ return call && (typeof call === "object" || typeof call === "function") ? call : self;
618
+ }
619
+
620
+ function _inherits(subClass, superClass) {
621
+ if (typeof superClass !== "function" && superClass !== null) {
622
+ throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
623
+ }
624
+
625
+ subClass.prototype = Object.create(superClass && superClass.prototype, {
626
+ constructor: {
627
+ value: subClass,
628
+ enumerable: false,
629
+ writable: true,
630
+ configurable: true
631
+ }
632
+ });
633
+ if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
634
+ }
635
+
636
+ var Clipboard = function (_Emitter) {
637
+ _inherits(Clipboard, _Emitter);
638
+
639
+ /**
640
+ * @param {String|HTMLElement|HTMLCollection|NodeList} trigger
641
+ * @param {Object} options
642
+ */
643
+
644
+ function Clipboard(trigger, options) {
645
+ _classCallCheck(this, Clipboard);
646
+
647
+ var _this = _possibleConstructorReturn(this, _Emitter.call(this));
648
+
649
+ _this.resolveOptions(options);
650
+ _this.listenClick(trigger);
651
+ return _this;
652
+ }
653
+
654
+ /**
655
+ * Defines if attributes would be resolved using internal setter functions
656
+ * or custom functions that were passed in the constructor.
657
+ * @param {Object} options
658
+ */
659
+
660
+
661
+ Clipboard.prototype.resolveOptions = function resolveOptions() {
662
+ var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
663
+
664
+ this.action = typeof options.action === 'function' ? options.action : this.defaultAction;
665
+ this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;
666
+ this.text = typeof options.text === 'function' ? options.text : this.defaultText;
667
+ };
668
+
669
+ Clipboard.prototype.listenClick = function listenClick(trigger) {
670
+ var _this2 = this;
671
+
672
+ this.listener = (0, _goodListener2.default)(trigger, 'click', function (e) {
673
+ return _this2.onClick(e);
674
+ });
675
+ };
676
+
677
+ Clipboard.prototype.onClick = function onClick(e) {
678
+ var trigger = e.delegateTarget || e.currentTarget;
679
+
680
+ if (this.clipboardAction) {
681
+ this.clipboardAction = null;
682
+ }
683
+
684
+ this.clipboardAction = new _clipboardAction2.default({
685
+ action: this.action(trigger),
686
+ target: this.target(trigger),
687
+ text: this.text(trigger),
688
+ trigger: trigger,
689
+ emitter: this
690
+ });
691
+ };
692
+
693
+ Clipboard.prototype.defaultAction = function defaultAction(trigger) {
694
+ return getAttributeValue('action', trigger);
695
+ };
696
+
697
+ Clipboard.prototype.defaultTarget = function defaultTarget(trigger) {
698
+ var selector = getAttributeValue('target', trigger);
699
+
700
+ if (selector) {
701
+ return document.querySelector(selector);
702
+ }
703
+ };
704
+
705
+ Clipboard.prototype.defaultText = function defaultText(trigger) {
706
+ return getAttributeValue('text', trigger);
707
+ };
708
+
709
+ Clipboard.prototype.destroy = function destroy() {
710
+ this.listener.destroy();
711
+
712
+ if (this.clipboardAction) {
713
+ this.clipboardAction.destroy();
714
+ this.clipboardAction = null;
715
+ }
716
+ };
717
+
718
+ return Clipboard;
719
+ }(_tinyEmitter2.default);
720
+
721
+ /**
722
+ * Helper function to retrieve attribute value.
723
+ * @param {String} suffix
724
+ * @param {Element} element
725
+ */
726
+ function getAttributeValue(suffix, element) {
727
+ var attribute = 'data-clipboard-' + suffix;
728
+
729
+ if (!element.hasAttribute(attribute)) {
730
+ return;
731
+ }
732
+
733
+ return element.getAttribute(attribute);
734
+ }
735
+
736
+ module.exports = Clipboard;
737
+ });
738
+
739
+ },{"./clipboard-action":8,"good-listener":4,"tiny-emitter":7}]},{},[9])(9)
740
+ });
assets/js/conditional-fields.js ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Handles showing and hiding fields conditionally, based on
3
+ * HTML data- attributes
4
+ */
5
+ jQuery( document ).ready( function( $ ) {
6
+
7
+ // Show/hide elements as necessary when a conditional field is changed
8
+ $( 'input, select' ).conditional( {
9
+ data: 'envira-conditional',
10
+ value: 'envira-conditional-value',
11
+ displayOnEnabled: 'envira-conditional-display'
12
+ } );
13
+
14
+ } );
15
+
16
+ /**
17
+ * jQuery Conditionals 1.0.0
18
+ *
19
+ * Copyright 2015 n7 Studios
20
+ * Released under the MIT license.
21
+ * http://jquery.org/license
22
+ */
23
+ (function( $ ) {
24
+ "use strict";
25
+
26
+ /**
27
+ * Create .conditional() function
28
+ *
29
+ * @param object options Override Default Settings
30
+ */
31
+ $.fn.conditional = function(options) {
32
+ // Default Settings
33
+ var settings = $.extend({
34
+ data: 'conditional',
35
+ value: 'conditional-value',
36
+ displayOnEnabled: 'conditional-display'
37
+ }, options);
38
+
39
+ // Setup conditionals on each DOM element
40
+ this.each(function() {
41
+ // Check for conditional elements
42
+ if ( typeof $( this ).data( settings.data ) === 'undefined' ) {
43
+ return true;
44
+ }
45
+
46
+ // Setup vars
47
+ var conditionalElements,
48
+ displayOnEnabled,
49
+ value,
50
+ displayElements;
51
+
52
+ // Toggle + toggle on change
53
+ $( this ).on( 'change', function() {
54
+ // List the DOM elements to toggle
55
+ conditionalElements = $( this ).data( settings.data ).split(',');
56
+
57
+ // Determine whether to display DOM elements when the input is 'enabled'
58
+ displayOnEnabled = $( this ).data( settings.displayOnEnabled );
59
+ if ( typeof displayOnEnabled === 'undefined' ) {
60
+ displayOnEnabled = true;
61
+ }
62
+
63
+ // Determine the value required to display elements
64
+ value = $( this ).data( settings.value );
65
+ if ( typeof value === 'undefined' ) {
66
+ value = '';
67
+ }
68
+
69
+ // By default, don't display elements
70
+ displayElements = false;
71
+
72
+ // Determine whether to display relational elements or not
73
+ switch ( $( this ).attr( 'type' ) ) {
74
+ case 'checkbox':
75
+ if ( displayOnEnabled ) {
76
+ displayElements = $( this ).is( ':checked' );
77
+ } else {
78
+ displayElements = ( $( this ).is( ':checked' ) ? false : true );
79
+ }
80
+ break;
81
+
82
+ default:
83
+ if ( displayOnEnabled ) {
84
+ if ( value !== '' ) {
85
+ displayElements = ( ( String( $( this ).val() ) !== String( value ) ) ? false : true );
86
+ } else {
87
+ displayElements = ( ( $( this ).val() === '' || $( this ).val() === '0' ) ? false : true );
88
+ }
89
+ } else {
90
+ if ( value !== '' ) {
91
+ displayElements = ( ( $( this ).val() !== value ) ? true : false );
92
+ } else {
93
+ displayElements = ( ( $( this ).val() === '' || $( this ).val() === '0' ) ? true : false );
94
+ }
95
+ }
96
+ break;
97
+ }
98
+
99
+ // Show/hide elements
100
+ for (var i = 0; i < conditionalElements.length; i++) {
101
+ if ( displayElements ) {
102
+ $( '#' + conditionalElements[i] ).fadeIn( 300 );
103
+ } else {
104
+ $( '#' + conditionalElements[i] ).fadeOut( 300 );
105
+ }
106
+ }
107
+ });
108
+
109
+ // Trigger a change on init so we run the above routine
110
+ $ ( this ).trigger( 'change' );
111
+ });
112
+
113
+ // Return DOM elements
114
+ return this;
115
+ };
116
+
117
+ })(jQuery);
assets/js/editor.js CHANGED
@@ -1,123 +1,478 @@
1
- /* ==========================================================
2
- * editor.js
3
- * http://enviragallery.com/
4
- *
5
- * This file can be used by 3rd party plugins to integrate
6
- * with their custom field systems. It allows the selection
7
- * process to be standardized so that 3rd party plugins can
8
- * trigger modal selection windows and receive the corresponding
9
- * selected data objects.
10
- *
11
- * Using this file requires three actions for the 3rd party plugin.
12
- *
13
- * 1. The media modal HTML output needs to be inserted directly
14
- * after the option/dropdown/button that is to be used to
15
- * trigger the modal. This can be done by placing the following
16
- * code after the output (first to return, latter to echo):
17
- *
18
- * Envira_Gallery_Editor::get_instance()->gallery_selection_modal();
19
- *
20
- * 2. This file should be enqueued on the page where the field resides.
21
- * You should add the class ".envira-gallery-modal-trigger" to the
22
- * option/dropdown/button that will trigger the modal. This will
23
- * be used as a reference point for showing, hiding and passing data
24
- * between the modal and your plugin.
25
- *
26
- * 3. Attaching to a global event that is fired once the data for the
27
- * selection has been retrieved. You should listen on the document
28
- * object for the "enviraGalleryModalData" event, like this:
29
- *
30
- * $(document).on("enviraGalleryModalData", function(e){
31
- * console.log(e.gallery);
32
- * });
33
- *
34
- * This will give you access to the entire array of gallery data that
35
- * the user has selected, including ID, title, slug and settings.
36
- * ==========================================================
37
- * Copyright 2013 Thomas Griffin.
38
- *
39
- * Licensed under the GPL License, Version 2.0 or later (the "License");
40
- * you may not use this file except in compliance with the License.
41
- * You may obtain a copy of the License at
42
- *
43
- * http://www.gnu.org/licenses/gpl-2.0.html
44
- *
45
- * Unless required by applicable law or agreed to in writing, software
46
- * distributed under the License is distributed on an "AS IS" BASIS,
47
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
48
- * See the License for the specific language governing permissions and
49
- * limitations under the License.
50
- * ========================================================== */
51
- ;(function($){
52
- $(function(){
53
- // Close the modal window on user action.
54
- var envira_trigger_target = envira_editor_frame = false;
55
- var envira_append_and_hide = function(e){
56
- e.preventDefault();
57
- $('.envira-gallery-default-ui .selected').removeClass('details selected');
58
- $('.envira-gallery-default-ui').appendTo('.envira-gallery-default-ui-wrapper').hide();
59
- envira_trigger_target = envira_editor_frame = false;
60
- };
61
-
62
- $(document).on('click', '.envira-gallery-choose-gallery, .envira-gallery-modal-trigger', function(e){
63
- e.preventDefault();
64
-
65
- // Store the trigger target.
66
- envira_trigger_target = e.target;
67
-
68
- // Show the modal.
69
- envira_editor_frame = true;
70
- $('.envira-gallery-default-ui').appendTo('body').show();
71
-
72
- $(document).on('click', '.media-modal-close, .media-modal-backdrop, .envira-gallery-cancel-insertion', envira_append_and_hide);
73
- $(document).on('keydown', function(e){
74
- if ( 27 == e.keyCode && envira_editor_frame ) {
75
- envira_append_and_hide(e);
76
- }
77
- });
78
- });
79
-
80
- $(document).on('click', '.envira-gallery-default-ui .thumbnail, .envira-gallery-default-ui .check, .envira-gallery-default-ui .media-modal-icon', function(e){
81
- e.preventDefault();
82
- if ( $(this).parent().parent().hasClass('selected') ) {
83
- $(this).parent().parent().removeClass('details selected');
84
- $('.envira-gallery-insert-gallery').attr('disabled', 'disabled');
85
- } else {
86
- $(this).parent().parent().parent().find('.selected').removeClass('details selected');
87
- $(this).parent().parent().addClass('details selected');
88
- $('.envira-gallery-insert-gallery').removeAttr('disabled');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  }
90
- });
91
-
92
- $(document).on('click', '.envira-gallery-default-ui .check', function(e){
93
- e.preventDefault();
94
- $(this).parent().parent().removeClass('details selected');
95
- $('.envira-gallery-insert-gallery').attr('disabled', 'disabled');
96
- });
97
-
98
- $(document).on('click', '.envira-gallery-default-ui .envira-gallery-insert-gallery', function(e){
99
- e.preventDefault();
100
-
101
- // Either insert into an editor or make an ajax request.
102
- if ( $(envira_trigger_target).hasClass('envira-gallery-choose-gallery') ) {
103
- wp.media.editor.insert('[envira-gallery id="' + $('.envira-gallery-default-ui .selected').data('envira-gallery-id') + '"]');
104
- } else {
105
- // Make the ajax request.
106
- var req_data = {
107
- action: 'envira_gallery_load_gallery_data',
108
- id: $('.envira-gallery-default-ui:first .selected').data('envira-gallery-id')
109
- };
110
- $.post(ajaxurl, req_data, function(res){
111
- // Trigger the event.
112
- $(document).trigger({ type: 'enviraGalleryModalData', gallery: res });
113
-
114
- // Close the modal.
115
- envira_append_and_hide(e);
116
- }, 'json');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
- // Hide the modal.
120
- envira_append_and_hide(e);
121
- });
122
- });
123
- }(jQuery));
1
+ /**
2
+ * Controller: Modal Window
3
+ * - Used by most Envira Backbone views to display information e.g. bulk edit, edit single image etc.
4
+ */
5
+ if ( typeof EnviraGalleryModalWindow == 'undefined' ) {
6
+
7
+ var EnviraGalleryModalWindow = new wp.media.view.Modal( {
8
+ controller: {
9
+ trigger: function() {
10
+ }
11
+ }
12
+ } );
13
+
14
+ }
15
+
16
+ /**
17
+ * View: Error
18
+ * - Renders a WordPress style error message when something goes wrong.
19
+ *
20
+ * @since 1.4.3.0
21
+ */
22
+ wp.media.view.EnviraGalleryError = wp.Backbone.View.extend( {
23
+
24
+ // The outer tag and class name to use. The item is wrapped in this
25
+ tagName : 'div',
26
+ className : 'notice error envira-gallery-error',
27
+
28
+ render: function() {
29
+
30
+ // Load the template to render
31
+ // See includes/admin/media-views.php
32
+ this.template = wp.media.template( 'envira-gallery-error' );
33
+
34
+ // Define the HTML for the template
35
+ this.$el.html( this.template( this.model ) );
36
+
37
+ // Return the template
38
+ return this;
39
+
40
+ }
41
+
42
+ } );
43
+
44
+ /**
45
+ * View: Single Item (Gallery or Album)
46
+ * - Renders an <li> element within the "Choose your Gallery / Album" view
47
+ *
48
+ * @since 1.5.0
49
+ */
50
+ var EnviraGallerySelectionItemView = wp.Backbone.View.extend( {
51
+
52
+ /**
53
+ * The Tag Name and Tag's Class(es)
54
+ */
55
+ tagName: 'li',
56
+ className: 'attachment',
57
+
58
+ /**
59
+ * Template
60
+ * - The template to load inside the above tagName element
61
+ */
62
+ template: wp.template( 'envira-selection-item' ),
63
+
64
+ /**
65
+ * Initialize
66
+ *
67
+ * @param object model EnviraGalleryImage Backbone Model
68
+ */
69
+ initialize: function( args ) {
70
+
71
+ // Assign the model to this view
72
+ this.model = args.model;
73
+
74
+ },
75
+
76
+ /**
77
+ * Render
78
+ * - Binds the model to the view, so we populate the view's fields and data
79
+ */
80
+ render: function() {
81
+
82
+ // Get HTML
83
+ this.$el.html( this.template( this.model.attributes ) );
84
+ return this;
85
+
86
+ }
87
+
88
+ } );
89
+
90
+ /**
91
+ * Gallery Selection View
92
+ */
93
+ var EnviraGallerySelectionView = wp.Backbone.View.extend( {
94
+
95
+ /**
96
+ * The Tag Name and Tag's Class(es)
97
+ */
98
+ tagName: 'div',
99
+ className: 'media-frame mode-select wp-core-ui hide-router hide-menu',
100
+
101
+ /**
102
+ * Template
103
+ * - The template to load inside the above tagName element
104
+ */
105
+ template: wp.template( 'envira-selection' ),
106
+
107
+ /**
108
+ * Events
109
+ * - Functions to call when specific events occur
110
+ */
111
+ events: {
112
+ // Clicked a gallery
113
+ 'click .attachment': 'click',
114
+
115
+ // Used the search input
116
+ 'keyup': 'search',
117
+ 'search': 'search',
118
+
119
+ // Insert Button
120
+ 'click button.media-button-insert': 'insert',
121
+ },
122
+
123
+ /**
124
+ * Initialize
125
+ */
126
+ initialize: function( args ) {
127
+
128
+ // Whether we're inserting galleries or albums
129
+ this.action = args.action;
130
+
131
+ // Define a collection, which will store the Galleries
132
+ this.selection = new Backbone.Collection(); // The galleries / albums the user has selected
133
+ this.collection = new Backbone.Collection(); // The available galleries / albums
134
+
135
+ // Define some other flags.
136
+ this.is_loading = false;
137
+ this.search_timeout = false;
138
+
139
+ // Define loading and loaded events
140
+ this.on( 'loading', this.loading, this );
141
+ this.on( 'loaded', this.loaded, this );
142
+
143
+ // Get Galleries
144
+ this.getItems( false, '' );
145
+
146
+ },
147
+
148
+ /**
149
+ * Called when a Gallery is clicked
150
+ *
151
+ * @param object event Event
152
+ */
153
+ click: function( event ) {
154
+
155
+ // Get the target element, whether it's a directory and its ID
156
+ var target = jQuery( event.currentTarget ),
157
+ id = jQuery( 'div.attachment-preview', target ).attr( 'data-id' );
158
+
159
+ // Add or remove item from the selection, depending on its current state
160
+ if ( target.hasClass( 'selected' ) ) {
161
+ // Remove
162
+ this.removeFromSelection( target, id );
163
+ } else {
164
+ // Add
165
+ this.addToSelection( target, id );
166
+ }
167
+
168
+ },
169
+
170
+ /**
171
+ * Called when the search event is fired (the user types into the search field)
172
+ *
173
+ * @param object event Event
174
+ */
175
+ search: function( event ) {
176
+
177
+ // If we're already loading something, bail
178
+ if ( this.is_loading ) {
179
+ return;
180
+ }
181
+
182
+ // Clear any existing timeout
183
+ clearTimeout( this.search_timeout );
184
+
185
+ // Check if a search term exists, and is at least 3 characters
186
+ var search = event.target.value;
187
+
188
+ // If search is empty, return the entire folder's contents
189
+ if ( search.length == 0 ) {
190
+ this.getItems( false, '' );
191
+ return;
192
+ }
193
+
194
+ // If search isn't empty but less than 3 characters, don't do anything
195
+ if ( search.length < 3 ) {
196
+ return;
197
+ }
198
+
199
+ // Set a small timeout before we perform the search. If the user keeps typing,
200
+ // this ensures we don't return the wrong results too early.
201
+ var that = this;
202
+ this.search_timeout = setTimeout( function() {
203
+ that.getItems( true, search );
204
+ }, 1000 );
205
+
206
+ },
207
+
208
+ /**
209
+ * Gets galleries by sending an AJAX request
210
+ *
211
+ * @param bool is_search Is a search request
212
+ * @param string search_terms Search Terms
213
+ */
214
+ getItems: function( is_search, search_terms ) {
215
+
216
+ // If we're already loading something, bail
217
+ if ( this.is_loading ) {
218
+ return;
219
+ }
220
+
221
+ // Clear the existing collection
222
+ this.clearSelection();
223
+ this.$el.find( 'ul.attachments' ).empty();
224
+ this.$el.find( 'div.envira-gallery-error' ).remove();
225
+
226
+ // Update the loading flag
227
+ this.trigger( 'loading' );
228
+
229
+ // Determine whether we're going to retrieve Galleries or Albums.
230
+ var action = '';
231
+ switch ( this.action ) {
232
+ case 'gallery':
233
+ action = 'envira_gallery_editor_get_galleries';
234
+ break;
235
+ case 'album':
236
+ action = 'envira_albums_editor_get_albums';
237
+ break;
238
+ }
239
+
240
+ // Perform AJAX request to get Galleries or Albums.
241
+ wp.media.ajax( action, {
242
+ context: this,
243
+ data: {
244
+ nonce: envira_gallery_editor.get_galleries_nonce,
245
+ search: is_search,
246
+ search_terms: search_terms,
247
+ },
248
+ success: function( items ) {
249
+
250
+ // Define a collection
251
+ var collection = new Backbone.Collection( items );
252
+
253
+ // Reset the collection
254
+ this.collection.reset();
255
+
256
+ // Add the collection's models (items) to this class' collection
257
+ this.collection.add( collection.models );
258
+
259
+ // Render each item in the collection
260
+ this.collection.each( function( model ) {
261
+
262
+ // Init with model
263
+ var child_view = new EnviraGallerySelectionItemView( {
264
+ model: model
265
+ } );
266
+
267
+ // Render view within our main view
268
+ this.$el.find( 'ul.attachments' ).append( child_view.render().el );
269
+
270
+ }, this );
271
+
272
+ // Tell wp.media we've finished loading items
273
+ this.trigger( 'loaded' );
274
+
275
+ },
276
+ error: function( error_message ) {
277
+
278
+ // Tell wp.media we've finished loading items, and send the error message
279
+ // for output
280
+ this.trigger( 'loaded', error_message );
281
+
282
  }
283
+ } );
284
+
285
+ },
286
+
287
+ /**
288
+ * Render
289
+ * - Binds the collection to the view, so we populate the view's attachments grid
290
+ */
291
+ render: function() {
292
+
293
+ // Get HTML
294
+ this.$el.html( this.template() );
295
+
296
+ // Return
297
+ return this;
298
+
299
+ },
300
+
301
+ /**
302
+ * Renders an error using
303
+ * wp.media.view.EnviraGalleryError
304
+ */
305
+ renderError: function( error ) {
306
+
307
+ // Define model
308
+ var model = {};
309
+ model.error = error;
310
+
311
+ // Define view
312
+ var view = new wp.media.view.EnviraGalleryError( {
313
+ model: model
314
+ } );
315
+
316
+ // Return rendered view
317
+ return view.render().el;
318
+
319
+ },
320
+
321
+ /**
322
+ * Tells the view we're loading by displaying a spinner
323
+ */
324
+ loading: function() {
325
+
326
+ // Set a flag so we know we're loading data
327
+ this.is_loading = true;
328
+
329
+ // Show the spinner
330
+ this.$el.find( '.spinner' ).css( 'visibility', 'visible' );
331
+
332
+ },
333
+
334
+ /**
335
+ * Hides the loading spinner
336
+ */
337
+ loaded: function( response ) {
338
+
339
+ // Set a flag so we know we're not loading anything now
340
+ this.is_loading = false;
341
+
342
+ // Hide the spinner
343
+ this.$el.find( '.spinner' ).css( 'visibility', 'hidden' );
344
+
345
+ // Display the error message, if it's provided
346
+ if ( typeof response !== 'undefined' ) {
347
+ this.$el.find( 'ul.attachments' ).before( this.renderError( response ) );
348
+ }
349
+
350
+ },
351
+
352
+ /**
353
+ * Adds the given target to the selection
354
+ *
355
+ * @param object target Selected Element
356
+ * @param string id Unique Identifier (i.e. third party API item's UID)
357
+ */
358
+ addToSelection: function( target, id ) {
359
+
360
+ // Trigger the loading event
361
+ this.trigger( 'loading' );
362
+
363
+ // Iterate through the current collection of models until we find the model
364
+ // that has a path matching the given path
365
+ this.collection.each( function( model ) {
366
+ // If this model matches the model the user selected, add it to the selection
367
+ if ( model.get( 'id' ) == id ) {
368
+ this.selection.add( model );
369
  }
370
+ }, this );
371
+
372
+ // Mark the item as selected in the media view
373
+ target.addClass( 'selected details' );
374
+
375
+ // If the selection is not empty, enable the Insert button
376
+ if ( this.selection.length > 0 ) {
377
+ this.$el.find( 'button.media-button-insert' ).attr( 'disabled', false );
378
+ }
379
+
380
+ // Trigger the loaded event
381
+ this.trigger( 'loaded' );
382
+
383
+ },
384
+
385
+ /**
386
+ * Removes the given target from the selection
387
+ *
388
+ * @param object target Deselected Element
389
+ * @param string id Unique Identifier (i.e. third party API item's UID)
390
+ */
391
+ removeFromSelection: function( target, id ) {
392
+
393
+ // Trigger the loading event
394
+ this.trigger( 'loading' );
395
+
396
+ // Iterate through the current collection of selected models until we find the model
397
+ // that has a path matching the given path
398
+ this.selection.each( function( model ) {
399
+ // remove this model from the collection of selected models
400
+ this.selection.remove([{ cid: model.cid }]);
401
+ }, this );
402
+
403
+ // Mark the item as deselected in the media view
404
+ target.removeClass( 'selected details' );
405
+
406
+ // If the selection is empty, disable the Insert button
407
+ if ( this.selection.length == 0 ) {
408
+ this.$el.find( 'button.media-button-insert' ).attr( 'disabled', 'disabled' );
409
+ }
410
+
411
+ // Trigger the loaded event
412
+ this.trigger( 'loaded' );
413
+
414
+ },
415
+
416
+ /**
417
+ * Clears all selected items
418
+ */
419
+ clearSelection: function() {
420
+
421
+ // Iterate through each item, removing the selected state from the UI
422
+ this.selection.each( function( model ) {
423
+ this.$el.find( 'div[data-id="' + model.get( 'id' ) + '"]' ).parent().removeClass( 'selected details' );
424
+ }, this );
425
+
426
+ // Disable the Insert button
427
+ this.$el.find( 'button.media-button-insert' ).attr( 'disabled', 'disabled' );
428
+
429
+ // Clear the selected models
430
+ this.selection.reset();
431
+
432
+ },
433
+
434
+ /**
435
+ * Inserts one or more Galleries or Albums into the Editor
436
+ */
437
+ insert: function() {
438
+
439
+ // Tell the View we're loading
440
+ this.trigger( 'loading' );
441
+
442
+ // For each selected item, insert a shortcode into the editor
443
+ this.selection.forEach( function( item ) {
444
+ wp.media.editor.insert( '[envira-' + this.action + ' id="' + item.id + '"]' );
445
+ }, this );
446
+
447
+ // Trigger the loaded event
448
+ this.trigger( 'loaded' );
449
+
450
+ // Close the modal
451
+ EnviraGalleryModalWindow.close();
452
+
453
+ }
454
+
455
+ } );
456
+
457
+ jQuery( document ).ready( function( $ ) {
458
+
459
+ // Open the "Add Gallery" / "Add Album" modal
460
+ $( document ).on( 'click', 'a.envira-gallery-choose-gallery, a.envira-albums-choose-album', function( e ) {
461
+
462
+ // Prevent default action
463
+ e.preventDefault();
464
+
465
+ // Get the action
466
+ var action = $( this ).data( 'action' );
467
+
468
+ // Define the modal's view
469
+ EnviraGalleryModalWindow.content( new EnviraGallerySelectionView( {
470
+ action: action
471
+ } ) );
472
+
473
+ // Open the modal window
474
+ EnviraGalleryModalWindow.open();
475
+
476
+ } );
477
 
478
+ } );
 
 
 
 
assets/js/envira.js CHANGED
@@ -1,71 +1,13 @@
1
- // Envira functions.
2
- function enviraGetColWidth(a, e) {
3
- var d, c = jQuery(window).width(),
4
- b = a.data("envira-columns");
5
- switch (b) {
6
- case 1:
7
- d = a.width();
8
- break;
9
- case 2:
10
- if (c <= 480) {
11
- d = a.width()
12
- } else {
13
- d = a.width() / 2
14
- }
15
- break;
16
- case 3:
17
- if (c <= 480) {
18
- d = a.width()
19
- } else {
20
- if (c <= 768) {
21
- d = a.width() / 2
22
- } else {
23
- d = a.width() / 3
24
- }
25
- }
26
- case 4:
27
- case 5:
28
- case 6:
29
- if (c <= 480) {
30
- d = a.width()
31
- } else {
32
- if (c <= 768) {
33
- d = a.width() / 2
34
- } else {
35
- if (c <= 1024) {
36
- d = a.width() / 3
37
- } else {
38
- d = a.width() / b
39
- }
40
- }
41
- }
42
- break
43
- }
44
- return parseInt(d - (e * (b - 1)) / b)
45
- }
46
-
47
- function enviraSetWidths(a, c) {
48
- var b = enviraGetColWidth(a, c);
49
- a.children().css({
50
- width: b
51
- })
52
- };
53
-
54
- function enviraIsMobile() {
55
- var check = false;
56
- (function(a) {
57
- if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true
58
- })(navigator.userAgent || navigator.vendor || window.opera);
59
- return check;
60
- }
61
-
62
- function enviraThrottle(a, b) {
63
- return function() {
64
- var d = this,
65
- c = [].slice(arguments);
66
- clearTimeout(a._throttleTimeout);
67
- a._throttleTimeout = setTimeout(function() {
68
- a.apply(d, c)
69
- }, b)
70
- }
71
- };
1
+ /**
2
+ * envira.js is a placeholder, which CodeKit attaches the following JS files to, before compiling as min/envira-min.js:
3
+ * - lib/fancybox.js
4
+ * - lib/imagesloaded.js
5
+ * - lib/isotope.js
6
+ * - lib/mousewheel.js
7
+ * - lib/touchsupport.js
8
+ * - lib/touchswipe.js
9
+ *
10
+ * To load more JS resources:
11
+ * - Add them to the lib subfolder
12
+ * - Add the to the imports directive of this file in CodeKit
13
+ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/js/gallery-help.js ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Handles:
3
+ * - Inline Video Help
4
+ *
5
+ * @since 1.5.0
6
+ */
7
+
8
+ // Setup vars
9
+ var envira_video_link = 'p.envira-intro a.envira-video',
10
+ envira_close_video_link = 'a.envira-video-close';
11
+
12
+ jQuery( document ).ready( function( $ ) {
13
+ /**
14
+ * Display Video Inline on Video Link Click
15
+ */
16
+ $( document ).on( 'click', envira_video_link, function( e ) {
17
+
18
+ // Prevent default action
19
+ e.preventDefault();
20
+
21
+ // Get the video URL
22
+ var envira_video_url = $( this ).attr( 'href' );
23
+
24
+ // Check if the video has the autoplay parameter included
25
+ // If not, add it now - this will play the video when it's inserted to the iframe.
26
+ if ( envira_video_url.search( 'autoplay=1' ) == -1 ) {
27
+ if ( envira_video_url.search( 'rel=' ) == -1 ) {
28
+ envira_video_url += '?rel=0&autoplay=1';
29
+ } else {
30
+ envira_video_url += '&autoplay=1';
31
+ }
32
+ }
33
+
34
+ // Destroy any other instances of Envira Video iframes
35
+ $( 'div.envira-video-help' ).remove();
36
+
37
+ // Get the intro paragraph
38
+ var envira_video_paragraph = $( this ).closest( 'p.envira-intro' );
39
+
40
+ // Load the video below the intro paragraph on the current tab
41
+ $( envira_video_paragraph ).append( '<div class="envira-video-help"><iframe src="' + envira_video_url + '" /><a href="#" class="envira-video-close dashicons dashicons-no"></a></div>' );
42
+
43
+ } );
44
+
45
+ /**
46
+ * Destroy Video when closed
47
+ */
48
+ $( document ).on( 'click', envira_close_video_link, function( e ) {
49
+
50
+ e.preventDefault();
51
+
52
+ $( this ).closest( '.envira-video-help' ).remove();
53
+
54
+ } );
55
+
56
+ } );
assets/js/lib/fancybox.js CHANGED
@@ -127,7 +127,7 @@
127
  // HTML templates
128
  tpl: {
129
  wrap : '<div class="envirabox-wrap" tabIndex="-1"><div class="envirabox-skin"><div class="envirabox-outer"><div class="envirabox-inner"></div></div></div></div>',
130
- image : '<img class="envirabox-image" src="{href}" alt="" />',
131
  iframe : '<iframe id="envirabox-frame{rnd}" name="envirabox-frame{rnd}" class="envirabox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen' + (IE ? ' allowtransparency="true"' : '') + '></iframe>',
132
  error : '<p class="envirabox-error">The requested content cannot be loaded.<br/>Please try again later.</p>',
133
  closeBtn : '<a title="Close" class="envirabox-item envirabox-close" href="javascript:;"></a>',
127
  // HTML templates
128
  tpl: {
129
  wrap : '<div class="envirabox-wrap" tabIndex="-1"><div class="envirabox-skin"><div class="envirabox-outer"><div class="envirabox-inner"></div></div></div></div>',
130
+ image : '<img class="envirabox-image" src="{href}" />',
131
  iframe : '<iframe id="envirabox-frame{rnd}" name="envirabox-frame{rnd}" class="envirabox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen' + (IE ? ' allowtransparency="true"' : '') + '></iframe>',
132
  error : '<p class="envirabox-error">The requested content cannot be loaded.<br/>Please try again later.</p>',
133
  closeBtn : '<a title="Close" class="envirabox-item envirabox-close" href="javascript:;"></a>',
assets/js/lib/imagesloaded.js ADDED
@@ -0,0 +1,892 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * imagesLoaded PACKAGED v3.1.8
3
+ * JavaScript is all like "You images are done yet or what?"
4
+ * MIT License
5
+ */
6
+
7
+
8
+ /**
9
+ * EventEmitter v4.2.6 - git.io/ee
10
+ * Oliver Caldwell
11
+ * MIT license
12
+ */
13
+
14
+ (function () {
15
+
16
+
17
+ /**
18
+ * Class for managing events.
19
+ * Can be extended to provide event functionality in other classes.
20
+ *
21
+ * @class EventEmitter Manages event registering and emitting.
22
+ */
23
+ function EventEmitter() {}
24
+
25
+ // Shortcuts to improve speed and size
26
+ var proto = EventEmitter.prototype;
27
+ var exports = this;
28
+ var originalGlobalValue = exports.EventEmitter;
29
+
30
+ /**
31
+ * Finds the index of the listener for the event in it's storage array.
32
+ *
33
+ * @param {Function[]} listeners Array of listeners to search through.
34
+ * @param {Function} listener Method to look for.
35
+ * @return {Number} Index of the specified listener, -1 if not found
36
+ * @api private
37
+ */
38
+ function indexOfListener(listeners, listener) {
39
+ var i = listeners.length;
40
+ while (i--) {
41
+ if (listeners[i].listener === listener) {
42
+ return i;
43
+ }
44
+ }
45
+
46
+ return -1;
47
+ }
48
+
49
+ /**
50
+ * Alias a method while keeping the context correct, to allow for overwriting of target method.
51
+ *
52
+ * @param {String} name The name of the target method.
53
+ * @return {Function} The aliased method
54
+ * @api private
55
+ */
56
+ function alias(name) {
57
+ return function aliasClosure() {
58
+ return this[name].apply(this, arguments);
59
+ };
60
+ }
61
+
62
+ /**
63
+ * Returns the listener array for the specified event.
64
+ * Will initialise the event object and listener arrays if required.
65
+ * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
66
+ * Each property in the object response is an array of listener functions.
67
+ *
68
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
69
+ * @return {Function[]|Object} All listener functions for the event.
70
+ */
71
+ proto.getListeners = function getListeners(evt) {
72
+ var events = this._getEvents();
73
+ var response;
74
+ var key;
75
+
76
+ // Return a concatenated array of all matching events if
77
+ // the selector is a regular expression.
78
+ if (typeof evt === 'object') {
79
+ response = {};
80
+ for (key in events) {
81
+ if (events.hasOwnProperty(key) && evt.test(key)) {
82
+ response[key] = events[key];
83
+ }
84
+ }
85
+ }
86
+ else {
87
+ response = events[evt] || (events[evt] = []);
88
+ }
89
+
90
+ return response;
91
+ };
92
+
93
+ /**
94
+ * Takes a list of listener objects and flattens it into a list of listener functions.
95
+ *
96
+ * @param {Object[]} listeners Raw listener objects.
97
+ * @return {Function[]} Just the listener functions.
98
+ */
99
+ proto.flattenListeners = function flattenListeners(listeners) {
100
+ var flatListeners = [];
101
+ var i;
102
+
103
+ for (i = 0; i < listeners.length; i += 1) {
104
+ flatListeners.push(listeners[i].listener);
105
+ }
106
+
107
+ return flatListeners;
108
+ };
109
+
110
+ /**
111
+ * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
112
+ *
113
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
114
+ * @return {Object} All listener functions for an event in an object.
115
+ */
116
+ proto.getListenersAsObject = function getListenersAsObject(evt) {
117
+ var listeners = this.getListeners(evt);
118
+ var response;
119
+
120
+ if (listeners instanceof Array) {
121
+ response = {};
122
+ response[evt] = listeners;
123
+ }
124
+
125
+ return response || listeners;
126
+ };
127
+
128
+ /**
129
+ * Adds a listener function to the specified event.
130
+ * The listener will not be added if it is a duplicate.
131
+ * If the listener returns true then it will be removed after it is called.
132
+ * If you pass a regular expression as the event name then the listener will be added to all events that match it.
133
+ *
134
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
135
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
136
+ * @return {Object} Current instance of EventEmitter for chaining.
137
+ */
138
+ proto.addListener = function addListener(evt, listener) {
139
+ var listeners = this.getListenersAsObject(evt);
140
+ var listenerIsWrapped = typeof listener === 'object';
141
+ var key;
142
+
143
+ for (key in listeners) {
144
+ if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
145
+ listeners[key].push(listenerIsWrapped ? listener : {
146
+ listener: listener,
147
+ once: false
148
+ });
149
+ }
150
+ }
151
+
152
+ return this;
153
+ };
154
+
155
+ /**
156
+ * Alias of addListener
157
+ */
158
+ proto.on = alias('addListener');
159
+
160
+ /**
161
+ * Semi-alias of addListener. It will add a listener that will be
162
+ * automatically removed after it's first execution.
163
+ *
164
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
165
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
166
+ * @return {Object} Current instance of EventEmitter for chaining.
167
+ */
168
+ proto.addOnceListener = function addOnceListener(evt, listener) {
169
+ return this.addListener(evt, {
170
+ listener: listener,
171
+ once: true
172
+ });
173
+ };
174
+
175
+ /**
176
+ * Alias of addOnceListener.
177
+ */
178
+ proto.once = alias('addOnceListener');
179
+
180
+ /**
181
+ * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
182
+ * You need to tell it what event names should be matched by a regex.
183
+ *
184
+ * @param {String} evt Name of the event to create.
185
+ * @return {Object} Current instance of EventEmitter for chaining.
186
+ */
187
+ proto.defineEvent = function defineEvent(evt) {
188
+ this.getListeners(evt);
189
+ return this;
190
+ };
191
+
192
+ /**
193
+ * Uses defineEvent to define multiple events.
194
+ *
195
+ * @param {String[]} evts An array of event names to define.
196
+ * @return {Object} Current instance of EventEmitter for chaining.
197
+ */
198
+ proto.defineEvents = function defineEvents(evts) {
199
+ for (var i = 0; i < evts.length; i += 1) {
200
+ this.defineEvent(evts[i]);
201
+ }
202
+ return this;
203
+ };
204
+
205
+ /**
206
+ * Removes a listener function from the specified event.
207
+ * When passed a regular expression as the event name, it will remove the listener from all events that match it.
208
+ *
209
+ * @param {String|RegExp} evt Name of the event to remove the listener from.
210
+ * @param {Function} listener Method to remove from the event.
211
+ * @return {Object} Current instance of EventEmitter for chaining.
212
+ */
213
+ proto.removeListener = function removeListener(evt, listener) {
214
+ var listeners = this.getListenersAsObject(evt);
215
+ var index;
216
+ var key;
217
+
218
+ for (key in listeners) {
219
+ if (listeners.hasOwnProperty(key)) {
220
+ index = indexOfListener(listeners[key], listener);
221
+
222
+ if (index !== -1) {
223
+ listeners[key].splice(index, 1);
224
+ }
225
+ }
226
+ }
227
+
228
+ return this;
229
+ };
230
+
231
+ /**
232
+ * Alias of removeListener
233
+ */
234
+ proto.off = alias('removeListener');
235
+
236
+ /**
237
+ * Adds listeners in bulk using the manipulateListeners method.
238
+ * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
239
+ * You can also pass it a regular expression to add the array of listeners to all events that match it.
240
+ * Yeah, this function does quite a bit. That's probably a bad thing.
241
+ *
242
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
243
+ * @param {Function[]} [listeners] An optional array of listener functions to add.
244
+ * @return {Object} Current instance of EventEmitter for chaining.
245
+ */
246
+ proto.addListeners = function addListeners(evt, listeners) {
247
+ // Pass through to manipulateListeners
248
+ return this.manipulateListeners(false, evt, listeners);
249
+ };
250
+
251
+ /**
252
+ * Removes listeners in bulk using the manipulateListeners method.
253
+ * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
254
+ * You can also pass it an event name and an array of listeners to be removed.
255
+ * You can also pass it a regular expression to remove the listeners from all events that match it.
256
+ *
257
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
258
+ * @param {Function[]} [listeners] An optional array of listener functions to remove.
259
+ * @return {Object} Current instance of EventEmitter for chaining.
260
+ */
261
+ proto.removeListeners = function removeListeners(evt, listeners) {
262
+ // Pass through to manipulateListeners
263
+ return this.manipulateListeners(true, evt, listeners);
264
+ };
265
+
266
+ /**
267
+ * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
268
+ * The first argument will determine if the listeners are removed (true) or added (false).
269
+ * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
270
+ * You can also pass it an event name and an array of listeners to be added/removed.
271
+ * You can also pass it a regular expression to manipulate the listeners of all events that match it.
272
+ *
273
+ * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
274
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
275
+ * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
276
+ * @return {Object} Current instance of EventEmitter for chaining.
277
+ */
278
+ proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
279
+ var i;
280
+ var value;
281
+ var single = remove ? this.removeListener : this.addListener;
282
+ var multiple = remove ? this.removeListeners : this.addListeners;
283
+
284
+ // If evt is an object then pass each of it's properties to this method
285
+ if (typeof evt === 'object' && !(evt instanceof RegExp)) {
286
+ for (i in evt) {
287
+ if (evt.hasOwnProperty(i) && (value = evt[i])) {
288
+ // Pass the single listener straight through to the singular method
289
+ if (typeof value === 'function') {
290
+ single.call(this, i, value);
291
+ }
292
+ else {
293
+ // Otherwise pass back to the multiple function
294
+ multiple.call(this, i, value);
295
+ }
296
+ }
297
+ }
298
+ }
299
+ else {
300
+ // So evt must be a string
301
+ // And listeners must be an array of listeners
302
+ // Loop over it and pass each one to the multiple method
303
+ i = listeners.length;
304
+ while (i--) {
305
+ single.call(this, evt, listeners[i]);
306
+ }
307
+ }
308
+
309
+ return this;
310
+ };
311
+
312
+ /**
313
+ * Removes all listeners from a specified event.
314
+ * If you do not specify an event then all listeners will be removed.
315
+ * That means every event will be emptied.
316
+ * You can also pass a regex to remove all events that match it.
317
+ *
318
+ * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
319
+ * @return {Object} Current instance of EventEmitter for chaining.
320
+ */
321
+ proto.removeEvent = function removeEvent(evt) {
322
+ var type = typeof evt;
323
+ var events = this._getEvents();
324
+ var key;
325
+
326
+ // Remove different things depending on the state of evt
327
+ if (type === 'string') {
328
+ // Remove all listeners for the specified event
329
+ delete events[evt];
330
+ }
331
+ else if (type === 'object') {
332
+ // Remove all events matching the regex.
333
+ for (key in events) {
334
+ if (events.hasOwnProperty(key) && evt.test(key)) {
335
+ delete events[key];
336
+ }
337
+ }
338
+ }
339
+ else {
340
+ // Remove all listeners in all events
341
+ delete this._events;
342
+ }
343
+
344
+ return this;
345
+ };
346
+
347
+ /**
348
+ * Alias of removeEvent.
349
+ *
350
+ * Added to mirror the node API.
351
+ */
352
+ proto.removeAllListeners = alias('removeEvent');
353
+
354
+ /**
355
+ * Emits an event of your choice.
356
+ * When emitted, every listener attached to that event will be executed.
357
+ * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
358
+ * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
359
+ * So they will not arrive within the array on the other side, they will be separate.
360
+ * You can also pass a regular expression to emit to all events that match it.
361
+ *
362
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
363
+ * @param {Array} [args] Optional array of arguments to be passed to each listener.
364
+ * @return {Object} Current instance of EventEmitter for chaining.
365
+ */
366
+ proto.emitEvent = function emitEvent(evt, args) {
367
+ var listeners = this.getListenersAsObject(evt);
368
+ var listener;
369
+ var i;
370
+ var key;
371
+ var response;
372
+
373
+ for (key in listeners) {
374
+ if (listeners.hasOwnProperty(key)) {
375
+ i = listeners[key].length;
376
+
377
+ while (i--) {
378
+ // If the listener returns true then it shall be removed from the event
379
+ // The function is executed either with a basic call or an apply if there is an args array
380
+ listener = listeners[key][i];
381
+
382
+ if (listener.once === true) {
383
+ this.removeListener(evt, listener.listener);
384
+ }
385
+
386
+ response = listener.listener.apply(this, args || []);
387
+
388
+ if (response === this._getOnceReturnValue()) {
389
+ this.removeListener(evt, listener.listener);
390
+ }
391
+ }
392
+ }
393
+ }
394
+
395
+ return this;
396
+ };
397
+
398
+ /**
399
+ * Alias of emitEvent
400
+ */
401
+ proto.trigger = alias('emitEvent');
402
+
403
+ /**
404
+ * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
405
+ * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
406
+ *
407
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
408
+ * @param {...*} Optional additional arguments to be passed to each listener.
409
+ * @return {Object} Current instance of EventEmitter for chaining.
410
+ */
411
+ proto.emit = function emit(evt) {
412
+ var args = Array.prototype.slice.call(arguments, 1);
413
+ return this.emitEvent(evt, args);
414
+ };
415
+
416
+ /**
417
+ * Sets the current value to check against when executing listeners. If a
418
+ * listeners return value matches the one set here then it will be removed
419
+ * after execution. This value defaults to true.
420
+ *
421
+ * @param {*} value The new value to check for when executing listeners.
422
+ * @return {Object} Current instance of EventEmitter for chaining.
423
+ */
424
+ proto.setOnceReturnValue = function setOnceReturnValue(value) {
425
+ this._onceReturnValue = value;
426
+ return this;
427
+ };
428
+
429
+ /**
430
+ * Fetches the current value to check against when executing listeners. If
431
+ * the listeners return value matches this one then it should be removed
432
+ * automatically. It will return true by default.
433
+ *
434
+ * @return {*|Boolean} The current value to check for or the default, true.
435
+ * @api private
436
+ */
437
+ proto._getOnceReturnValue = function _getOnceReturnValue() {
438
+ if (this.hasOwnProperty('_onceReturnValue')) {
439
+ return this._onceReturnValue;
440
+ }
441
+ else {
442
+ return true;
443
+ }
444
+ };
445
+
446
+ /**
447
+ * Fetches the events object and creates one if required.
448
+ *
449
+ * @return {Object} The events storage object.
450
+ * @api private
451
+ */
452
+ proto._getEvents = function _getEvents() {
453
+ return this._events || (this._events = {});
454
+ };
455
+
456
+ /**
457
+ * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
458
+ *
459
+ * @return {Function} Non conflicting EventEmitter class.
460
+ */
461
+ EventEmitter.noConflict = function noConflict() {
462
+ exports.EventEmitter = originalGlobalValue;
463
+ return EventEmitter;
464
+ };
465
+
466
+ // Expose the class either via AMD, CommonJS or the global object
467
+ if (typeof define === 'function' && define.amd) {
468
+ define('eventEmitter/EventEmitter',[],function () {
469
+ return EventEmitter;
470
+ });
471
+ }
472
+ else if (typeof module === 'object' && module.exports){
473
+ module.exports = EventEmitter;
474
+ }
475
+ else {
476
+ this.EventEmitter = EventEmitter;
477
+ }
478
+ }.call(this));
479
+
480
+ /**
481
+ * eventie v1.0.4
482
+ * event binding helper
483
+ * eventie.bind( elem, 'click', myFn )
484
+ * eventie.unbind( elem, 'click', myFn )
485
+ */
486
+
487
+ /*jshint browser: true, undef: true, unused: true */
488
+ /*global define: false */
489
+
490
+ ( function( window ) {
491
+
492
+
493
+
494
+ var docElem = document.documentElement;
495
+
496
+ var bind = function() {};
497
+
498
+ function getIEEvent( obj ) {
499
+ var event = window.event;
500
+ // add event.target
501
+ event.target = event.target || event.srcElement || obj;
502
+ return event;
503
+ }
504
+
505
+ if ( docElem.addEventListener ) {
506
+ bind = function( obj, type, fn ) {
507
+ obj.addEventListener( type, fn, false );
508
+ };
509
+ } else if ( docElem.attachEvent ) {
510
+ bind = function( obj, type, fn ) {
511
+ obj[ type + fn ] = fn.handleEvent ?
512
+ function() {
513
+ var event = getIEEvent( obj );
514
+ fn.handleEvent.call( fn, event );
515
+ } :
516
+ function() {
517
+ var event = getIEEvent( obj );
518
+ fn.call( obj, event );
519
+ };
520
+ obj.attachEvent( "on" + type, obj[ type + fn ] );
521
+ };
522
+ }
523
+
524
+ var unbind = function() {};
525
+
526
+ if ( docElem.removeEventListener ) {
527
+ unbind = function( obj, type, fn ) {
528
+ obj.removeEventListener( type, fn, false );
529
+ };
530
+ } else if ( docElem.detachEvent ) {
531
+ unbind = function( obj, type, fn ) {
532
+ obj.detachEvent( "on" + type, obj[ type + fn ] );
533
+ try {
534
+ delete obj[ type + fn ];
535
+ } catch ( err ) {
536
+ // can't delete window object properties
537
+ obj[ type + fn ] = undefined;
538
+ }
539
+ };
540
+ }
541
+
542
+ var eventie = {
543
+ bind: bind,
544
+ unbind: unbind
545
+ };
546
+
547
+ // transport
548
+ if ( typeof define === 'function' && define.amd ) {
549
+ // AMD
550
+ define( 'eventie/eventie',eventie );
551
+ } else {
552
+ // browser global
553
+ window.eventie = eventie;
554
+ }
555
+
556
+ })( this );
557
+
558
+ /**
559
+ * imagesLoaded v3.1.8
560
+ * JavaScript is all like "You images are done yet or what?"
561
+ * MIT License
562
+ */
563
+
564
+ ( function( window, factory ) {
565
+ // universal module definition
566
+
567
+ /*global define: false, module: false, require: false */
568
+
569
+ if ( typeof define === 'function' && define.amd ) {
570
+ // AMD
571
+ define( [
572
+ 'eventEmitter/EventEmitter',
573
+ 'eventie/eventie'
574
+ ], function( EventEmitter, eventie ) {
575
+ return factory( window, EventEmitter, eventie );
576
+ });
577
+ } else if ( typeof exports === 'object' ) {
578
+ // CommonJS
579
+ module.exports = factory(
580
+ window,
581
+ require('wolfy87-eventemitter'),
582
+ require('eventie')
583
+ );
584
+ } else {
585
+ // browser global
586
+ window.imagesLoaded = factory(
587
+ window,
588
+ window.EventEmitter,
589
+ window.eventie
590
+ );
591
+ }
592
+
593
+ })( window,
594
+
595
+ // -------------------------- factory -------------------------- //
596
+
597
+ function factory( window, EventEmitter, eventie ) {
598
+
599
+
600
+
601
+ var $ = window.jQuery;
602
+ var console = window.console;
603
+ var hasConsole = typeof console !== 'undefined';
604
+
605
+ // -------------------------- helpers -------------------------- //
606
+
607
+ // extend objects
608
+ function extend( a, b ) {
609
+ for ( var prop in b ) {
610
+ a[ prop ] = b[ prop ];
611
+ }
612
+ return a;
613
+ }
614
+
615
+ var objToString = Object.prototype.toString;
616
+ function isArray( obj ) {
617
+ return objToString.call( obj ) === '[object Array]';
618
+ }
619
+
620
+ // turn element or nodeList into an array
621
+ function makeArray( obj ) {
622
+ var ary = [];
623
+ if ( isArray( obj ) ) {
624
+ // use object if already an array
625
+ ary = obj;
626
+ } else if ( typeof obj.length === 'number' ) {
627
+ // convert nodeList to array
628
+ for ( var i=0, len = obj.length; i < len; i++ ) {
629
+ ary.push( obj[i] );
630
+ }
631
+ } else {
632
+ // array of single index
633
+ ary.push( obj );
634
+ }
635
+ return ary;
636
+ }
637
+
638
+ // -------------------------- imagesLoaded -------------------------- //
639
+
640
+ /**
641
+ * @param {Array, Element, NodeList, String} elem
642
+ * @param {Object or Function} options - if function, use as callback
643
+ * @param {Function} onAlways - callback function
644
+ */
645
+ function ImagesLoaded( elem, options, onAlways ) {
646
+ // coerce ImagesLoaded() without new, to be new ImagesLoaded()
647
+ if ( !( this instanceof ImagesLoaded ) ) {
648
+ return new ImagesLoaded( elem, options );
649
+ }
650
+ // use elem as selector string
651
+ if ( typeof elem === 'string' ) {
652
+ elem = document.querySelectorAll( elem );
653
+ }
654
+
655
+ this.elements = makeArray( elem );
656
+ this.options = extend( {}, this.options );
657
+
658
+ if ( typeof options === 'function' ) {
659
+ onAlways = options;
660
+ } else {
661
+ extend( this.options, options );
662
+ }
663
+
664
+ if ( onAlways ) {
665
+ this.on( 'always', onAlways );
666
+ }
667
+
668
+ this.getImages();
669
+
670
+ if ( $ ) {
671
+ // add jQuery Deferred object
672
+ this.jqDeferred = new $.Deferred();
673
+ }
674
+
675
+ // HACK check async to allow time to bind listeners
676
+ var _this = this;
677
+ setTimeout( function() {
678
+ _this.check();
679
+ });
680
+ }
681
+
682
+ ImagesLoaded.prototype = new EventEmitter();
683
+
684
+ ImagesLoaded.prototype.options = {};
685
+
686
+ ImagesLoaded.prototype.getImages = function() {
687
+ this.images = [];
688
+
689
+ // filter & find items if we have an item selector
690
+ for ( var i=0, len = this.elements.length; i < len; i++ ) {
691
+ var elem = this.elements[i];
692
+ // filter siblings
693
+ if ( elem.nodeName === 'IMG' ) {
694
+ this.addImage( elem );
695
+ }
696
+ // find children
697
+ // no non-element nodes, #143
698
+ var nodeType = elem.nodeType;
699
+ if ( !nodeType || !( nodeType === 1 || nodeType === 9 || nodeType === 11 ) ) {
700
+ continue;
701
+ }
702
+ var childElems = elem.querySelectorAll('img');
703
+ // concat childElems to filterFound array
704
+ for ( var j=0, jLen = childElems.length; j < jLen; j++ ) {
705
+ var img = childElems[j];
706
+ this.addImage( img );
707
+ }
708
+ }
709
+ };
710
+
711
+ /**
712
+ * @param {Image} img
713
+ */
714
+ ImagesLoaded.prototype.addImage = function( img ) {
715
+ var loadingImage = new LoadingImage( img );
716
+ this.images.push( loadingImage );
717
+ };
718
+
719
+ ImagesLoaded.prototype.check = function() {
720
+ var _this = this;
721
+ var checkedCount = 0;
722
+ var length = this.images.length;
723
+ this.hasAnyBroken = false;
724
+ // complete if no images
725
+ if ( !length ) {
726
+ this.complete();
727
+ return;
728
+ }
729
+
730
+ function onConfirm( image, message ) {
731
+ if ( _this.options.debug && hasConsole ) {
732
+ console.log( 'confirm', image, message );
733
+ }
734
+
735
+ _this.progress( image );
736
+ checkedCount++;
737
+ if ( checkedCount === length ) {
738
+ _this.complete();
739
+ }
740
+ return true; // bind once
741
+ }
742
+
743
+ for ( var i=0; i < length; i++ ) {
744
+ var loadingImage = this.images[i];
745
+ loadingImage.on( 'confirm', onConfirm );
746
+ loadingImage.check();
747
+ }
748
+ };
749
+
750
+ ImagesLoaded.prototype.progress = function( image ) {
751
+ this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
752
+ // HACK - Chrome triggers event before object properties have changed. #83
753
+ var _this = this;
754
+ setTimeout( function() {
755
+ _this.emit( 'progress', _this, image );
756
+ if ( _this.jqDeferred && _this.jqDeferred.notify ) {
757
+ _this.jqDeferred.notify( _this, image );
758
+ }
759
+ });
760
+ };
761
+
762
+ ImagesLoaded.prototype.complete = function() {
763
+ var eventName = this.hasAnyBroken ? 'fail' : 'done';
764
+ this.isComplete = true;
765
+ var _this = this;
766
+ // HACK - another setTimeout so that confirm happens after progress
767
+ setTimeout( function() {
768
+ _this.emit( eventName, _this );
769
+ _this.emit( 'always', _this );
770
+ if ( _this.jqDeferred ) {
771
+ var jqMethod = _this.hasAnyBroken ? 'reject' : 'resolve';
772
+ _this.jqDeferred[ jqMethod ]( _this );
773
+ }
774
+ });
775
+ };
776
+
777
+ // -------------------------- jquery -------------------------- //
778
+
779
+ if ( $ ) {
780
+ $.fn.imagesLoaded = function( options, callback ) {
781
+ var instance = new ImagesLoaded( this, options, callback );
782
+ return instance.jqDeferred.promise( $(this) );
783
+ };
784
+ }
785
+
786
+
787
+ // -------------------------- -------------------------- //
788
+
789
+ function LoadingImage( img ) {
790
+ this.img = img;
791
+ }
792
+
793
+ LoadingImage.prototype = new EventEmitter();
794
+
795
+ LoadingImage.prototype.check = function() {
796
+ // first check cached any previous images that have same src
797
+ var resource = cache[ this.img.src ] || new Resource( this.img.src );
798
+ if ( resource.isConfirmed ) {
799
+ this.confirm( resource.isLoaded, 'cached was confirmed' );
800
+ return;
801
+ }
802
+
803
+ // If complete is true and browser supports natural sizes,
804
+ // try to check for image status manually.
805
+ if ( this.img.complete && this.img.naturalWidth !== undefined ) {
806
+ // report based on naturalWidth
807
+ this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
808
+ return;
809
+ }
810
+
811
+ // If none of the checks above matched, simulate loading on detached element.
812
+ var _this = this;
813
+ resource.on( 'confirm', function( resrc, message ) {
814
+ _this.confirm( resrc.isLoaded, message );
815
+ return true;
816
+ });
817
+
818
+ resource.check();
819
+ };
820
+
821
+ LoadingImage.prototype.confirm = function( isLoaded, message ) {
822
+ this.isLoaded = isLoaded;
823
+ this.emit( 'confirm', this, message );
824
+ };
825
+
826
+ // -------------------------- Resource -------------------------- //
827
+
828
+ // Resource checks each src, only once
829
+ // separate class from LoadingImage to prevent memory leaks. See #115
830
+
831
+ var cache = {};
832
+
833
+ function Resource( src ) {
834
+ this.src = src;
835
+ // add to cache
836
+ cache[ src ] = this;
837
+ }
838
+
839
+ Resource.prototype = new EventEmitter();
840
+
841
+ Resource.prototype.check = function() {
842
+ // only trigger checking once
843
+ if ( this.isChecked ) {
844
+ return;
845
+ }
846
+ // simulate loading on detached element
847
+ var proxyImage = new Image();
848
+ eventie.bind( proxyImage, 'load', this );
849
+ eventie.bind( proxyImage, 'error', this );
850
+ proxyImage.src = this.src;
851
+ // set flag
852
+ this.isChecked = true;
853
+ };
854
+
855
+ // ----- events ----- //
856
+
857
+ // trigger specified handler for event type
858
+ Resource.prototype.handleEvent = function( event ) {
859
+ var method = 'on' + event.type;
860
+ if ( this[ method ] ) {
861
+ this[ method ]( event );
862
+ }
863
+ };
864
+
865
+ Resource.prototype.onload = function( event ) {
866
+ this.confirm( true, 'onload' );
867
+ this.unbindProxyEvents( event );
868
+ };
869
+
870
+ Resource.prototype.onerror = function( event ) {
871
+ this.confirm( false, 'onerror' );
872
+ this.unbindProxyEvents( event );
873
+ };
874
+
875
+ // ----- confirm ----- //
876
+
877
+ Resource.prototype.confirm = function( isLoaded, message ) {
878
+ this.isConfirmed = true;
879
+ this.isLoaded = isLoaded;
880
+ this.emit( 'confirm', this, message );
881
+ };
882
+
883
+ Resource.prototype.unbindProxyEvents = function( event ) {
884
+ eventie.unbind( event.target, 'load', this );
885
+ eventie.unbind( event.target, 'error', this );
886
+ };
887
+
888
+ // ----- ----- //
889
+
890
+ return ImagesLoaded;
891
+
892
+ });
assets/js/lib/isotope.js CHANGED
@@ -1,950 +1,4256 @@
1
- // Isotope 1.5.26.
2
- ;
3
- (function(n, f, i) {
4
- var s = n.document;
5
- var w = s.documentElement;
6
- var k = n.Modernizr;
7
- var p = function(z) {
8
- return z.charAt(0).toUpperCase() + z.slice(1)
9
- };
10
- var u = "Moz Webkit O Ms".split(" ");
11
- var o = function(D) {
12
- var C = w.style,
13
- A;
14
- if (typeof C[D] === "string") {
15
- return D
16
- }
17
- D = p(D);
18
- for (var B = 0, z = u.length; B < z; B++) {
19
- A = u[B] + D;
20
- if (typeof C[A] === "string") {
21
- return A
22
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  }
24
- };
25
- var c = o("transform"),
26
- v = o("transitionProperty");;
27
- var j = {
28
- csstransforms: function() {
29
- return !!c
30
- },
31
- csstransforms3d: function() {
32
- var B = !! o("perspective");
33
- if (B && "webkitPerspective" in w.style) {
34
- var A = f("<style>@media (transform-3d),(-webkit-transform-3d){#modernizr{height:3px}}</style>").appendTo("head"),
35
- z = f('<div id="modernizr" />').appendTo("html");
36
- B = z.height() === 3;
37
- z.remove();
38
- A.remove()
39
- }
40
- return B
41
- },
42
- csstransitions: function() {
43
- return !!v
44
  }
45
- };
46
- var m;
47
- if (k) {
48
- for (m in j) {
49
- if (!k.hasOwnProperty(m)) {
50
- k.addTest(m, j[m])
51
- }
52
  }
 
 
 
53
  } else {
54
- k = n.Modernizr = {
55
- _version: "1.6ish: miniModernizr for Isotope"
56
- };
57
- var y = " ";
58
- var q;
59
- for (m in j) {
60
- q = j[m]();
61
- k[m] = q;
62
- y += " " + (q ? "" : "no-") + m
 
63
  }
64
- f("html").addClass(y)
65
- } if (k.csstransforms) {
66
- var e = k.csstransforms3d ? {
67
- translate: function(z) {
68
- return "translate3d(" + z[0] + "px, " + z[1] + "px, 0) "
69
- },
70
- scale: function(z) {
71
- return "scale3d(" + z + ", " + z + ", 1) "
72
- }
73
- } : {
74
- translate: function(z) {
75
- return "translate(" + z[0] + "px, " + z[1] + "px) "
76
- },
77
- scale: function(z) {
78
- return "scale(" + z + ") "
79
- }
80
- };
81
- var t = function(C, A, H) {
82
- var F = f.data(C, "isoTransform") || {}, J = {}, B, D = {}, G;
83
- J[A] = H;
84
- f.extend(F, J);
85
- for (B in F) {
86
- G = F[B];
87
- D[B] = e[B](G)
88
- }
89
- var E = D.translate || "",
90
- I = D.scale || "",
91
- z = E + I;
92
- f.data(C, "isoTransform", F);
93
- C.style[c] = z
94
- };
95
- f.cssNumber.scale = true;
96
- f.cssHooks.scale = {
97
- set: function(z, A) {
98
- t(z, "scale", A)
99
- },
100
- get: function(B, A) {
101
- var z = f.data(B, "isoTransform");
102
- return z && z.scale ? z.scale : 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  };
105
- f.fx.step.scale = function(z) {
106
- f.cssHooks.scale.set(z.elem, z.now + z.unit)
107
- };
108
- f.cssNumber.translate = true;
109
- f.cssHooks.translate = {
110
- set: function(z, A) {
111
- t(z, "translate", A)
112
- },
113
- get: function(B, A) {
114
- var z = f.data(B, "isoTransform");
115
- return z && z.translate ? z.translate : [0, 0]
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  }
117
  }
118
- }
119
- var b, a;
120
- if (k.csstransitions) {
121
- b = {
122
- WebkitTransitionProperty: "webkitTransitionEnd",
123
- MozTransitionProperty: "transitionend",
124
- OTransitionProperty: "oTransitionEnd otransitionend",
125
- transitionProperty: "transitionend"
126
- }[v];
127
- a = o("transitionDuration")
128
- }
129
- var l = f.event,
130
- h = f.event.handle ? "handle" : "dispatch",
131
- d;
132
- l.special.smartresize = {
133
- setup: function() {
134
- f(this).bind("resize", l.special.smartresize.handler)
135
- },
136
- teardown: function() {
137
- f(this).unbind("resize", l.special.smartresize.handler)
138
- },
139
- handler: function(C, z) {
140
- var B = this,
141
- A = arguments;
142
- C.type = "smartresize";
143
- if (d) {
144
- clearTimeout(d)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  }
146
- d = setTimeout(function() {
147
- l[h].apply(B, A)
148
- }, z === "execAsap" ? 0 : 100)
149
  }
 
 
150
  };
151
- f.fn.smartresize = function(z) {
152
- return z ? this.bind("smartresize", z) : this.trigger("smartresize", ["execAsap"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  };
154
- f.Isotope = function(z, A, B) {
155
- this.element = f(A);
156
- this._create(z);
157
- this._init(B)
 
 
 
 
 
 
 
 
 
 
 
 
158
  };
159
- var g = ["width", "height"];
160
- var r = f(n);
161
- f.Isotope.settings = {
162
- resizable: true,
163
- layoutMode: "masonry",
164
- containerClass: "isotope",
165
- itemClass: "isotope-item",
166
- hiddenClass: "isotope-hidden",
167
- hiddenStyle: {
168
- opacity: 0,
169
- scale: 0.001
170
- },
171
- visibleStyle: {
172
- opacity: 1,
173
- scale: 1
174
- },
175
- containerStyle: {
176
- position: "relative",
177
- overflow: "hidden"
178
- },
179
- animationEngine: "best-available",
180
- animationOptions: {
181
- queue: false,
182
- duration: 800
183
- },
184
- sortBy: "original-order",
185
- sortAscending: true,
186
- resizesContainer: true,
187
- transformsEnabled: true,
188
- itemPositionDataEnabled: false
189
  };
190
- f.Isotope.prototype = {
191
- _create: function(E) {
192
- this.options = f.extend({}, f.Isotope.settings, E);
193
- this.styleQueue = [];
194
- this.elemCount = 0;
195
- var C = this.element[0].style;
196
- this.originalStyle = {};
197
- var B = g.slice(0);
198
- for (var G in this.options.containerStyle) {
199
- B.push(G)
200
- }
201
- for (var F = 0, A = B.length; F < A; F++) {
202
- G = B[F];
203
- this.originalStyle[G] = C[G] || ""
204
- }
205
- this.element.css(this.options.containerStyle);
206
- this._updateAnimationEngine();
207
- this._updateUsingTransforms();
208
- var D = {
209
- "original-order": function(I, H) {
210
- H.elemCount++;
211
- return H.elemCount
212
- },
213
- random: function() {
214
- return Math.random()
215
- }
216
- };
217
- this.options.getSortData = f.extend(this.options.getSortData, D);
218
- this.reloadItems();
219
- this.offset = {
220
- left: parseInt((this.element.css("padding-left") || 0), 10),
221
- top: parseInt((this.element.css("padding-top") || 0), 10)
222
- };
223
- var z = this;
224
- setTimeout(function() {
225
- z.element.addClass(z.options.containerClass)
226
- }, 0);
227
- if (this.options.resizable) {
228
- r.bind("smartresize.isotope", function() {
229
- z.resize()
230
- })
231
- }
232
- this.element.delegate("." + this.options.hiddenClass, "click", function() {
233
- return false
234
- })
235
- },
236
- _getAtoms: function(C) {
237
- var z = this.options.itemSelector,
238
- B = z ? C.filter(z).add(C.find(z)) : C,
239
- A = {
240
- position: "absolute"
241
- };
242
- B = B.filter(function(D, E) {
243
- return E.nodeType === 1
244
- });
245
- if (this.usingTransforms) {
246
- A.left = 0;
247
- A.top = 0
248
- }
249
- B.css(A).addClass(this.options.itemClass);
250
- this.updateSortData(B, true);
251
- return B
252
- },
253
- _init: function(z) {
254
- this.$filteredAtoms = this._filter(this.$allAtoms);
255
- this._sort();
256
- this.reLayout(z)
257
- },
258
- option: function(B) {
259
- if (f.isPlainObject(B)) {
260
- this.options = f.extend(true, this.options, B);
261
- var z;
262
- for (var A in B) {
263
- z = "_update" + p(A);
264
- if (this[z]) {
265
- this[z]()
266
- }
267
  }
268
  }
269
- },
270
- _updateAnimationEngine: function() {
271
- var A = this.options.animationEngine.toLowerCase().replace(/[ _\-]/g, "");
272
- var z;
273
- switch (A) {
274
- case "css":
275
- case "none":
276
- z = false;
277
- break;
278
- case "jquery":
279
- z = true;
280
- break;
281
- default:
282
- z = !k.csstransitions
283
- }
284
- this.isUsingJQueryAnimation = z;
285
- this._updateUsingTransforms()
286
- },
287
- _updateTransformsEnabled: function() {
288
- this._updateUsingTransforms()
289
- },
290
- _updateUsingTransforms: function() {
291
- var z = this.usingTransforms = this.options.transformsEnabled && k.csstransforms && k.csstransitions && !this.isUsingJQueryAnimation;
292
- if (!z) {
293
- delete this.options.hiddenStyle.scale;
294
- delete this.options.visibleStyle.scale
295
- }
296
- this.getPositionStyles = z ? this._translate : this._positionAbs
297
- },
298
- _filter: function(F) {
299
- var B = this.options.filter === "" ? "*" : this.options.filter;
300
- if (!B) {
301
- return F
302
- }
303
- var E = this.options.hiddenClass,
304
- A = "." + E,
305
- D = F.filter(A),
306
- z = D;
307
- if (B !== "*") {
308
- z = D.filter(B);
309
- var C = F.not(A).not(B).addClass(E);
310
- this.styleQueue.push({
311
- $el: C,
312
- style: this.options.hiddenStyle
313
- })
314
- }
315
- this.styleQueue.push({
316
- $el: z,
317
- style: this.options.visibleStyle
318
- });
319
- z.removeClass(E);
320
- return F.filter(B)
321
- },
322
- updateSortData: function(E, B) {
323
- var A = this,
324
- C = this.options.getSortData,
325
- D, z;
326
- E.each(function() {
327
- D = f(this);
328
- z = {};
329
- for (var F in C) {
330
- if (!B && F === "original-order") {
331
- z[F] = f.data(this, "isotope-sort-data")[F]
332
- } else {
333
- z[F] = C[F](D, A)
334
- }
335
- }
336
- f.data(this, "isotope-sort-data", z)
337
- })
338
- },
339
- _sort: function() {
340
- var C = this.options.sortBy,
341
- B = this._getSorter,
342
- z = this.options.sortAscending ? 1 : -1,
343
- A = function(G, F) {
344
- var E = B(G, C),
345
- D = B(F, C);
346
- if (E === D && C !== "original-order") {
347
- E = B(G, "original-order");
348
- D = B(F, "original-order")
349
  }
350
- return ((E > D) ? 1 : (E < D) ? -1 : 0) * z
351
- };
352
- this.$filteredAtoms.sort(A)
353
- },
354
- _getSorter: function(z, A) {
355
- return f.data(z, "isotope-sort-data")[A]
356
- },
357
- _translate: function(z, A) {
358
- return {
359
- translate: [z, A]
360
- }
361
- },
362
- _positionAbs: function(z, A) {
363
- return {
364
- left: z,
365
- top: A
366
- }
367
- },
368
- _pushPosition: function(B, A, C) {
369
- A = Math.round(A + this.offset.left);
370
- C = Math.round(C + this.offset.top);
371
- var z = this.getPositionStyles(A, C);
372
- this.styleQueue.push({
373
- $el: B,
374
- style: z
375
- });
376
- if (this.options.itemPositionDataEnabled) {
377
- B.data("isotope-item-position", {
378
- x: A,
379
- y: C
380
- })
381
- }
382
- },
383
- layout: function(C, B) {
384
- var A = this.options.layoutMode;
385
- this["_" + A + "Layout"](C);
386
- if (this.options.resizesContainer) {
387
- var z = this["_" + A + "GetContainerSize"]();
388
- this.styleQueue.push({
389
- $el: this.element,
390
- style: z
391
- })
392
- }
393
- this._processStyleQueue(C, B);
394
- this.isLaidOut = true
395
- },
396
- _processStyleQueue: function(A, P) {
397
- var C = !this.isLaidOut ? "css" : (this.isUsingJQueryAnimation ? "animate" : "css"),
398
- F = this.options.animationOptions,
399
- G = this.options.onLayout,
400
- N, D, J, K;
401
- D = function(Q, R) {
402
- R.$el[C](R.style, F)
403
- };
404
- if (this._isInserting && this.isUsingJQueryAnimation) {
405
- D = function(Q, R) {
406
- N = R.$el.hasClass("no-transition") ? "css" : C;
407
- R.$el[N](R.style, F)
408
- }
409
- } else {
410
- if (P || G || F.complete) {
411
- var B = false,
412
- I = [P, G, F.complete],
413
- O = this;
414
- J = true;
415
- K = function() {
416
- if (B) {
417
- return
418
- }
419
- var S;
420
- for (var R = 0, Q = I.length; R < Q; R++) {
421
- S = I[R];
422
- if (typeof S === "function") {
423
- S.call(O.element, A, O)
424
- }
425
- }
426
- B = true
427
- };
428
- if (this.isUsingJQueryAnimation && C === "animate") {
429
- F.complete = K;
430
- J = false
431
- } else {
432
- if (k.csstransitions) {
433
- var H = 0,
434
- L = this.styleQueue[0],
435
- M = L && L.$el,
436
- z;
437
- while (!M || !M.length) {
438
- z = this.styleQueue[H++];
439
- if (!z) {
440
- return
441
- }
442
- M = z.$el
443
- }
444
- var E = parseFloat(getComputedStyle(M[0])[a]);
445
- if (E > 0) {
446
- D = function(Q, R) {
447
- R.$el[C](R.style, F).one(b, K)
448
- };
449
- J = false
450
- }
451
- }
452
  }
453
  }
454
  }
455
- f.each(this.styleQueue, D);
456
- if (J) {
457
- K()
458
- }
459
- this.styleQueue = []
460
- },
461
- resize: function() {
462
- if (this["_" + this.options.layoutMode + "ResizeChanged"]()) {
463
- this.reLayout()
464
- }
465
- },
466
- reLayout: function(z) {
467
- this["_" + this.options.layoutMode + "Reset"]();
468
- this.layout(this.$filteredAtoms, z)
469
- },
470
- addItems: function(A, B) {
471
- var z = this._getAtoms(A);
472
- this.$allAtoms = this.$allAtoms.add(z);
473
- if (B) {
474
- B(z)
475
- }
476
- },
477
- insert: function(A, B) {
478
- this.element.append(A);
479
- var z = this;
480
- this.addItems(A, function(C) {
481
- var D = z._filter(C);
482
- z._addHideAppended(D);
483
- z._sort();
484
- z.reLayout();
485
- z._revealAppended(D, B)
486
- })
487
- },
488
- appended: function(A, B) {
489
- var z = this;
490
- this.addItems(A, function(C) {
491
- z._addHideAppended(C);
492
- z.layout(C);
493
- z._revealAppended(C, B)
494
- })
495
- },
496
- _addHideAppended: function(z) {
497
- this.$filteredAtoms = this.$filteredAtoms.add(z);
498
- z.addClass("no-transition");
499
- this._isInserting = true;
500
- this.styleQueue.push({
501
- $el: z,
502
- style: this.options.hiddenStyle
503
- })
504
- },
505
- _revealAppended: function(A, B) {
506
- var z = this;
507
- setTimeout(function() {
508
- A.removeClass("no-transition");
509
- z.styleQueue.push({
510
- $el: A,
511
- style: z.options.visibleStyle
512
- });
513
- z._isInserting = false;
514
- z._processStyleQueue(A, B)
515
- }, 10)
516
- },
517
- reloadItems: function() {
518
- this.$allAtoms = this._getAtoms(this.element.children())
519
- },
520
- remove: function(B, C) {
521
- this.$allAtoms = this.$allAtoms.not(B);
522
- this.$filteredAtoms = this.$filteredAtoms.not(B);
523
- var z = this;
524
- var A = function() {
525
- B.remove();
526
- if (C) {
527
- C.call(z.element)
528
- }
529
- };
530
- if (B.filter(":not(." + this.options.hiddenClass + ")").length) {
531
- this.styleQueue.push({
532
- $el: B,
533
- style: this.options.hiddenStyle
534
- });
535
- this._sort();
536
- this.reLayout(A)
537
- } else {
538
- A()
539
  }
540
- },
541
- shuffle: function(z) {
542
- this.updateSortData(this.$allAtoms);
543
- this.options.sortBy = "random";
544
- this._sort();
545
- this.reLayout(z)
546
- },
547
- destroy: function() {
548
- var B = this.usingTransforms;
549
- var A = this.options;
550
- this.$allAtoms.removeClass(A.hiddenClass + " " + A.itemClass).each(function() {
551
- var D = this.style;
552
- D.position = "";
553
- D.top = "";
554
- D.left = "";
555
- D.opacity = "";
556
- if (B) {
557
- D[c] = ""
 
 
 
 
 
 
 
 
 
 
 
558
  }
559
- });
560
- var z = this.element[0].style;
561
- for (var C in this.originalStyle) {
562
- z[C] = this.originalStyle[C]
563
  }
564
- this.element.unbind(".isotope").undelegate("." + A.hiddenClass, "click").removeClass(A.containerClass).removeData("isotope");
565
- r.unbind(".isotope")
566
- },
567
- _getSegments: function(F) {
568
- var C = this.options.layoutMode,
569
- B = F ? "rowHeight" : "columnWidth",
570
- A = F ? "height" : "width",
571
- E = F ? "rows" : "cols",
572
- G = this.element[A](),
573
- z, D = this.options[C] && this.options[C][B] || this.$filteredAtoms["outer" + p(A)](true) || G;
574
- z = Math.floor(G / D);
575
- z = Math.max(z, 1);
576
- this[C][E] = z;
577
- this[C][B] = D
578
- },
579
- _checkIfSegmentsChanged: function(C) {
580
- var A = this.options.layoutMode,
581
- B = C ? "rows" : "cols",
582
- z = this[A][B];
583
- this._getSegments(C);
584
- return (this[A][B] !== z)
585
- },
586
- _masonryReset: function() {
587
- this.masonry = {};
588
- this._getSegments();
589
- var z = this.masonry.cols;
590
- this.masonry.colYs = [];
591
- while (z--) {
592
- this.masonry.colYs.push(0)
593
- }
594
- },
595
- _masonryLayout: function(B) {
596
- var z = this,
597
- A = z.masonry;
598
- B.each(function() {
599
- var G = f(this),
600
- E = Math.ceil(G.outerWidth(true) / A.columnWidth);
601
- E = Math.min(E, A.cols);
602
- if (E === 1) {
603
- z._masonryPlaceBrick(G, A.colYs)
604
- } else {
605
- var H = A.cols + 1 - E,
606
- D = [],
607
- F, C;
608
- for (C = 0; C < H; C++) {
609
- F = A.colYs.slice(C, C + E);
610
- D[C] = Math.max.apply(Math, F)
611
  }
612
- z._masonryPlaceBrick(G, D)
613
- }
614
- })
615
- },
616
- _masonryPlaceBrick: function(C, G) {
617
- var z = Math.min.apply(Math, G),
618
- I = 0;
619
- for (var B = 0, D = G.length; B < D; B++) {
620
- if (G[B] === z) {
621
- I = B;
622
- break
623
- }
624
- }
625
- var H = this.masonry.columnWidth * I,
626
- F = z;
627
- this._pushPosition(C, H, F);
628
- var E = z + C.outerHeight(true),
629
- A = this.masonry.cols + 1 - D;
630
- for (B = 0; B < A; B++) {
631
- this.masonry.colYs[I + B] = E
632
- }
633
- },
634
- _masonryGetContainerSize: function() {
635
- var z = Math.max.apply(Math, this.masonry.colYs);
636
- return {
637
- height: z
638
- }
639
- },
640
- _masonryResizeChanged: function() {
641
- return this._checkIfSegmentsChanged()
642
- },
643
- _fitRowsReset: function() {
644
- this.fitRows = {
645
- x: 0,
646
- y: 0,
647
- height: 0
648
- }
649
- },
650
- _fitRowsLayout: function(C) {
651
- var z = this,
652
- B = this.element.width(),
653
- A = this.fitRows;
654
- C.each(function() {
655
- var F = f(this),
656
- E = F.outerWidth(true),
657
- D = F.outerHeight(true);
658
- if (A.x !== 0 && E + A.x > B) {
659
- A.x = 0;
660
- A.y = A.height
661
- }
662
- z._pushPosition(F, A.x, A.y);
663
- A.height = Math.max(A.y + D, A.height);
664
- A.x += E
665
- })
666
- },
667
- _fitRowsGetContainerSize: function() {
668
- return {
669
- height: this.fitRows.height
670
- }
671
- },
672
- _fitRowsResizeChanged: function() {
673
- return true
674
- },
675
- _cellsByRowReset: function() {
676
- this.cellsByRow = {
677
- index: 0
678
- };
679
- this._getSegments();
680
- this._getSegments(true)
681
- },
682
- _cellsByRowLayout: function(B) {
683
- var z = this,
684
- A = this.cellsByRow;
685
- B.each(function() {
686
- var E = f(this),
687
- D = A.index % A.cols,
688
- F = Math.floor(A.index / A.cols),
689
- C = (D + 0.5) * A.columnWidth - E.outerWidth(true) / 2,
690
- G = (F + 0.5) * A.rowHeight - E.outerHeight(true) / 2;
691
- z._pushPosition(E, C, G);
692
- A.index++
693
- })
694
- },
695
- _cellsByRowGetContainerSize: function() {
696
- return {
697
- height: Math.ceil(this.$filteredAtoms.length / this.cellsByRow.cols) * this.cellsByRow.rowHeight + this.offset.top
698
- }
699
- },
700
- _cellsByRowResizeChanged: function() {
701
- return this._checkIfSegmentsChanged()
702
- },
703
- _straightDownReset: function() {
704
- this.straightDown = {
705
- y: 0
706
- }
707
- },
708
- _straightDownLayout: function(A) {
709
- var z = this;
710
- A.each(function(B) {
711
- var C = f(this);
712
- z._pushPosition(C, 0, z.straightDown.y);
713
- z.straightDown.y += C.outerHeight(true)
714
- })
715
- },
716
- _straightDownGetContainerSize: function() {
717
- return {
718
- height: this.straightDown.y
719
- }
720
- },
721
- _straightDownResizeChanged: function() {
722
- return true
723
- },
724
- _masonryHorizontalReset: function() {
725
- this.masonryHorizontal = {};
726
- this._getSegments(true);
727
- var z = this.masonryHorizontal.rows;
728
- this.masonryHorizontal.rowXs = [];
729
- while (z--) {
730
- this.masonryHorizontal.rowXs.push(0)
731
- }
732
- },
733
- _masonryHorizontalLayout: function(B) {
734
- var z = this,
735
- A = z.masonryHorizontal;
736
- B.each(function() {
737
- var G = f(this),
738
- E = Math.ceil(G.outerHeight(true) / A.rowHeight);
739
- E = Math.min(E, A.rows);
740
- if (E === 1) {
741
- z._masonryHorizontalPlaceBrick(G, A.rowXs)
742
- } else {
743
- var H = A.rows + 1 - E,
744
- D = [],
745
- F, C;
746
- for (C = 0; C < H; C++) {
747
- F = A.rowXs.slice(C, C + E);
748
- D[C] = Math.max.apply(Math, F)
749
  }
750
- z._masonryHorizontalPlaceBrick(G, D)
751
- }
752
- })
753
- },
754
- _masonryHorizontalPlaceBrick: function(C, H) {
755
- var z = Math.min.apply(Math, H),
756
- F = 0;
757
- for (var B = 0, D = H.length; B < D; B++) {
758
- if (H[B] === z) {
759
- F = B;
760
- break
761
- }
762
- }
763
- var I = z,
764
- G = this.masonryHorizontal.rowHeight * F;
765
- this._pushPosition(C, I, G);
766
- var E = z + C.outerWidth(true),
767
- A = this.masonryHorizontal.rows + 1 - D;
768
- for (B = 0; B < A; B++) {
769
- this.masonryHorizontal.rowXs[F + B] = E
770
- }
771
- },
772
- _masonryHorizontalGetContainerSize: function() {
773
- var z = Math.max.apply(Math, this.masonryHorizontal.rowXs);
774
- return {
775
- width: z
776
- }
777
- },
778
- _masonryHorizontalResizeChanged: function() {
779
- return this._checkIfSegmentsChanged(true)
780
- },
781
- _fitColumnsReset: function() {
782
- this.fitColumns = {
783
- x: 0,
784
- y: 0,
785
- width: 0
786
- }
787
- },
788
- _fitColumnsLayout: function(C) {
789
- var z = this,
790
- B = this.element.height(),
791
- A = this.fitColumns;
792
- C.each(function() {
793
- var F = f(this),
794
- E = F.outerWidth(true),
795
- D = F.outerHeight(true);
796
- if (A.y !== 0 && D + A.y > B) {
797
- A.x = A.width;
798
- A.y = 0
799
  }
800
- z._pushPosition(F, A.x, A.y);
801
- A.width = Math.max(A.x + E, A.width);
802
- A.y += D
803
- })
804
- },
805
- _fitColumnsGetContainerSize: function() {
806
- return {
807
- width: this.fitColumns.width
808
  }
809
- },
810
- _fitColumnsResizeChanged: function() {
811
- return true
812
- },
813
- _cellsByColumnReset: function() {
814
- this.cellsByColumn = {
815
- index: 0
816
- };
817
- this._getSegments();
818
- this._getSegments(true)
819
- },
820
- _cellsByColumnLayout: function(B) {
821
- var z = this,
822
- A = this.cellsByColumn;
823
- B.each(function() {
824
- var E = f(this),
825
- D = Math.floor(A.index / A.rows),
826
- F = A.index % A.rows,
827
- C = (D + 0.5) * A.columnWidth - E.outerWidth(true) / 2,
828
- G = (F + 0.5) * A.rowHeight - E.outerHeight(true) / 2;
829
- z._pushPosition(E, C, G);
830
- A.index++
831
- })
832
- },
833
- _cellsByColumnGetContainerSize: function() {
834
- return {
835
- width: Math.ceil(this.$filteredAtoms.length / this.cellsByColumn.rows) * this.cellsByColumn.columnWidth
836
- }
837
- },
838
- _cellsByColumnResizeChanged: function() {
839
- return this._checkIfSegmentsChanged(true)
840
- },
841
- _straightAcrossReset: function() {
842
- this.straightAcross = {
843
- x: 0
844
- }
845
- },
846
- _straightAcrossLayout: function(A) {
847
- var z = this;
848
- A.each(function(B) {
849
- var C = f(this);
850
- z._pushPosition(C, z.straightAcross.x, 0);
851
- z.straightAcross.x += C.outerWidth(true)
852
- })
853
- },
854
- _straightAcrossGetContainerSize: function() {
855
- return {
856
- width: this.straightAcross.x
857
- }
858
- },
859
- _straightAcrossResizeChanged: function() {
860
- return true
861
- }
862
- };;
863
- f.fn.imagesLoaded = function(G) {
864
- var E = this,
865
- C = E.find("img").add(E.filter("img")),
866
- z = C.length,
867
- F = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==",
868
- B = [];
869
-
870
- function D() {
871
- G.call(E, C)
872
  }
873
 
874
- function A(I) {
875
- var H = I.target;
876
- if (H.src !== F && f.inArray(H, B) === -1) {
877
- B.push(H);
878
- if (--z <= 0) {
879
- setTimeout(D);
880
- C.unbind(".imagesLoaded", A)
881
- }
882
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
883
  }
884
- if (!z) {
885
- D()
886
  }
887
- C.bind("load.imagesLoaded error.imagesLoaded", A).each(function() {
888
- var H = this.src;
889
- this.src = F;
890
- this.src = H
891
- });
892
- return E
893
  };
894
- var x = function(z) {
895
- if (n.console) {
896
- n.console.error(z)
897
- }
 
 
 
 
 
898
  };
899
- f.fn.isotope = function(A, B) {
900
- if (typeof A === "string") {
901
- var z = Array.prototype.slice.call(arguments, 1);
902
- this.each(function() {
903
- var C = f.data(this, "isotope");
904
- if (!C) {
905
- x("cannot call methods on isotope prior to initialization; attempted to call method '" + A + "'");
906
- return
907
- }
908
- if (!f.isFunction(C[A]) || A.charAt(0) === "_") {
909
- x("no such method '" + A + "' for isotope instance");
910
- return
911
- }
912
- C[A].apply(C, z)
913
- })
914
- } else {
915
- this.each(function() {
916
- var C = f.data(this, "isotope");
917
- if (C) {
918
- C.option(A);
919
- C._init(B)
920
- } else {
921
- f.data(this, "isotope", new f.Isotope(A, this, B))
922
- }
923
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
924
  }
925
- return this
926
- }
927
- })(window, jQuery);
928
- // Isoptope custom extensions and methods.
929
- jQuery.Isotope.prototype._getMasonryGutterColumns = function() {
930
- var a = this.options.masonry && this.options.masonry.gutterWidth || 0;
931
- containerWidth = this.element.width();
932
- this.masonry.columnWidth = this.options.masonry && this.options.masonry.columnWidth || this.$filteredAtoms.outerWidth(true) || containerWidth;
933
- this.masonry.columnWidth += a;
934
- this.masonry.cols = Math.floor((containerWidth + a) / this.masonry.columnWidth);
935
- this.masonry.cols = Math.max(this.masonry.cols, 1)
936
- };
937
- jQuery.Isotope.prototype._masonryReset = function() {
938
- this.masonry = {};
939
- this._getMasonryGutterColumns();
940
- var a = this.masonry.cols;
941
- this.masonry.colYs = [];
942
- while (a--) {
943
- this.masonry.colYs.push(0)
944
- }
945
- };
946
- jQuery.Isotope.prototype._masonryResizeChanged = function() {
947
- var a = this.masonry.cols;
948
- this._getMasonryGutterColumns();
949
- return (this.masonry.cols !== a)
950
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Enviratope PACKAGED v2.2.2
3
+ *
4
+ * Licensed GPLv3 for open source use
5
+ * or Enviratope Commercial License for commercial use
6
+ *
7
+ * http://enviratope.metafizzy.co
8
+ * Copyright 2015 Metafizzy
9
+ */
10
+
11
+ /**
12
+ * Bridget makes jQuery widgets
13
+ * v1.1.0
14
+ * MIT license
15
+ */
16
+
17
+ ( function( window ) {
18
+
19
+
20
+
21
+ // -------------------------- utils -------------------------- //
22
+
23
+ var slice = Array.prototype.slice;
24
+
25
+ function noop() {}
26
+
27
+ // -------------------------- definition -------------------------- //
28
+
29
+ function defineBridget( $ ) {
30
+
31
+ // bail if no jQuery
32
+ if ( !$ ) {
33
+ return;
34
+ }
35
+
36
+ // -------------------------- addOptionMethod -------------------------- //
37
+
38
+ /**
39
+ * adds option method -> $().plugin('option', {...})
40
+ * @param {Function} PluginClass - constructor class
41
+ */
42
+ function addOptionMethod( PluginClass ) {
43
+ // don't overwrite original option method
44
+ if ( PluginClass.prototype.option ) {
45
+ return;
46
+ }
47
+
48
+ // option setter
49
+ PluginClass.prototype.option = function( opts ) {
50
+ // bail out if not an object
51
+ if ( !$.isPlainObject( opts ) ){
52
+ return;
53
+ }
54
+ this.options = $.extend( true, this.options, opts );
55
+ };
56
+ }
57
+
58
+ // -------------------------- plugin bridge -------------------------- //
59
+
60
+ // helper function for logging errors
61
+ // $.error breaks jQuery chaining
62
+ var logError = typeof console === 'undefined' ? noop :
63
+ function( message ) {
64
+ console.error( message );
65
+ };
66
+
67
+ /**
68
+ * jQuery plugin bridge, access methods like $elem.plugin('method')
69
+ * @param {String} namespace - plugin name
70
+ * @param {Function} PluginClass - constructor class
71
+ */
72
+ function bridge( namespace, PluginClass ) {
73
+ // add to jQuery fn namespace
74
+ $.fn[ namespace ] = function( options ) {
75
+ if ( typeof options === 'string' ) {
76
+ // call plugin method when first argument is a string
77
+ // get arguments for method
78
+ var args = slice.call( arguments, 1 );
79
+
80
+ for ( var i=0, len = this.length; i < len; i++ ) {
81
+ var elem = this[i];
82
+ var instance = $.data( elem, namespace );
83
+ if ( !instance ) {
84
+ logError( "cannot call methods on " + namespace + " prior to initialization; " +
85
+ "attempted to call '" + options + "'" );
86
+ continue;
87
  }
88
+ if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) {
89
+ logError( "no such method '" + options + "' for " + namespace + " instance" );
90
+ continue;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  }
92
+
93
+ // trigger method with arguments
94
+ var returnValue = instance[ options ].apply( instance, args );
95
+
96
+ // break look and return first value if provided
97
+ if ( returnValue !== undefined ) {
98
+ return returnValue;
99
  }
100
+ }
101
+ // return this if no return value
102
+ return this;
103
  } else {
104
+ return this.each( function() {
105
+ var instance = $.data( this, namespace );
106
+ if ( instance ) {
107
+ // apply options & init
108
+ instance.option( options );
109
+ instance._init();
110
+ } else {
111
+ // initialize new instance
112
+ instance = new PluginClass( this, options );
113
+ $.data( this, namespace, instance );
114
  }
115
+ });
116
+ }
117
+ };
118
+
119
+ }
120
+
121
+ // -------------------------- bridget -------------------------- //
122
+
123
+ /**
124
+ * converts a Prototypical class into a proper jQuery plugin
125
+ * the class must have a ._init method
126
+ * @param {String} namespace - plugin name, used in $().pluginName
127
+ * @param {Function} PluginClass - constructor class
128
+ */
129
+ $.bridget = function( namespace, PluginClass ) {
130
+ addOptionMethod( PluginClass );
131
+ bridge( namespace, PluginClass );
132
+ };
133
+
134
+ return $.bridget;
135
+
136
+ }
137
+
138
+ // transport
139
+ if ( typeof define === 'function' && define.amd ) {
140
+ // AMD
141
+ define( 'jquery-bridget/jquery.bridget',[ 'jquery' ], defineBridget );
142
+ } else if ( typeof exports === 'object' ) {
143
+ defineBridget( require('jquery') );
144
+ } else {
145
+ // get jquery from browser global
146
+ defineBridget( window.jQuery );
147
+ }
148
+
149
+ })( window );
150
+
151
+ /*!
152
+ * eventie v1.0.6
153
+ * event binding helper
154
+ * eventie.bind( elem, 'click', myFn )
155
+ * eventie.unbind( elem, 'click', myFn )
156
+ * MIT license
157
+ */
158
+
159
+ /*jshint browser: true, undef: true, unused: true */
160
+ /*global define: false, module: false */
161
+
162
+ ( function( window ) {
163
+
164
+
165
+
166
+ var docElem = document.documentElement;
167
+
168
+ var bind = function() {};
169
+
170
+ function getIEEvent( obj ) {
171
+ var event = window.event;
172
+ // add event.target
173
+ event.target = event.target || event.srcElement || obj;
174
+ return event;
175
+ }
176
+
177
+ if ( docElem.addEventListener ) {
178
+ bind = function( obj, type, fn ) {
179
+ obj.addEventListener( type, fn, false );
180
+ };
181
+ } else if ( docElem.attachEvent ) {
182
+ bind = function( obj, type, fn ) {
183
+ obj[ type + fn ] = fn.handleEvent ?
184
+ function() {
185
+ var event = getIEEvent( obj );
186
+ fn.handleEvent.call( fn, event );
187
+ } :
188
+ function() {
189
+ var event = getIEEvent( obj );
190
+ fn.call( obj, event );
191
+ };
192
+ obj.attachEvent( "on" + type, obj[ type + fn ] );
193
+ };
194
+ }
195
+
196
+ var unbind = function() {};
197
+
198
+ if ( docElem.removeEventListener ) {
199
+ unbind = function( obj, type, fn ) {
200
+ obj.removeEventListener( type, fn, false );
201
+ };
202
+ } else if ( docElem.detachEvent ) {
203
+ unbind = function( obj, type, fn ) {
204
+ obj.detachEvent( "on" + type, obj[ type + fn ] );
205
+ try {
206
+ delete obj[ type + fn ];
207
+ } catch ( err ) {
208
+ // can't delete window object properties
209
+ obj[ type + fn ] = undefined;
210
+ }
211
+ };
212
+ }
213
+
214
+ var eventie = {
215
+ bind: bind,
216
+ unbind: unbind
217
+ };
218
+
219
+ // ----- module definition ----- //
220
+
221
+ if ( typeof define === 'function' && define.amd ) {
222
+ // AMD
223
+ define( 'eventie/eventie',eventie );
224
+ } else if ( typeof exports === 'object' ) {
225
+ // CommonJS
226
+ module.exports = eventie;
227
+ } else {
228
+ // browser global
229
+ window.eventie = eventie;
230
+ }
231
+
232
+ })( window );
233
+
234
+ /*!
235
+ * EventEmitter v4.2.11 - git.io/ee
236
+ * Unlicense - http://unlicense.org/
237
+ * Oliver Caldwell - http://oli.me.uk/
238
+ * @preserve
239
+ */
240
+
241
+ ;(function () {
242
+ 'use strict';
243
+
244
+ /**
245
+ * Class for managing events.
246
+ * Can be extended to provide event functionality in other classes.
247
+ *
248
+ * @class EventEmitter Manages event registering and emitting.
249
+ */
250
+ function EventEmitter() {}
251
+
252
+ // Shortcuts to improve speed and size
253
+ var proto = EventEmitter.prototype;
254
+ var exports = this;
255
+ var originalGlobalValue = exports.EventEmitter;
256
+
257
+ /**
258
+ * Finds the index of the listener for the event in its storage array.
259
+ *
260
+ * @param {Function[]} listeners Array of listeners to search through.
261
+ * @param {Function} listener Method to look for.
262
+ * @return {Number} Index of the specified listener, -1 if not found
263
+ * @api private
264
+ */
265
+ function indexOfListener(listeners, listener) {
266
+ var i = listeners.length;
267
+ while (i--) {
268
+ if (listeners[i].listener === listener) {
269
+ return i;
270
  }
271
+ }
272
+
273
+ return -1;
274
+ }
275
+
276
+ /**
277
+ * Alias a method while keeping the context correct, to allow for overwriting of target method.
278
+ *
279
+ * @param {String} name The name of the target method.
280
+ * @return {Function} The aliased method
281
+ * @api private
282
+ */
283
+ function alias(name) {
284
+ return function aliasClosure() {
285
+ return this[name].apply(this, arguments);
286
  };
287
+ }
288
+
289
+ /**
290
+ * Returns the listener array for the specified event.
291
+ * Will initialise the event object and listener arrays if required.
292
+ * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
293
+ * Each property in the object response is an array of listener functions.
294
+ *
295
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
296
+ * @return {Function[]|Object} All listener functions for the event.
297
+ */
298
+ proto.getListeners = function getListeners(evt) {
299
+ var events = this._getEvents();
300
+ var response;
301
+ var key;
302
+
303
+ // Return a concatenated array of all matching events if
304
+ // the selector is a regular expression.
305
+ if (evt instanceof RegExp) {
306
+ response = {};
307
+ for (key in events) {
308
+ if (events.hasOwnProperty(key) && evt.test(key)) {
309
+ response[key] = events[key];
310
+ }
311
  }
312
  }
313
+ else {
314
+ response = events[evt] || (events[evt] = []);
315
+ }
316
+
317
+ return response;
318
+ };
319
+
320
+ /**
321
+ * Takes a list of listener objects and flattens it into a list of listener functions.
322
+ *
323
+ * @param {Object[]} listeners Raw listener objects.
324
+ * @return {Function[]} Just the listener functions.
325
+ */
326
+ proto.flattenListeners = function flattenListeners(listeners) {
327
+ var flatListeners = [];
328
+ var i;
329
+
330
+ for (i = 0; i < listeners.length; i += 1) {
331
+ flatListeners.push(listeners[i].listener);
332
+ }
333
+
334
+ return flatListeners;
335
+ };
336
+
337
+ /**
338
+ * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
339
+ *
340
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
341
+ * @return {Object} All listener functions for an event in an object.
342
+ */
343
+ proto.getListenersAsObject = function getListenersAsObject(evt) {
344
+ var listeners = this.getListeners(evt);
345
+ var response;
346
+
347
+ if (listeners instanceof Array) {
348
+ response = {};
349
+ response[evt] = listeners;
350
+ }
351
+
352
+ return response || listeners;
353
+ };
354
+
355
+ /**
356
+ * Adds a listener function to the specified event.
357
+ * The listener will not be added if it is a duplicate.
358
+ * If the listener returns true then it will be removed after it is called.
359
+ * If you pass a regular expression as the event name then the listener will be added to all events that match it.
360
+ *
361
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
362
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
363
+ * @return {Object} Current instance of EventEmitter for chaining.
364
+ */
365
+ proto.addListener = function addListener(evt, listener) {
366
+ var listeners = this.getListenersAsObject(evt);
367
+ var listenerIsWrapped = typeof listener === 'object';
368
+ var key;
369
+
370
+ for (key in listeners) {
371
+ if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
372
+ listeners[key].push(listenerIsWrapped ? listener : {
373
+ listener: listener,
374
+ once: false
375
+ });
376
  }
 
 
 
377
  }
378
+
379
+ return this;
380
  };
381
+
382
+ /**
383
+ * Alias of addListener
384
+ */
385
+ proto.on = alias('addListener');
386
+
387
+ /**
388
+ * Semi-alias of addListener. It will add a listener that will be
389
+ * automatically removed after its first execution.
390
+ *
391
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
392
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
393
+ * @return {Object} Current instance of EventEmitter for chaining.
394
+ */
395
+ proto.addOnceListener = function addOnceListener(evt, listener) {
396
+ return this.addListener(evt, {
397
+ listener: listener,
398
+ once: true
399
+ });
400
  };
401
+
402
+ /**
403
+ * Alias of addOnceListener.
404
+ */
405
+ proto.once = alias('addOnceListener');
406
+
407
+ /**
408
+ * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
409
+ * You need to tell it what event names should be matched by a regex.
410
+ *
411
+ * @param {String} evt Name of the event to create.
412
+ * @return {Object} Current instance of EventEmitter for chaining.
413
+ */
414
+ proto.defineEvent = function defineEvent(evt) {
415
+ this.getListeners(evt);
416
+ return this;
417
  };
418
+
419
+ /**
420
+ * Uses defineEvent to define multiple events.
421
+ *
422
+ * @param {String[]} evts An array of event names to define.
423
+ * @return {Object} Current instance of EventEmitter for chaining.
424
+ */
425
+ proto.defineEvents = function defineEvents(evts) {
426
+ for (var i = 0; i < evts.length; i += 1) {
427
+ this.defineEvent(evts[i]);
428
+ }
429
+ return this;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
430
  };
431
+
432
+ /**
433
+ * Removes a listener function from the specified event.
434
+ * When passed a regular expression as the event name, it will remove the listener from all events that match it.
435
+ *
436
+ * @param {String|RegExp} evt Name of the event to remove the listener from.
437
+ * @param {Function} listener Method to remove from the event.
438
+ * @return {Object} Current instance of EventEmitter for chaining.
439
+ */
440
+ proto.removeListener = function removeListener(evt, listener) {
441
+ var listeners = this.getListenersAsObject(evt);
442
+ var index;
443
+ var key;
444
+
445
+ for (key in listeners) {
446
+ if (listeners.hasOwnProperty(key)) {
447
+ index = indexOfListener(listeners[key], listener);
448
+
449
+ if (index !== -1) {
450
+ listeners[key].splice(index, 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
451
  }
452
  }
453
+ }
454
+
455
+ return this;
456
+ };
457
+
458
+ /**
459
+ * Alias of removeListener
460
+ */
461
+ proto.off = alias('removeListener');
462
+
463
+ /**
464
+ * Adds listeners in bulk using the manipulateListeners method.
465
+ * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
466
+ * You can also pass it a regular expression to add the array of listeners to all events that match it.
467
+ * Yeah, this function does quite a bit. That's probably a bad thing.
468
+ *
469
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
470
+ * @param {Function[]} [listeners] An optional array of listener functions to add.
471
+ * @return {Object} Current instance of EventEmitter for chaining.
472
+ */
473
+ proto.addListeners = function addListeners(evt, listeners) {
474
+ // Pass through to manipulateListeners
475
+ return this.manipulateListeners(false, evt, listeners);
476
+ };
477
+
478
+ /**
479
+ * Removes listeners in bulk using the manipulateListeners method.
480
+ * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
481
+ * You can also pass it an event name and an array of listeners to be removed.
482
+ * You can also pass it a regular expression to remove the listeners from all events that match it.
483
+ *
484
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
485
+ * @param {Function[]} [listeners] An optional array of listener functions to remove.
486
+ * @return {Object} Current instance of EventEmitter for chaining.
487
+ */
488
+ proto.removeListeners = function removeListeners(evt, listeners) {
489
+ // Pass through to manipulateListeners
490
+ return this.manipulateListeners(true, evt, listeners);
491
+ };
492
+
493
+ /**
494
+ * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
495
+ * The first argument will determine if the listeners are removed (true) or added (false).
496
+ * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
497
+ * You can also pass it an event name and an array of listeners to be added/removed.
498
+ * You can also pass it a regular expression to manipulate the listeners of all events that match it.
499
+ *
500
+ * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
501
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
502
+ * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
503
+ * @return {Object} Current instance of EventEmitter for chaining.
504
+ */
505
+ proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
506
+ var i;
507
+ var value;
508
+ var single = remove ? this.removeListener : this.addListener;
509
+ var multiple = remove ? this.removeListeners : this.addListeners;
510
+
511
+ // If evt is an object then pass each of its properties to this method
512
+ if (typeof evt === 'object' && !(evt instanceof RegExp)) {
513
+ for (i in evt) {
514
+ if (evt.hasOwnProperty(i) && (value = evt[i])) {
515
+ // Pass the single listener straight through to the singular method
516
+ if (typeof value === 'function') {
517
+ single.call(this, i, value);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
518
  }
519
+ else {
520
+ // Otherwise pass back to the multiple function
521
+ multiple.call(this, i, value);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
522
  }
523
  }
524
  }
525
+ }
526
+ else {
527
+ // So evt must be a string
528
+ // And listeners must be an array of listeners
529
+ // Loop over it and pass each one to the multiple method
530
+ i = listeners.length;
531
+ while (i--) {
532
+ single.call(this, evt, listeners[i]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
533
  }
534
+ }
535
+
536
+ return this;
537
+ };
538
+
539
+ /**
540
+ * Removes all listeners from a specified event.
541
+ * If you do not specify an event then all listeners will be removed.
542
+ * That means every event will be emptied.
543
+ * You can also pass a regex to remove all events that match it.
544
+ *
545
+ * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
546
+ * @return {Object} Current instance of EventEmitter for chaining.
547
+ */
548
+ proto.removeEvent = function removeEvent(evt) {
549
+ var type = typeof evt;
550
+ var events = this._getEvents();
551
+ var key;
552
+
553
+ // Remove different things depending on the state of evt
554
+ if (type === 'string') {
555
+ // Remove all listeners for the specified event
556
+ delete events[evt];
557
+ }
558
+ else if (evt instanceof RegExp) {
559
+ // Remove all events matching the regex.
560
+ for (key in events) {
561
+ if (events.hasOwnProperty(key) && evt.test(key)) {
562
+ delete events[key];
563
  }
 
 
 
 
564
  }
565
+ }
566
+ else {
567
+ // Remove all listeners in all events
568
+ delete this._events;
569
+ }
570
+
571
+ return this;
572
+ };
573
+
574
+ /**
575
+ * Alias of removeEvent.
576
+ *
577
+ * Added to mirror the node API.
578
+ */
579
+ proto.removeAllListeners = alias('removeEvent');
580
+
581
+ /**
582
+ * Emits an event of your choice.
583
+ * When emitted, every listener attached to that event will be executed.
584
+ * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
585
+ * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
586
+ * So they will not arrive within the array on the other side, they will be separate.
587
+ * You can also pass a regular expression to emit to all events that match it.
588
+ *
589
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
590
+ * @param {Array} [args] Optional array of arguments to be passed to each listener.
591
+ * @return {Object} Current instance of EventEmitter for chaining.
592
+ */
593
+ proto.emitEvent = function emitEvent(evt, args) {
594
+ var listeners = this.getListenersAsObject(evt);
595
+ var listener;
596
+ var i;
597
+ var key;
598
+ var response;
599
+
600
+ for (key in listeners) {
601
+ if (listeners.hasOwnProperty(key)) {
602
+ i = listeners[key].length;
603
+
604
+ while (i--) {
605
+ // If the listener returns true then it shall be removed from the event
606
+ // The function is executed either with a basic call or an apply if there is an args array
607
+ listener = listeners[key][i];
608
+
609
+ if (listener.once === true) {
610
+ this.removeListener(evt, listener.listener);
 
611
  }
612
+
613
+ response = listener.listener.apply(this, args || []);
614
+
615
+ if (response === this._getOnceReturnValue()) {
616
+ this.removeListener(evt, listener.listener);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
617
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
618
  }
 
 
 
 
 
 
 
 
619
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
620
  }
621
 
622
+ return this;
623
+ };
624
+
625
+ /**
626
+ * Alias of emitEvent
627
+ */
628
+ proto.trigger = alias('emitEvent');
629
+
630
+ /**
631
+ * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
632
+ * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
633
+ *
634
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
635
+ * @param {...*} Optional additional arguments to be passed to each listener.
636
+ * @return {Object} Current instance of EventEmitter for chaining.
637
+ */
638
+ proto.emit = function emit(evt) {
639
+ var args = Array.prototype.slice.call(arguments, 1);
640
+ return this.emitEvent(evt, args);
641
+ };
642
+
643
+ /**
644
+ * Sets the current value to check against when executing listeners. If a
645
+ * listeners return value matches the one set here then it will be removed
646
+ * after execution. This value defaults to true.
647
+ *
648
+ * @param {*} value The new value to check for when executing listeners.
649
+ * @return {Object} Current instance of EventEmitter for chaining.
650
+ */
651
+ proto.setOnceReturnValue = function setOnceReturnValue(value) {
652
+ this._onceReturnValue = value;
653
+ return this;
654
+ };
655
+
656
+ /**
657
+ * Fetches the current value to check against when executing listeners. If
658
+ * the listeners return value matches this one then it should be removed
659
+ * automatically. It will return true by default.
660
+ *
661
+ * @return {*|Boolean} The current value to check for or the default, true.
662
+ * @api private
663
+ */
664
+ proto._getOnceReturnValue = function _getOnceReturnValue() {
665
+ if (this.hasOwnProperty('_onceReturnValue')) {
666
+ return this._onceReturnValue;
667
  }
668
+ else {
669
+ return true;
670
  }
 
 
 
 
 
 
671
  };
672
+
673
+ /**
674
+ * Fetches the events object and creates one if required.
675
+ *
676
+ * @return {Object} The events storage object.
677
+ * @api private
678
+ */
679
+ proto._getEvents = function _getEvents() {
680
+ return this._events || (this._events = {});
681
  };
682
+
683
+ /**
684
+ * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
685
+ *
686
+ * @return {Function} Non conflicting EventEmitter class.
687
+ */
688
+ EventEmitter.noConflict = function noConflict() {
689
+ exports.EventEmitter = originalGlobalValue;
690
+ return EventEmitter;
691
+ };
692
+
693
+ // Expose the class either via AMD, CommonJS or the global object
694
+ if (typeof define === 'function' && define.amd) {
695
+ define('eventEmitter/EventEmitter',[],function () {
696
+ return EventEmitter;
697
+ });
698
+ }
699
+ else if (typeof module === 'object' && module.exports){
700
+ module.exports = EventEmitter;
701
+ }
702
+ else {
703
+ exports.EventEmitter = EventEmitter;
704
+ }
705
+ }.call(this));
706
+
707
+ /*!
708
+ * getStyleProperty v1.0.4
709
+ * original by kangax
710
+ * http://perfectionkills.com/feature-testing-css-properties/
711
+ * MIT license
712
+ */
713
+
714
+ /*jshint browser: true, strict: true, undef: true */
715
+ /*global define: false, exports: false, module: false */
716
+
717
+ ( function( window ) {
718
+
719
+
720
+
721
+ var prefixes = 'Webkit Moz ms Ms O'.split(' ');
722
+ var docElemStyle = document.documentElement.style;
723
+
724
+ function getStyleProperty( propName ) {
725
+ if ( !propName ) {
726
+ return;
727
+ }
728
+
729
+ // test standard property first
730
+ if ( typeof docElemStyle[ propName ] === 'string' ) {
731
+ return propName;
732
+ }
733
+
734
+ // capitalize
735
+ propName = propName.charAt(0).toUpperCase() + propName.slice(1);
736
+
737
+ // test vendor specific properties
738
+ var prefixed;
739
+ for ( var i=0, len = prefixes.length; i < len; i++ ) {
740
+ prefixed = prefixes[i] + propName;
741
+ if ( typeof docElemStyle[ prefixed ] === 'string' ) {
742
+ return prefixed;
743
+ }
744
+ }
745
+ }
746
+
747
+ // transport
748
+ if ( typeof define === 'function' && define.amd ) {
749
+ // AMD
750
+ define( 'get-style-property/get-style-property',[],function() {
751
+ return getStyleProperty;
752
+ });
753
+ } else if ( typeof exports === 'object' ) {
754
+ // CommonJS for Component
755
+ module.exports = getStyleProperty;
756
+ } else {
757
+ // browser global
758
+ window.getStyleProperty = getStyleProperty;
759
+ }
760
+
761
+ })( window );
762
+
763
+ /*!
764
+ * getSize v1.2.2
765
+ * measure size of elements
766
+ * MIT license
767
+ */
768
+
769
+ /*jshint browser: true, strict: true, undef: true, unused: true */
770
+ /*global define: false, exports: false, require: false, module: false, console: false */
771
+
772
+ ( function( window, undefined ) {
773
+
774
+
775
+
776
+ // -------------------------- helpers -------------------------- //
777
+
778
+ // get a number from a string, not a percentage
779
+ function getStyleSize( value ) {
780
+ var num = parseFloat( value );
781
+ // not a percent like '100%', and a number
782
+ var isValid = value.indexOf('%') === -1 && !isNaN( num );
783
+ return isValid && num;
784
+ }
785
+
786
+ function noop() {}
787
+
788
+ var logError = typeof console === 'undefined' ? noop :
789
+ function( message ) {
790
+ console.error( message );
791
+ };
792
+
793
+ // -------------------------- measurements -------------------------- //
794
+
795
+ var measurements = [
796
+ 'paddingLeft',
797
+ 'paddingRight',
798
+ 'paddingTop',
799
+ 'paddingBottom',
800
+ 'marginLeft',
801
+ 'marginRight',
802
+ 'marginTop',
803
+ 'marginBottom',
804
+ 'borderLeftWidth',
805
+ 'borderRightWidth',
806
+ 'borderTopWidth',
807
+ 'borderBottomWidth'
808
+ ];
809
+
810
+ function getZeroSize() {
811
+ var size = {
812
+ width: 0,
813
+ height: 0,
814
+ innerWidth: 0,
815
+ innerHeight: 0,
816
+ outerWidth: 0,
817
+ outerHeight: 0
818
+ };
819
+ for ( var i=0, len = measurements.length; i < len; i++ ) {
820
+ var measurement = measurements[i];
821
+ size[ measurement ] = 0;
822
+ }
823
+ return size;
824
+ }
825
+
826
+
827
+
828
+ function defineGetSize( getStyleProperty ) {
829
+
830
+ // -------------------------- setup -------------------------- //
831
+
832
+ var isSetup = false;
833
+
834
+ var getStyle, boxSizingProp, isBoxSizeOuter;
835
+
836
+ /**
837
+ * setup vars and functions
838
+ * do it on initial getSize(), rather than on script load
839
+ * For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397
840
+ */
841
+ function setup() {
842
+ // setup once
843
+ if ( isSetup ) {
844
+ return;
845
+ }
846
+ isSetup = true;
847
+
848
+ var getComputedStyle = window.getComputedStyle;
849
+ getStyle = ( function() {
850
+ var getStyleFn = getComputedStyle ?
851
+ function( elem ) {
852
+ return getComputedStyle( elem, null );
853
+ } :
854
+ function( elem ) {
855
+ return elem.currentStyle;
856
+ };
857
+
858
+ return function getStyle( elem ) {
859
+ var style = getStyleFn( elem );
860
+ if ( !style ) {
861
+ logError( 'Style returned ' + style +
862
+ '. Are you running this code in a hidden iframe on Firefox? ' +
863
+ 'See http://bit.ly/getsizebug1' );
864
  }
865
+ return style;
866
+ };
867
+ })();
868
+
869
+ // -------------------------- box sizing -------------------------- //
870
+
871
+ boxSizingProp = getStyleProperty('boxSizing');
872
+
873
+ /**
874
+ * WebKit measures the outer-width on style.width on border-box elems
875
+ * IE & Firefox measures the inner-width
876
+ */
877
+ if ( boxSizingProp ) {
878
+ var div = document.createElement('div');
879
+ div.style.width = '200px';
880
+ div.style.padding = '1px 2px 3px 4px';
881
+ div.style.borderStyle = 'solid';
882
+ div.style.borderWidth = '1px 2px 3px 4px';
883
+ div.style[ boxSizingProp ] = 'border-box';
884
+
885
+ var body = document.body || document.documentElement;
886
+ body.appendChild( div );
887
+ var style = getStyle( div );
888
+
889
+ isBoxSizeOuter = getStyleSize( style.width ) === 200;
890
+ body.removeChild( div );
891
+ }
892
+
893
+ }
894
+
895
+ // -------------------------- getSize -------------------------- //
896
+
897
+ function getSize( elem ) {
898
+ setup();
899
+
900
+ // use querySeletor if elem is string
901
+ if ( typeof elem === 'string' ) {
902
+ elem = document.querySelector( elem );
903
+ }
904
+
905
+ // do not proceed on non-objects
906
+ if ( !elem || typeof elem !== 'object' || !elem.nodeType ) {
907
+ return;
908
+ }
909
+
910
+ var style = getStyle( elem );
911
+
912
+ // if hidden, everything is 0
913
+ if ( style.display === 'none' ) {
914
+ return getZeroSize();
915
+ }
916
+
917
+ var size = {};
918
+ size.width = elem.offsetWidth;
919
+ size.height = elem.offsetHeight;
920
+
921
+ var isBorderBox = size.isBorderBox = !!( boxSizingProp &&
922
+ style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' );
923
+
924
+ // get all measurements
925
+ for ( var i=0, len = measurements.length; i < len; i++ ) {
926
+ var measurement = measurements[i];
927
+ var value = style[ measurement ];
928
+ value = mungeNonPixel( elem, value );
929
+ var num = parseFloat( value );
930
+ // any 'auto', 'medium' value will be 0
931
+ size[ measurement ] = !isNaN( num ) ? num : 0;
932
+ }
933
+
934
+ var paddingWidth = size.paddingLeft + size.paddingRight;
935
+ var paddingHeight = size.paddingTop + size.paddingBottom;
936
+ var marginWidth = size.marginLeft + size.marginRight;
937
+ var marginHeight = size.marginTop + size.marginBottom;
938
+ var borderWidth = size.borderLeftWidth + size.borderRightWidth;
939
+ var borderHeight = size.borderTopWidth + size.borderBottomWidth;
940
+
941
+ var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
942
+
943
+ // overwrite width and height if we can get it from style
944
+ var styleWidth = getStyleSize( style.width );
945
+ if ( styleWidth !== false ) {
946
+ size.width = styleWidth +
947
+ // add padding and border unless it's already including it
948
+ ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
949
+ }
950
+
951
+ var styleHeight = getStyleSize( style.height );
952
+ if ( styleHeight !== false ) {
953
+ size.height = styleHeight +
954
+ // add padding and border unless it's already including it
955
+ ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
956
+ }
957
+
958
+ size.innerWidth = size.width - ( paddingWidth + borderWidth );
959
+ size.innerHeight = size.height - ( paddingHeight + borderHeight );
960
+
961
+ size.outerWidth = size.width + marginWidth;
962
+ size.outerHeight = size.height + marginHeight;
963
+
964
+ return size;
965
+ }
966
+
967
+ // IE8 returns percent values, not pixels
968
+ // taken from jQuery's curCSS
969
+ function mungeNonPixel( elem, value ) {
970
+ // IE8 and has percent value
971
+ if ( window.getComputedStyle || value.indexOf('%') === -1 ) {
972
+ return value;
973
+ }
974
+ var style = elem.style;
975
+ // Remember the original values
976
+ var left = style.left;
977
+ var rs = elem.runtimeStyle;
978
+ var rsLeft = rs && rs.left;
979
+
980
+ // Put in the new values to get a computed value out
981
+ if ( rsLeft ) {
982
+ rs.left = elem.currentStyle.left;
983
+ }
984
+ style.left = value;
985
+ value = style.pixelLeft;
986
+
987
+ // Revert the changed values
988
+ style.left = left;
989
+ if ( rsLeft ) {
990
+ rs.left = rsLeft;
991
+ }
992
+
993
+ return value;
994
+ }
995
+
996
+ return getSize;
997
+
998
+ }
999
+
1000
+ // transport
1001
+ if ( typeof define === 'function' && define.amd ) {
1002
+ // AMD for RequireJS
1003
+ define( 'get-size/get-size',[ 'get-style-property/get-style-property' ], defineGetSize );
1004
+ } else if ( typeof exports === 'object' ) {
1005
+ // CommonJS for Component
1006
+ module.exports = defineGetSize( require('desandro-get-style-property') );
1007
+ } else {
1008
+ // browser global
1009
+ window.getSize = defineGetSize( window.getStyleProperty );
1010
+ }
1011
+
1012
+ })( window );
1013
+
1014
+ /*!
1015
+ * docReady v1.0.4
1016
+ * Cross browser DOMContentLoaded event emitter
1017
+ * MIT license
1018
+ */
1019
+
1020
+ /*jshint browser: true, strict: true, undef: true, unused: true*/
1021
+ /*global define: false, require: false, module: false */
1022
+
1023
+ ( function( window ) {
1024
+
1025
+
1026
+
1027
+ var document = window.document;
1028
+ // collection of functions to be triggered on ready
1029
+ var queue = [];
1030
+
1031
+ function docReady( fn ) {
1032
+ // throw out non-functions
1033
+ if ( typeof fn !== 'function' ) {
1034
+ return;
1035
+ }
1036
+
1037
+ if ( docReady.isReady ) {
1038
+ // ready now, hit it
1039
+ fn();
1040
+ } else {
1041
+ // queue function when ready
1042
+ queue.push( fn );
1043
+ }
1044
+ }
1045
+
1046
+ docReady.isReady = false;
1047
+
1048
+ // triggered on various doc ready events
1049
+ function onReady( event ) {
1050
+ // bail if already triggered or IE8 document is not ready just yet
1051
+ var isIE8NotReady = event.type === 'readystatechange' && document.readyState !== 'complete';
1052
+ if ( docReady.isReady || isIE8NotReady ) {
1053
+ return;
1054
+ }
1055
+
1056
+ trigger();
1057
+ }
1058
+
1059
+ function trigger() {
1060
+ docReady.isReady = true;
1061
+ // process queue
1062
+ for ( var i=0, len = queue.length; i < len; i++ ) {
1063
+ var fn = queue[i];
1064
+ fn();
1065
+ }
1066
+ }
1067
+
1068
+ function defineDocReady( eventie ) {
1069
+ // trigger ready if page is ready
1070
+ if ( document.readyState === 'complete' ) {
1071
+ trigger();
1072
+ } else {
1073
+ // listen for events
1074
+ eventie.bind( document, 'DOMContentLoaded', onReady );
1075
+ eventie.bind( document, 'readystatechange', onReady );
1076
+ eventie.bind( window, 'load', onReady );
1077
+ }
1078
+
1079
+ return docReady;
1080
+ }
1081
+
1082
+ // transport
1083
+ if ( typeof define === 'function' && define.amd ) {
1084
+ // AMD
1085
+ define( 'doc-ready/doc-ready',[ 'eventie/eventie' ], defineDocReady );
1086
+ } else if ( typeof exports === 'object' ) {
1087
+ module.exports = defineDocReady( require('eventie') );
1088
+ } else {
1089
+ // browser global
1090
+ window.docReady = defineDocReady( window.eventie );
1091
+ }
1092
+
1093
+ })( window );
1094
+
1095
+ /**
1096
+ * matchesSelector v1.0.3
1097
+ * matchesSelector( element, '.selector' )
1098
+ * MIT license
1099
+ */
1100
+
1101
+ /*jshint browser: true, strict: true, undef: true, unused: true */
1102
+ /*global define: false, module: false */
1103
+
1104
+ ( function( ElemProto ) {
1105
+
1106
+ 'use strict';
1107
+
1108
+ var matchesMethod = ( function() {
1109
+ // check for the standard method name first
1110
+ if ( ElemProto.matches ) {
1111
+ return 'matches';
1112
+ }
1113
+ // check un-prefixed
1114
+ if ( ElemProto.matchesSelector ) {
1115
+ return 'matchesSelector';
1116
+ }
1117
+ // check vendor prefixes
1118
+ var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];
1119
+
1120
+ for ( var i=0, len = prefixes.length; i < len; i++ ) {
1121
+ var prefix = prefixes[i];
1122
+ var method = prefix + 'MatchesSelector';
1123
+ if ( ElemProto[ method ] ) {
1124
+ return method;
1125
+ }
1126
+ }
1127
+ })();
1128
+
1129
+ // ----- match ----- //
1130
+
1131
+ function match( elem, selector ) {
1132
+ return elem[ matchesMethod ]( selector );
1133
+ }
1134
+
1135
+ // ----- appendToFragment ----- //
1136
+
1137
+ function checkParent( elem ) {
1138
+ // not needed if already has parent
1139
+ if ( elem.parentNode ) {
1140
+ return;
1141
+ }
1142
+ var fragment = document.createDocumentFragment();
1143
+ fragment.appendChild( elem );
1144
+ }
1145
+
1146
+ // ----- query ----- //
1147
+
1148
+ // fall back to using QSA
1149
+ // thx @jonathantneal https://gist.github.com/3062955
1150
+ function query( elem, selector ) {
1151
+ // append to fragment if no parent
1152
+ checkParent( elem );
1153
+
1154
+ // match elem with all selected elems of parent
1155
+ var elems = elem.parentNode.querySelectorAll( selector );
1156
+ for ( var i=0, len = elems.length; i < len; i++ ) {
1157
+ // return true if match
1158
+ if ( elems[i] === elem ) {
1159
+ return true;
1160
+ }
1161
+ }
1162
+ // otherwise return false
1163
+ return false;
1164
+ }
1165
+
1166
+ // ----- matchChild ----- //
1167
+
1168
+ function matchChild( elem, selector ) {
1169
+ checkParent( elem );
1170
+ return match( elem, selector );
1171
+ }
1172
+
1173
+ // ----- matchesSelector ----- //
1174
+
1175
+ var matchesSelector;
1176
+
1177
+ if ( matchesMethod ) {
1178
+ // IE9 supports matchesSelector, but doesn't work on orphaned elems
1179
+ // check for that
1180
+ var div = document.createElement('div');
1181
+ var supportsOrphans = match( div, 'div' );
1182
+ matchesSelector = supportsOrphans ? match : matchChild;
1183
+ } else {
1184
+ matchesSelector = query;
1185
+ }
1186
+
1187
+ // transport
1188
+ if ( typeof define === 'function' && define.amd ) {
1189
+ // AMD
1190
+ define( 'matches-selector/matches-selector',[],function() {
1191
+ return matchesSelector;
1192
+ });
1193
+ } else if ( typeof exports === 'object' ) {
1194
+ module.exports = matchesSelector;
1195
+ }
1196
+ else {
1197
+ // browser global
1198
+ window.matchesSelector = matchesSelector;
1199
+ }
1200
+
1201
+ })( Element.prototype );
1202
+
1203
+ /**
1204
+ * Fizzy UI utils v1.0.1
1205
+ * MIT license
1206
+ */
1207
+
1208
+ /*jshint browser: true, undef: true, unused: true, strict: true */
1209
+
1210
+ ( function( window, factory ) {
1211
+ /*global define: false, module: false, require: false */
1212
+ 'use strict';
1213
+ // universal module definition
1214
+
1215
+ if ( typeof define == 'function' && define.amd ) {
1216
+ // AMD
1217
+ define( 'fizzy-ui-utils/utils',[
1218
+ 'doc-ready/doc-ready',
1219
+ 'matches-selector/matches-selector'
1220
+ ], function( docReady, matchesSelector ) {
1221
+ return factory( window, docReady, matchesSelector );
1222
+ });
1223
+ } else if ( typeof exports == 'object' ) {
1224
+ // CommonJS
1225
+ module.exports = factory(
1226
+ window,
1227
+ require('doc-ready'),
1228
+ require('desandro-matches-selector')
1229
+ );
1230
+ } else {
1231
+ // browser global
1232
+ window.fizzyUIUtils = factory(
1233
+ window,
1234
+ window.docReady,
1235
+ window.matchesSelector
1236
+ );
1237
+ }
1238
+
1239
+ }( window, function factory( window, docReady, matchesSelector ) {
1240
+
1241
+
1242
+
1243
+ var utils = {};
1244
+
1245
+ // ----- extend ----- //
1246
+
1247
+ // extends objects
1248
+ utils.extend = function( a, b ) {
1249
+ for ( var prop in b ) {
1250
+ a[ prop ] = b[ prop ];
1251
+ }
1252
+ return a;
1253
+ };
1254
+
1255
+ // ----- modulo ----- //
1256
+
1257
+ utils.modulo = function( num, div ) {
1258
+ return ( ( num % div ) + div ) % div;
1259
+ };
1260
+
1261
+ // ----- isArray ----- //
1262
+
1263
+ var objToString = Object.prototype.toString;
1264
+ utils.isArray = function( obj ) {
1265
+ return objToString.call( obj ) == '[object Array]';
1266
+ };
1267
+
1268
+ // ----- makeArray ----- //
1269
+
1270
+ // turn element or nodeList into an array
1271
+ utils.makeArray = function( obj ) {
1272
+ var ary = [];
1273
+ if ( utils.isArray( obj ) ) {
1274
+ // use object if already an array
1275
+ ary = obj;
1276
+ } else if ( obj && typeof obj.length == 'number' ) {
1277
+ // convert nodeList to array
1278
+ for ( var i=0, len = obj.length; i < len; i++ ) {
1279
+ ary.push( obj[i] );
1280
+ }
1281
+ } else {
1282
+ // array of single index
1283
+ ary.push( obj );
1284
+ }
1285
+ return ary;
1286
+ };
1287
+
1288
+ // ----- indexOf ----- //
1289
+
1290
+ // index of helper cause IE8
1291
+ utils.indexOf = Array.prototype.indexOf ? function( ary, obj ) {
1292
+ return ary.indexOf( obj );
1293
+ } : function( ary, obj ) {
1294
+ for ( var i=0, len = ary.length; i < len; i++ ) {
1295
+ if ( ary[i] === obj ) {
1296
+ return i;
1297
+ }
1298
+ }
1299
+ return -1;
1300
+ };
1301
+
1302
+ // ----- removeFrom ----- //
1303
+
1304
+ utils.removeFrom = function( ary, obj ) {
1305
+ var index = utils.indexOf( ary, obj );
1306
+ if ( index != -1 ) {
1307
+ ary.splice( index, 1 );
1308
+ }
1309
+ };
1310
+
1311
+ // ----- isElement ----- //
1312
+
1313
+ // http://stackoverflow.com/a/384380/182183
1314
+ utils.isElement = ( typeof HTMLElement == 'function' || typeof HTMLElement == 'object' ) ?
1315
+ function isElementDOM2( obj ) {
1316
+ return obj instanceof HTMLElement;
1317
+ } :
1318
+ function isElementQuirky( obj ) {
1319
+ return obj && typeof obj == 'object' &&
1320
+ obj.nodeType == 1 && typeof obj.nodeName == 'string';
1321
+ };
1322
+
1323
+ // ----- setText ----- //
1324
+
1325
+ utils.setText = ( function() {
1326
+ var setTextProperty;
1327
+ function setText( elem, text ) {
1328
+ // only check setTextProperty once
1329
+ setTextProperty = setTextProperty || ( document.documentElement.textContent !== undefined ? 'textContent' : 'innerText' );
1330
+ elem[ setTextProperty ] = text;
1331
+ }
1332
+ return setText;
1333
+ })();
1334
+
1335
+ // ----- getParent ----- //
1336
+
1337
+ utils.getParent = function( elem, selector ) {
1338
+ while ( elem != document.body ) {
1339
+ elem = elem.parentNode;
1340
+ if ( matchesSelector( elem, selector ) ) {
1341
+ return elem;
1342
+ }
1343
+ }
1344
+ };
1345
+
1346
+ // ----- getQueryElement ----- //
1347
+
1348
+ // use element as selector string
1349
+ utils.getQueryElement = function( elem ) {
1350
+ if ( typeof elem == 'string' ) {
1351
+ return document.querySelector( elem );
1352
+ }
1353
+ return elem;
1354
+ };
1355
+
1356
+ // ----- handleEvent ----- //
1357
+
1358
+ // enable .ontype to trigger from .addEventListener( elem, 'type' )
1359
+ utils.handleEvent = function( event ) {
1360
+ var method = 'on' + event.type;
1361
+ if ( this[ method ] ) {
1362
+ this[ method ]( event );
1363
+ }
1364
+ };
1365
+
1366
+ // ----- filterFindElements ----- //
1367
+
1368
+ utils.filterFindElements = function( elems, selector ) {
1369
+ // make array of elems
1370
+ elems = utils.makeArray( elems );
1371
+ var ffElems = [];
1372
+
1373
+ for ( var i=0, len = elems.length; i < len; i++ ) {
1374
+ var elem = elems[i];
1375
+ // check that elem is an actual element
1376
+ if ( !utils.isElement( elem ) ) {
1377
+ continue;
1378
+ }
1379
+ // filter & find items if we have a selector
1380
+ if ( selector ) {
1381
+ // filter siblings
1382
+ if ( matchesSelector( elem, selector ) ) {
1383
+ ffElems.push( elem );
1384
+ }
1385
+ // find children
1386
+ var childElems = elem.querySelectorAll( selector );
1387
+ // concat childElems to filterFound array
1388
+ for ( var j=0, jLen = childElems.length; j < jLen; j++ ) {
1389
+ ffElems.push( childElems[j] );
1390
+ }
1391
+ } else {
1392
+ ffElems.push( elem );
1393
+ }
1394
+ }
1395
+
1396
+ return ffElems;
1397
+ };
1398
+
1399
+ // ----- debounceMethod ----- //
1400
+
1401
+ utils.debounceMethod = function( _class, methodName, threshold ) {
1402
+ // original method
1403
+ var method = _class.prototype[ methodName ];
1404
+ var timeoutName = methodName + 'Timeout';
1405
+
1406
+ _class.prototype[ methodName ] = function() {
1407
+ var timeout = this[ timeoutName ];
1408
+ if ( timeout ) {
1409
+ clearTimeout( timeout );
1410
+ }
1411
+ var args = arguments;
1412
+
1413
+ var _this = this;
1414
+ this[ timeoutName ] = setTimeout( function() {
1415
+ method.apply( _this, args );
1416
+ delete _this[ timeoutName ];
1417
+ }, threshold || 100 );
1418
+ };
1419
+ };
1420
+
1421
+ // ----- htmlInit ----- //
1422
+
1423
+ // http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
1424
+ utils.toDashed = function( str ) {
1425
+ return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
1426
+ return $1 + '-' + $2;
1427
+ }).toLowerCase();
1428
+ };
1429
+
1430
+ var console = window.console;
1431
+ /**
1432
+ * allow user to initialize classes via .js-namespace class
1433
+ * htmlInit( Widget, 'widgetName' )
1434
+ * options are parsed from data-namespace-option attribute
1435
+ */
1436
+ utils.htmlInit = function( WidgetClass, namespace ) {
1437
+ docReady( function() {
1438
+ var dashedNamespace = utils.toDashed( namespace );
1439
+ var elems = document.querySelectorAll( '.js-' + dashedNamespace );
1440
+ var dataAttr = 'data-' + dashedNamespace + '-options';
1441
+
1442
+ for ( var i=0, len = elems.length; i < len; i++ ) {
1443
+ var elem = elems[i];
1444
+ var attr = elem.getAttribute( dataAttr );
1445
+ var options;
1446
+ try {
1447
+ options = attr && JSON.parse( attr );
1448
+ } catch ( error ) {
1449
+ // log error, do not initialize
1450
+ if ( console ) {
1451
+ console.error( 'Error parsing ' + dataAttr + ' on ' +
1452
+ elem.nodeName.toLowerCase() + ( elem.id ? '#' + elem.id : '' ) + ': ' +
1453
+ error );
1454
+ }
1455
+ continue;
1456
+ }
1457
+ // initialize
1458
+ var instance = new WidgetClass( elem, options );
1459
+ // make available via $().data('layoutname')
1460
+ var jQuery = window.jQuery;
1461
+ if ( jQuery ) {
1462
+ jQuery.data( elem, namespace, instance );
1463
+ }
1464
+ }
1465
+ });
1466
+ };
1467
+
1468
+ // ----- ----- //
1469
+
1470
+ return utils;
1471
+
1472
+ }));
1473
+
1474
+ /**
1475
+ * Outlayer Item
1476
+ */
1477
+
1478
+ ( function( window, factory ) {
1479
+ 'use strict';
1480
+ // universal module definition
1481
+ if ( typeof define === 'function' && define.amd ) {
1482
+ // AMD
1483
+ define( 'outlayer/item',[
1484
+ 'eventEmitter/EventEmitter',
1485
+ 'get-size/get-size',
1486
+ 'get-style-property/get-style-property',
1487
+ 'fizzy-ui-utils/utils'
1488
+ ],
1489
+ function( EventEmitter, getSize, getStyleProperty, utils ) {
1490
+ return factory( window, EventEmitter, getSize, getStyleProperty, utils );
1491
+ }
1492
+ );
1493
+ } else if (typeof exports === 'object') {
1494
+ // CommonJS
1495
+ module.exports = factory(
1496
+ window,
1497
+ require('wolfy87-eventemitter'),
1498
+ require('get-size'),
1499
+ require('desandro-get-style-property'),
1500
+ require('fizzy-ui-utils')
1501
+ );
1502
+ } else {
1503
+ // browser global
1504
+ window.Outlayer = {};
1505
+ window.Outlayer.Item = factory(
1506
+ window,
1507
+ window.EventEmitter,
1508
+ window.getSize,
1509
+ window.getStyleProperty,
1510
+ window.fizzyUIUtils
1511
+ );
1512
+ }
1513
+
1514
+ }( window, function factory( window, EventEmitter, getSize, getStyleProperty, utils ) {
1515
+ 'use strict';
1516
+
1517
+ // ----- helpers ----- //
1518
+
1519
+ var getComputedStyle = window.getComputedStyle;
1520
+ var getStyle = getComputedStyle ?
1521
+ function( elem ) {
1522
+ return getComputedStyle( elem, null );
1523
+ } :
1524
+ function( elem ) {
1525
+ return elem.currentStyle;
1526
+ };
1527
+
1528
+
1529
+ function isEmptyObj( obj ) {
1530
+ for ( var prop in obj ) {
1531
+ return false;
1532
+ }
1533
+ prop = null;
1534
+ return true;
1535
+ }
1536
+
1537
+ // -------------------------- CSS3 support -------------------------- //
1538
+
1539
+ var transitionProperty = getStyleProperty('transition');
1540
+ var transformProperty = getStyleProperty('transform');
1541
+ var supportsCSS3 = transitionProperty && transformProperty;
1542
+ var is3d = !!getStyleProperty('perspective');
1543
+
1544
+ var transitionEndEvent = {
1545
+ WebkitTransition: 'webkitTransitionEnd',
1546
+ MozTransition: 'transitionend',
1547
+ OTransition: 'otransitionend',
1548
+ transition: 'transitionend'
1549
+ }[ transitionProperty ];
1550
+
1551
+ // properties that could have vendor prefix
1552
+ var prefixableProperties = [
1553
+ 'transform',
1554
+ 'transition',
1555
+ 'transitionDuration',
1556
+ 'transitionProperty'
1557
+ ];
1558
+
1559
+ // cache all vendor properties
1560
+ var vendorProperties = ( function() {
1561
+ var cache = {};
1562
+ for ( var i=0, len = prefixableProperties.length; i < len; i++ ) {
1563
+ var prop = prefixableProperties[i];
1564
+ var supportedProp = getStyleProperty( prop );
1565
+ if ( supportedProp && supportedProp !== prop ) {
1566
+ cache[ prop ] = supportedProp;
1567
+ }
1568
+ }
1569
+ return cache;
1570
+ })();
1571
+
1572
+ // -------------------------- Item -------------------------- //
1573
+
1574
+ function Item( element, layout ) {
1575
+ if ( !element ) {
1576
+ return;
1577
+ }
1578
+
1579
+ this.element = element;
1580
+ // parent layout class, i.e. Masonry, Enviratope, or Packery
1581
+ this.layout = layout;
1582
+ this.position = {
1583
+ x: 0,
1584
+ y: 0
1585
+ };
1586
+
1587
+ this._create();
1588
+ }
1589
+
1590
+ // inherit EventEmitter
1591
+ utils.extend( Item.prototype, EventEmitter.prototype );
1592
+
1593
+ Item.prototype._create = function() {
1594
+ // transition objects
1595
+ this._transn = {
1596
+ ingProperties: {},
1597
+ clean: {},
1598
+ onEnd: {}
1599
+ };
1600
+
1601
+ this.css({
1602
+ position: 'absolute'
1603
+ });
1604
+ };
1605
+
1606
+ // trigger specified handler for event type
1607
+ Item.prototype.handleEvent = function( event ) {
1608
+ var method = 'on' + event.type;
1609
+ if ( this[ method ] ) {
1610
+ this[ method ]( event );
1611
+ }
1612
+ };
1613
+
1614
+ Item.prototype.getSize = function() {
1615
+ this.size = getSize( this.element );
1616
+ };
1617
+
1618
+ /**
1619
+ * apply CSS styles to element
1620
+ * @param {Object} style
1621
+ */
1622
+ Item.prototype.css = function( style ) {
1623
+ var elemStyle = this.element.style;
1624
+
1625
+ for ( var prop in style ) {
1626
+ // use vendor property if available
1627
+ var supportedProp = vendorProperties[ prop ] || prop;
1628
+ elemStyle[ supportedProp ] = style[ prop ];
1629
+ }
1630
+ };
1631
+
1632
+ // measure position, and sets it
1633
+ Item.prototype.getPosition = function() {
1634
+ var style = getStyle( this.element );
1635
+ var layoutOptions = this.layout.options;
1636
+ var isOriginLeft = layoutOptions.isOriginLeft;
1637
+ var isOriginTop = layoutOptions.isOriginTop;
1638
+ var xValue = style[ isOriginLeft ? 'left' : 'right' ];
1639
+ var yValue = style[ isOriginTop ? 'top' : 'bottom' ];
1640
+ // convert percent to pixels
1641
+ var layoutSize = this.layout.size;
1642
+ var x = xValue.indexOf('%') != -1 ?
1643
+ ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 );
1644
+ var y = yValue.indexOf('%') != -1 ?
1645
+ ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 );
1646
+
1647
+ // clean up 'auto' or other non-integer values
1648
+ x = isNaN( x ) ? 0 : x;
1649
+ y = isNaN( y ) ? 0 : y;
1650
+ // remove padding from measurement
1651
+ x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
1652
+ y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
1653
+
1654
+ this.position.x = x;
1655
+ this.position.y = y;
1656
+ };
1657
+
1658
+ // set settled position, apply padding
1659
+ Item.prototype.layoutPosition = function() {
1660
+ var layoutSize = this.layout.size;
1661
+ var layoutOptions = this.layout.options;
1662
+ var style = {};
1663
+
1664
+ // x
1665
+ var xPadding = layoutOptions.isOriginLeft ? 'paddingLeft' : 'paddingRight';
1666
+ var xProperty = layoutOptions.isOriginLeft ? 'left' : 'right';
1667
+ var xResetProperty = layoutOptions.isOriginLeft ? 'right' : 'left';
1668
+
1669
+ var x = this.position.x + layoutSize[ xPadding ];
1670
+ // set in percentage or pixels
1671
+ style[ xProperty ] = this.getXValue( x );
1672
+ // reset other property
1673
+ style[ xResetProperty ] = '';
1674
+
1675
+ // y
1676
+ var yPadding = layoutOptions.isOriginTop ? 'paddingTop' : 'paddingBottom';
1677
+ var yProperty = layoutOptions.isOriginTop ? 'top' : 'bottom';
1678
+ var yResetProperty = layoutOptions.isOriginTop ? 'bottom' : 'top';
1679
+
1680
+ var y = this.position.y + layoutSize[ yPadding ];
1681
+ // set in percentage or pixels
1682
+ style[ yProperty ] = this.getYValue( y );
1683
+ // reset other property
1684
+ style[ yResetProperty ] = '';
1685
+
1686
+ this.css( style );
1687
+ this.emitEvent( 'layout', [ this ] );
1688
+ };
1689
+
1690
+ Item.prototype.getXValue = function( x ) {
1691
+ var layoutOptions = this.layout.options;
1692
+ return layoutOptions.percentPosition && !layoutOptions.isHorizontal ?
1693
+ ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';
1694
+ };
1695
+
1696
+ Item.prototype.getYValue = function( y ) {
1697
+ var layoutOptions = this.layout.options;
1698
+ return layoutOptions.percentPosition && layoutOptions.isHorizontal ?
1699
+ ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';
1700
+ };
1701
+
1702
+
1703
+ Item.prototype._transitionTo = function( x, y ) {
1704
+ this.getPosition();
1705
+ // get current x & y from top/left
1706
+ var curX = this.position.x;
1707
+ var curY = this.position.y;
1708
+
1709
+ var compareX = parseInt( x, 10 );
1710
+ var compareY = parseInt( y, 10 );
1711
+ var didNotMove = compareX === this.position.x && compareY === this.position.y;
1712
+
1713
+ // save end position
1714
+ this.setPosition( x, y );
1715
+
1716
+ // if did not move and not transitioning, just go to layout
1717
+ if ( didNotMove && !this.isTransitioning ) {
1718
+ this.layoutPosition();
1719
+ return;
1720
+ }
1721
+
1722
+ var transX = x - curX;
1723
+ var transY = y - curY;
1724
+ var transitionStyle = {};
1725
+ transitionStyle.transform = this.getTranslate( transX, transY );
1726
+
1727
+ this.transition({
1728
+ to: transitionStyle,
1729
+ onTransitionEnd: {
1730
+ transform: this.layoutPosition
1731
+ },
1732
+ isCleaning: true
1733
+ });
1734
+ };
1735
+
1736
+ Item.prototype.getTranslate = function( x, y ) {
1737
+ // flip cooridinates if origin on right or bottom
1738
+ var layoutOptions = this.layout.options;
1739
+ x = layoutOptions.isOriginLeft ? x : -x;
1740
+ y = layoutOptions.isOriginTop ? y : -y;
1741
+
1742
+ if ( is3d ) {
1743
+ return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
1744
+ }
1745
+
1746
+ return 'translate(' + x + 'px, ' + y + 'px)';
1747
+ };
1748
+
1749
+ // non transition + transform support
1750
+ Item.prototype.goTo = function( x, y ) {
1751
+ this.setPosition( x, y );
1752
+ this.layoutPosition();
1753
+ };
1754
+
1755
+ // use transition and transforms if supported
1756
+ Item.prototype.moveTo = supportsCSS3 ?
1757
+ Item.prototype._transitionTo : Item.prototype.goTo;
1758
+
1759
+ Item.prototype.setPosition = function( x, y ) {
1760
+ this.position.x = parseInt( x, 10 );
1761
+ this.position.y = parseInt( y, 10 );
1762
+ };
1763
+
1764
+ // ----- transition ----- //
1765
+
1766
+ /**
1767
+ * @param {Object} style - CSS
1768
+ * @param {Function} onTransitionEnd
1769
+ */
1770
+
1771
+ // non transition, just trigger callback
1772
+ Item.prototype._nonTransition = function( args ) {
1773
+ this.css( args.to );
1774
+ if ( args.isCleaning ) {
1775
+ this._removeStyles( args.to );
1776
+ }
1777
+ for ( var prop in args.onTransitionEnd ) {
1778
+ args.onTransitionEnd[ prop ].call( this );
1779
+ }
1780
+ };
1781
+
1782
+ /**
1783
+ * proper transition
1784
+ * @param {Object} args - arguments
1785
+ * @param {Object} to - style to transition to
1786
+ * @param {Object} from - style to start transition from
1787
+ * @param {Boolean} isCleaning - removes transition styles after transition
1788
+ * @param {Function} onTransitionEnd - callback
1789
+ */
1790
+ Item.prototype._transition = function( args ) {
1791
+ // redirect to nonTransition if no transition duration
1792
+ if ( !parseFloat( this.layout.options.transitionDuration ) ) {
1793
+ this._nonTransition( args );
1794
+ return;
1795
+ }
1796
+
1797
+ var _transition = this._transn;
1798
+ // keep track of onTransitionEnd callback by css property
1799
+ for ( var prop in args.onTransitionEnd ) {
1800
+ _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];
1801
+ }
1802
+ // keep track of properties that are transitioning
1803
+ for ( prop in args.to ) {
1804
+ _transition.ingProperties[ prop ] = true;
1805
+ // keep track of properties to clean up when transition is done
1806
+ if ( args.isCleaning ) {
1807
+ _transition.clean[ prop ] = true;
1808
+ }
1809
+ }
1810
+
1811
+ // set from styles
1812
+ if ( args.from ) {
1813
+ this.css( args.from );
1814
+ // force redraw. http://blog.alexmaccaw.com/css-transitions
1815
+ var h = this.element.offsetHeight;
1816
+ // hack for JSHint to hush about unused var
1817
+ h = null;
1818
+ }
1819
+ // enable transition
1820
+ this.enableTransition( args.to );
1821
+ // set styles that are transitioning
1822
+ this.css( args.to );
1823
+
1824
+ this.isTransitioning = true;
1825
+
1826
+ };
1827
+
1828
+ // dash before all cap letters, including first for
1829
+ // WebkitTransform => -webkit-transform
1830
+ function toDashedAll( str ) {
1831
+ return str.replace( /([A-Z])/g, function( $1 ) {
1832
+ return '-' + $1.toLowerCase();
1833
+ });
1834
+ }
1835
+
1836
+ var transitionProps = 'opacity,' +
1837
+ toDashedAll( vendorProperties.transform || 'transform' );
1838
+
1839
+ Item.prototype.enableTransition = function(/* style */) {
1840
+ // HACK changing transitionProperty during a transition
1841
+ // will cause transition to jump
1842
+ if ( this.isTransitioning ) {
1843
+ return;
1844
+ }
1845
+
1846
+ // make `transition: foo, bar, baz` from style object
1847
+ // HACK un-comment this when enableTransition can work
1848
+ // while a transition is happening
1849
+ // var transitionValues = [];
1850
+ // for ( var prop in style ) {
1851
+ // // dash-ify camelCased properties like WebkitTransition
1852
+ // prop = vendorProperties[ prop ] || prop;
1853
+ // transitionValues.push( toDashedAll( prop ) );
1854
+ // }
1855
+ // enable transition styles
1856
+ this.css({
1857
+ transitionProperty: transitionProps,
1858
+ transitionDuration: this.layout.options.transitionDuration
1859
+ });
1860
+ // listen for transition end event
1861
+ this.element.addEventListener( transitionEndEvent, this, false );
1862
+ };
1863
+
1864
+ Item.prototype.transition = Item.prototype[ transitionProperty ? '_transition' : '_nonTransition' ];
1865
+
1866
+ // ----- events ----- //
1867
+
1868
+ Item.prototype.onwebkitTransitionEnd = function( event ) {
1869
+ this.ontransitionend( event );
1870
+ };
1871
+
1872
+ Item.prototype.onotransitionend = function( event ) {
1873
+ this.ontransitionend( event );
1874
+ };
1875
+
1876
+ // properties that I munge to make my life easier
1877
+ var dashedVendorProperties = {
1878
+ '-webkit-transform': 'transform',
1879
+ '-moz-transform': 'transform',
1880
+ '-o-transform': 'transform'
1881
+ };
1882
+
1883
+ Item.prototype.ontransitionend = function( event ) {
1884
+ // disregard bubbled events from children
1885
+ if ( event.target !== this.element ) {
1886
+ return;
1887
+ }
1888
+ var _transition = this._transn;
1889
+ // get property name of transitioned property, convert to prefix-free
1890
+ var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;
1891
+
1892
+ // remove property that has completed transitioning
1893
+ delete _transition.ingProperties[ propertyName ];
1894
+ // check if any properties are still transitioning
1895
+ if ( isEmptyObj( _transition.ingProperties ) ) {
1896
+ // all properties have completed transitioning
1897
+ this.disableTransition();
1898
+ }
1899
+ // clean style
1900
+ if ( propertyName in _transition.clean ) {
1901
+ // clean up style
1902
+ this.element.style[ event.propertyName ] = '';
1903
+ delete _transition.clean[ propertyName ];
1904
+ }
1905
+ // trigger onTransitionEnd callback
1906
+ if ( propertyName in _transition.onEnd ) {
1907
+ var onTransitionEnd = _transition.onEnd[ propertyName ];
1908
+ onTransitionEnd.call( this );
1909
+ delete _transition.onEnd[ propertyName ];
1910
+ }
1911
+
1912
+ this.emitEvent( 'transitionEnd', [ this ] );
1913
+ };
1914
+
1915
+ Item.prototype.disableTransition = function() {
1916
+ this.removeTransitionStyles();
1917
+ this.element.removeEventListener( transitionEndEvent, this, false );
1918
+ this.isTransitioning = false;
1919
+ };
1920
+
1921
+ /**
1922
+ * removes style property from element
1923
+ * @param {Object} style
1924
+ **/
1925
+ Item.prototype._removeStyles = function( style ) {
1926
+ // clean up transition styles
1927
+ var cleanStyle = {};
1928
+ for ( var prop in style ) {
1929
+ cleanStyle[ prop ] = '';
1930
+ }
1931
+ this.css( cleanStyle );
1932
+ };
1933
+
1934
+ var cleanTransitionStyle = {
1935
+ transitionProperty: '',
1936
+ transitionDuration: ''
1937
+ };
1938
+
1939
+ Item.prototype.removeTransitionStyles = function() {
1940
+ // remove transition
1941
+ this.css( cleanTransitionStyle );
1942
+ };
1943
+
1944
+ // ----- show/hide/remove ----- //
1945
+
1946
+ // remove element from DOM
1947
+ Item.prototype.removeElem = function() {
1948
+ this.element.parentNode.removeChild( this.element );
1949
+ // remove display: none
1950
+ this.css({ display: '' });
1951
+ this.emitEvent( 'remove', [ this ] );
1952
+ };
1953
+
1954
+ Item.prototype.remove = function() {
1955
+ // just remove element if no transition support or no transition
1956
+ if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {
1957
+ this.removeElem();
1958
+ return;
1959
+ }
1960
+
1961
+ // start transition
1962
+ var _this = this;
1963
+ this.once( 'transitionEnd', function() {
1964
+ _this.removeElem();
1965
+ });
1966
+ this.hide();
1967
+ };
1968
+
1969
+ Item.prototype.reveal = function() {
1970
+ delete this.isHidden;
1971
+ // remove display: none
1972
+ this.css({ display: '' });
1973
+
1974
+ var options = this.layout.options;
1975
+
1976
+ var onTransitionEnd = {};
1977
+ var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');
1978
+ onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;
1979
+
1980
+ this.transition({
1981
+ from: options.hiddenStyle,
1982
+ to: options.visibleStyle,
1983
+ isCleaning: true,
1984
+ onTransitionEnd: onTransitionEnd
1985
+ });
1986
+ };
1987
+
1988
+ Item.prototype.onRevealTransitionEnd = function() {
1989
+ // check if still visible
1990
+ // during transition, item may have been hidden
1991
+ if ( !this.isHidden ) {
1992
+ this.emitEvent('reveal');
1993
+ }
1994
+ };
1995
+
1996
+ /**
1997
+ * get style property use for hide/reveal transition end
1998
+ * @param {String} styleProperty - hiddenStyle/visibleStyle
1999
+ * @returns {String}
2000
+ */
2001
+ Item.prototype.getHideRevealTransitionEndProperty = function( styleProperty ) {
2002
+ var optionStyle = this.layout.options[ styleProperty ];
2003
+ // use opacity
2004
+ if ( optionStyle.opacity ) {
2005
+ return 'opacity';
2006
+ }
2007
+ // get first property
2008
+ for ( var prop in optionStyle ) {
2009
+ return prop;
2010
+ }
2011
+ };
2012
+
2013
+ Item.prototype.hide = function() {
2014
+ // set flag
2015
+ this.isHidden = true;
2016
+ // remove display: none
2017
+ this.css({ display: '' });
2018
+
2019
+ var options = this.layout.options;
2020
+
2021
+ var onTransitionEnd = {};
2022
+ var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');
2023
+ onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;
2024
+
2025
+ this.transition({
2026
+ from: options.visibleStyle,
2027
+ to: options.hiddenStyle,
2028
+ // keep hidden stuff hidden
2029
+ isCleaning: true,
2030
+ onTransitionEnd: onTransitionEnd
2031
+ });
2032
+ };
2033
+
2034
+ Item.prototype.onHideTransitionEnd = function() {
2035
+ // check if still hidden
2036
+ // during transition, item may have been un-hidden
2037
+ if ( this.isHidden ) {
2038
+ this.css({ display: 'none' });
2039
+ this.emitEvent('hide');
2040
+ }
2041
+ };
2042
+
2043
+ Item.prototype.destroy = function() {
2044
+ this.css({
2045
+ position: '',
2046
+ left: '',
2047
+ right: '',
2048
+ top: '',
2049
+ bottom: '',
2050
+ transition: '',
2051
+ transform: ''
2052
+ });
2053
+ };
2054
+
2055
+ return Item;
2056
+
2057
+ }));
2058
+
2059
+ /*!
2060
+ * Outlayer v1.4.2
2061
+ * the brains and guts of a layout library
2062
+ * MIT license
2063
+ */
2064
+
2065
+ ( function( window, factory ) {
2066
+ 'use strict';
2067
+ // universal module definition
2068
+
2069
+ if ( typeof define == 'function' && define.amd ) {
2070
+ // AMD
2071
+ define( 'outlayer/outlayer',[
2072
+ 'eventie/eventie',
2073
+ 'eventEmitter/EventEmitter',
2074
+ 'get-size/get-size',
2075
+ 'fizzy-ui-utils/utils',
2076
+ './item'
2077
+ ],
2078
+ function( eventie, EventEmitter, getSize, utils, Item ) {
2079
+ return factory( window, eventie, EventEmitter, getSize, utils, Item);
2080
+ }
2081
+ );
2082
+ } else if ( typeof exports == 'object' ) {
2083
+ // CommonJS
2084
+ module.exports = factory(
2085
+ window,
2086
+ require('eventie'),
2087
+ require('wolfy87-eventemitter'),
2088
+ require('get-size'),
2089
+ require('fizzy-ui-utils'),
2090
+ require('./item')
2091
+ );
2092
+ } else {
2093
+ // browser global
2094
+ window.Outlayer = factory(
2095
+ window,
2096
+ window.eventie,
2097
+ window.EventEmitter,
2098
+ window.getSize,
2099
+ window.fizzyUIUtils,
2100
+ window.Outlayer.Item
2101
+ );
2102
+ }
2103
+
2104
+ }( window, function factory( window, eventie, EventEmitter, getSize, utils, Item ) {
2105
+ 'use strict';
2106
+
2107
+ // ----- vars ----- //
2108
+
2109
+ var console = window.console;
2110
+ var jQuery = window.jQuery;
2111
+ var noop = function() {};
2112
+
2113
+ // -------------------------- Outlayer -------------------------- //
2114
+
2115
+ // globally unique identifiers
2116
+ var GUID = 0;
2117
+ // internal store of all Outlayer intances
2118
+ var instances = {};
2119
+
2120
+
2121
+ /**
2122
+ * @param {Element, String} element
2123
+ * @param {Object} options
2124
+ * @constructor
2125
+ */
2126
+ function Outlayer( element, options ) {
2127
+ var queryElement = utils.getQueryElement( element );
2128
+ if ( !queryElement ) {
2129
+ if ( console ) {
2130
+ console.error( 'Bad element for ' + this.constructor.namespace +
2131
+ ': ' + ( queryElement || element ) );
2132
+ }
2133
+ return;
2134
+ }
2135
+ this.element = queryElement;
2136
+ // add jQuery
2137
+ if ( jQuery ) {
2138
+ this.$element = jQuery( this.element );
2139
+ }
2140
+
2141
+ // options
2142
+ this.options = utils.extend( {}, this.constructor.defaults );
2143
+ this.option( options );
2144
+
2145
+ // add id for Outlayer.getFromElement
2146
+ var id = ++GUID;
2147
+ this.element.outlayerGUID = id; // expando
2148
+ instances[ id ] = this; // associate via id
2149
+
2150
+ // kick it off
2151
+ this._create();
2152
+
2153
+ if ( this.options.isInitLayout ) {
2154
+ this.layout();
2155
+ }
2156
+ }
2157
+
2158
+ // settings are for internal use only
2159
+ Outlayer.namespace = 'outlayer';
2160
+ Outlayer.Item = Item;
2161
+
2162
+ // default options
2163
+ Outlayer.defaults = {
2164
+ containerStyle: {
2165
+ position: 'relative'
2166
+ },
2167
+ isInitLayout: true,
2168
+ isOriginLeft: true,
2169
+ isOriginTop: true,
2170
+ isResizeBound: true,
2171
+ isResizingContainer: true,
2172
+ // item options
2173
+ transitionDuration: '0.4s',
2174
+ hiddenStyle: {
2175
+ opacity: 0,
2176
+ transform: 'scale(0.001)'
2177
+ },
2178
+ visibleStyle: {
2179
+ opacity: 1,
2180
+ transform: 'scale(1)'
2181
+ }
2182
+ };
2183
+
2184
+ // inherit EventEmitter
2185
+ utils.extend( Outlayer.prototype, EventEmitter.prototype );
2186
+
2187
+ /**
2188
+ * set options
2189
+ * @param {Object} opts
2190
+ */
2191
+ Outlayer.prototype.option = function( opts ) {
2192
+ utils.extend( this.options, opts );
2193
+ };
2194
+
2195
+ Outlayer.prototype._create = function() {
2196
+ // get items from children
2197
+ this.reloadItems();
2198
+ // elements that affect layout, but are not laid out
2199
+ this.stamps = [];
2200
+ this.stamp( this.options.stamp );
2201
+ // set container style
2202
+ utils.extend( this.element.style, this.options.containerStyle );
2203
+
2204
+ // bind resize method
2205
+ if ( this.options.isResizeBound ) {
2206
+ this.bindResize();
2207
+ }
2208
+ };
2209
+
2210
+ // goes through all children again and gets bricks in proper order
2211
+ Outlayer.prototype.reloadItems = function() {
2212
+ // collection of item elements
2213
+ this.items = this._itemize( this.element.children );
2214
+ };
2215
+
2216
+
2217
+ /**
2218
+ * turn elements into Outlayer.Items to be used in layout
2219
+ * @param {Array or NodeList or HTMLElement} elems
2220
+ * @returns {Array} items - collection of new Outlayer Items
2221
+ */
2222
+ Outlayer.prototype._itemize = function( elems ) {
2223
+
2224
+ var itemElems = this._filterFindItemElements( elems );
2225
+ var Item = this.constructor.Item;
2226
+
2227
+ // create new Outlayer Items for collection
2228
+ var items = [];
2229
+ for ( var i=0, len = itemElems.length; i < len; i++ ) {
2230
+ var elem = itemElems[i];
2231
+ var item = new Item( elem, this );
2232
+ items.push( item );
2233
+ }
2234
+
2235
+ return items;
2236
+ };
2237
+
2238
+ /**
2239
+ * get item elements to be used in layout
2240
+ * @param {Array or NodeList or HTMLElement} elems
2241
+ * @returns {Array} items - item elements
2242
+ */
2243
+ Outlayer.prototype._filterFindItemElements = function( elems ) {
2244
+ return utils.filterFindElements( elems, this.options.itemSelector );
2245
+ };
2246
+
2247
+ /**
2248
+ * getter method for getting item elements
2249
+ * @returns {Array} elems - collection of item elements
2250
+ */
2251
+ Outlayer.prototype.getItemElements = function() {
2252
+ var elems = [];
2253
+ for ( var i=0, len = this.items.length; i < len; i++ ) {
2254
+ elems.push( this.items[i].element );
2255
+ }
2256
+ return elems;
2257
+ };
2258
+
2259
+ // ----- init & layout ----- //
2260
+
2261
+ /**
2262
+ * lays out all items
2263
+ */
2264
+ Outlayer.prototype.layout = function() {
2265
+ this._resetLayout();
2266
+ this._manageStamps();
2267
+
2268
+ // don't animate first layout
2269
+ var isInstant = this.options.isLayoutInstant !== undefined ?
2270
+ this.options.isLayoutInstant : !this._isLayoutInited;
2271
+ this.layoutItems( this.items, isInstant );
2272
+
2273
+ // flag for initalized
2274
+ this._isLayoutInited = true;
2275
+ };
2276
+
2277
+ // _init is alias for layout
2278
+ Outlayer.prototype._init = Outlayer.prototype.layout;
2279
+
2280
+ /**
2281
+ * logic before any new layout
2282
+ */
2283
+ Outlayer.prototype._resetLayout = function() {
2284
+ this.getSize();
2285
+ };
2286
+
2287
+
2288
+ Outlayer.prototype.getSize = function() {
2289
+ this.size = getSize( this.element );
2290
+ };
2291
+
2292
+ /**
2293
+ * get measurement from option, for columnWidth, rowHeight, gutter
2294
+ * if option is String -> get element from selector string, & get size of element
2295
+ * if option is Element -> get size of element
2296
+ * else use option as a number
2297
+ *
2298
+ * @param {String} measurement
2299
+ * @param {String} size - width or height
2300
+ * @private
2301
+ */
2302
+ Outlayer.prototype._getMeasurement = function( measurement, size ) {
2303
+ var option = this.options[ measurement ];
2304
+ var elem;
2305
+ if ( !option ) {
2306
+ // default to 0
2307
+ this[ measurement ] = 0;
2308
+ } else {
2309
+ // use option as an element
2310
+ if ( typeof option === 'string' ) {
2311
+ elem = this.element.querySelector( option );
2312
+ } else if ( utils.isElement( option ) ) {
2313
+ elem = option;
2314
+ }
2315
+ // use size of element, if element
2316
+ this[ measurement ] = elem ? getSize( elem )[ size ] : option;
2317
+ }
2318
+ };
2319
+
2320
+ /**
2321
+ * layout a collection of item elements
2322
+ * @api public
2323
+ */
2324
+ Outlayer.prototype.layoutItems = function( items, isInstant ) {
2325
+ items = this._getItemsForLayout( items );
2326
+
2327
+ this._layoutItems( items, isInstant );
2328
+
2329
+ this._postLayout();
2330
+ };
2331
+
2332
+ /**
2333
+ * get the items to be laid out
2334
+ * you may want to skip over some items
2335
+ * @param {Array} items
2336
+ * @returns {Array} items
2337
+ */
2338
+ Outlayer.prototype._getItemsForLayout = function( items ) {
2339
+ var layoutItems = [];
2340
+ for ( var i=0, len = items.length; i < len; i++ ) {
2341
+ var item = items[i];
2342
+ if ( !item.isIgnored ) {
2343
+ layoutItems.push( item );
2344
+ }
2345
+ }
2346
+ return layoutItems;
2347
+ };
2348
+
2349
+ /**
2350
+ * layout items
2351
+ * @param {Array} items
2352
+ * @param {Boolean} isInstant
2353
+ */
2354
+ Outlayer.prototype._layoutItems = function( items, isInstant ) {
2355
+ this._emitCompleteOnItems( 'layout', items );
2356
+
2357
+ if ( !items || !items.length ) {
2358
+ // no items, emit event with empty array
2359
+ return;
2360
+ }
2361
+
2362
+ var queue = [];
2363
+
2364
+ for ( var i=0, len = items.length; i < len; i++ ) {
2365
+ var item = items[i];
2366
+ // get x/y object from method
2367
+ var position = this._getItemLayoutPosition( item );
2368
+ // enqueue
2369
+ position.item = item;
2370
+ position.isInstant = isInstant || item.isLayoutInstant;
2371
+ queue.push( position );
2372
+ }
2373
+
2374
+ this._processLayoutQueue( queue );
2375
+ };
2376
+
2377
+ /**
2378
+ * get item layout position
2379
+ * @param {Outlayer.Item} item
2380
+ * @returns {Object} x and y position
2381
+ */
2382
+ Outlayer.prototype._getItemLayoutPosition = function( /* item */ ) {
2383
+ return {
2384
+ x: 0,
2385
+ y: 0
2386
+ };
2387
+ };
2388
+
2389
+ /**
2390
+ * iterate over array and position each item
2391
+ * Reason being - separating this logic prevents 'layout invalidation'
2392
+ * thx @paul_irish
2393
+ * @param {Array} queue
2394
+ */
2395
+ Outlayer.prototype._processLayoutQueue = function( queue ) {
2396
+ for ( var i=0, len = queue.length; i < len; i++ ) {
2397
+ var obj = queue[i];
2398
+ this._positionItem( obj.item, obj.x, obj.y, obj.isInstant );
2399
+ }
2400
+ };
2401
+
2402
+ /**
2403
+ * Sets position of item in DOM
2404
+ * @param {Outlayer.Item} item
2405
+ * @param {Number} x - horizontal position
2406
+ * @param {Number} y - vertical position
2407
+ * @param {Boolean} isInstant - disables transitions
2408
+ */
2409
+ Outlayer.prototype._positionItem = function( item, x, y, isInstant ) {
2410
+ if ( isInstant ) {
2411
+ // if not transition, just set CSS
2412
+ item.goTo( x, y );
2413
+ } else {
2414
+ item.moveTo( x, y );
2415
+ }
2416
+ };
2417
+
2418
+ /**
2419
+ * Any logic you want to do after each layout,
2420
+ * i.e. size the container
2421
+ */
2422
+ Outlayer.prototype._postLayout = function() {
2423
+ this.resizeContainer();
2424
+ };
2425
+
2426
+ Outlayer.prototype.resizeContainer = function() {
2427
+ if ( !this.options.isResizingContainer ) {
2428
+ return;
2429
+ }
2430
+ var size = this._getContainerSize();
2431
+ if ( size ) {
2432
+ this._setContainerMeasure( size.width, true );
2433
+ this._setContainerMeasure( size.height, false );
2434
+ }
2435
+ };
2436
+
2437
+ /**
2438
+ * Sets width or height of container if returned
2439
+ * @returns {Object} size
2440
+ * @param {Number} width
2441
+ * @param {Number} height
2442
+ */
2443
+ Outlayer.prototype._getContainerSize = noop;
2444
+
2445
+ /**
2446
+ * @param {Number} measure - size of width or height
2447
+ * @param {Boolean} isWidth
2448
+ */
2449
+ Outlayer.prototype._setContainerMeasure = function( measure, isWidth ) {
2450
+ if ( measure === undefined ) {
2451
+ return;
2452
+ }
2453
+
2454
+ var elemSize = this.size;
2455
+ // add padding and border width if border box
2456
+ if ( elemSize.isBorderBox ) {
2457
+ measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +
2458
+ elemSize.borderLeftWidth + elemSize.borderRightWidth :
2459
+ elemSize.paddingBottom + elemSize.paddingTop +
2460
+ elemSize.borderTopWidth + elemSize.borderBottomWidth;
2461
+ }
2462
+
2463
+ measure = Math.max( measure, 0 );
2464
+ this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';
2465
+ };
2466
+
2467
+ /**
2468
+ * emit eventComplete on a collection of items events
2469
+ * @param {String} eventName
2470
+ * @param {Array} items - Outlayer.Items
2471
+ */
2472
+ Outlayer.prototype._emitCompleteOnItems = function( eventName, items ) {
2473
+ var _this = this;
2474
+ function onComplete() {
2475
+ _this.dispatchEvent( eventName + 'Complete', null, [ items ] );
2476
+ }
2477
+
2478
+ var count = items.length;
2479
+ if ( !items || !count ) {
2480
+ onComplete();
2481
+ return;
2482
+ }
2483
+
2484
+ var doneCount = 0;
2485
+ function tick() {
2486
+ doneCount++;
2487
+ if ( doneCount === count ) {
2488
+ onComplete();
2489
+ }
2490
+ }
2491
+
2492
+ // bind callback
2493
+ for ( var i=0, len = items.length; i < len; i++ ) {
2494
+ var item = items[i];
2495
+ item.once( eventName, tick );
2496
+ }
2497
+ };
2498
+
2499
+ /**
2500
+ * emits events via eventEmitter and jQuery events
2501
+ * @param {String} type - name of event
2502
+ * @param {Event} event - original event
2503
+ * @param {Array} args - extra arguments
2504
+ */
2505
+ Outlayer.prototype.dispatchEvent = function( type, event, args ) {
2506
+ // add original event to arguments
2507
+ var emitArgs = event ? [ event ].concat( args ) : args;
2508
+ this.emitEvent( type, emitArgs );
2509
+
2510
+ if ( jQuery ) {
2511
+ // set this.$element
2512
+ this.$element = this.$element || jQuery( this.element );
2513
+ if ( event ) {
2514
+ // create jQuery event
2515
+ var $event = jQuery.Event( event );
2516
+ $event.type = type;
2517
+ this.$element.trigger( $event, args );
2518
+ } else {
2519
+ // just trigger with type if no event available
2520
+ this.$element.trigger( type, args );
2521
+ }
2522
+ }
2523
+ };
2524
+
2525
+ // -------------------------- ignore & stamps -------------------------- //
2526
+
2527
+
2528
+ /**
2529
+ * keep item in collection, but do not lay it out
2530
+ * ignored items do not get skipped in layout
2531
+ * @param {Element} elem
2532
+ */
2533
+ Outlayer.prototype.ignore = function( elem ) {
2534
+ var item = this.getItem( elem );
2535
+ if ( item ) {
2536
+ item.isIgnored = true;
2537
+ }
2538
+ };
2539
+
2540
+ /**
2541
+ * return item to layout collection
2542
+ * @param {Element} elem
2543
+ */
2544
+ Outlayer.prototype.unignore = function( elem ) {
2545
+ var item = this.getItem( elem );
2546
+ if ( item ) {
2547
+ delete item.isIgnored;
2548
+ }
2549
+ };
2550
+
2551
+ /**
2552
+ * adds elements to stamps
2553
+ * @param {NodeList, Array, Element, or String} elems
2554
+ */
2555
+ Outlayer.prototype.stamp = function( elems ) {
2556
+ elems = this._find( elems );
2557
+ if ( !elems ) {
2558
+ return;
2559
+ }
2560
+
2561
+ this.stamps = this.stamps.concat( elems );
2562
+ // ignore
2563
+ for ( var i=0, len = elems.length; i < len; i++ ) {
2564
+ var elem = elems[i];
2565
+ this.ignore( elem );
2566
+ }
2567
+ };
2568
+
2569
+ /**
2570
+ * removes elements to stamps
2571
+ * @param {NodeList, Array, or Element} elems
2572
+ */
2573
+ Outlayer.prototype.unstamp = function( elems ) {
2574
+ elems = this._find( elems );
2575
+ if ( !elems ){
2576
+ return;
2577
+ }
2578
+
2579
+ for ( var i=0, len = elems.length; i < len; i++ ) {
2580
+ var elem = elems[i];
2581
+ // filter out removed stamp elements
2582
+ utils.removeFrom( this.stamps, elem );
2583
+ this.unignore( elem );
2584
+ }
2585
+
2586
+ };
2587
+
2588
+ /**
2589
+ * finds child elements
2590
+ * @param {NodeList, Array, Element, or String} elems
2591
+ * @returns {Array} elems
2592
+ */
2593
+ Outlayer.prototype._find = function( elems ) {
2594
+ if ( !elems ) {
2595
+ return;
2596
+ }
2597
+ // if string, use argument as selector string
2598
+ if ( typeof elems === 'string' ) {
2599
+ elems = this.element.querySelectorAll( elems );
2600
+ }
2601
+ elems = utils.makeArray( elems );
2602
+ return elems;
2603
+ };
2604
+
2605
+ Outlayer.prototype._manageStamps = function() {
2606
+ if ( !this.stamps || !this.stamps.length ) {
2607
+ return;
2608
+ }
2609
+
2610
+ this._getBoundingRect();
2611
+
2612
+ for ( var i=0, len = this.stamps.length; i < len; i++ ) {
2613
+ var stamp = this.stamps[i];
2614
+ this._manageStamp( stamp );
2615
+ }
2616
+ };
2617
+
2618
+ // update boundingLeft / Top
2619
+ Outlayer.prototype._getBoundingRect = function() {
2620
+ // get bounding rect for container element
2621
+ var boundingRect = this.element.getBoundingClientRect();
2622
+ var size = this.size;
2623
+ this._boundingRect = {
2624
+ left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,
2625
+ top: boundingRect.top + size.paddingTop + size.borderTopWidth,
2626
+ right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),
2627
+ bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )
2628
+ };
2629
+ };
2630
+
2631
+ /**
2632
+ * @param {Element} stamp
2633
+ **/
2634
+ Outlayer.prototype._manageStamp = noop;
2635
+
2636
+ /**
2637
+ * get x/y position of element relative to container element
2638
+ * @param {Element} elem
2639
+ * @returns {Object} offset - has left, top, right, bottom
2640
+ */
2641
+ Outlayer.prototype._getElementOffset = function( elem ) {
2642
+ var boundingRect = elem.getBoundingClientRect();
2643
+ var thisRect = this._boundingRect;
2644
+ var size = getSize( elem );
2645
+ var offset = {
2646
+ left: boundingRect.left - thisRect.left - size.marginLeft,
2647
+ top: boundingRect.top - thisRect.top - size.marginTop,
2648
+ right: thisRect.right - boundingRect.right - size.marginRight,
2649
+ bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom
2650
+ };
2651
+ return offset;
2652
+ };
2653
+
2654
+ // -------------------------- resize -------------------------- //
2655
+
2656
+ // enable event handlers for listeners
2657
+ // i.e. resize -> onresize
2658
+ Outlayer.prototype.handleEvent = function( event ) {
2659
+ var method = 'on' + event.type;
2660
+ if ( this[ method ] ) {
2661
+ this[ method ]( event );
2662
+ }
2663
+ };
2664
+
2665
+ /**
2666
+ * Bind layout to window resizing
2667
+ */
2668
+ Outlayer.prototype.bindResize = function() {
2669
+ // bind just one listener
2670
+ if ( this.isResizeBound ) {
2671
+ return;
2672
+ }
2673
+ eventie.bind( window, 'resize', this );
2674
+ this.isResizeBound = true;
2675
+ };
2676
+
2677
+ /**
2678
+ * Unbind layout to window resizing
2679
+ */
2680
+ Outlayer.prototype.unbindResize = function() {
2681
+ if ( this.isResizeBound ) {
2682
+ eventie.unbind( window, 'resize', this );
2683
+ }
2684
+ this.isResizeBound = false;
2685
+ };
2686
+
2687
+ // original debounce by John Hann
2688
+ // http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/
2689
+
2690
+ // this fires every resize
2691
+ Outlayer.prototype.onresize = function() {
2692
+ if ( this.resizeTimeout ) {
2693
+ clearTimeout( this.resizeTimeout );
2694
+ }
2695
+
2696
+ var _this = this;
2697
+ function delayed() {
2698
+ _this.resize();
2699
+ delete _this.resizeTimeout;
2700
+ }
2701
+
2702
+ this.resizeTimeout = setTimeout( delayed, 100 );
2703
+ };
2704
+
2705
+ // debounced, layout on resize
2706
+ Outlayer.prototype.resize = function() {
2707
+ // don't trigger if size did not change
2708
+ // or if resize was unbound. See #9
2709
+ if ( !this.isResizeBound || !this.needsResizeLayout() ) {
2710
+ return;
2711
+ }
2712
+
2713
+ this.layout();
2714
+ };
2715
+
2716
+ /**
2717
+ * check if layout is needed post layout
2718
+ * @returns Boolean
2719
+ */
2720
+ Outlayer.prototype.needsResizeLayout = function() {
2721
+ var size = getSize( this.element );
2722
+ // check that this.size and size are there
2723
+ // IE8 triggers resize on body size change, so they might not be
2724
+ var hasSizes = this.size && size;
2725
+ return hasSizes && size.innerWidth !== this.size.innerWidth;
2726
+ };
2727
+
2728
+ // -------------------------- methods -------------------------- //
2729
+
2730
+ /**
2731
+ * add items to Outlayer instance
2732
+ * @param {Array or NodeList or Element} elems
2733
+ * @returns {Array} items - Outlayer.Items
2734
+ **/
2735
+ Outlayer.prototype.addItems = function( elems ) {
2736
+ var items = this._itemize( elems );
2737
+ // add items to collection
2738
+ if ( items.length ) {
2739
+ this.items = this.items.concat( items );
2740
+ }
2741
+ return items;
2742
+ };
2743
+
2744
+ /**
2745
+ * Layout newly-appended item elements
2746
+ * @param {Array or NodeList or Element} elems
2747
+ */
2748
+ Outlayer.prototype.appended = function( elems ) {
2749
+ var items = this.addItems( elems );
2750
+ if ( !items.length ) {
2751
+ return;
2752
+ }
2753
+ // layout and reveal just the new items
2754
+ this.layoutItems( items, true );
2755
+ this.reveal( items );
2756
+ };
2757
+
2758
+ /**
2759
+ * Layout prepended elements
2760
+ * @param {Array or NodeList or Element} elems
2761
+ */
2762
+ Outlayer.prototype.prepended = function( elems ) {
2763
+ var items = this._itemize( elems );
2764
+ if ( !items.length ) {
2765
+ return;
2766
+ }
2767
+ // add items to beginning of collection
2768
+ var previousItems = this.items.slice(0);
2769
+ this.items = items.concat( previousItems );
2770
+ // start new layout
2771
+ this._resetLayout();
2772
+ this._manageStamps();
2773
+ // layout new stuff without transition
2774
+ this.layoutItems( items, true );
2775
+ this.reveal( items );
2776
+ // layout previous items
2777
+ this.layoutItems( previousItems );
2778
+ };
2779
+
2780
+ /**
2781
+ * reveal a collection of items
2782
+ * @param {Array of Outlayer.Items} items
2783
+ */
2784
+ Outlayer.prototype.reveal = function( items ) {
2785
+ this._emitCompleteOnItems( 'reveal', items );
2786
+
2787
+ var len = items && items.length;
2788
+ for ( var i=0; len && i < len; i++ ) {
2789
+ var item = items[i];
2790
+ item.reveal();
2791
+ }
2792
+ };
2793
+
2794
+ /**
2795
+ * hide a collection of items
2796
+ * @param {Array of Outlayer.Items} items
2797
+ */
2798
+ Outlayer.prototype.hide = function( items ) {
2799
+ this._emitCompleteOnItems( 'hide', items );
2800
+
2801
+ var len = items && items.length;
2802
+ for ( var i=0; len && i < len; i++ ) {
2803
+ var item = items[i];
2804
+ item.hide();
2805
+ }
2806
+ };
2807
+
2808
+ /**
2809
+ * reveal item elements
2810
+ * @param {Array}, {Element}, {NodeList} items
2811
+ */
2812
+ Outlayer.prototype.revealItemElements = function( elems ) {
2813
+ var items = this.getItems( elems );
2814
+ this.reveal( items );
2815
+ };
2816
+
2817
+ /**
2818
+ * hide item elements
2819
+ * @param {Array}, {Element}, {NodeList} items
2820
+ */
2821
+ Outlayer.prototype.hideItemElements = function( elems ) {
2822
+ var items = this.getItems( elems );
2823
+ this.hide( items );
2824
+ };
2825
+
2826
+ /**
2827
+ * get Outlayer.Item, given an Element
2828
+ * @param {Element} elem
2829
+ * @param {Function} callback
2830
+ * @returns {Outlayer.Item} item
2831
+ */
2832
+ Outlayer.prototype.getItem = function( elem ) {
2833
+ // loop through items to get the one that matches
2834
+ for ( var i=0, len = this.items.length; i < len; i++ ) {
2835
+ var item = this.items[i];
2836
+ if ( item.element === elem ) {
2837
+ // return item
2838
+ return item;
2839
+ }
2840
+ }
2841
+ };
2842
+
2843
+ /**
2844
+ * get collection of Outlayer.Items, given Elements
2845
+ * @param {Array} elems
2846
+ * @returns {Array} items - Outlayer.Items
2847
+ */
2848
+ Outlayer.prototype.getItems = function( elems ) {
2849
+ elems = utils.makeArray( elems );
2850
+ var items = [];
2851
+ for ( var i=0, len = elems.length; i < len; i++ ) {
2852
+ var elem = elems[i];
2853
+ var item = this.getItem( elem );
2854
+ if ( item ) {
2855
+ items.push( item );
2856
+ }
2857
+ }
2858
+
2859
+ return items;
2860
+ };
2861
+
2862
+ /**
2863
+ * remove element(s) from instance and DOM
2864
+ * @param {Array or NodeList or Element} elems
2865
+ */
2866
+ Outlayer.prototype.remove = function( elems ) {
2867
+ var removeItems = this.getItems( elems );
2868
+
2869
+ this._emitCompleteOnItems( 'remove', removeItems );
2870
+
2871
+ // bail if no items to remove
2872
+ if ( !removeItems || !removeItems.length ) {
2873
+ return;
2874
+ }
2875
+
2876
+ for ( var i=0, len = removeItems.length; i < len; i++ ) {
2877
+ var item = removeItems[i];
2878
+ item.remove();
2879
+ // remove item from collection
2880
+ utils.removeFrom( this.items, item );
2881
+ }
2882
+ };
2883
+
2884
+ // ----- destroy ----- //
2885
+
2886
+ // remove and disable Outlayer instance
2887
+ Outlayer.prototype.destroy = function() {
2888
+ // clean up dynamic styles
2889
+ var style = this.element.style;
2890
+ style.height = '';
2891
+ style.position = '';
2892
+ style.width = '';
2893
+ // destroy items
2894
+ for ( var i=0, len = this.items.length; i < len; i++ ) {
2895
+ var item = this.items[i];
2896
+ item.destroy();
2897
+ }
2898
+
2899
+ this.unbindResize();
2900
+
2901
+ var id = this.element.outlayerGUID;
2902
+ delete instances[ id ]; // remove reference to instance by id
2903
+ delete this.element.outlayerGUID;
2904
+ // remove data for jQuery
2905
+ if ( jQuery ) {
2906
+ jQuery.removeData( this.element, this.constructor.namespace );
2907
+ }
2908
+
2909
+ };
2910
+
2911
+ // -------------------------- data -------------------------- //
2912
+
2913
+ /**
2914
+ * get Outlayer instance from element
2915
+ * @param {Element} elem
2916
+ * @returns {Outlayer}
2917
+ */
2918
+ Outlayer.data = function( elem ) {
2919
+ elem = utils.getQueryElement( elem );
2920
+ var id = elem && elem.outlayerGUID;
2921
+ return id && instances[ id ];
2922
+ };
2923
+
2924
+
2925
+ // -------------------------- create Outlayer class -------------------------- //
2926
+
2927
+ /**
2928
+ * create a layout class
2929
+ * @param {String} namespace
2930
+ */
2931
+ Outlayer.create = function( namespace, options ) {
2932
+ // sub-class Outlayer
2933
+ function Layout() {
2934
+ Outlayer.apply( this, arguments );
2935
+ }
2936
+ // inherit Outlayer prototype, use Object.create if there
2937
+ if ( Object.create ) {
2938
+ Layout.prototype = Object.create( Outlayer.prototype );
2939
+ } else {
2940
+ utils.extend( Layout.prototype, Outlayer.prototype );
2941
+ }
2942
+ // set contructor, used for namespace and Item
2943
+ Layout.prototype.constructor = Layout;
2944
+
2945
+ Layout.defaults = utils.extend( {}, Outlayer.defaults );
2946
+ // apply new options
2947
+ utils.extend( Layout.defaults, options );
2948
+ // keep prototype.settings for backwards compatibility (Packery v1.2.0)
2949
+ Layout.prototype.settings = {};
2950
+
2951
+ Layout.namespace = namespace;
2952
+
2953
+ Layout.data = Outlayer.data;
2954
+
2955
+ // sub-class Item
2956
+ Layout.Item = function LayoutItem() {
2957
+ Item.apply( this, arguments );
2958
+ };
2959
+
2960
+ Layout.Item.prototype = new Item();
2961
+
2962
+ // -------------------------- declarative -------------------------- //
2963
+
2964
+ utils.htmlInit( Layout, namespace );
2965
+
2966
+ // -------------------------- jQuery bridge -------------------------- //
2967
+
2968
+ // make into jQuery plugin
2969
+ if ( jQuery && jQuery.bridget ) {
2970
+ jQuery.bridget( namespace, Layout );
2971
+ }
2972
+
2973
+ return Layout;
2974
+ };
2975
+
2976
+ // ----- fin ----- //
2977
+
2978
+ // back in global
2979
+ Outlayer.Item = Item;
2980
+
2981
+ return Outlayer;
2982
+
2983
+ }));
2984
+
2985
+
2986
+ /**
2987
+ * Enviratope Item
2988
+ **/
2989
+
2990
+ ( function( window, factory ) {
2991
+ 'use strict';
2992
+ // universal module definition
2993
+ if ( typeof define == 'function' && define.amd ) {
2994
+ // AMD
2995
+ define( 'enviratope/js/item',[
2996
+ 'outlayer/outlayer'
2997
+ ],
2998
+ factory );
2999
+ } else if ( typeof exports == 'object' ) {
3000
+ // CommonJS
3001
+ module.exports = factory(
3002
+ require('outlayer')
3003
+ );
3004
+ } else {
3005
+ // browser global
3006
+ window.Enviratope = window.Enviratope || {};
3007
+ window.Enviratope.Item = factory(
3008
+ window.Outlayer
3009
+ );
3010
+ }
3011
+
3012
+ }( window, function factory( Outlayer ) {
3013
+ 'use strict';
3014
+
3015
+ // -------------------------- Item -------------------------- //
3016
+
3017
+ // sub-class Outlayer Item
3018
+ function Item() {
3019
+ Outlayer.Item.apply( this, arguments );
3020
+ }
3021
+
3022
+ Item.prototype = new Outlayer.Item();
3023
+
3024
+ Item.prototype._create = function() {
3025
+ // assign id, used for original-order sorting
3026
+ this.id = this.layout.itemGUID++;
3027
+ Outlayer.Item.prototype._create.call( this );
3028
+ this.sortData = {};
3029
+ };
3030
+
3031
+ Item.prototype.updateSortData = function() {
3032
+ if ( this.isIgnored ) {
3033
+ return;
3034
+ }
3035
+ // default sorters
3036
+ this.sortData.id = this.id;
3037
+ // for backward compatibility
3038
+ this.sortData['original-order'] = this.id;
3039
+ this.sortData.random = Math.random();
3040
+ // go thru getSortData obj and apply the sorters
3041
+ var getSortData = this.layout.options.getSortData;
3042
+ var sorters = this.layout._sorters;
3043
+ for ( var key in getSortData ) {
3044
+ var sorter = sorters[ key ];
3045
+ this.sortData[ key ] = sorter( this.element, this );
3046
+ }
3047
+ };
3048
+
3049
+ var _destroy = Item.prototype.destroy;
3050
+ Item.prototype.destroy = function() {
3051
+ // call super
3052
+ _destroy.apply( this, arguments );
3053
+ // reset display, #741
3054
+ this.css({
3055
+ display: ''
3056
+ });
3057
+ };
3058
+
3059
+ return Item;
3060
+
3061
+ }));
3062
+
3063
+ /**
3064
+ * Enviratope LayoutMode
3065
+ */
3066
+
3067
+ ( function( window, factory ) {
3068
+ 'use strict';
3069
+ // universal module definition
3070
+
3071
+ if ( typeof define == 'function' && define.amd ) {
3072
+ // AMD
3073
+ define( 'enviratope/js/layout-mode',[
3074
+ 'get-size/get-size',
3075
+ 'outlayer/outlayer'
3076
+ ],
3077
+ factory );
3078
+ } else if ( typeof exports == 'object' ) {
3079
+ // CommonJS
3080
+ module.exports = factory(
3081
+ require('get-size'),
3082
+ require('outlayer')
3083
+ );
3084
+ } else {
3085
+ // browser global
3086
+ window.Enviratope = window.Enviratope || {};
3087
+ window.Enviratope.LayoutMode = factory(
3088
+ window.getSize,
3089
+ window.Outlayer
3090
+ );
3091
+ }
3092
+
3093
+ }( window, function factory( getSize, Outlayer ) {
3094
+ 'use strict';
3095
+
3096
+ // layout mode class
3097
+ function LayoutMode( enviratope ) {
3098
+ this.enviratope = enviratope;
3099
+ // link properties
3100
+ if ( enviratope ) {
3101
+ this.options = enviratope.options[ this.namespace ];
3102
+ this.element = enviratope.element;
3103
+ this.items = enviratope.filteredItems;
3104
+ this.size = enviratope.size;
3105
+ }
3106
+ }
3107
+
3108
+ /**
3109
+ * some methods should just defer to default Outlayer method
3110
+ * and reference the Enviratope instance as `this`
3111
+ **/
3112
+ ( function() {
3113
+ var facadeMethods = [
3114
+ '_resetLayout',
3115
+ '_getItemLayoutPosition',
3116
+ '_manageStamp',
3117
+ '_getContainerSize',
3118
+ '_getElementOffset',
3119
+ 'needsResizeLayout'
3120
+ ];
3121
+
3122
+ for ( var i=0, len = facadeMethods.length; i < len; i++ ) {
3123
+ var methodName = facadeMethods[i];
3124
+ LayoutMode.prototype[ methodName ] = getOutlayerMethod( methodName );
3125
+ }
3126
+
3127
+ function getOutlayerMethod( methodName ) {
3128
+ return function() {
3129
+ return Outlayer.prototype[ methodName ].apply( this.enviratope, arguments );
3130
+ };
3131
+ }
3132
+ })();
3133
+
3134
+ // ----- ----- //
3135
+
3136
+ // for horizontal layout modes, check vertical size
3137
+ LayoutMode.prototype.needsVerticalResizeLayout = function() {
3138
+ // don't trigger if size did not change
3139
+ var size = getSize( this.enviratope.element );
3140
+ // check that this.size and size are there
3141
+ // IE8 triggers resize on body size change, so they might not be
3142
+ var hasSizes = this.enviratope.size && size;
3143
+ return hasSizes && size.innerHeight != this.enviratope.size.innerHeight;
3144
+ };
3145
+
3146
+ // ----- measurements ----- //
3147
+
3148
+ LayoutMode.prototype._getMeasurement = function() {
3149
+ this.enviratope._getMeasurement.apply( this, arguments );
3150
+ };
3151
+
3152
+ LayoutMode.prototype.getColumnWidth = function() {
3153
+ this.getSegmentSize( 'column', 'Width' );
3154
+ };
3155
+
3156
+ LayoutMode.prototype.getRowHeight = function() {
3157
+ this.getSegmentSize( 'row', 'Height' );
3158
+ };
3159
+
3160
+ /**
3161
+ * get columnWidth or rowHeight
3162
+ * segment: 'column' or 'row'
3163
+ * size 'Width' or 'Height'
3164
+ **/
3165
+ LayoutMode.prototype.getSegmentSize = function( segment, size ) {
3166
+ var segmentName = segment + size;
3167
+ var outerSize = 'outer' + size;
3168
+ // columnWidth / outerWidth // rowHeight / outerHeight
3169
+ this._getMeasurement( segmentName, outerSize );
3170
+ // got rowHeight or columnWidth, we can chill
3171
+ if ( this[ segmentName ] ) {
3172
+ return;
3173
+ }
3174
+ // fall back to item of first element
3175
+ var firstItemSize = this.getFirstItemSize();
3176
+ this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||
3177
+ // or size of container
3178
+ this.enviratope.size[ 'inner' + size ];
3179
+ };
3180
+
3181
+ LayoutMode.prototype.getFirstItemSize = function() {
3182
+ var firstItem = this.enviratope.filteredItems[0];
3183
+ return firstItem && firstItem.element && getSize( firstItem.element );
3184
+ };
3185
+
3186
+ // ----- methods that should reference enviratope ----- //
3187
+
3188
+ LayoutMode.prototype.layout = function() {
3189
+ this.enviratope.layout.apply( this.enviratope, arguments );
3190
+ };
3191
+
3192
+ LayoutMode.prototype.getSize = function() {
3193
+ this.enviratope.getSize();
3194
+ this.size = this.enviratope.size;
3195
+ };
3196
+
3197
+ // -------------------------- create -------------------------- //
3198
+
3199
+ LayoutMode.modes = {};
3200
+
3201
+ LayoutMode.create = function( namespace, options ) {
3202
+
3203
+ function Mode() {
3204
+ LayoutMode.apply( this, arguments );
3205
+ }
3206
+
3207
+ Mode.prototype = new LayoutMode();
3208
+
3209
+ // default options
3210
+ if ( options ) {
3211
+ Mode.options = options;
3212
+ }
3213
+
3214
+ Mode.prototype.namespace = namespace;
3215
+ // register in Enviratope
3216
+ LayoutMode.modes[ namespace ] = Mode;
3217
+
3218
+ return Mode;
3219
+ };
3220
+
3221
+ return LayoutMode;
3222
+
3223
+ }));
3224
+
3225
+ /*!
3226
+ * Masonry v3.3.1
3227
+ * Cascading grid layout library
3228
+ * http://masonry.desandro.com
3229
+ * MIT License
3230
+ * by David DeSandro
3231
+ */
3232
+
3233
+ ( function( window, factory ) {
3234
+ 'use strict';
3235
+ // universal module definition
3236
+ if ( typeof define === 'function' && define.amd ) {
3237
+ // AMD
3238
+ define( 'masonry/masonry',[
3239
+ 'outlayer/outlayer',
3240
+ 'get-size/get-size',
3241
+ 'fizzy-ui-utils/utils'
3242
+ ],
3243
+ factory );
3244
+ } else if ( typeof exports === 'object' ) {
3245
+ // CommonJS
3246
+ module.exports = factory(
3247
+ require('outlayer'),
3248
+ require('get-size'),
3249
+ require('fizzy-ui-utils')
3250
+ );
3251
+ } else {
3252
+ // browser global
3253
+ window.Masonry = factory(
3254
+ window.Outlayer,
3255
+ window.getSize,
3256
+ window.fizzyUIUtils
3257
+ );
3258
+ }
3259
+
3260
+ }( window, function factory( Outlayer, getSize, utils ) {
3261
+
3262
+
3263
+
3264
+ // -------------------------- masonryDefinition -------------------------- //
3265
+
3266
+ // create an Outlayer layout class
3267
+ var Masonry = Outlayer.create('masonry');
3268
+
3269
+ Masonry.prototype._resetLayout = function() {
3270
+ this.getSize();
3271
+ this._getMeasurement( 'columnWidth', 'outerWidth' );
3272
+ this._getMeasurement( 'gutter', 'outerWidth' );
3273
+ this.measureColumns();
3274
+
3275
+ // reset column Y
3276
+ var i = this.cols;
3277
+ this.colYs = [];
3278
+ while (i--) {
3279
+ this.colYs.push( 0 );
3280
+ }
3281
+
3282
+ this.maxY = 0;
3283
+ };
3284
+
3285
+ Masonry.prototype.measureColumns = function() {
3286
+ this.getContainerWidth();
3287
+ // if columnWidth is 0, default to outerWidth of first item
3288
+ if ( !this.columnWidth ) {
3289
+ var firstItem = this.items[0];
3290
+ var firstItemElem = firstItem && firstItem.element;
3291
+ // columnWidth fall back to item of first element
3292
+ this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||
3293
+ // if first elem has no width, default to size of container
3294
+ this.containerWidth;
3295
+ }
3296
+
3297
+ var columnWidth = this.columnWidth += this.gutter;
3298
+
3299
+ // calculate columns
3300
+ var containerWidth = this.containerWidth + this.gutter;
3301
+ var cols = containerWidth / columnWidth;
3302
+ // fix rounding errors, typically with gutters
3303
+ var excess = columnWidth - containerWidth % columnWidth;
3304
+ // if overshoot is less than a pixel, round up, otherwise floor it
3305
+ var mathMethod = excess && excess < 1 ? 'round' : 'floor';
3306
+ cols = Math[ mathMethod ]( cols );
3307
+ this.cols = Math.max( cols, 1 );
3308
+ };
3309
+
3310
+ Masonry.prototype.getContainerWidth = function() {
3311
+ // container is parent if fit width
3312
+ var container = this.options.isFitWidth ? this.element.parentNode : this.element;
3313
+ // check that this.size and size are there
3314
+ // IE8 triggers resize on body size change, so they might not be
3315
+ var size = getSize( container );
3316
+ this.containerWidth = size && size.innerWidth;
3317
+ };
3318
+
3319
+ Masonry.prototype._getItemLayoutPosition = function( item ) {
3320
+ item.getSize();
3321
+ // how many columns does this brick span
3322
+ var remainder = item.size.outerWidth % this.columnWidth;
3323
+ var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
3324
+ // round if off by 1 pixel, otherwise use ceil
3325
+ var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );
3326
+ colSpan = Math.min( colSpan, this.cols );
3327
+
3328
+ var colGroup = this._getColGroup( colSpan );
3329
+ // get the minimum Y value from the columns
3330
+ var minimumY = Math.min.apply( Math, colGroup );
3331
+ var shortColIndex = utils.indexOf( colGroup, minimumY );
3332
+
3333
+ // position the brick
3334
+ var position = {
3335
+ x: this.columnWidth * shortColIndex,
3336
+ y: minimumY
3337
+ };
3338
+
3339
+ // apply setHeight to necessary columns
3340
+ var setHeight = minimumY + item.size.outerHeight;
3341
+ var setSpan = this.cols + 1 - colGroup.length;
3342
+ for ( var i = 0; i < setSpan; i++ ) {
3343
+ this.colYs[ shortColIndex + i ] = setHeight;
3344
+ }
3345
+
3346
+ return position;
3347
+ };
3348
+
3349
+ /**
3350
+ * @param {Number} colSpan - number of columns the element spans
3351
+ * @returns {Array} colGroup
3352
+ */
3353
+ Masonry.prototype._getColGroup = function( colSpan ) {
3354
+ if ( colSpan < 2 ) {
3355
+ // if brick spans only one column, use all the column Ys
3356
+ return this.colYs;
3357
+ }
3358
+
3359
+ var colGroup = [];
3360
+ // how many different places could this brick fit horizontally
3361
+ var groupCount = this.cols + 1 - colSpan;
3362
+ // for each group potential horizontal position
3363
+ for ( var i = 0; i < groupCount; i++ ) {
3364
+ // make an array of colY values for that one group
3365
+ var groupColYs = this.colYs.slice( i, i + colSpan );
3366
+ // and get the max value of the array
3367
+ colGroup[i] = Math.max.apply( Math, groupColYs );
3368
+ }
3369
+ return colGroup;
3370
+ };
3371
+
3372
+ Masonry.prototype._manageStamp = function( stamp ) {
3373
+ var stampSize = getSize( stamp );
3374
+ var offset = this._getElementOffset( stamp );
3375
+ // get the columns that this stamp affects
3376
+ var firstX = this.options.isOriginLeft ? offset.left : offset.right;
3377
+ var lastX = firstX + stampSize.outerWidth;
3378
+ var firstCol = Math.floor( firstX / this.columnWidth );
3379
+ firstCol = Math.max( 0, firstCol );
3380
+ var lastCol = Math.floor( lastX / this.columnWidth );
3381
+ // lastCol should not go over if multiple of columnWidth #425
3382
+ lastCol -= lastX % this.columnWidth ? 0 : 1;
3383
+ lastCol = Math.min( this.cols - 1, lastCol );
3384
+ // set colYs to bottom of the stamp
3385
+ var stampMaxY = ( this.options.isOriginTop ? offset.top : offset.bottom ) +
3386
+ stampSize.outerHeight;
3387
+ for ( var i = firstCol; i <= lastCol; i++ ) {
3388
+ this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );
3389
+ }
3390
+ };
3391
+
3392
+ Masonry.prototype._getContainerSize = function() {
3393
+ this.maxY = Math.max.apply( Math, this.colYs );
3394
+ var size = {
3395
+ height: this.maxY
3396
+ };
3397
+
3398
+ if ( this.options.isFitWidth ) {
3399
+ size.width = this._getContainerFitWidth();
3400
+ }
3401
+
3402
+ return size;
3403
+ };
3404
+
3405
+ Masonry.prototype._getContainerFitWidth = function() {
3406
+ var unusedCols = 0;
3407
+ // count unused columns
3408
+ var i = this.cols;
3409
+ while ( --i ) {
3410
+ if ( this.colYs[i] !== 0 ) {
3411
+ break;
3412
+ }
3413
+ unusedCols++;
3414
+ }
3415
+ // fit container to columns that have been used
3416
+ return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;
3417
+ };
3418
+
3419
+ Masonry.prototype.needsResizeLayout = function() {
3420
+ var previousWidth = this.containerWidth;
3421
+ this.getContainerWidth();
3422
+ return previousWidth !== this.containerWidth;
3423
+ };
3424
+
3425
+ return Masonry;
3426
+
3427
+ }));
3428
+
3429
+ /*!
3430
+ * Masonry layout mode
3431
+ * sub-classes Masonry
3432
+ * http://masonry.desandro.com
3433
+ */
3434
+
3435
+ ( function( window, factory ) {
3436
+ 'use strict';
3437
+ // universal module definition
3438
+ if ( typeof define == 'function' && define.amd ) {
3439
+ // AMD
3440
+ define( 'enviratope/js/layout-modes/masonry',[
3441
+ '../layout-mode',
3442
+ 'masonry/masonry'
3443
+ ],
3444
+ factory );
3445
+ } else if ( typeof exports == 'object' ) {
3446
+ // CommonJS
3447
+ module.exports = factory(
3448
+ require('../layout-mode'),
3449
+ require('masonry-layout')
3450
+ );
3451
+ } else {
3452
+ // browser global
3453
+ factory(
3454
+ window.Enviratope.LayoutMode,
3455
+ window.Masonry
3456
+ );
3457
+ }
3458
+
3459
+ }( window, function factory( LayoutMode, Masonry ) {
3460
+ 'use strict';
3461
+
3462
+ // -------------------------- helpers -------------------------- //
3463
+
3464
+ // extend objects
3465
+ function extend( a, b ) {
3466
+ for ( var prop in b ) {
3467
+ a[ prop ] = b[ prop ];
3468
+ }
3469
+ return a;
3470
+ }
3471
+
3472
+ // -------------------------- masonryDefinition -------------------------- //
3473
+
3474
+ // create an Outlayer layout class
3475
+ var MasonryMode = LayoutMode.create('masonry');
3476
+
3477
+ // save on to these methods
3478
+ var _getElementOffset = MasonryMode.prototype._getElementOffset;
3479
+ var layout = MasonryMode.prototype.layout;
3480
+ var _getMeasurement = MasonryMode.prototype._getMeasurement;
3481
+
3482
+ // sub-class Masonry
3483
+ extend( MasonryMode.prototype, Masonry.prototype );
3484
+
3485
+ // set back, as it was overwritten by Masonry
3486
+ MasonryMode.prototype._getElementOffset = _getElementOffset;
3487
+ MasonryMode.prototype.layout = layout;
3488
+ MasonryMode.prototype._getMeasurement = _getMeasurement;
3489
+
3490
+ var measureColumns = MasonryMode.prototype.measureColumns;
3491
+ MasonryMode.prototype.measureColumns = function() {
3492
+ // set items, used if measuring first item
3493
+ this.items = this.enviratope.filteredItems;
3494
+ measureColumns.call( this );
3495
+ };
3496
+
3497
+ // HACK copy over isOriginLeft/Top options
3498
+ var _manageStamp = MasonryMode.prototype._manageStamp;
3499
+ MasonryMode.prototype._manageStamp = function() {
3500
+ this.options.isOriginLeft = this.enviratope.options.isOriginLeft;
3501
+ this.options.isOriginTop = this.enviratope.options.isOriginTop;
3502
+ _manageStamp.apply( this, arguments );
3503
+ };
3504
+
3505
+ return MasonryMode;
3506
+
3507
+ }));
3508
+
3509
+ /**
3510
+ * fitRows layout mode
3511
+ */
3512
+
3513
+ ( function( window, factory ) {
3514
+ 'use strict';
3515
+ // universal module definition
3516
+ if ( typeof define == 'function' && define.amd ) {
3517
+ // AMD
3518
+ define( 'enviratope/js/layout-modes/fit-rows',[
3519
+ '../layout-mode'
3520
+ ],
3521
+ factory );
3522
+ } else if ( typeof exports == 'object' ) {
3523
+ // CommonJS
3524
+ module.exports = factory(
3525
+ require('../layout-mode')
3526
+ );
3527
+ } else {
3528
+ // browser global
3529
+ factory(
3530
+ window.Enviratope.LayoutMode
3531
+ );
3532
+ }
3533
+
3534
+ }( window, function factory( LayoutMode ) {
3535
+ 'use strict';
3536
+
3537
+ var FitRows = LayoutMode.create('fitRows');
3538
+
3539
+ FitRows.prototype._resetLayout = function() {
3540
+ this.x = 0;
3541
+ this.y = 0;
3542
+ this.maxY = 0;
3543
+ this._getMeasurement( 'gutter', 'outerWidth' );
3544
+ };
3545
+
3546
+ FitRows.prototype._getItemLayoutPosition = function( item ) {
3547
+ item.getSize();
3548
+
3549
+ var itemWidth = item.size.outerWidth + this.gutter;
3550
+ // if this element cannot fit in the current row
3551
+ var containerWidth = this.enviratope.size.innerWidth + this.gutter;
3552
+ if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {
3553
+ this.x = 0;
3554
+ this.y = this.maxY;
3555
+ }
3556
+
3557
+ var position = {
3558
+ x: this.x,
3559
+ y: this.y
3560
+ };
3561
+
3562
+ this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );
3563
+ this.x += itemWidth;
3564
+
3565
+ return position;
3566
+ };
3567
+
3568
+ FitRows.prototype._getContainerSize = function() {
3569
+ return { height: this.maxY };
3570
+ };
3571
+
3572
+ return FitRows;
3573
+
3574
+ }));
3575
+
3576
+ /**
3577
+ * vertical layout mode
3578
+ */
3579
+
3580
+ ( function( window, factory ) {
3581
+ 'use strict';
3582
+ // universal module definition
3583
+ if ( typeof define == 'function' && define.amd ) {
3584
+ // AMD
3585
+ define( 'enviratope/js/layout-modes/vertical',[
3586
+ '../layout-mode'
3587
+ ],
3588
+ factory );
3589
+ } else if ( typeof exports == 'object' ) {
3590
+ // CommonJS
3591
+ module.exports = factory(
3592
+ require('../layout-mode')
3593
+ );
3594
+ } else {
3595
+ // browser global
3596
+ factory(
3597
+ window.Enviratope.LayoutMode
3598
+ );
3599
+ }
3600
+
3601
+ }( window, function factory( LayoutMode ) {
3602
+ 'use strict';
3603
+
3604
+ var Vertical = LayoutMode.create( 'vertical', {
3605
+ horizontalAlignment: 0
3606
+ });
3607
+
3608
+ Vertical.prototype._resetLayout = function() {
3609
+ this.y = 0;
3610
+ };
3611
+
3612
+ Vertical.prototype._getItemLayoutPosition = function( item ) {
3613
+ item.getSize();
3614
+ var x = ( this.enviratope.size.innerWidth - item.size.outerWidth ) *
3615
+ this.options.horizontalAlignment;
3616
+ var y = this.y;
3617
+ this.y += item.size.outerHeight;
3618
+ return { x: x, y: y };
3619
+ };
3620
+
3621
+ Vertical.prototype._getContainerSize = function() {
3622
+ return { height: this.y };
3623
+ };
3624
+
3625
+ return Vertical;
3626
+
3627
+ }));
3628
+
3629
+ /*!
3630
+ * Enviratope v2.2.2
3631
+ *
3632
+ * Licensed GPLv3 for open source use
3633
+ * or Enviratope Commercial License for commercial use
3634
+ *
3635
+ * http://enviratope.metafizzy.co
3636
+ * Copyright 2015 Metafizzy
3637
+ */
3638
+
3639
+ ( function( window, factory ) {
3640
+ 'use strict';
3641
+ // universal module definition
3642
+
3643
+ if ( typeof define == 'function' && define.amd ) {
3644
+ // AMD
3645
+ define( [
3646
+ 'outlayer/outlayer',
3647
+ 'get-size/get-size',
3648
+ 'matches-selector/matches-selector',
3649
+ 'fizzy-ui-utils/utils',
3650
+ 'enviratope/js/item',
3651
+ 'enviratope/js/layout-mode',
3652
+ // include default layout modes
3653
+ 'enviratope/js/layout-modes/masonry',
3654
+ 'enviratope/js/layout-modes/fit-rows',
3655
+ 'enviratope/js/layout-modes/vertical'
3656
+ ],
3657
+ function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {
3658
+ return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );
3659
+ });
3660
+ } else if ( typeof exports == 'object' ) {
3661
+ // CommonJS
3662
+ module.exports = factory(
3663
+ window,
3664
+ require('outlayer'),
3665
+ require('get-size'),
3666
+ require('desandro-matches-selector'),
3667
+ require('fizzy-ui-utils'),
3668
+ require('./item'),
3669
+ require('./layout-mode'),
3670
+ // include default layout modes
3671
+ require('./layout-modes/masonry'),
3672
+ require('./layout-modes/fit-rows'),
3673
+ require('./layout-modes/vertical')
3674
+ );
3675
+ } else {
3676
+ // browser global
3677
+ window.Enviratope = factory(
3678
+ window,
3679
+ window.Outlayer,
3680
+ window.getSize,
3681
+ window.matchesSelector,
3682
+ window.fizzyUIUtils,
3683
+ window.Enviratope.Item,
3684
+ window.Enviratope.LayoutMode
3685
+ );
3686
+ }
3687
+
3688
+ }( window, function factory( window, Outlayer, getSize, matchesSelector, utils,
3689
+ Item, LayoutMode ) {
3690
+
3691
+
3692
+
3693
+ // -------------------------- vars -------------------------- //
3694
+
3695
+ var jQuery = window.jQuery;
3696
+
3697
+ // -------------------------- helpers -------------------------- //
3698
+
3699
+ var trim = String.prototype.trim ?
3700
+ function( str ) {
3701
+ return str.trim();
3702
+ } :
3703
+ function( str ) {
3704
+ return str.replace( /^\s+|\s+$/g, '' );
3705
+ };
3706
+
3707
+ var docElem = document.documentElement;
3708
+
3709
+ var getText = docElem.textContent ?
3710
+ function( elem ) {
3711
+ return elem.textContent;
3712
+ } :
3713
+ function( elem ) {
3714
+ return elem.innerText;
3715
+ };
3716
+
3717
+ // -------------------------- enviratopeDefinition -------------------------- //
3718
+
3719
+ // create an Outlayer layout class
3720
+ var Enviratope = Outlayer.create( 'enviratope', {
3721
+ layoutMode: "masonry",
3722
+ isJQueryFiltering: true,
3723
+ sortAscending: true
3724
+ });
3725
+
3726
+ Enviratope.Item = Item;
3727
+ Enviratope.LayoutMode = LayoutMode;
3728
+
3729
+ Enviratope.prototype._create = function() {
3730
+ this.itemGUID = 0;
3731
+ // functions that sort items
3732
+ this._sorters = {};
3733
+ this._getSorters();
3734
+ // call super
3735
+ Outlayer.prototype._create.call( this );
3736
+
3737
+ // create layout modes
3738
+ this.modes = {};
3739
+ // start filteredItems with all items
3740
+ this.filteredItems = this.items;
3741
+ // keep of track of sortBys
3742
+ this.sortHistory = [ 'original-order' ];
3743
+ // create from registered layout modes
3744
+ for ( var name in LayoutMode.modes ) {
3745
+ this._initLayoutMode( name );
3746
+ }
3747
+ };
3748
+
3749
+ Enviratope.prototype.reloadItems = function() {
3750
+ // reset item ID counter
3751
+ this.itemGUID = 0;
3752
+ // call super
3753
+ Outlayer.prototype.reloadItems.call( this );
3754
+ };
3755
+
3756
+ Enviratope.prototype._itemize = function() {
3757
+ var items = Outlayer.prototype._itemize.apply( this, arguments );
3758
+ // assign ID for original-order
3759
+ for ( var i=0, len = items.length; i < len; i++ ) {
3760
+ var item = items[i];
3761
+ item.id = this.itemGUID++;
3762
+ }
3763
+ this._updateItemsSortData( items );
3764
+ return items;
3765
+ };
3766
+
3767
+
3768
+ // -------------------------- layout -------------------------- //
3769
+
3770
+ Enviratope.prototype._initLayoutMode = function( name ) {
3771
+ var Mode = LayoutMode.modes[ name ];
3772
+ // set mode options
3773
+ // HACK extend initial options, back-fill in default options
3774
+ var initialOpts = this.options[ name ] || {};
3775
+ this.options[ name ] = Mode.options ?
3776
+ utils.extend( Mode.options, initialOpts ) : initialOpts;
3777
+ // init layout mode instance
3778
+ this.modes[ name ] = new Mode( this );
3779
+ };
3780
+
3781
+
3782
+ Enviratope.prototype.layout = function() {
3783
+ // if first time doing layout, do all magic
3784
+ if ( !this._isLayoutInited && this.options.isInitLayout ) {
3785
+ this.arrange();
3786
+ return;
3787
+ }
3788
+ this._layout();
3789
+ };
3790
+
3791
+ // private method to be used in layout() & magic()
3792
+ Enviratope.prototype._layout = function() {
3793
+ // don't animate first layout
3794
+ var isInstant = this._getIsInstant();
3795
+ // layout flow
3796
+ this._resetLayout();
3797
+ this._manageStamps();
3798
+ this.layoutItems( this.filteredItems, isInstant );
3799
+
3800
+ // flag for initalized
3801
+ this._isLayoutInited = true;
3802
+ };
3803
+
3804
+ // filter + sort + layout
3805
+ Enviratope.prototype.arrange = function( opts ) {
3806
+ // set any options pass
3807
+ this.option( opts );
3808
+ this._getIsInstant();
3809
+ // filter, sort, and layout
3810
+
3811
+ // filter
3812
+ var filtered = this._filter( this.items );
3813
+ this.filteredItems = filtered.matches;
3814
+
3815
+ var _this = this;
3816
+ function hideReveal() {
3817
+ _this.reveal( filtered.needReveal );
3818
+ _this.hide( filtered.needHide );
3819
+ }
3820
+
3821
+ this._bindArrangeComplete();
3822
+
3823
+ if ( this._isInstant ) {
3824
+ this._noTransition( hideReveal );
3825
+ } else {
3826
+ hideReveal();
3827
+ }
3828
+
3829
+ this._sort();
3830
+ this._layout();
3831
+ };
3832
+ // alias to _init for main plugin method
3833
+ Enviratope.prototype._init = Enviratope.prototype.arrange;
3834
+
3835
+ // HACK
3836
+ // Don't animate/transition first layout
3837
+ // Or don't animate/transition other layouts
3838
+ Enviratope.prototype._getIsInstant = function() {
3839
+ var isInstant = this.options.isLayoutInstant !== undefined ?
3840
+ this.options.isLayoutInstant : !this._isLayoutInited;
3841
+ this._isInstant = isInstant;
3842
+ return isInstant;
3843
+ };
3844
+
3845
+ // listen for layoutComplete, hideComplete and revealComplete
3846
+ // to trigger arrangeComplete
3847
+ Enviratope.prototype._bindArrangeComplete = function() {
3848
+ // listen for 3 events to trigger arrangeComplete
3849
+ var isLayoutComplete, isHideComplete, isRevealComplete;
3850
+ var _this = this;
3851
+ function arrangeParallelCallback() {
3852
+ if ( isLayoutComplete && isHideComplete && isRevealComplete ) {
3853
+ _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );
3854
+ }
3855
+ }
3856
+ this.once( 'layoutComplete', function() {
3857
+ isLayoutComplete = true;
3858
+ arrangeParallelCallback();
3859
+ });
3860
+ this.once( 'hideComplete', function() {
3861
+ isHideComplete = true;
3862
+ arrangeParallelCallback();
3863
+ });
3864
+ this.once( 'revealComplete', function() {
3865
+ isRevealComplete = true;
3866
+ arrangeParallelCallback();
3867
+ });
3868
+ };
3869
+
3870
+ // -------------------------- filter -------------------------- //
3871
+
3872
+ Enviratope.prototype._filter = function( items ) {
3873
+ var filter = this.options.filter;
3874
+ filter = filter || '*';
3875
+ var matches = [];
3876
+ var hiddenMatched = [];
3877
+ var visibleUnmatched = [];
3878
+
3879
+ var test = this._getFilterTest( filter );
3880
+
3881
+ // test each item
3882
+ for ( var i=0, len = items.length; i < len; i++ ) {
3883
+ var item = items[i];
3884
+ if ( item.isIgnored ) {
3885
+ continue;
3886
+ }
3887
+ // add item to either matched or unmatched group
3888
+ var isMatched = test( item );
3889
+ // item.isFilterMatched = isMatched;
3890
+ // add to matches if its a match
3891
+ if ( isMatched ) {
3892
+ matches.push( item );
3893
+ }
3894
+ // add to additional group if item needs to be hidden or revealed
3895
+ if ( isMatched && item.isHidden ) {
3896
+ hiddenMatched.push( item );
3897
+ } else if ( !isMatched && !item.isHidden ) {
3898
+ visibleUnmatched.push( item );
3899
+ }
3900
+ }
3901
+
3902
+ // return collections of items to be manipulated
3903
+ return {
3904
+ matches: matches,
3905
+ needReveal: hiddenMatched,
3906
+ needHide: visibleUnmatched
3907
+ };
3908
+ };
3909
+
3910
+ // get a jQuery, function, or a matchesSelector test given the filter
3911
+ Enviratope.prototype._getFilterTest = function( filter ) {
3912
+ if ( jQuery && this.options.isJQueryFiltering ) {
3913
+ // use jQuery
3914
+ return function( item ) {
3915
+ return jQuery( item.element ).is( filter );
3916
+ };
3917
+ }
3918
+ if ( typeof filter == 'function' ) {
3919
+ // use filter as function
3920
+ return function( item ) {
3921
+ return filter( item.element );
3922
+ };
3923
+ }
3924
+ // default, use filter as selector string
3925
+ return function( item ) {
3926
+ return matchesSelector( item.element, filter );
3927
+ };
3928
+ };
3929
+
3930
+ // -------------------------- sorting -------------------------- //
3931
+
3932
+ /**
3933
+ * @params {Array} elems
3934
+ * @public
3935
+ */
3936
+ Enviratope.prototype.updateSortData = function( elems ) {
3937
+ // get items
3938
+ var items;
3939
+ if ( elems ) {
3940
+ elems = utils.makeArray( elems );
3941
+ items = this.getItems( elems );
3942
+ } else {
3943
+ // update all items if no elems provided
3944
+ items = this.items;
3945
+ }
3946
+
3947
+ this._getSorters();
3948
+ this._updateItemsSortData( items );
3949
+ };
3950
+
3951
+ Enviratope.prototype._getSorters = function() {
3952
+ var getSortData = this.options.getSortData;
3953
+ for ( var key in getSortData ) {
3954
+ var sorter = getSortData[ key ];
3955
+ this._sorters[ key ] = mungeSorter( sorter );
3956
+ }
3957
+ };
3958
+
3959
+ /**
3960
+ * @params {Array} items - of Enviratope.Items
3961
+ * @private
3962
+ */
3963
+ Enviratope.prototype._updateItemsSortData = function( items ) {
3964
+ // do not update if no items
3965
+ var len = items && items.length;
3966
+
3967
+ for ( var i=0; len && i < len; i++ ) {
3968
+ var item = items[i];
3969
+ item.updateSortData();
3970
+ }
3971
+ };
3972
+
3973
+ // ----- munge sorter ----- //
3974
+
3975
+ // encapsulate this, as we just need mungeSorter
3976
+ // other functions in here are just for munging
3977
+ var mungeSorter = ( function() {
3978
+ // add a magic layer to sorters for convienent shorthands
3979
+ // `.foo-bar` will use the text of .foo-bar querySelector
3980
+ // `[foo-bar]` will use attribute
3981
+ // you can also add parser
3982
+ // `.foo-bar parseInt` will parse that as a number
3983
+ function mungeSorter( sorter ) {
3984
+ // if not a string, return function or whatever it is
3985
+ if ( typeof sorter != 'string' ) {
3986
+ return sorter;
3987
+ }
3988
+ // parse the sorter string
3989
+ var args = trim( sorter ).split(' ');
3990
+ var query = args[0];
3991
+ // check if query looks like [an-attribute]
3992
+ var attrMatch = query.match( /^\[(.+)\]$/ );
3993
+ var attr = attrMatch && attrMatch[1];
3994
+ var getValue = getValueGetter( attr, query );
3995
+ // use second argument as a parser
3996
+ var parser = Enviratope.sortDataParsers[ args[1] ];
3997
+ // parse the value, if there was a parser
3998
+ sorter = parser ? function( elem ) {
3999
+ return elem && parser( getValue( elem ) );
4000
+ } :
4001
+ // otherwise just return value
4002
+ function( elem ) {
4003
+ return elem && getValue( elem );
4004
+ };
4005
+
4006
+ return sorter;
4007
+ }
4008
+
4009
+ // get an attribute getter, or get text of the querySelector
4010
+ function getValueGetter( attr, query ) {
4011
+ var getValue;
4012
+ // if query looks like [foo-bar], get attribute
4013
+ if ( attr ) {
4014
+ getValue = function( elem ) {
4015
+ return elem.getAttribute( attr );
4016
+ };
4017
+ } else {
4018
+ // otherwise, assume its a querySelector, and get its text
4019
+ getValue = function( elem ) {
4020
+ var child = elem.querySelector( query );
4021
+ return child && getText( child );
4022
+ };
4023
+ }
4024
+ return getValue;
4025
+ }
4026
+
4027
+ return mungeSorter;
4028
+ })();
4029
+
4030
+ // parsers used in getSortData shortcut strings
4031
+ Enviratope.sortDataParsers = {
4032
+ 'parseInt': function( val ) {
4033
+ return parseInt( val, 10 );
4034
+ },
4035
+ 'parseFloat': function( val ) {
4036
+ return parseFloat( val );
4037
+ }
4038
+ };
4039
+
4040
+ // ----- sort method ----- //
4041
+
4042
+ // sort filteredItem order
4043
+ Enviratope.prototype._sort = function() {
4044
+ var sortByOpt = this.options.sortBy;
4045
+ if ( !sortByOpt ) {
4046
+ return;
4047
+ }
4048
+ // concat all sortBy and sortHistory
4049
+ var sortBys = [].concat.apply( sortByOpt, this.sortHistory );
4050
+ // sort magic
4051
+ var itemSorter = getItemSorter( sortBys, this.options.sortAscending );
4052
+ this.filteredItems.sort( itemSorter );
4053
+ // keep track of sortBy History
4054
+ if ( sortByOpt != this.sortHistory[0] ) {
4055
+ // add to front, oldest goes in last
4056
+ this.sortHistory.unshift( sortByOpt );
4057
+ }
4058
+ };
4059
+
4060
+ // returns a function used for sorting
4061
+ function getItemSorter( sortBys, sortAsc ) {
4062
+ return function sorter( itemA, itemB ) {
4063
+ // cycle through all sortKeys
4064
+ for ( var i = 0, len = sortBys.length; i < len; i++ ) {
4065
+ var sortBy = sortBys[i];
4066
+ var a = itemA.sortData[ sortBy ];
4067
+ var b = itemB.sortData[ sortBy ];
4068
+ if ( a > b || a < b ) {
4069
+ // if sortAsc is an object, use the value given the sortBy key
4070
+ var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;
4071
+ var direction = isAscending ? 1 : -1;
4072
+ return ( a > b ? 1 : -1 ) * direction;
4073
+ }
4074
+ }
4075
+ return 0;
4076
+ };
4077
+ }
4078
+
4079
+ // -------------------------- methods -------------------------- //
4080
+
4081
+ // get layout mode
4082
+ Enviratope.prototype._mode = function() {
4083
+ var layoutMode = this.options.layoutMode;
4084
+ var mode = this.modes[ layoutMode ];
4085
+ if ( !mode ) {
4086
+ // TODO console.error
4087
+ throw new Error( 'No layout mode: ' + layoutMode );
4088
+ }
4089
+ // HACK sync mode's options
4090
+ // any options set after init for layout mode need to be synced
4091
+ mode.options = this.options[ layoutMode ];
4092
+ return mode;
4093
+ };
4094
+
4095
+ Enviratope.prototype._resetLayout = function() {
4096
+ // trigger original reset layout
4097
+ Outlayer.prototype._resetLayout.call( this );
4098
+ this._mode()._resetLayout();
4099
+ };
4100
+
4101
+ Enviratope.prototype._getItemLayoutPosition = function( item ) {
4102
+ return this._mode()._getItemLayoutPosition( item );
4103
+ };
4104
+
4105
+ Enviratope.prototype._manageStamp = function( stamp ) {
4106
+ this._mode()._manageStamp( stamp );
4107
+ };
4108
+
4109
+ Enviratope.prototype._getContainerSize = function() {
4110
+ return this._mode()._getContainerSize();
4111
+ };
4112
+
4113
+ Enviratope.prototype.needsResizeLayout = function() {
4114
+ return this._mode().needsResizeLayout();
4115
+ };
4116
+
4117
+ // -------------------------- adding & removing -------------------------- //
4118
+
4119
+ // HEADS UP overwrites default Outlayer appended
4120
+ Enviratope.prototype.appended = function( elems ) {
4121
+ var items = this.addItems( elems );
4122
+ if ( !items.length ) {
4123
+ return;
4124
+ }
4125
+ // filter, layout, reveal new items
4126
+ var filteredItems = this._filterRevealAdded( items );
4127
+ // add to filteredItems
4128
+ this.filteredItems = this.filteredItems.concat( filteredItems );
4129
+ };
4130
+
4131
+ // HEADS UP overwrites default Outlayer prepended
4132
+ Enviratope.prototype.prepended = function( elems ) {
4133
+ var items = this._itemize( elems );
4134
+ if ( !items.length ) {
4135
+ return;
4136
+ }
4137
+ // start new layout
4138
+ this._resetLayout();
4139
+ this._manageStamps();
4140
+ // filter, layout, reveal new items
4141
+ var filteredItems = this._filterRevealAdded( items );
4142
+ // layout previous items
4143
+ this.layoutItems( this.filteredItems );
4144
+ // add to items and filteredItems
4145
+ this.filteredItems = filteredItems.concat( this.filteredItems );
4146
+ this.items = items.concat( this.items );
4147
+ };
4148
+
4149
+ Enviratope.prototype._filterRevealAdded = function( items ) {
4150
+ var filtered = this._filter( items );
4151
+ this.hide( filtered.needHide );
4152
+ // reveal all new items
4153
+ this.reveal( filtered.matches );
4154
+ // layout new items, no transition
4155
+ this.layoutItems( filtered.matches, true );
4156
+ return filtered.matches;
4157
+ };
4158
+
4159
+ /**
4160
+ * Filter, sort, and layout newly-appended item elements
4161
+ * @param {Array or NodeList or Element} elems
4162
+ */
4163
+ Enviratope.prototype.insert = function( elems ) {
4164
+ var items = this.addItems( elems );
4165
+ if ( !items.length ) {
4166
+ return;
4167
+ }
4168
+ // append item elements
4169
+ var i, item;
4170
+ var len = items.length;
4171
+ for ( i=0; i < len; i++ ) {
4172
+ item = items[i];
4173
+ this.element.appendChild( item.element );
4174
+ }
4175
+ // filter new stuff
4176
+ var filteredInsertItems = this._filter( items ).matches;
4177
+ // set flag
4178
+ for ( i=0; i < len; i++ ) {
4179
+ items[i].isLayoutInstant = true;
4180
+ }
4181
+ this.arrange();
4182
+ // reset flag
4183
+ for ( i=0; i < len; i++ ) {
4184
+ delete items[i].isLayoutInstant;
4185
+ }
4186
+ this.reveal( filteredInsertItems );
4187
+ };
4188
+
4189
+ var _remove = Enviratope.prototype.remove;
4190
+ Enviratope.prototype.remove = function( elems ) {
4191
+ elems = utils.makeArray( elems );
4192
+ var removeItems = this.getItems( elems );
4193
+ // do regular thing
4194
+ _remove.call( this, elems );
4195
+ // bail if no items to remove
4196
+ var len = removeItems && removeItems.length;
4197
+ if ( !len ) {
4198
+ return;
4199
+ }
4200
+ // remove elems from filteredItems
4201
+ for ( var i=0; i < len; i++ ) {
4202
+ var item = removeItems[i];
4203
+ // remove item from collection
4204
+ utils.removeFrom( this.filteredItems, item );
4205
+ }
4206
+ };
4207
+
4208
+ Enviratope.prototype.shuffle = function() {
4209
+ // update random sortData
4210
+ for ( var i=0, len = this.items.length; i < len; i++ ) {
4211
+ var item = this.items[i];
4212
+ item.sortData.random = Math.random();
4213
+ }
4214
+ this.options.sortBy = 'random';
4215
+ this._sort();
4216
+ this._layout();
4217
+ };
4218
+
4219
+ /**
4220
+ * trigger fn without transition
4221
+ * kind of hacky to have this in the first place
4222
+ * @param {Function} fn
4223
+ * @returns ret
4224
+ * @private
4225
+ */
4226
+ Enviratope.prototype._noTransition = function( fn ) {
4227
+ // save transitionDuration before disabling
4228
+ var transitionDuration = this.options.transitionDuration;
4229
+ // disable transition
4230
+ this.options.transitionDuration = 0;
4231
+ // do it
4232
+ var returnValue = fn.call( this );
4233
+ // re-enable transition for reveal
4234
+ this.options.transitionDuration = transitionDuration;
4235
+ return returnValue;
4236
+ };
4237
+
4238
+ // ----- helper methods ----- //
4239
+
4240
+ /**
4241
+ * getter method for getting filtered item elements
4242
+ * @returns {Array} elems - collection of item elements
4243
+ */
4244
+ Enviratope.prototype.getFilteredItemElements = function() {
4245
+ var elems = [];
4246
+ for ( var i=0, len = this.filteredItems.length; i < len; i++ ) {
4247
+ elems.push( this.filteredItems[i].element );
4248
+ }
4249
+ return elems;
4250
+ };
4251
+
4252
+ // ----- ----- //
4253
+
4254
+ return Enviratope;
4255
+
4256
+ }));
assets/js/lib/touchswipe.js ADDED
@@ -0,0 +1,2038 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * @fileOverview TouchSwipe - jQuery Plugin
3
+ * @version 1.6.6
4
+ *
5
+ * @author Matt Bryson http://www.github.com/mattbryson
6
+ * @see https://github.com/mattbryson/TouchSwipe-Jquery-Plugin
7
+ * @see http://labs.rampinteractive.co.uk/touchSwipe/
8
+ * @see http://plugins.jquery.com/project/touchSwipe
9
+ *
10
+ * Copyright (c) 2010-2015 Matt Bryson
11
+ * Dual licensed under the MIT or GPL Version 2 licenses.
12
+ *
13
+ */
14
+
15
+ /*
16
+ *
17
+ * Changelog
18
+ * $Date: 2010-12-12 (Wed, 12 Dec 2010) $
19
+ * $version: 1.0.0
20
+ * $version: 1.0.1 - removed multibyte comments
21
+ *
22
+ * $Date: 2011-21-02 (Mon, 21 Feb 2011) $
23
+ * $version: 1.1.0 - added allowPageScroll property to allow swiping and scrolling of page
24
+ * - changed handler signatures so one handler can be used for multiple events
25
+ * $Date: 2011-23-02 (Wed, 23 Feb 2011) $
26
+ * $version: 1.2.0 - added click handler. This is fired if the user simply clicks and does not swipe. The event object and click target are passed to handler.
27
+ * - If you use the http://code.google.com/p/jquery-ui-for-ipad-and-iphone/ plugin, you can also assign jQuery mouse events to children of a touchSwipe object.
28
+ * $version: 1.2.1 - removed console log!
29
+ *
30
+ * $version: 1.2.2 - Fixed bug where scope was not preserved in callback methods.
31
+ *
32
+ * $Date: 2011-28-04 (Thurs, 28 April 2011) $
33
+ * $version: 1.2.4 - Changed licence terms to be MIT or GPL inline with jQuery. Added check for support of touch events to stop non compatible browsers erroring.
34
+ *
35
+ * $Date: 2011-27-09 (Tues, 27 September 2011) $
36
+ * $version: 1.2.5 - Added support for testing swipes with mouse on desktop browser (thanks to https://github.com/joelhy)
37
+ *
38
+ * $Date: 2012-14-05 (Mon, 14 May 2012) $
39
+ * $version: 1.2.6 - Added timeThreshold between start and end touch, so user can ignore slow swipes (thanks to Mark Chase). Default is null, all swipes are detected
40
+ *
41
+ * $Date: 2012-05-06 (Tues, 05 June 2012) $
42
+ * $version: 1.2.7 - Changed time threshold to have null default for backwards compatibility. Added duration param passed back in events, and refactored how time is handled.
43
+ *
44
+ * $Date: 2012-05-06 (Tues, 05 June 2012) $
45
+ * $version: 1.2.8 - Added the possibility to return a value like null or false in the trigger callback. In that way we can control when the touch start/move should take effect or not (simply by returning in some cases return null; or return false;) This effects the ontouchstart/ontouchmove event.
46
+ *
47
+ * $Date: 2012-06-06 (Wed, 06 June 2012) $
48
+ * $version: 1.3.0 - Refactored whole plugin to allow for methods to be executed, as well as exposed defaults for user override. Added 'enable', 'disable', and 'destroy' methods
49
+ *
50
+ * $Date: 2012-05-06 (Fri, 05 June 2012) $
51
+ * $version: 1.3.1 - Bug fixes - bind() with false as last argument is no longer supported in jQuery 1.6, also, if you just click, the duration is now returned correctly.
52
+ *
53
+ * $Date: 2012-29-07 (Sun, 29 July 2012) $
54
+ * $version: 1.3.2 - Added fallbackToMouseEvents option to NOT capture mouse events on non touch devices.
55
+ * - Added "all" fingers value to the fingers property, so any combination of fingers triggers the swipe, allowing event handlers to check the finger count
56
+ *
57
+ * $Date: 2012-09-08 (Thurs, 9 Aug 2012) $
58
+ * $version: 1.3.3 - Code tidy prep for minefied version
59
+ *
60
+ * $Date: 2012-04-10 (wed, 4 Oct 2012) $
61
+ * $version: 1.4.0 - Added pinch support, pinchIn and pinchOut
62
+ *
63
+ * $Date: 2012-11-10 (Thurs, 11 Oct 2012) $
64
+ * $version: 1.5.0 - Added excludedElements, a jquery selector that specifies child elements that do NOT trigger swipes. By default, this is one select that removes all form, input select, button and anchor elements.
65
+ *
66
+ * $Date: 2012-22-10 (Mon, 22 Oct 2012) $
67
+ * $version: 1.5.1 - Fixed bug with jQuery 1.8 and trailing comma in excludedElements
68
+ * - Fixed bug with IE and eventPreventDefault()
69
+ * $Date: 2013-01-12 (Fri, 12 Jan 2013) $
70
+ * $version: 1.6.0 - Fixed bugs with pinching, mainly when both pinch and swipe enabled, as well as adding time threshold for multifinger gestures, so releasing one finger beofre the other doesnt trigger as single finger gesture.
71
+ * - made the demo site all static local HTML pages so they can be run locally by a developer
72
+ * - added jsDoc comments and added documentation for the plugin
73
+ * - code tidy
74
+ * - added triggerOnTouchLeave property that will end the event when the user swipes off the element.
75
+ * $Date: 2013-03-23 (Sat, 23 Mar 2013) $
76
+ * $version: 1.6.1 - Added support for ie8 touch events
77
+ * $version: 1.6.2 - Added support for events binding with on / off / bind in jQ for all callback names.
78
+ * - Deprecated the 'click' handler in favour of tap.
79
+ * - added cancelThreshold property
80
+ * - added option method to update init options at runtime
81
+ * $version 1.6.3 - added doubletap, longtap events and longTapThreshold, doubleTapThreshold property
82
+ *
83
+ * $Date: 2013-04-04 (Thurs, 04 April 2013) $
84
+ * $version 1.6.4 - Fixed bug with cancelThreshold introduced in 1.6.3, where swipe status no longer fired start event, and stopped once swiping back.
85
+ *
86
+ * $Date: 2013-08-24 (Sat, 24 Aug 2013) $
87
+ * $version 1.6.5 - Merged a few pull requests fixing various bugs, added AMD support.
88
+ *
89
+ * $Date: 2014-06-04 (Wed, 04 June 2014) $
90
+ * $version 1.6.6 - Merge of pull requests.
91
+ * - IE10 touch support
92
+ * - Only prevent default event handling on valid swipe
93
+ * - Separate license/changelog comment
94
+ * - Detect if the swipe is valid at the end of the touch event.
95
+ * - Pass fingerdata to event handlers.
96
+ * - Add 'hold' gesture
97
+ * - Be more tolerant about the tap distance
98
+ * - Typos and minor fixes
99
+ *
100
+ * $Date: 2015-22-01 (Thurs, 22 Jan 2015) $
101
+ * $version 1.6.7 - Added patch from https://github.com/mattbryson/TouchSwipe-Jquery-Plugin/issues/206 to fix memory leak
102
+ */
103
+
104
+ /**
105
+ * See (http://jquery.com/).
106
+ * @name $
107
+ * @class
108
+ * See the jQuery Library (http://jquery.com/) for full details. This just
109
+ * documents the function and classes that are added to jQuery by this plug-in.
110
+ */
111
+
112
+ /**
113
+ * See (http://jquery.com/)
114
+ * @name fn
115
+ * @class
116
+ * See the jQuery Library (http://jquery.com/) for full details. This just
117
+ * documents the function and classes that are added to jQuery by this plug-in.
118
+ * @memberOf $
119
+ */
120
+
121
+
122
+
123
+ (function (factory) {
124
+ if (typeof define === 'function' && define.amd && define.amd.jQuery) {
125
+ // AMD. Register as anonymous module.
126
+ define(['jquery'], factory);
127
+ } else {
128
+ // Browser globals.
129
+ factory(jQuery);
130
+ }
131
+ }(function ($) {
132
+ "use strict";
133
+
134
+ //Constants
135
+ var LEFT = "left",
136
+ RIGHT = "right",
137
+ UP = "up",
138
+ DOWN = "down",
139
+ IN = "in",
140
+ OUT = "out",
141
+
142
+ NONE = "none",
143
+ AUTO = "auto",
144
+
145
+ SWIPE = "swipe",
146
+ PINCH = "pinch",
147
+ TAP = "tap",
148
+ DOUBLE_TAP = "doubletap",
149
+ LONG_TAP = "longtap",
150
+ HOLD = "hold",
151
+
152
+ HORIZONTAL = "horizontal",
153
+ VERTICAL = "vertical",
154
+
155
+ ALL_FINGERS = "all",
156
+
157
+ DOUBLE_TAP_THRESHOLD = 10,
158
+
159
+ PHASE_START = "start",
160
+ PHASE_MOVE = "move",
161
+ PHASE_END = "end",
162
+ PHASE_CANCEL = "cancel",
163
+
164
+ SUPPORTS_TOUCH = 'ontouchstart' in window,
165
+
166
+ SUPPORTS_POINTER_IE10 = window.navigator.msPointerEnabled && !window.navigator.pointerEnabled,
167
+
168
+ SUPPORTS_POINTER = window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
169
+
170
+ PLUGIN_NS = 'TouchSwipe';
171
+
172
+
173
+
174
+ /**
175
+ * The default configuration, and available options to configure touch swipe with.
176
+ * You can set the default values by updating any of the properties prior to instantiation.
177
+ * @name $.fn.swipe.defaults
178
+ * @namespace
179
+ * @property {int} [fingers=1] The number of fingers to detect in a swipe. Any swipes that do not meet this requirement will NOT trigger swipe handlers.
180
+ * @property {int} [threshold=75] The number of pixels that the user must move their finger by before it is considered a swipe.
181
+ * @property {int} [cancelThreshold=null] The number of pixels that the user must move their finger back from the original swipe direction to cancel the gesture.
182
+ * @property {int} [pinchThreshold=20] The number of pixels that the user must pinch their finger by before it is considered a pinch.
183
+ * @property {int} [maxTimeThreshold=null] Time, in milliseconds, between touchStart and touchEnd must NOT exceed in order to be considered a swipe.
184
+ * @property {int} [fingerReleaseThreshold=250] Time in milliseconds between releasing multiple fingers. If 2 fingers are down, and are released one after the other, if they are within this threshold, it counts as a simultaneous release.
185
+ * @property {int} [longTapThreshold=500] Time in milliseconds between tap and release for a long tap
186
+ * @property {int} [doubleTapThreshold=200] Time in milliseconds between 2 taps to count as a double tap
187
+ * @property {function} [swipe=null] A handler to catch all swipes. See {@link $.fn.swipe#event:swipe}
188
+ * @property {function} [swipeLeft=null] A handler that is triggered for "left" swipes. See {@link $.fn.swipe#event:swipeLeft}
189
+ * @property {function} [swipeRight=null] A handler that is triggered for "right" swipes. See {@link $.fn.swipe#event:swipeRight}
190
+ * @property {function} [swipeUp=null] A handler that is triggered for "up" swipes. See {@link $.fn.swipe#event:swipeUp}
191
+ * @property {function} [swipeDown=null] A handler that is triggered for "down" swipes. See {@link $.fn.swipe#event:swipeDown}
192
+ * @property {function} [swipeStatus=null] A handler triggered for every phase of the swipe. See {@link $.fn.swipe#event:swipeStatus}
193
+ * @property {function} [pinchIn=null] A handler triggered for pinch in events. See {@link $.fn.swipe#event:pinchIn}
194
+ * @property {function} [pinchOut=null] A handler triggered for pinch out events. See {@link $.fn.swipe#event:pinchOut}
195
+ * @property {function} [pinchStatus=null] A handler triggered for every phase of a pinch. See {@link $.fn.swipe#event:pinchStatus}
196
+ * @property {function} [tap=null] A handler triggered when a user just taps on the item, rather than swipes it. If they do not move, tap is triggered, if they do move, it is not.
197
+ * @property {function} [doubleTap=null] A handler triggered when a user double taps on the item. The delay between taps can be set with the doubleTapThreshold property. See {@link $.fn.swipe.defaults#doubleTapThreshold}
198
+ * @property {function} [longTap=null] A handler triggered when a user long taps on the item. The delay between start and end can be set with the longTapThreshold property. See {@link $.fn.swipe.defaults#longTapThreshold}
199
+ * @property (function) [hold=null] A handler triggered when a user reaches longTapThreshold on the item. See {@link $.fn.swipe.defaults#longTapThreshold}
200
+ * @property {boolean} [triggerOnTouchEnd=true] If true, the swipe events are triggered when the touch end event is received (user releases finger). If false, it will be triggered on reaching the threshold, and then cancel the touch event automatically.
201
+ * @property {boolean} [triggerOnTouchLeave=false] If true, then when the user leaves the swipe object, the swipe will end and trigger appropriate handlers.
202
+ * @property {string|undefined} [allowPageScroll='auto'] How the browser handles page scrolls when the user is swiping on a touchSwipe object. See {@link $.fn.swipe.pageScroll}. <br/><br/>
203
+ <code>"auto"</code> : all undefined swipes will cause the page to scroll in that direction. <br/>
204
+ <code>"none"</code> : the page will not scroll when user swipes. <br/>
205
+ <code>"horizontal"</code> : will force page to scroll on horizontal swipes. <br/>
206
+ <code>"vertical"</code> : will force page to scroll on vertical swipes. <br/>
207
+ * @property {boolean} [fallbackToMouseEvents=true] If true mouse events are used when run on a non touch device, false will stop swipes being triggered by mouse events on non tocuh devices.
208
+ * @property {string} [excludedElements="button, input, select, textarea, a, .noSwipe"] A jquery selector that specifies child elements that do NOT trigger swipes. By default this excludes all form, input, select, button, anchor and .noSwipe elements.
209
+
210
+ */
211
+ var defaults = {
212
+ fingers: 1,
213
+ threshold: 75,
214
+ cancelThreshold:null,
215
+ pinchThreshold:20,
216
+ maxTimeThreshold: null,
217
+ fingerReleaseThreshold:250,
218
+ longTapThreshold:500,
219
+ doubleTapThreshold:200,
220
+ swipe: null,
221
+ swipeLeft: null,
222
+ swipeRight: null,
223
+ swipeUp: null,
224
+ swipeDown: null,
225
+ swipeStatus: null,
226
+ pinchIn:null,
227
+ pinchOut:null,
228
+ pinchStatus:null,
229
+ click:null, //Deprecated since 1.6.2
230
+ tap:null,
231
+ doubleTap:null,
232
+ longTap:null,
233
+ hold:null,
234
+ triggerOnTouchEnd: true,
235
+ triggerOnTouchLeave:false,
236
+ allowPageScroll: "auto",
237
+ fallbackToMouseEvents: true,
238
+ excludedElements:"label, button, input, select, textarea, a, .noSwipe"
239
+ };
240
+
241
+
242
+
243
+ /**
244
+ * Applies TouchSwipe behaviour to one or more jQuery objects.
245
+ * The TouchSwipe plugin can be instantiated via this method, or methods within
246
+ * TouchSwipe can be executed via this method as per jQuery plugin architecture.
247
+ * @see TouchSwipe
248
+ * @class
249
+ * @param {Mixed} method If the current DOMNode is a TouchSwipe object, and <code>method</code> is a TouchSwipe method, then
250
+ * the <code>method</code> is executed, and any following arguments are passed to the TouchSwipe method.
251
+ * If <code>method</code> is an object, then the TouchSwipe class is instantiated on the current DOMNode, passing the
252
+ * configuration properties defined in the object. See TouchSwipe
253
+ *
254
+ */
255
+ $.fn.swipe = function (method) {
256
+ var $this = $(this),
257
+ plugin = $this.data(PLUGIN_NS);
258
+
259
+ //Check if we are already instantiated and trying to execute a method
260
+ if (plugin && typeof method === 'string') {
261
+ if (plugin[method]) {
262
+ return plugin[method].apply(this, Array.prototype.slice.call(arguments, 1));
263
+ } else {
264
+ $.error('Method ' + method + ' does not exist on jQuery.swipe');
265
+ }
266
+ }
267
+ //Else not instantiated and trying to pass init object (or nothing)
268
+ else if (!plugin && (typeof method === 'object' || !method)) {
269
+ return init.apply(this, arguments);
270
+ }
271
+
272
+ return $this;
273
+ };
274
+
275
+ //Expose our defaults so a user could override the plugin defaults
276
+ $.fn.swipe.defaults = defaults;
277
+
278
+ /**
279
+ * The phases that a touch event goes through. The <code>phase</code> is passed to the event handlers.
280
+ * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
281
+ * @namespace
282
+ * @readonly
283
+ * @property {string} PHASE_START Constant indicating the start phase of the touch event. Value is <code>"start"</code>.
284
+ * @property {string} PHASE_MOVE Constant indicating the move phase of the touch event. Value is <code>"move"</code>.
285
+ * @property {string} PHASE_END Constant indicating the end phase of the touch event. Value is <code>"end"</code>.
286
+ * @property {string} PHASE_CANCEL Constant indicating the cancel phase of the touch event. Value is <code>"cancel"</code>.
287
+ */
288
+ $.fn.swipe.phases = {
289
+ PHASE_START: PHASE_START,
290
+ PHASE_MOVE: PHASE_MOVE,
291
+ PHASE_END: PHASE_END,
292
+ PHASE_CANCEL: PHASE_CANCEL
293
+ };
294
+
295
+ /**
296
+ * The direction constants that are passed to the event handlers.
297
+ * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
298
+ * @namespace
299
+ * @readonly
300
+ * @property {string} LEFT Constant indicating the left direction. Value is <code>"left"</code>.
301
+ * @property {string} RIGHT Constant indicating the right direction. Value is <code>"right"</code>.
302
+ * @property {string} UP Constant indicating the up direction. Value is <code>"up"</code>.
303
+ * @property {string} DOWN Constant indicating the down direction. Value is <code>"cancel"</code>.
304
+ * @property {string} IN Constant indicating the in direction. Value is <code>"in"</code>.
305
+ * @property {string} OUT Constant indicating the out direction. Value is <code>"out"</code>.
306
+ */
307
+ $.fn.swipe.directions = {
308
+ LEFT: LEFT,
309
+ RIGHT: RIGHT,
310
+ UP: UP,
311
+ DOWN: DOWN,
312
+ IN : IN,
313
+ OUT: OUT
314
+ };
315
+
316
+ /**
317
+ * The page scroll constants that can be used to set the value of <code>allowPageScroll</code> option
318
+ * These properties are read only
319
+ * @namespace
320
+ * @readonly
321
+ * @see $.fn.swipe.defaults#allowPageScroll
322
+ * @property {string} NONE Constant indicating no page scrolling is allowed. Value is <code>"none"</code>.
323
+ * @property {string} HORIZONTAL Constant indicating horizontal page scrolling is allowed. Value is <code>"horizontal"</code>.
324
+ * @property {string} VERTICAL Constant indicating vertical page scrolling is allowed. Value is <code>"vertical"</code>.
325
+ * @property {string} AUTO Constant indicating either horizontal or vertical will be allowed, depending on the swipe handlers registered. Value is <code>"auto"</code>.
326
+ */
327
+ $.fn.swipe.pageScroll = {
328
+ NONE: NONE,
329
+ HORIZONTAL: HORIZONTAL,
330
+ VERTICAL: VERTICAL,
331
+ AUTO: AUTO
332
+ };
333
+
334
+ /**
335
+ * Constants representing the number of fingers used in a swipe. These are used to set both the value of <code>fingers</code> in the
336
+ * options object, as well as the value of the <code>fingers</code> event property.
337
+ * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
338
+ * @namespace
339
+ * @readonly
340
+ * @see $.fn.swipe.defaults#fingers
341
+ * @property {string} ONE Constant indicating 1 finger is to be detected / was detected. Value is <code>1</code>.
342
+ * @property {string} TWO Constant indicating 2 fingers are to be detected / were detected. Value is <code>1</code>.
343
+ * @property {string} THREE Constant indicating 3 finger are to be detected / were detected. Value is <code>1</code>.
344
+ * @property {string} ALL Constant indicating any combination of finger are to be detected. Value is <code>"all"</code>.
345
+ */
346
+ $.fn.swipe.fingers = {
347
+ ONE: 1,
348
+ TWO: 2,
349
+ THREE: 3,
350
+ ALL: ALL_FINGERS
351
+ };
352
+
353
+ /**
354
+ * Initialise the plugin for each DOM element matched
355
+ * This creates a new instance of the main TouchSwipe class for each DOM element, and then
356
+ * saves a reference to that instance in the elements data property.
357
+ * @internal
358
+ */
359
+ function init(options) {
360
+ //Prep and extend the options
361
+ if (options && (options.allowPageScroll === undefined && (options.swipe !== undefined || options.swipeStatus !== undefined))) {
362
+ options.allowPageScroll = NONE;
363
+ }
364
+
365
+ //Check for deprecated options
366
+ //Ensure that any old click handlers are assigned to the new tap, unless we have a tap
367
+ if(options.click!==undefined && options.tap===undefined) {
368
+ options.tap = options.click;
369
+ }
370
+
371
+ if (!options) {
372
+ options = {};
373
+ }
374
+
375
+ //pass empty object so we dont modify the defaults
376
+ options = $.extend({}, $.fn.swipe.defaults, options);
377
+
378
+ //For each element instantiate the plugin
379
+ return this.each(function () {
380
+ var $this = $(this);
381
+
382
+ //Check we havent already initialised the plugin
383
+ var plugin = $this.data(PLUGIN_NS);
384
+
385
+ if (!plugin) {
386
+ plugin = new TouchSwipe(this, options);
387
+ $this.data(PLUGIN_NS, plugin);
388
+ }
389
+ });
390
+ }
391
+
392
+ /**
393
+ * Main TouchSwipe Plugin Class.
394
+ * Do not use this to construct your TouchSwipe object, use the jQuery plugin method $.fn.swipe(); {@link $.fn.swipe}
395
+ * @private
396
+ * @name TouchSwipe
397
+ * @param {DOMNode} element The HTML DOM object to apply to plugin to
398
+ * @param {Object} options The options to configure the plugin with. @link {$.fn.swipe.defaults}
399
+ * @see $.fh.swipe.defaults
400
+ * @see $.fh.swipe
401
+ * @class
402
+ */
403
+ function TouchSwipe(element, options) {
404
+ var useTouchEvents = (SUPPORTS_TOUCH || SUPPORTS_POINTER || !options.fallbackToMouseEvents),
405
+ START_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerDown' : 'pointerdown') : 'touchstart') : 'mousedown',
406
+ MOVE_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerMove' : 'pointermove') : 'touchmove') : 'mousemove',
407
+ END_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerUp' : 'pointerup') : 'touchend') : 'mouseup',
408
+ LEAVE_EV = useTouchEvents ? null : 'mouseleave', //we manually detect leave on touch devices, so null event here
409
+ CANCEL_EV = (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerCancel' : 'pointercancel') : 'touchcancel');
410
+
411
+
412
+
413
+ //touch properties
414
+ var distance = 0,
415
+ direction = null,
416
+ duration = 0,
417
+ startTouchesDistance = 0,
418
+ endTouchesDistance = 0,
419
+ pinchZoom = 1,
420
+ pinchDistance = 0,
421
+ pinchDirection = 0,
422
+ maximumsMap=null;
423
+
424
+
425
+
426
+ //jQuery wrapped element for this instance
427
+ var $element = $(element);
428
+
429
+ //Current phase of th touch cycle
430
+ var phase = "start";
431
+
432
+ // the current number of fingers being used.
433
+ var fingerCount = 0;
434
+
435
+ //track mouse points / delta
436
+ var fingerData=null;
437
+
438
+ //track times
439
+ var startTime = 0,
440
+ endTime = 0,
441
+ previousTouchEndTime=0,
442
+ previousTouchFingerCount=0,
443
+ doubleTapStartTime=0;
444
+
445
+ //Timeouts
446
+ var singleTapTimeout=null,
447
+ holdTimeout=null;
448
+
449
+ // Add gestures to all swipable areas if supported
450
+ try {
451
+ $element.bind(START_EV, touchStart);
452
+ $element.bind(CANCEL_EV, touchCancel);
453
+ }
454
+ catch (e) {
455
+ $.error('events not supported ' + START_EV + ',' + CANCEL_EV + ' on jQuery.swipe');
456
+ }
457
+
458
+ //
459
+ //Public methods
460
+ //
461
+
462
+ /**
463
+ * re-enables the swipe plugin with the previous configuration
464
+ * @function
465
+ * @name $.fn.swipe#enable
466
+ * @return {DOMNode} The Dom element that was registered with TouchSwipe
467
+ * @example $("#element").swipe("enable");
468
+ */
469
+ this.enable = function () {
470
+ $element.bind(START_EV, touchStart);
471
+ $element.bind(CANCEL_EV, touchCancel);
472
+ return $element;
473
+ };
474
+
475
+ /**
476
+ * disables the swipe plugin
477
+ * @function
478
+ * @name $.fn.swipe#disable
479
+ * @return {DOMNode} The Dom element that is now registered with TouchSwipe
480
+ * @example $("#element").swipe("disable");
481
+ */
482
+ this.disable = function () {
483
+ removeListeners();
484
+ return $element;
485
+ };
486
+
487
+ /**
488
+ * Destroy the swipe plugin completely. To use any swipe methods, you must re initialise the plugin.
489
+ * @function
490
+ * @name $.fn.swipe#destroy
491
+ * @example $("#element").swipe("destroy");
492
+ */
493
+ this.destroy = function () {
494
+ removeListeners();
495
+ $element.data(PLUGIN_NS, null);
496
+ $element = null;
497
+ };
498
+
499
+
500
+ /**
501
+ * Allows run time updating of the swipe configuration options.
502
+ * @function
503
+ * @name $.fn.swipe#option
504
+ * @param {String} property The option property to get or set
505
+ * @param {Object} [value] The value to set the property to
506
+ * @return {Object} If only a property name is passed, then that property value is returned.
507
+ * @example $("#element").swipe("option", "threshold"); // return the threshold
508
+ * @example $("#element").swipe("option", "threshold", 100); // set the threshold after init
509
+ * @see $.fn.swipe.defaults
510
+ *
511
+ */
512
+ this.option = function (property, value) {
513
+ if(options[property]!==undefined) {
514
+ if(value===undefined) {
515
+ return options[property];
516
+ } else {
517
+ options[property] = value;
518
+ }
519
+ } else {
520
+ $.error('Option ' + property + ' does not exist on jQuery.swipe.options');
521
+ }
522
+
523
+ return null;
524
+ }
525
+
526
+ //
527
+ // Private methods
528
+ //
529
+
530
+ //
531
+ // EVENTS
532
+ //
533
+ /**
534
+ * Event handler for a touch start event.
535
+ * Stops the default click event from triggering and stores where we touched
536
+ * @inner
537
+ * @param {object} jqEvent The normalised jQuery event object.
538
+ */
539
+ function touchStart(jqEvent) {
540
+ //If we already in a touch event (a finger already in use) then ignore subsequent ones..
541
+ if( getTouchInProgress() )
542
+ return;
543
+
544
+ //Check if this element matches any in the excluded elements selectors, or its parent is excluded, if so, DON'T swipe
545
+ if( $(jqEvent.target).closest( options.excludedElements, $element ).length>0 )
546
+ return;
547
+
548
+ //As we use Jquery bind for events, we need to target the original event object
549
+ //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
550
+ var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
551
+
552
+ var ret,
553
+ evt = SUPPORTS_TOUCH ? event.touches[0] : event;
554
+
555
+ phase = PHASE_START;
556
+
557
+ //If we support touches, get the finger count
558
+ if (SUPPORTS_TOUCH) {
559
+ // get the total number of fingers touching the screen
560
+ fingerCount = event.touches.length;
561
+ }
562
+ //Else this is the desktop, so stop the browser from dragging the image
563
+ else {
564
+ jqEvent.preventDefault(); //call this on jq event so we are cross browser
565
+ }
566
+
567
+ //clear vars..
568
+ distance = 0;
569
+ direction = null;
570
+ pinchDirection=null;
571
+ duration = 0;
572
+ startTouchesDistance=0;
573
+ endTouchesDistance=0;
574
+ pinchZoom = 1;
575
+ pinchDistance = 0;
576
+ fingerData=createAllFingerData();
577
+ maximumsMap=createMaximumsData();
578
+ cancelMultiFingerRelease();
579
+
580
+
581
+ // check the number of fingers is what we are looking for, or we are capturing pinches
582
+ if (!SUPPORTS_TOUCH || (fingerCount === options.fingers || options.fingers === ALL_FINGERS) || hasPinches()) {
583
+ // get the coordinates of the touch
584
+ createFingerData( 0, evt );
585
+ startTime = getTimeStamp();
586
+
587
+ if(fingerCount==2) {
588
+ //Keep track of the initial pinch distance, so we can calculate the diff later
589
+ //Store second finger data as start
590
+ createFingerData( 1, event.touches[1] );
591
+ startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
592
+ }
593
+
594
+ if (options.swipeStatus || options.pinchStatus) {
595
+ ret = triggerHandler(event, phase);
596
+ }
597
+ }
598
+ else {
599
+ //A touch with more or less than the fingers we are looking for, so cancel
600
+ ret = false;
601
+ }
602
+
603
+ //If we have a return value from the users handler, then return and cancel
604
+ if (ret === false) {
605
+ phase = PHASE_CANCEL;
606
+ triggerHandler(event, phase);
607
+ return ret;
608
+ }
609
+ else {
610
+ if (options.hold) {
611
+ holdTimeout = setTimeout($.proxy(function() {
612
+ //Trigger the event
613
+ $element.trigger('hold', [event.target]);
614
+ //Fire the callback
615
+ if(options.hold) {
616
+ ret = options.hold.call($element, event, event.target);
617
+ }
618
+ }, this), options.longTapThreshold );
619
+ }
620
+
621
+ setTouchInProgress(true);
622
+ }
623
+
624
+ return null;
625
+ };
626
+
627
+
628
+
629
+ /**
630
+ * Event handler for a touch move event.
631
+ * If we change fingers during move, then cancel the event
632
+ * @inner
633
+ * @param {object} jqEvent The normalised jQuery event object.
634
+ */
635
+ function touchMove(jqEvent) {
636
+
637
+ //As we use Jquery bind for events, we need to target the original event object
638
+ //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
639
+ var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
640
+
641
+ //If we are ending, cancelling, or within the threshold of 2 fingers being released, don't track anything..
642
+ if (phase === PHASE_END || phase === PHASE_CANCEL || inMultiFingerRelease())
643
+ return;
644
+
645
+ var ret,
646
+ evt = SUPPORTS_TOUCH ? event.touches[0] : event;
647
+
648
+
649
+ //Update the finger data
650
+ var currentFinger = updateFingerData(evt);
651
+ endTime = getTimeStamp();
652
+
653
+ if (SUPPORTS_TOUCH) {
654
+ fingerCount = event.touches.length;
655
+ }
656
+
657
+ if (options.hold)
658
+ clearTimeout(holdTimeout);
659
+
660
+ phase = PHASE_MOVE;
661
+
662
+ //If we have 2 fingers get Touches distance as well
663
+ if(fingerCount==2) {
664
+
665
+ //Keep track of the initial pinch distance, so we can calculate the diff later
666
+ //We do this here as well as the start event, in case they start with 1 finger, and the press 2 fingers
667
+ if(startTouchesDistance==0) {
668
+ //Create second finger if this is the first time...
669
+ createFingerData( 1, event.touches[1] );
670
+
671
+ startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
672
+ } else {
673
+ //Else just update the second finger
674
+ updateFingerData(event.touches[1]);
675
+
676
+ endTouchesDistance = calculateTouchesDistance(fingerData[0].end, fingerData[1].end);
677
+ pinchDirection = calculatePinchDirection(fingerData[0].end, fingerData[1].end);
678
+ }
679
+
680
+
681
+ pinchZoom = calculatePinchZoom(startTouchesDistance, endTouchesDistance);
682
+ pinchDistance = Math.abs(startTouchesDistance - endTouchesDistance);
683
+ }
684
+
685
+
686
+ if ( (fingerCount === options.fingers || options.fingers === ALL_FINGERS) || !SUPPORTS_TOUCH || hasPinches() ) {
687
+
688
+ direction = calculateDirection(currentFinger.start, currentFinger.end);
689
+
690
+ //Check if we need to prevent default event (page scroll / pinch zoom) or not
691
+ validateDefaultEvent(jqEvent, direction);
692
+
693
+ //Distance and duration are all off the main finger
694
+ distance = calculateDistance(currentFinger.start, currentFinger.end);
695
+ duration = calculateDuration();
696
+
697
+ //Cache the maximum distance we made in this direction
698
+ setMaxDistance(direction, distance);
699
+
700
+
701
+ if (options.swipeStatus || options.pinchStatus) {
702
+ ret = triggerHandler(event, phase);
703
+ }
704
+
705
+
706
+ //If we trigger end events when threshold are met, or trigger events when touch leaves element
707
+ if(!options.triggerOnTouchEnd || options.triggerOnTouchLeave) {
708
+
709
+ var inBounds = true;
710
+
711
+ //If checking if we leave the element, run the bounds check (we can use touchleave as its not supported on webkit)
712
+ if(options.triggerOnTouchLeave) {
713
+ var bounds = getbounds( this );
714
+ inBounds = isInBounds( currentFinger.end, bounds );
715
+ }
716
+
717
+ //Trigger end handles as we swipe if thresholds met or if we have left the element if the user has asked to check these..
718
+ if(!options.triggerOnTouchEnd && inBounds) {
719
+ phase = getNextPhase( PHASE_MOVE );
720
+ }
721
+ //We end if out of bounds here, so set current phase to END, and check if its modified
722
+ else if(options.triggerOnTouchLeave && !inBounds ) {
723
+ phase = getNextPhase( PHASE_END );
724
+ }
725
+
726
+ if(phase==PHASE_CANCEL || phase==PHASE_END) {
727
+ triggerHandler(event, phase);
728
+ }
729
+ }
730
+ }
731
+ else {
732
+ phase = PHASE_CANCEL;
733
+ triggerHandler(event, phase);
734
+ }
735
+
736
+ if (ret === false) {
737
+ phase = PHASE_CANCEL;
738
+ triggerHandler(event, phase);
739
+ }
740
+ }
741
+
742
+
743
+
744
+ /**
745
+ * Event handler for a touch end event.
746
+ * Calculate the direction and trigger events
747
+ * @inner
748
+ * @param {object} jqEvent The normalised jQuery event object.
749
+ */
750
+ function touchEnd(jqEvent) {
751
+ //As we use Jquery bind for events, we need to target the original event object
752
+ var event = jqEvent.originalEvent;
753
+
754
+
755
+ //If we are still in a touch with another finger return
756
+ //This allows us to wait a fraction and see if the other finger comes up, if it does within the threshold, then we treat it as a multi release, not a single release.
757
+ if (SUPPORTS_TOUCH) {
758
+ if(event.touches.length>0) {
759
+ startMultiFingerRelease();
760
+ return true;
761
+ }
762
+ }
763
+
764
+ //If a previous finger has been released, check how long ago, if within the threshold, then assume it was a multifinger release.
765
+ //This is used to allow 2 fingers to release fractionally after each other, whilst maintainig the event as containg 2 fingers, not 1
766
+ if(inMultiFingerRelease()) {
767
+ fingerCount=previousTouchFingerCount;
768
+ }
769
+
770
+ //Set end of swipe
771
+ endTime = getTimeStamp();
772
+
773
+ //Get duration incase move was never fired
774
+ duration = calculateDuration();
775
+
776
+ //If we trigger handlers at end of swipe OR, we trigger during, but they didnt trigger and we are still in the move phase
777
+ if(didSwipeBackToCancel() || !validateSwipeDistance()) {
778
+ phase = PHASE_CANCEL;
779
+ triggerHandler(event, phase);
780
+ } else if (options.triggerOnTouchEnd || (options.triggerOnTouchEnd == false && phase === PHASE_MOVE)) {
781
+ //call this on jq event so we are cross browser
782
+ jqEvent.preventDefault();
783
+ phase = PHASE_END;
784
+ triggerHandler(event, phase);
785
+ }
786
+ //Special cases - A tap should always fire on touch end regardless,
787
+ //So here we manually trigger the tap end handler by itself
788
+ //We dont run trigger handler as it will re-trigger events that may have fired already
789
+ else if (!options.triggerOnTouchEnd && hasTap()) {
790
+ //Trigger the pinch events...
791
+ phase = PHASE_END;
792
+ triggerHandlerForGesture(event, phase, TAP);
793
+ }
794
+ else if (phase === PHASE_MOVE) {
795
+ phase = PHASE_CANCEL;
796
+ triggerHandler(event, phase);
797
+ }
798
+
799
+ setTouchInProgress(false);
800
+
801
+ return null;
802
+ }
803
+
804
+
805
+
806
+ /**
807
+ * Event handler for a touch cancel event.
808
+ * Clears current vars
809
+ * @inner
810
+ */
811
+ function touchCancel() {
812
+ // reset the variables back to default values
813
+ fingerCount = 0;
814
+ endTime = 0;
815
+ startTime = 0;
816
+ startTouchesDistance=0;
817
+ endTouchesDistance=0;
818
+ pinchZoom=1;
819
+
820
+ //If we were in progress of tracking a possible multi touch end, then re set it.
821
+ cancelMultiFingerRelease();
822
+
823
+ setTouchInProgress(false);
824
+ }
825
+
826
+
827
+ /**
828
+ * Event handler for a touch leave event.
829
+ * This is only triggered on desktops, in touch we work this out manually
830
+ * as the touchleave event is not supported in webkit
831
+ * @inner
832
+ */
833
+ function touchLeave(jqEvent) {
834
+ var event = jqEvent.originalEvent;
835
+
836
+ //If we have the trigger on leave property set....
837
+ if(options.triggerOnTouchLeave) {
838
+ phase = getNextPhase( PHASE_END );
839
+ triggerHandler(event, phase);
840
+ }
841
+ }
842
+
843
+ /**
844
+ * Removes all listeners that were associated with the plugin
845
+ * @inner
846
+ */
847
+ function removeListeners() {
848
+ $element.unbind(START_EV, touchStart);
849
+ $element.unbind(CANCEL_EV, touchCancel);
850
+ $element.unbind(MOVE_EV, touchMove);
851
+ $element.unbind(END_EV, touchEnd);
852
+
853
+ //we only have leave events on desktop, we manually calculate leave on touch as its not supported in webkit
854
+ if(LEAVE_EV) {
855
+ $element.unbind(LEAVE_EV, touchLeave);
856
+ }
857
+
858
+ setTouchInProgress(false);
859
+ }
860
+
861
+
862
+ /**
863
+ * Checks if the time and distance thresholds have been met, and if so then the appropriate handlers are fired.
864
+ */
865
+ function getNextPhase(currentPhase) {
866
+
867
+ var nextPhase = currentPhase;
868
+
869
+ // Ensure we have valid swipe (under time and over distance and check if we are out of bound...)
870
+ var validTime = validateSwipeTime();
871
+ var validDistance = validateSwipeDistance();
872
+ var didCancel = didSwipeBackToCancel();
873
+
874
+ //If we have exceeded our time, then cancel
875
+ if(!validTime || didCancel) {
876
+ nextPhase = PHASE_CANCEL;
877
+ }
878
+ //Else if we are moving, and have reached distance then end
879
+ else if (validDistance && currentPhase == PHASE_MOVE && (!options.triggerOnTouchEnd || options.triggerOnTouchLeave) ) {
880
+ nextPhase = PHASE_END;
881
+ }
882
+ //Else if we have ended by leaving and didn't reach distance, then cancel
883
+ else if (!validDistance && currentPhase==PHASE_END && options.triggerOnTouchLeave) {
884
+ nextPhase = PHASE_CANCEL;
885
+ }
886
+
887
+ return nextPhase;
888
+ }
889
+
890
+
891
+ /**
892
+ * Trigger the relevant event handler
893
+ * The handlers are passed the original event, the element that was swiped, and in the case of the catch all handler, the direction that was swiped, "left", "right", "up", or "down"
894
+ * @param {object} event the original event object
895
+ * @param {string} phase the phase of the swipe (start, end cancel etc) {@link $.fn.swipe.phases}
896
+ * @inner
897
+ */
898
+ function triggerHandler(event, phase) {
899
+
900
+ var ret = undefined;
901
+
902
+ // SWIPE GESTURES
903
+ if(didSwipe() || hasSwipes()) { //hasSwipes as status needs to fire even if swipe is invalid
904
+ //Trigger the swipe events...
905
+ ret = triggerHandlerForGesture(event, phase, SWIPE);
906
+ }
907
+
908
+ // PINCH GESTURES (if the above didn't cancel)
909
+ else if((didPinch() || hasPinches()) && ret!==false) {
910
+ //Trigger the pinch events...
911
+ ret = triggerHandlerForGesture(event, phase, PINCH);
912
+ }
913
+
914
+ // CLICK / TAP (if the above didn't cancel)
915
+ if(didDoubleTap() && ret!==false) {
916
+ //Trigger the tap events...
917
+ ret = triggerHandlerForGesture(event, phase, DOUBLE_TAP);
918
+ }
919
+
920
+ // CLICK / TAP (if the above didn't cancel)
921
+ else if(didLongTap() && ret!==false) {
922
+ //Trigger the tap events...
923
+ ret = triggerHandlerForGesture(event, phase, LONG_TAP);
924
+ }
925
+
926
+ // CLICK / TAP (if the above didn't cancel)
927
+ else if(didTap() && ret!==false) {
928
+ //Trigger the tap event..
929
+ ret = triggerHandlerForGesture(event, phase, TAP);
930
+ }
931
+
932
+
933
+
934
+ // If we are cancelling the gesture, then manually trigger the reset handler
935
+ if (phase === PHASE_CANCEL) {
936
+ touchCancel(event);
937
+ }
938
+
939
+ // If we are ending the gesture, then manually trigger the reset handler IF all fingers are off
940
+ if(phase === PHASE_END) {
941
+ //If we support touch, then check that all fingers are off before we cancel
942
+ if (SUPPORTS_TOUCH) {
943
+ if(event.touches.length==0) {
944
+ touchCancel(event);
945
+ }
946
+ }
947
+ else {
948
+ touchCancel(event);
949
+ }
950
+ }
951
+
952
+ return ret;
953
+ }
954
+
955
+
956
+
957
+ /**
958
+ * Trigger the relevant event handler
959
+ * The handlers are passed the original event, the element that was swiped, and in the case of the catch all handler, the direction that was swiped, "left", "right", "up", or "down"
960
+ * @param {object} event the original event object
961
+ * @param {string} phase the phase of the swipe (start, end cancel etc) {@link $.fn.swipe.phases}
962
+ * @param {string} gesture the gesture to trigger a handler for : PINCH or SWIPE {@link $.fn.swipe.gestures}
963
+ * @return Boolean False, to indicate that the event should stop propagation, or void.
964
+ * @inner
965
+ */
966
+ function triggerHandlerForGesture(event, phase, gesture) {
967
+
968
+ var ret=undefined;
969
+
970
+ //SWIPES....
971
+ if(gesture==SWIPE) {
972
+ //Trigger status every time..
973
+
974
+ //Trigger the event...
975
+ $element.trigger('swipeStatus', [phase, direction || null, distance || 0, duration || 0, fingerCount, fingerData]);
976
+
977
+ //Fire the callback
978
+ if (options.swipeStatus) {
979
+ ret = options.swipeStatus.call($element, event, phase, direction || null, distance || 0, duration || 0, fingerCount, fingerData);
980
+ //If the status cancels, then dont run the subsequent event handlers..
981
+ if(ret===false) return false;
982
+ }
983
+
984
+
985
+
986
+
987
+ if (phase == PHASE_END && validateSwipe()) {
988
+ //Fire the catch all event
989
+ $element.trigger('swipe', [direction, distance, duration, fingerCount, fingerData]);
990
+
991
+ //Fire catch all callback
992
+ if (options.swipe) {
993
+ ret = options.swipe.call($element, event, direction, distance, duration, fingerCount, fingerData);
994
+ //If the status cancels, then dont run the subsequent event handlers..
995
+ if(ret===false) return false;
996
+ }
997
+
998
+ //trigger direction specific event handlers
999
+ switch (direction) {
1000
+ case LEFT:
1001
+ //Trigger the event
1002
+ $element.trigger('swipeLeft', [direction, distance, duration, fingerCount, fingerData]);
1003
+
1004
+ //Fire the callback
1005
+ if (options.swipeLeft) {
1006
+ ret = options.swipeLeft.call($element, event, direction, distance, duration, fingerCount, fingerData);
1007
+ }
1008
+ break;
1009
+
1010
+ case RIGHT:
1011
+ //Trigger the event
1012
+ $element.trigger('swipeRight', [direction, distance, duration, fingerCount, fingerData]);
1013
+
1014
+ //Fire the callback
1015
+ if (options.swipeRight) {
1016
+ ret = options.swipeRight.call($element, event, direction, distance, duration, fingerCount, fingerData);
1017
+ }
1018
+ break;
1019
+
1020
+ case UP:
1021
+ //Trigger the event
1022
+ $element.trigger('swipeUp', [direction, distance, duration, fingerCount, fingerData]);
1023
+
1024
+ //Fire the callback
1025
+ if (options.swipeUp) {
1026
+ ret = options.swipeUp.call($element, event, direction, distance, duration, fingerCount, fingerData);
1027
+ }
1028
+ break;
1029
+
1030
+ case DOWN:
1031
+ //Trigger the event
1032
+ $element.trigger('swipeDown', [direction, distance, duration, fingerCount, fingerData]);
1033
+
1034
+ //Fire the callback
1035
+ if (options.swipeDown) {
1036
+ ret = options.swipeDown.call($element, event, direction, distance, duration, fingerCount, fingerData);
1037
+ }
1038
+ break;
1039
+ }
1040
+ }
1041
+ }
1042
+
1043
+
1044
+ //PINCHES....
1045
+ if(gesture==PINCH) {
1046
+ //Trigger the event
1047
+ $element.trigger('pinchStatus', [phase, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
1048
+
1049
+ //Fire the callback
1050
+ if (options.pinchStatus) {
1051
+ ret = options.pinchStatus.call($element, event, phase, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
1052
+ //If the status cancels, then dont run the subsequent event handlers..
1053
+ if(ret===false) return false;
1054
+ }
1055
+
1056
+ if(phase==PHASE_END && validatePinch()) {
1057
+
1058
+ switch (pinchDirection) {
1059
+ case IN:
1060
+ //Trigger the event
1061
+ $element.trigger('pinchIn', [pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
1062
+
1063
+ //Fire the callback
1064
+ if (options.pinchIn) {
1065
+ ret = options.pinchIn.call($element, event, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
1066
+ }
1067
+ break;
1068
+
1069
+ case OUT:
1070
+ //Trigger the event
1071
+ $element.trigger('pinchOut', [pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
1072
+
1073
+ //Fire the callback
1074
+ if (options.pinchOut) {
1075
+ ret = options.pinchOut.call($element, event, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
1076
+ }
1077
+ break;
1078
+ }
1079
+ }
1080
+ }
1081
+
1082
+
1083
+
1084
+
1085
+
1086
+ if(gesture==TAP) {
1087
+ if(phase === PHASE_CANCEL || phase === PHASE_END) {
1088
+
1089
+
1090
+ //Cancel any existing double tap
1091
+ clearTimeout(singleTapTimeout);
1092
+ //Cancel hold timeout
1093
+ clearTimeout(holdTimeout);
1094
+
1095
+ //If we are also looking for doubelTaps, wait incase this is one...
1096
+ if(hasDoubleTap() && !inDoubleTap()) {
1097
+ //Cache the time of this tap
1098
+ doubleTapStartTime = getTimeStamp();
1099
+
1100
+ //Now wait for the double tap timeout, and trigger this single tap
1101
+ //if its not cancelled by a double tap
1102
+ singleTapTimeout = setTimeout($.proxy(function() {
1103
+ doubleTapStartTime=null;
1104
+ //Trigger the event
1105
+ $element.trigger('tap', [event.target]);
1106
+
1107
+
1108
+ //Fire the callback
1109
+ if(options.tap) {
1110
+ ret = options.tap.call($element, event, event.target);
1111
+ }
1112
+ }, this), options.doubleTapThreshold );
1113
+
1114
+ } else {
1115
+ doubleTapStartTime=null;
1116
+
1117
+ //Trigger the event
1118
+ $element.trigger('tap', [event.target]);
1119
+
1120
+
1121
+ //Fire the callback
1122
+ if(options.tap) {
1123
+ ret = options.tap.call($element, event, event.target);
1124
+ }
1125
+ }
1126
+ }
1127
+ }
1128
+
1129
+ else if (gesture==DOUBLE_TAP) {
1130
+ if(phase === PHASE_CANCEL || phase === PHASE_END) {
1131
+ //Cancel any pending singletap
1132
+ clearTimeout(singleTapTimeout);
1133
+ doubleTapStartTime=null;
1134
+
1135
+ //Trigger the event
1136
+ $element.trigger('doubletap', [event.target]);
1137
+
1138
+ //Fire the callback
1139
+ if(options.doubleTap) {
1140
+ ret = options.doubleTap.call($element, event, event.target);
1141
+ }
1142
+ }
1143
+ }
1144
+
1145
+ else if (gesture==LONG_TAP) {
1146
+ if(phase === PHASE_CANCEL || phase === PHASE_END) {
1147
+ //Cancel any pending singletap (shouldnt be one)
1148
+ clearTimeout(singleTapTimeout);
1149
+ doubleTapStartTime=null;
1150
+
1151
+ //Trigger the event
1152
+ $element.trigger('longtap', [event.target]);
1153
+
1154
+ //Fire the callback
1155
+ if(options.longTap) {
1156
+ ret = options.longTap.call($element, event, event.target);
1157
+ }
1158
+ }
1159
+ }
1160
+
1161
+ return ret;
1162
+ }
1163
+
1164
+
1165
+
1166
+
1167
+ //
1168
+ // GESTURE VALIDATION
1169
+ //
1170
+
1171
+ /**
1172
+ * Checks the user has swipe far enough
1173
+ * @return Boolean if <code>threshold</code> has been set, return true if the threshold was met, else false.
1174
+ * If no threshold was set, then we return true.
1175
+ * @inner
1176
+ */
1177
+ function validateSwipeDistance() {
1178
+ var valid = true;
1179
+ //If we made it past the min swipe distance..
1180
+ if (options.threshold !== null) {
1181
+ valid = distance >= options.threshold;
1182
+ }
1183
+
1184
+ return valid;
1185
+ }
1186
+
1187
+ /**
1188
+ * Checks the user has swiped back to cancel.
1189
+ * @return Boolean if <code>cancelThreshold</code> has been set, return true if the cancelThreshold was met, else false.
1190
+ * If no cancelThreshold was set, then we return true.
1191
+ * @inner
1192
+ */
1193
+ function didSwipeBackToCancel() {
1194
+ var cancelled = false;
1195
+ if(options.cancelThreshold !== null && direction !==null) {
1196
+ cancelled = (getMaxDistance( direction ) - distance) >= options.cancelThreshold;
1197
+ }
1198
+
1199
+ return cancelled;
1200
+ }
1201
+
1202
+ /**
1203
+ * Checks the user has pinched far enough
1204
+ * @return Boolean if <code>pinchThreshold</code> has been set, return true if the threshold was met, else false.
1205
+ * If no threshold was set, then we return true.
1206
+ * @inner
1207
+ */
1208
+ function validatePinchDistance() {
1209
+ if (options.pinchThreshold !== null) {
1210
+ return pinchDistance >= options.pinchThreshold;
1211
+ }
1212
+ return true;
1213
+ }
1214
+
1215
+ /**
1216
+ * Checks that the time taken to swipe meets the minimum / maximum requirements
1217
+ * @return Boolean
1218
+ * @inner
1219
+ */
1220
+ function validateSwipeTime() {
1221
+ var result;
1222
+ //If no time set, then return true
1223
+
1224
+ if (options.maxTimeThreshold) {
1225
+ if (duration >= options.maxTimeThreshold) {
1226
+ result = false;
1227
+ } else {
1228
+ result = true;
1229
+ }
1230
+ }
1231
+ else {
1232
+ result = true;
1233
+ }
1234
+
1235
+ return result;
1236
+ }
1237
+
1238
+
1239
+ /**
1240
+ * Checks direction of the swipe and the value allowPageScroll to see if we should allow or prevent the default behaviour from occurring.
1241
+ * This will essentially allow page scrolling or not when the user is swiping on a touchSwipe object.
1242
+ * @param {object} jqEvent The normalised jQuery representation of the event object.
1243
+ * @param {string} direction The direction of the event. See {@link $.fn.swipe.directions}
1244
+ * @see $.fn.swipe.directions
1245
+ * @inner
1246
+ */
1247
+ function validateDefaultEvent(jqEvent, direction) {
1248
+ if (options.allowPageScroll === NONE || hasPinches()) {
1249
+ jqEvent.preventDefault();
1250
+ } else {
1251
+ var auto = options.allowPageScroll === AUTO;
1252
+
1253
+ switch (direction) {
1254
+ case LEFT:
1255
+ if ((options.swipeLeft && auto) || (!auto && options.allowPageScroll != HORIZONTAL)) {
1256
+ jqEvent.preventDefault();
1257
+ }
1258
+ break;
1259
+
1260
+ case RIGHT:
1261
+ if ((options.swipeRight && auto) || (!auto && options.allowPageScroll != HORIZONTAL)) {
1262
+ jqEvent.preventDefault();
1263
+ }
1264
+ break;
1265
+
1266
+ case UP:
1267
+ if ((options.swipeUp && auto) || (!auto && options.allowPageScroll != VERTICAL)) {
1268
+ jqEvent.preventDefault();
1269
+ }
1270
+ break;
1271
+
1272
+ case DOWN:
1273
+ if ((options.swipeDown && auto) || (!auto && options.allowPageScroll != VERTICAL)) {
1274
+ jqEvent.preventDefault();
1275
+ }
1276
+ break;
1277
+ }
1278
+ }
1279
+
1280
+ }
1281
+
1282
+
1283
+ // PINCHES
1284
+ /**
1285
+ * Returns true of the current pinch meets the thresholds
1286
+ * @return Boolean
1287
+ * @inner
1288
+ */
1289
+ function validatePinch() {
1290
+ var hasCorrectFingerCount = validateFingers();
1291
+ var hasEndPoint = validateEndPoint();
1292
+ var hasCorrectDistance = validatePinchDistance();
1293
+ return hasCorrectFingerCount && hasEndPoint && hasCorrectDistance;
1294
+
1295
+ }
1296
+
1297
+ /**
1298
+ * Returns true if any Pinch events have been registered
1299
+ * @return Boolean
1300
+ * @inner
1301
+ */
1302
+ function hasPinches() {
1303
+ //Enure we dont return 0 or null for false values
1304
+ return !!(options.pinchStatus || options.pinchIn || options.pinchOut);
1305
+ }
1306
+
1307
+ /**
1308
+ * Returns true if we are detecting pinches, and have one
1309
+ * @return Boolean
1310
+ * @inner
1311
+ */
1312
+ function didPinch() {
1313
+ //Enure we dont return 0 or null for false values
1314
+ return !!(validatePinch() && hasPinches());
1315
+ }
1316
+
1317
+
1318
+
1319
+
1320
+ // SWIPES
1321
+ /**
1322
+ * Returns true if the current swipe meets the thresholds
1323
+ * @return Boolean
1324
+ * @inner
1325
+ */
1326
+ function validateSwipe() {
1327
+ //Check validity of swipe
1328
+ var hasValidTime = validateSwipeTime();
1329
+ var hasValidDistance = validateSwipeDistance();
1330
+ var hasCorrectFingerCount = validateFingers();
1331
+ var hasEndPoint = validateEndPoint();
1332
+ var didCancel = didSwipeBackToCancel();
1333
+
1334
+ // if the user swiped more than the minimum length, perform the appropriate action
1335
+ // hasValidDistance is null when no distance is set
1336
+ var valid = !didCancel && hasEndPoint && hasCorrectFingerCount && hasValidDistance && hasValidTime;
1337
+
1338
+ return valid;
1339
+ }
1340
+
1341
+ /**
1342
+ * Returns true if any Swipe events have been registered
1343
+ * @return Boolean
1344
+ * @inner
1345
+ */
1346
+ function hasSwipes() {
1347
+ //Enure we dont return 0 or null for false values
1348
+ return !!(options.swipe || options.swipeStatus || options.swipeLeft || options.swipeRight || options.swipeUp || options.swipeDown);
1349
+ }
1350
+
1351
+
1352
+ /**
1353
+ * Returns true if we are detecting swipes and have one
1354
+ * @return Boolean
1355
+ * @inner
1356
+ */
1357
+ function didSwipe() {
1358
+ //Enure we dont return 0 or null for false values
1359
+ return !!(validateSwipe() && hasSwipes());
1360
+ }
1361
+
1362
+ /**
1363
+ * Returns true if we have matched the number of fingers we are looking for
1364
+ * @return Boolean
1365
+ * @inner
1366
+ */
1367
+ function validateFingers() {
1368
+ //The number of fingers we want were matched, or on desktop we ignore
1369
+ return ((fingerCount === options.fingers || options.fingers === ALL_FINGERS) || !SUPPORTS_TOUCH);
1370
+ }
1371
+
1372
+ /**
1373
+ * Returns true if we have an end point for the swipe
1374
+ * @return Boolean
1375
+ * @inner
1376
+ */
1377
+ function validateEndPoint() {
1378
+ //We have an end value for the finger
1379
+ return fingerData[0].end.x !== 0;
1380
+ }
1381
+
1382
+ // TAP / CLICK
1383
+ /**
1384
+ * Returns true if a click / tap events have been registered
1385
+ * @return Boolean
1386
+ * @inner
1387
+ */
1388
+ function hasTap() {
1389
+ //Enure we dont return 0 or null for false values
1390
+ return !!(options.tap) ;
1391
+ }
1392
+
1393
+ /**
1394
+ * Returns true if a double tap events have been registered
1395
+ * @return Boolean
1396
+ * @inner
1397
+ */
1398
+ function hasDoubleTap() {
1399
+ //Enure we dont return 0 or null for false values
1400
+ return !!(options.doubleTap) ;
1401
+ }
1402
+
1403
+ /**
1404
+ * Returns true if any long tap events have been registered
1405
+ * @return Boolean
1406
+ * @inner
1407
+ */
1408
+ function hasLongTap() {
1409
+ //Enure we dont return 0 or null for false values
1410
+ return !!(options.longTap) ;
1411
+ }
1412
+
1413
+ /**
1414
+ * Returns true if we could be in the process of a double tap (one tap has occurred, we are listening for double taps, and the threshold hasn't past.
1415
+ * @return Boolean
1416
+ * @inner
1417
+ */
1418
+ function validateDoubleTap() {
1419
+ if(doubleTapStartTime==null){
1420
+ return false;
1421
+ }
1422
+ var now = getTimeStamp();
1423
+ return (hasDoubleTap() && ((now-doubleTapStartTime) <= options.doubleTapThreshold));
1424
+ }
1425
+
1426
+ /**
1427
+ * Returns true if we could be in the process of a double tap (one tap has occurred, we are listening for double taps, and the threshold hasn't past.
1428
+ * @return Boolean
1429
+ * @inner
1430
+ */
1431
+ function inDoubleTap() {
1432
+ return validateDoubleTap();
1433
+ }
1434
+
1435
+
1436
+ /**
1437
+ * Returns true if we have a valid tap
1438
+ * @return Boolean
1439
+ * @inner
1440
+ */
1441
+ function validateTap() {
1442
+ return ((fingerCount === 1 || !SUPPORTS_TOUCH) && (isNaN(distance) || distance < options.threshold));
1443
+ }
1444
+
1445
+ /**
1446
+ * Returns true if we have a valid long tap
1447
+ * @return Boolean
1448
+ * @inner
1449
+ */
1450
+ function validateLongTap() {
1451
+ //slight threshold on moving finger
1452
+ return ((duration > options.longTapThreshold) && (distance < DOUBLE_TAP_THRESHOLD));
1453
+ }
1454
+
1455
+ /**
1456
+ * Returns true if we are detecting taps and have one
1457
+ * @return Boolean
1458
+ * @inner
1459
+ */
1460
+ function didTap() {
1461
+ //Enure we dont return 0 or null for false values
1462
+ return !!(validateTap() && hasTap());
1463
+ }
1464
+
1465
+
1466
+ /**
1467
+ * Returns true if we are detecting double taps and have one
1468
+ * @return Boolean
1469
+ * @inner
1470
+ */
1471
+ function didDoubleTap() {
1472
+ //Enure we dont return 0 or null for false values
1473
+ return !!(validateDoubleTap() && hasDoubleTap());
1474
+ }
1475
+
1476
+ /**
1477
+ * Returns true if we are detecting long taps and have one
1478
+ * @return Boolean
1479
+ * @inner
1480
+ */
1481
+ function didLongTap() {
1482
+ //Enure we dont return 0 or null for false values
1483
+ return !!(validateLongTap() && hasLongTap());
1484
+ }
1485
+
1486
+
1487
+
1488
+
1489
+ // MULTI FINGER TOUCH
1490
+ /**
1491
+ * Starts tracking the time between 2 finger releases, and keeps track of how many fingers we initially had up
1492
+ * @inner
1493
+ */
1494
+ function startMultiFingerRelease() {
1495
+ previousTouchEndTime = getTimeStamp();
1496
+ previousTouchFingerCount = event.touches.length+1;
1497
+ }
1498
+
1499
+ /**
1500
+ * Cancels the tracking of time between 2 finger releases, and resets counters
1501
+ * @inner
1502
+ */
1503
+ function cancelMultiFingerRelease() {
1504
+ previousTouchEndTime = 0;
1505
+ previousTouchFingerCount = 0;
1506
+ }
1507
+
1508
+ /**
1509
+ * Checks if we are in the threshold between 2 fingers being released
1510
+ * @return Boolean
1511
+ * @inner
1512
+ */
1513
+ function inMultiFingerRelease() {
1514
+
1515
+ var withinThreshold = false;
1516
+
1517
+ if(previousTouchEndTime) {
1518
+ var diff = getTimeStamp() - previousTouchEndTime
1519
+ if( diff<=options.fingerReleaseThreshold ) {
1520
+ withinThreshold = true;
1521
+ }
1522
+ }
1523
+
1524
+ return withinThreshold;
1525
+ }
1526
+
1527
+
1528
+ /**
1529
+ * gets a data flag to indicate that a touch is in progress
1530
+ * @return Boolean
1531
+ * @inner
1532
+ */
1533
+ function getTouchInProgress() {
1534
+ //strict equality to ensure only true and false are returned
1535
+ return !!($element.data(PLUGIN_NS+'_intouch') === true);
1536
+ }
1537
+
1538
+ /**
1539
+ * Sets a data flag to indicate that a touch is in progress
1540
+ * @param {boolean} val The value to set the property to
1541
+ * @inner
1542
+ */
1543
+ function setTouchInProgress(val) {
1544
+
1545
+ //Add or remove event listeners depending on touch status
1546
+ if(val===true) {
1547
+ $element.bind(MOVE_EV, touchMove);
1548
+ $element.bind(END_EV, touchEnd);
1549
+
1550
+ //we only have leave events on desktop, we manually calcuate leave on touch as its not supported in webkit
1551
+ if(LEAVE_EV) {
1552
+ $element.bind(LEAVE_EV, touchLeave);
1553
+ }
1554
+ } else {
1555
+ $element.unbind(MOVE_EV, touchMove, false);
1556
+ $element.unbind(END_EV, touchEnd, false);
1557
+
1558
+ //we only have leave events on desktop, we manually calcuate leave on touch as its not supported in webkit
1559
+ if(LEAVE_EV) {
1560
+ $element.unbind(LEAVE_EV, touchLeave, false);
1561
+ }
1562
+ }
1563
+
1564
+
1565
+ //strict equality to ensure only true and false can update the value
1566
+ $element.data(PLUGIN_NS+'_intouch', val === true);
1567
+ }
1568
+
1569
+
1570
+ /**
1571
+ * Creates the finger data for the touch/finger in the event object.
1572
+ * @param {int} index The index in the array to store the finger data (usually the order the fingers were pressed)
1573
+ * @param {object} evt The event object containing finger data
1574
+ * @return finger data object
1575
+ * @inner
1576
+ */
1577
+ function createFingerData( index, evt ) {
1578
+ var id = evt.identifier!==undefined ? evt.identifier : 0;
1579
+
1580
+ fingerData[index].identifier = id;
1581
+ fingerData[index].start.x = fingerData[index].end.x = evt.pageX||evt.clientX;
1582
+ fingerData[index].start.y = fingerData[index].end.y = evt.pageY||evt.clientY;
1583
+
1584
+ return fingerData[index];
1585
+ }
1586
+
1587
+ /**
1588
+ * Updates the finger data for a particular event object
1589
+ * @param {object} evt The event object containing the touch/finger data to upadte
1590
+ * @return a finger data object.
1591
+ * @inner
1592
+ */
1593
+ function updateFingerData(evt) {
1594
+
1595
+ var id = evt.identifier!==undefined ? evt.identifier : 0;
1596
+ var f = getFingerData( id );
1597
+
1598
+ f.end.x = evt.pageX||evt.clientX;
1599
+ f.end.y = evt.pageY||evt.clientY;
1600
+
1601
+ return f;
1602
+ }
1603
+
1604
+ /**
1605
+ * Returns a finger data object by its event ID.
1606
+ * Each touch event has an identifier property, which is used
1607
+ * to track repeat touches
1608
+ * @param {int} id The unique id of the finger in the sequence of touch events.
1609
+ * @return a finger data object.
1610
+ * @inner
1611
+ */
1612
+ function getFingerData( id ) {
1613
+ for(var i=0; i<fingerData.length; i++) {
1614
+ if(fingerData[i].identifier == id) {
1615
+ return fingerData[i];
1616
+ }
1617
+ }
1618
+ }
1619
+
1620
+ /**
1621
+ * Creats all the finger onjects and returns an array of finger data
1622
+ * @return Array of finger objects
1623
+ * @inner
1624
+ */
1625
+ function createAllFingerData() {
1626
+ var fingerData=[];
1627
+ for (var i=0; i<=5; i++) {
1628
+ fingerData.push({
1629
+ start:{ x: 0, y: 0 },
1630
+ end:{ x: 0, y: 0 },
1631
+ identifier:0
1632
+ });
1633
+ }
1634
+
1635
+ return fingerData;
1636
+ }
1637
+
1638
+ /**
1639
+ * Sets the maximum distance swiped in the given direction.
1640
+ * If the new value is lower than the current value, the max value is not changed.
1641
+ * @param {string} direction The direction of the swipe
1642
+ * @param {int} distance The distance of the swipe
1643
+ * @inner
1644
+ */
1645
+ function setMaxDistance(direction, distance) {
1646
+ distance = Math.max(distance, getMaxDistance(direction) );
1647
+ maximumsMap[direction].distance = distance;
1648
+ }
1649
+
1650
+ /**
1651
+ * gets the maximum distance swiped in the given direction.
1652
+ * @param {string} direction The direction of the swipe
1653
+ * @return int The distance of the swipe
1654
+ * @inner
1655
+ */
1656
+ function getMaxDistance(direction) {
1657
+ if (maximumsMap[direction]) return maximumsMap[direction].distance;
1658
+ return undefined;
1659
+ }
1660
+
1661
+ /**
1662
+ * Creats a map of directions to maximum swiped values.
1663
+ * @return Object A dictionary of maximum values, indexed by direction.
1664
+ * @inner
1665
+ */
1666
+ function createMaximumsData() {
1667
+ var maxData={};
1668
+ maxData[LEFT]=createMaximumVO(LEFT);
1669
+ maxData[RIGHT]=createMaximumVO(RIGHT);
1670
+ maxData[UP]=createMaximumVO(UP);
1671
+ maxData[DOWN]=createMaximumVO(DOWN);
1672
+
1673
+ return maxData;
1674
+ }
1675
+
1676
+ /**
1677
+ * Creates a map maximum swiped values for a given swipe direction
1678
+ * @param {string} The direction that these values will be associated with
1679
+ * @return Object Maximum values
1680
+ * @inner
1681
+ */
1682
+ function createMaximumVO(dir) {
1683
+ return {
1684
+ direction:dir,
1685
+ distance:0
1686
+ }
1687
+ }
1688
+
1689
+
1690
+ //
1691
+ // MATHS / UTILS
1692
+ //
1693
+
1694
+ /**
1695
+ * Calculate the duration of the swipe
1696
+ * @return int
1697
+ * @inner
1698
+ */
1699
+ function calculateDuration() {
1700
+ return endTime - startTime;
1701
+ }
1702
+
1703
+ /**
1704
+ * Calculate the distance between 2 touches (pinch)
1705
+ * @param {point} startPoint A point object containing x and y co-ordinates
1706
+ * @param {point} endPoint A point object containing x and y co-ordinates
1707
+ * @return int;
1708
+ * @inner
1709
+ */
1710
+ function calculateTouchesDistance(startPoint, endPoint) {
1711
+ var diffX = Math.abs(startPoint.x - endPoint.x);
1712
+ var diffY = Math.abs(startPoint.y - endPoint.y);
1713
+
1714
+ return Math.round(Math.sqrt(diffX*diffX+diffY*diffY));
1715
+ }
1716
+
1717
+ /**
1718
+ * Calculate the zoom factor between the start and end distances
1719
+ * @param {int} startDistance Distance (between 2 fingers) the user started pinching at
1720
+ * @param {int} endDistance Distance (between 2 fingers) the user ended pinching at
1721
+ * @return float The zoom value from 0 to 1.
1722
+ * @inner
1723
+ */
1724
+ function calculatePinchZoom(startDistance, endDistance) {
1725
+ var percent = (endDistance/startDistance) * 1;
1726
+ return percent.toFixed(2);
1727
+ }
1728
+
1729
+
1730
+ /**
1731
+ * Returns the pinch direction, either IN or OUT for the given points
1732
+ * @return string Either {@link $.fn.swipe.directions.IN} or {@link $.fn.swipe.directions.OUT}
1733
+ * @see $.fn.swipe.directions
1734
+ * @inner
1735
+ */
1736
+ function calculatePinchDirection() {
1737
+ if(pinchZoom<1) {
1738
+ return OUT;
1739
+ }
1740
+ else {
1741
+ return IN;
1742
+ }
1743
+ }
1744
+
1745
+
1746
+ /**
1747
+ * Calculate the length / distance of the swipe
1748
+ * @param {point} startPoint A point object containing x and y co-ordinates
1749
+ * @param {point} endPoint A point object containing x and y co-ordinates
1750
+ * @return int
1751
+ * @inner
1752
+ */
1753
+ function calculateDistance(startPoint, endPoint) {
1754
+ return Math.round(Math.sqrt(Math.pow(endPoint.x - startPoint.x, 2) + Math.pow(endPoint.y - startPoint.y, 2)));
1755
+ }
1756
+
1757
+ /**
1758
+ * Calculate the angle of the swipe
1759
+ * @param {point} startPoint A point object containing x and y co-ordinates
1760
+ * @param {point} endPoint A point object containing x and y co-ordinates
1761
+ * @return int
1762
+ * @inner
1763
+ */
1764
+ function calculateAngle(startPoint, endPoint) {
1765
+ var x = startPoint.x - endPoint.x;
1766
+ var y = endPoint.y - startPoint.y;
1767
+ var r = Math.atan2(y, x); //radians
1768
+ var angle = Math.round(r * 180 / Math.PI); //degrees
1769
+
1770
+ //ensure value is positive
1771
+ if (angle < 0) {
1772
+ angle = 360 - Math.abs(angle);
1773
+ }
1774
+
1775
+ return angle;
1776
+ }
1777
+
1778
+ /**
1779
+ * Calculate the direction of the swipe
1780
+ * This will also call calculateAngle to get the latest angle of swipe
1781
+ * @param {point} startPoint A point object containing x and y co-ordinates
1782
+ * @param {point} endPoint A point object containing x and y co-ordinates
1783
+ * @return string Either {@link $.fn.swipe.directions.LEFT} / {@link $.fn.swipe.directions.RIGHT} / {@link $.fn.swipe.directions.DOWN} / {@link $.fn.swipe.directions.UP}
1784
+ * @see $.fn.swipe.directions
1785
+ * @inner
1786
+ */
1787
+ function calculateDirection(startPoint, endPoint ) {
1788
+ var angle = calculateAngle(startPoint, endPoint);
1789
+
1790
+ if ((angle <= 45) && (angle >= 0)) {
1791
+ return LEFT;
1792
+ } else if ((angle <= 360) && (angle >= 315)) {
1793
+ return LEFT;
1794
+ } else if ((angle >= 135) && (angle <= 225)) {
1795
+ return RIGHT;
1796
+ } else if ((angle > 45) && (angle < 135)) {
1797
+ return DOWN;
1798
+ } else {
1799
+ return UP;
1800
+ }
1801
+ }
1802
+
1803
+
1804
+ /**
1805
+ * Returns a MS time stamp of the current time
1806
+ * @return int
1807
+ * @inner
1808
+ */
1809
+ function getTimeStamp() {
1810
+ var now = new Date();
1811
+ return now.getTime();
1812
+ }
1813
+
1814
+
1815
+
1816
+ /**
1817
+ * Returns a bounds object with left, right, top and bottom properties for the element specified.
1818
+ * @param {DomNode} The DOM node to get the bounds for.
1819
+ */
1820
+ function getbounds( el ) {
1821
+ el = $(el);
1822
+ var offset = el.offset();
1823
+
1824
+ var bounds = {
1825
+ left:offset.left,
1826
+ right:offset.left+el.outerWidth(),
1827
+ top:offset.top,
1828
+ bottom:offset.top+el.outerHeight()
1829
+ }
1830
+
1831
+ return bounds;
1832
+ }
1833
+
1834
+
1835
+ /**
1836
+ * Checks if the point object is in the bounds object.
1837
+ * @param {object} point A point object.
1838
+ * @param {int} point.x The x value of the point.
1839
+ * @param {int} point.y The x value of the point.
1840
+ * @param {object} bounds The bounds object to test
1841
+ * @param {int} bounds.left The leftmost value
1842
+ * @param {int} bounds.right The righttmost value
1843
+ * @param {int} bounds.top The topmost value
1844
+ * @param {int} bounds.bottom The bottommost value
1845
+ */
1846
+ function isInBounds(point, bounds) {
1847
+ return (point.x > bounds.left && point.x < bounds.right && point.y > bounds.top && point.y < bounds.bottom);
1848
+ };
1849
+
1850
+
1851
+ }
1852
+
1853
+
1854
+
1855
+
1856
+ /**
1857
+ * A catch all handler that is triggered for all swipe directions.
1858
+ * @name $.fn.swipe#swipe
1859
+ * @event
1860
+ * @default null
1861
+ * @param {EventObject} event The original event object
1862
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1863
+ * @param {int} distance The distance the user swiped
1864
+ * @param {int} duration The duration of the swipe in milliseconds
1865
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1866
+ * @param {object} fingerData The coordinates of fingers in event
1867
+ */
1868
+
1869
+
1870
+
1871
+
1872
+ /**
1873
+ * A handler that is triggered for "left" swipes.
1874
+ * @name $.fn.swipe#swipeLeft
1875
+ * @event
1876
+ * @default null
1877
+ * @param {EventObject} event The original event object
1878
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1879
+ * @param {int} distance The distance the user swiped
1880
+ * @param {int} duration The duration of the swipe in milliseconds
1881
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1882
+ * @param {object} fingerData The coordinates of fingers in event
1883
+ */
1884
+
1885
+ /**
1886
+ * A handler that is triggered for "right" swipes.
1887
+ * @name $.fn.swipe#swipeRight
1888
+ * @event
1889
+ * @default null
1890
+ * @param {EventObject} event The original event object
1891
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1892
+ * @param {int} distance The distance the user swiped
1893
+ * @param {int} duration The duration of the swipe in milliseconds
1894
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1895
+ * @param {object} fingerData The coordinates of fingers in event
1896
+ */
1897
+
1898
+ /**
1899
+ * A handler that is triggered for "up" swipes.
1900
+ * @name $.fn.swipe#swipeUp
1901
+ * @event
1902
+ * @default null
1903
+ * @param {EventObject} event The original event object
1904
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1905
+ * @param {int} distance The distance the user swiped
1906
+ * @param {int} duration The duration of the swipe in milliseconds
1907
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1908
+ * @param {object} fingerData The coordinates of fingers in event
1909
+ */
1910
+
1911
+ /**
1912
+ * A handler that is triggered for "down" swipes.
1913
+ * @name $.fn.swipe#swipeDown
1914
+ * @event
1915
+ * @default null
1916
+ * @param {EventObject} event The original event object
1917
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1918
+ * @param {int} distance The distance the user swiped
1919
+ * @param {int} duration The duration of the swipe in milliseconds
1920
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1921
+ * @param {object} fingerData The coordinates of fingers in event
1922
+ */
1923
+
1924
+ /**
1925
+ * A handler triggered for every phase of the swipe. This handler is constantly fired for the duration of the pinch.
1926
+ * This is triggered regardless of swipe thresholds.
1927
+ * @name $.fn.swipe#swipeStatus
1928
+ * @event
1929
+ * @default null
1930
+ * @param {EventObject} event The original event object
1931
+ * @param {string} phase The phase of the swipe event. See {@link $.fn.swipe.phases}
1932
+ * @param {string} direction The direction the user swiped in. This is null if the user has yet to move. See {@link $.fn.swipe.directions}
1933
+ * @param {int} distance The distance the user swiped. This is 0 if the user has yet to move.
1934
+ * @param {int} duration The duration of the swipe in milliseconds
1935
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1936
+ * @param {object} fingerData The coordinates of fingers in event
1937
+ */
1938
+
1939
+ /**
1940
+ * A handler triggered for pinch in events.
1941
+ * @name $.fn.swipe#pinchIn
1942
+ * @event
1943
+ * @default null
1944
+ * @param {EventObject} event The original event object
1945
+ * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
1946
+ * @param {int} distance The distance the user pinched
1947
+ * @param {int} duration The duration of the swipe in milliseconds
1948
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1949
+ * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
1950
+ * @param {object} fingerData The coordinates of fingers in event
1951
+ */
1952
+
1953
+ /**
1954
+ * A handler triggered for pinch out events.
1955
+ * @name $.fn.swipe#pinchOut
1956
+ * @event
1957
+ * @default null
1958
+ * @param {EventObject} event The original event object
1959
+ * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
1960
+ * @param {int} distance The distance the user pinched
1961
+ * @param {int} duration The duration of the swipe in milliseconds
1962
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1963
+ * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
1964
+ * @param {object} fingerData The coordinates of fingers in event
1965
+ */
1966
+
1967
+ /**
1968
+ * A handler triggered for all pinch events. This handler is constantly fired for the duration of the pinch. This is triggered regardless of thresholds.
1969
+ * @name $.fn.swipe#pinchStatus
1970
+ * @event
1971
+ * @default null
1972
+ * @param {EventObject} event The original event object
1973
+ * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
1974
+ * @param {int} distance The distance the user pinched
1975
+ * @param {int} duration The duration of the swipe in milliseconds
1976
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1977
+ * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
1978
+ * @param {object} fingerData The coordinates of fingers in event
1979
+ */
1980
+
1981
+ /**
1982
+ * A click handler triggered when a user simply clicks, rather than swipes on an element.
1983
+ * This is deprecated since version 1.6.2, any assignment to click will be assigned to the tap handler.
1984
+ * You cannot use <code>on</code> to bind to this event as the default jQ <code>click</code> event will be triggered.
1985
+ * Use the <code>tap</code> event instead.
1986
+ * @name $.fn.swipe#click
1987
+ * @event
1988
+ * @deprecated since version 1.6.2, please use {@link $.fn.swipe#tap} instead
1989
+ * @default null
1990
+ * @param {EventObject} event The original event object
1991
+ * @param {DomObject} target The element clicked on.
1992
+ */
1993
+
1994
+ /**
1995
+ * A click / tap handler triggered when a user simply clicks or taps, rather than swipes on an element.
1996
+ * @name $.fn.swipe#tap
1997
+ * @event
1998
+ * @default null
1999
+ * @param {EventObject} event The original event object
2000
+ * @param {DomObject} target The element clicked on.
2001
+ */
2002
+
2003
+ /**
2004
+ * A double tap handler triggered when a user double clicks or taps on an element.
2005
+ * You can set the time delay for a double tap with the {@link $.fn.swipe.defaults#doubleTapThreshold} property.
2006
+ * Note: If you set both <code>doubleTap</code> and <code>tap</code> handlers, the <code>tap</code> event will be delayed by the <code>doubleTapThreshold</code>
2007
+ * as the script needs to check if its a double tap.
2008
+ * @name $.fn.swipe#doubleTap
2009
+ * @see $.fn.swipe.defaults#doubleTapThreshold
2010
+ * @event
2011
+ * @default null
2012
+ * @param {EventObject} event The original event object
2013
+ * @param {DomObject} target The element clicked on.
2014
+ */
2015
+
2016
+ /**
2017
+ * A long tap handler triggered once a tap has been release if the tap was longer than the longTapThreshold.
2018
+ * You can set the time delay for a long tap with the {@link $.fn.swipe.defaults#longTapThreshold} property.
2019
+ * @name $.fn.swipe#longTap
2020
+ * @see $.fn.swipe.defaults#longTapThreshold
2021
+ * @event
2022
+ * @default null
2023
+ * @param {EventObject} event The original event object
2024
+ * @param {DomObject} target The element clicked on.
2025
+ */
2026
+
2027
+ /**
2028
+ * A hold tap handler triggered as soon as the longTapThreshold is reached
2029
+ * You can set the time delay for a long tap with the {@link $.fn.swipe.defaults#longTapThreshold} property.
2030
+ * @name $.fn.swipe#hold
2031
+ * @see $.fn.swipe.defaults#longTapThreshold
2032
+ * @event
2033
+ * @default null
2034
+ * @param {EventObject} event The original event object
2035
+ * @param {DomObject} target The element clicked on.
2036
+ */
2037
+
2038
+ }));
assets/js/media-delete.js ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( document ).ready( function( $ ) {
2
+
3
+ /**
4
+ * Delete Multiple Images
5
+ */
6
+ $( document ).on( 'click', 'a.envira-gallery-images-delete', function( e ) {
7
+
8
+ e.preventDefault();
9
+
10
+ // Bail out if the user does not actually want to remove the image.
11
+ var confirm_delete = confirm(envira_gallery_metabox.remove_multiple);
12
+ if ( ! confirm_delete ) {
13
+ return false;
14
+ }
15
+
16
+ // Build array of image attachment IDs
17
+ var attach_ids = [];
18
+ $( 'ul#envira-gallery-output > li.selected' ).each( function() {
19
+ attach_ids.push( $( this ).attr( 'id' ) );
20
+ } );
21
+
22
+ // Send an AJAX request to delete the selected items from the Gallery
23
+ var attach_id = $( this ).parent().attr( 'id' );
24
+ $.ajax( {
25
+ url: envira_gallery_metabox.ajax,
26
+ type: 'post',
27
+ dataType: 'json',
28
+ data: {
29
+ action: 'envira_gallery_remove_images',
30
+ attachment_ids:attach_ids,
31
+ post_id: envira_gallery_metabox.id,
32
+ nonce: envira_gallery_metabox.remove_nonce
33
+ },
34
+ success: function( response ) {
35
+ // Remove each image
36
+ $( 'ul#envira-gallery-output > li.selected' ).remove();
37
+
38
+ // Hide Select Options
39
+ $( 'nav.envira-select-options' ).fadeOut();
40
+
41
+ // Refresh the modal view to ensure no items are still checked if they have been removed.
42
+ $( '.envira-gallery-load-library' ).attr( 'data-envira-gallery-offset', 0 ).addClass( 'has-search' ).trigger( 'click' );
43
+
44
+ // Repopulate the Envira Gallery Image Collection
45
+ EnviraGalleryImagesUpdate( false );
46
+ },
47
+ error: function( xhr, textStatus, e ) {
48
+ // Inject the error message into the tab settings area
49
+ $( envira_gallery_output ).before( '<div class="error"><p>' + textStatus.responseText + '</p></div>' );
50
+ }
51
+ } );
52
+
53
+ } );
54
+
55
+ /**
56
+ * Delete Single Image
57
+ */
58
+ $( document ).on( 'click', '#envira-gallery-main .envira-gallery-remove-image', function( e ) {
59
+
60
+ e.preventDefault();
61
+
62
+ // Bail out if the user does not actually want to remove the image.
63
+ var confirm_delete = confirm( envira_gallery_metabox.remove );
64
+ if ( ! confirm_delete ) {
65
+ return;
66
+ }
67
+
68
+ // Send an AJAX request to delete the selected items from the Gallery
69
+ var attach_id = $( this ).parent().attr( 'id' );
70
+ $.ajax( {
71
+ url: envira_gallery_metabox.ajax,
72
+ type: 'post',
73
+ dataType: 'json',
74
+ data: {
75
+ action: 'envira_gallery_remove_image',
76
+ attachment_id: attach_id,
77
+ post_id: envira_gallery_metabox.id,
78
+ nonce: envira_gallery_metabox.remove_nonce
79
+ },
80
+ success: function( response ) {
81
+ $( '#' + attach_id ).fadeOut( 'normal', function() {
82
+ $( this ).remove();
83
+
84
+ // Refresh the modal view to ensure no items are still checked if they have been removed.
85
+ $( '.envira-gallery-load-library' ).attr( 'data-envira-gallery-offset', 0 ).addClass( 'has-search' ).trigger( 'click' );
86
+
87
+ // Repopulate the Envira Gallery Image Collection
88
+ EnviraGalleryImagesUpdate( false );
89
+ } );
90
+ },
91
+ error: function( xhr, textStatus, e ) {
92
+ // Inject the error message into the tab settings area
93
+ $( envira_gallery_output ).before( '<div class="error"><p>' + textStatus.responseText + '</p></div>' );
94
+ }
95
+ } );
96
+ } );
97
+
98
+ } );
assets/js/media-edit.js ADDED
@@ -0,0 +1,535 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Image Model
3
+ */
4
+ var EnviraGalleryImage = Backbone.Model.extend( {
5
+
6
+ /**
7
+ * Defaults
8
+ * As we always populate this model with existing data, we
9
+ * leave these blank to just show how this model is structured.
10
+ */
11
+ defaults: {
12
+ 'id': '',
13
+ 'title': '',
14
+ 'caption': '',
15
+ 'alt': '',
16
+ 'link': '',
17
+ },
18
+
19
+ } );
20
+
21
+ /**
22
+ * Images Collection
23
+ * - Comprises of all images in an Envira Gallery
24
+ * - Each image is represented by an EnviraGalleryImage Model
25
+ */
26
+ var EnviraGalleryImages = new Backbone.Collection;
27
+
28
+ /**
29
+ * Modal Window
30
+ * - Used by most Envira Backbone views to display information e.g. bulk edit, edit single image etc.
31
+ */
32
+ if ( typeof EnviraGalleryModalWindow == 'undefined' ) {
33
+ var EnviraGalleryModalWindow = new wp.media.view.Modal( {
34
+ controller: {
35
+ trigger: function() {
36
+ }
37
+ }
38
+ } );
39
+ }
40
+
41
+ /**
42
+ * View
43
+ */
44
+ var EnviraGalleryEditView = wp.Backbone.View.extend( {
45
+
46
+ /**
47
+ * The Tag Name and Tag's Class(es)
48
+ */
49
+ tagName: 'div',
50
+ className: 'edit-attachment-frame mode-select hide-menu hide-router',
51
+
52
+ /**
53
+ * Template
54
+ * - The template to load inside the above tagName element
55
+ */
56
+ template: wp.template( 'envira-meta-editor' ),
57
+
58
+ /**
59
+ * Events
60
+ * - Functions to call when specific events occur
61
+ */
62
+ events: {
63
+ 'click .edit-media-header .left': 'loadPreviousItem',
64
+ 'click .edit-media-header .right': 'loadNextItem',
65
+
66
+ 'keyup input': 'updateItem',
67
+ 'keyup textarea': 'updateItem',
68
+ 'change input': 'updateItem',
69
+ 'change textarea': 'updateItem',
70
+ 'blur textarea': 'updateItem',
71
+ 'change select': 'updateItem',
72
+
73
+ 'click .actions a.envira-gallery-meta-submit': 'saveItem',
74
+
75
+ 'keyup input#link-search': 'searchLinks',
76
+ 'click div.query-results li': 'insertLink',
77
+
78
+ 'click button.media-file': 'insertMediaFileLink',
79
+ 'click button.attachment-page': 'insertAttachmentPageLink',
80
+ },
81
+
82
+ /**
83
+ * Initialize
84
+ *
85
+ * @param object model EnviraGalleryImage Backbone Model
86
+ */
87
+ initialize: function( args ) {
88
+
89
+ // Define loading and loaded events, which update the UI with what's happening.
90
+ this.on( 'loading', this.loading, this );
91
+ this.on( 'loaded', this.loaded, this );
92
+
93
+ // Set some flags
94
+ this.is_loading = false;
95
+ this.collection = args.collection;
96
+ this.child_views = args.child_views;
97
+ this.attachment_id = args.attachment_id;
98
+ this.attachment_index = 0;
99
+ this.search_timer = '';
100
+
101
+ // Get the model from the collection
102
+ var count = 0;
103
+ this.collection.each( function( model ) {
104
+ // If this model's id matches the attachment id, this is the model we want
105
+ if ( model.get( 'id' ) == this.attachment_id ) {
106
+ this.model = model;
107
+ this.attachment_index = count;
108
+ return false;
109
+ }
110
+
111
+ // Increment the index count
112
+ count++;
113
+ }, this );
114
+
115
+ },
116
+
117
+ /**
118
+ * Render
119
+ * - Binds the model to the view, so we populate the view's fields and data
120
+ */
121
+ render: function() {
122
+
123
+ // Get HTML
124
+ this.$el.html( this.template( this.model.attributes ) );
125
+
126
+ // If any child views exist, render them now
127
+ if ( this.child_views.length > 0 ) {
128
+ this.child_views.forEach( function( view ) {
129
+ // Init with model
130
+ var child_view = new view( {
131
+ model: this.model
132
+ } );
133
+
134
+ // Render view within our main view
135
+ this.$el.find( 'div.addons' ).append( child_view.render().el );
136
+ }, this );
137
+ }
138
+
139
+ // Set caption
140
+ this.$el.find( 'textarea[name=caption]' ).val( this.model.get( 'caption' ) );
141
+
142
+ // Init QuickTags on the caption editor
143
+ // Delay is required for the first load for some reason
144
+ setTimeout( function() {
145
+ quicktags( {
146
+ id: 'caption',
147
+ buttons:'strong,em,link,ul,ol,li,close'
148
+ } );
149
+ QTags._buttonsInit();
150
+ }, 500 );
151
+
152
+ // Init Link Searching on Captions, if Captions enabled
153
+ if ( typeof wpLink !== 'undefined' ) {
154
+ wpLink.init;
155
+ }
156
+
157
+ // Enable / disable the buttons depending on the index
158
+ if ( this.attachment_index == 0 ) {
159
+ // Disable left button
160
+ this.$el.find( 'button.left' ).addClass( 'disabled' );
161
+ }
162
+ if ( this.attachment_index == ( this.collection.length - 1 ) ) {
163
+ // Disable right button
164
+ this.$el.find( 'button.right' ).addClass( 'disabled' );
165
+ }
166
+
167
+ // Return
168
+ return this;
169
+
170
+ },
171
+
172
+ /**
173
+ * Renders an error using
174
+ * wp.media.view.EnviraGalleryError
175
+ */
176
+ renderError: function( error ) {
177
+
178
+ // Define model
179
+ var model = {};
180
+ model.error = error;
181
+
182
+ // Define view
183
+ var view = new wp.media.view.EnviraGalleryError( {
184
+ model: model
185
+ } );
186
+
187
+ // Return rendered view
188
+ return view.render().el;
189
+
190
+ },
191
+
192
+ /**
193
+ * Tells the view we're loading by displaying a spinner
194
+ */
195
+ loading: function() {
196
+
197
+ // Set a flag so we know we're loading data
198
+ this.is_loading = true;
199
+
200
+ // Show the spinner
201
+ this.$el.find( '.spinner' ).css( 'visibility', 'visible' );
202
+
203
+ },
204
+
205
+ /**
206
+ * Hides the loading spinner
207
+ */
208
+ loaded: function( response ) {
209
+
210
+ // Set a flag so we know we're not loading anything now
211
+ this.is_loading = false;
212
+
213
+ // Hide the spinner
214
+ this.$el.find( '.spinner' ).css( 'visibility', 'hidden' );
215
+
216
+ // Display the error message, if it's provided
217
+ if ( typeof response !== 'undefined' ) {
218
+ this.$el.find( 'div.media-toolbar' ).after( this.renderError( response ) );
219
+ }
220
+
221
+ },
222
+
223
+ /**
224
+ * Load the previous model in the collection
225
+ */
226
+ loadPreviousItem: function() {
227
+
228
+ // Decrement the index
229
+ this.attachment_index--;
230
+
231
+ // Get the model at the new index from the collection
232
+ this.model = this.collection.at( this.attachment_index );
233
+
234
+ // Update the attachment_id
235
+ this.attachment_id = this.model.get( 'id' );
236
+
237
+ // Re-render the view
238
+ this.render();
239
+
240
+ },
241
+
242
+ /**
243
+ * Load the next model in the collection
244
+ */
245
+ loadNextItem: function() {
246
+
247
+ // Increment the index
248
+ this.attachment_index++;
249
+
250
+ // Get the model at the new index from the collection
251
+ this.model = this.collection.at( this.attachment_index );
252
+
253
+ // Update the attachment_id
254
+ this.attachment_id = this.model.get( 'id' );
255
+
256
+ // Re-render the view
257
+ this.render();
258
+
259
+ },
260
+
261
+ /**
262
+ * Updates the model based on the changed view data
263
+ */
264
+ updateItem: function( event ) {
265
+
266
+ // Check if the target has a name. If not, it's not a model value we want to store
267
+ if ( event.target.name == '' ) {
268
+ return;
269
+ }
270
+
271
+ // Update the model's value, depending on the input type
272
+ if ( event.target.type == 'checkbox' ) {
273
+ value = ( event.target.checked ? 1 : 0 );
274
+ } else {
275
+ value = event.target.value;
276
+ }
277
+
278
+ // Update the model
279
+ this.model.set( event.target.name, value );
280
+
281
+ },
282
+
283
+ /**
284
+ * Saves the image metadata
285
+ */
286
+ saveItem: function() {
287
+
288
+ // Tell the View we're loading
289
+ this.trigger( 'loading' );
290
+
291
+ // Make an AJAX request to save the image metadata
292
+ wp.media.ajax( 'envira_gallery_save_meta', {
293
+ context: this,
294
+ data: {
295
+ nonce: envira_gallery_metabox.save_nonce,
296
+ post_id: envira_gallery_metabox.id,
297
+ attach_id: this.model.get( 'id' ),
298
+ meta: this.model.attributes,
299
+ },
300
+ success: function( response ) {
301
+
302
+ // Tell the view we've finished successfully
303
+ this.trigger( 'loaded loaded:success' );
304
+
305
+ // Assign the model's JSON string back to the underlying item
306
+ var item = JSON.stringify( this.model.attributes ),
307
+ item_element = jQuery( 'ul#envira-gallery-output li#' + this.model.get( 'id' ) );
308
+
309
+ // Assign the JSON
310
+ jQuery( item_element ).attr( 'data-envira-gallery-image-model', item );
311
+
312
+ // Update the title and hint
313
+ jQuery( 'div.meta div.title span', item_element ).text( this.model.get( 'title' ) );
314
+ jQuery( 'div.meta div.title a.hint', item_element ).attr( 'title', this.model.get( 'title' ) );
315
+
316
+ // Display or hide the title hint depending on the title length
317
+ if ( this.model.get( 'title' ).length > 20 ) {
318
+ jQuery( 'div.meta div.title a.hint', item_element ).removeClass( 'hidden' );
319
+ } else {
320
+ jQuery( 'div.meta div.title a.hint', item_element ).addClass( 'hidden' );
321
+ }
322
+
323
+ // Show the user the 'saved' notice for 1.5 seconds
324
+ var saved = this.$el.find( '.saved' );
325
+ saved.fadeIn();
326
+ setTimeout( function() {
327
+ saved.fadeOut();
328
+ }, 1500 );
329
+
330
+ },
331
+ error: function( error_message ) {
332
+
333
+ // Tell wp.media we've finished, but there was an error
334
+ this.trigger( 'loaded loaded:error', error_message );
335
+
336
+ }
337
+ } );
338
+
339
+ },
340
+
341
+ /**
342
+ * Searches Links
343
+ */
344
+ searchLinks: function( event ) {
345
+
346
+
347
+ },
348
+
349
+ /**
350
+ * Inserts the clicked link into the URL field
351
+ */
352
+ insertLink: function( event ) {
353
+
354
+
355
+
356
+ },
357
+
358
+ /**
359
+ * Inserts the direct media link for the Media Library item
360
+ *
361
+ * The button triggering this event is only displayed if we are editing a
362
+ * Media Library item, so there's no need to perform further checks
363
+ */
364
+ insertMediaFileLink: function( event ) {
365
+
366
+ // Tell the View we're loading
367
+ this.trigger( 'loading' );
368
+
369
+ // Make an AJAX request to get the media link
370
+ wp.media.ajax( 'envira_gallery_get_attachment_links', {
371
+ context: this,
372
+ data: {
373
+ nonce: envira_gallery_metabox.save_nonce,
374
+ attachment_id: this.model.get( 'id' ),
375
+ },
376
+ success: function( response ) {
377
+
378
+ // Update model
379
+ this.model.set( 'link', response.media_link );
380
+
381
+ // Tell the view we've finished successfully
382
+ this.trigger( 'loaded loaded:success' );
383
+
384
+ // Re-render the view
385
+ this.render();
386
+
387
+ },
388
+ error: function( error_message ) {
389
+
390
+ // Tell wp.media we've finished, but there was an error
391
+ this.trigger( 'loaded loaded:error', error_message );
392
+
393
+ }
394
+ } );
395
+
396
+ },
397
+
398
+ /**
399
+ * Inserts the attachment page link for the Media Library item
400
+ *
401
+ * The button triggering this event is only displayed if we are editing a
402
+ * Media Library item, so there's no need to perform further checks
403
+ */
404
+ insertAttachmentPageLink: function( event ) {
405
+
406
+ // Tell the View we're loading
407
+ this.trigger( 'loading' );
408
+
409
+ // Make an AJAX request to get the media link
410
+ wp.media.ajax( 'envira_gallery_get_attachment_links', {
411
+ context: this,
412
+ data: {
413
+ nonce: envira_gallery_metabox.save_nonce,
414
+ attachment_id: this.model.get( 'id' ),
415
+ },
416
+ success: function( response ) {
417
+
418
+ // Update model
419
+ this.model.set( 'link', response.attachment_page );
420
+
421
+ // Tell the view we've finished successfully
422
+ this.trigger( 'loaded loaded:success' );
423
+
424
+ // Re-render the view
425
+ this.render();
426
+
427
+ },
428
+ error: function( error_message ) {
429
+
430
+ // Tell wp.media we've finished, but there was an error
431
+ this.trigger( 'loaded loaded:error', error_message );
432
+
433
+ }
434
+ } );
435
+
436
+ }
437
+
438
+ } );
439
+
440
+ /**
441
+ * Sub Views
442
+ * - Addons must populate this array with their own Backbone Views, which will be appended
443
+ * to the settings region
444
+ */
445
+ var EnviraGalleryChildViews = [];
446
+
447
+ /**
448
+ * DOM
449
+ */
450
+ jQuery( document ).ready( function( $ ) {
451
+
452
+ // Edit Image
453
+ $( document ).on( 'click', '#envira-gallery-main a.envira-gallery-modify-image', function( e ) {
454
+
455
+ // Prevent default action
456
+ e.preventDefault();
457
+
458
+ // (Re)populate the collection
459
+ // The collection can change based on whether the user previously selected specific images
460
+ EnviraGalleryImagesUpdate( false );
461
+
462
+ // Get the selected attachment
463
+ var attachment_id = $( this ).parent().data( 'envira-gallery-image' );
464
+
465
+ // Pass the collection of images for this gallery to the modal view, as well
466
+ // as the selected attachment
467
+ EnviraGalleryModalWindow.content( new EnviraGalleryEditView( {
468
+ collection: EnviraGalleryImages,
469
+ child_views: EnviraGalleryChildViews,
470
+ attachment_id: attachment_id,
471
+ } ) );
472
+
473
+ // Open the modal window
474
+ EnviraGalleryModalWindow.open();
475
+
476
+ } );
477
+
478
+ } );
479
+
480
+ /**
481
+ * Populates the EnviraGalleryImages Backbone collection, which comprises of a set of Envira Gallery Images
482
+ *
483
+ * Called when images are added, deleted, reordered or selected
484
+ *
485
+ * @global EnviraGalleryImages The backbone collection of images
486
+ * @param bool selected_only Only populate collection with images the user has selected
487
+ */
488
+ function EnviraGalleryImagesUpdate( selected_only ) {
489
+
490
+ // Clear the collection
491
+ EnviraGalleryImages.reset();
492
+
493
+ // Iterate through the gallery images in the DOM, adding them to the collection
494
+ var selector = 'ul#envira-gallery-output li.envira-gallery-image' + ( selected_only ? '.selected' : '' );
495
+
496
+ jQuery( selector ).each( function() {
497
+ // Build an EnviraGalleryImage Backbone Model from the JSON supplied in the element
498
+ var envira_gallery_image = jQuery.parseJSON( jQuery( this ).attr( 'data-envira-gallery-image-model' ) );
499
+
500
+ // Strip slashes from some fields
501
+ envira_gallery_image.alt = EnviraGalleryStripslashes( envira_gallery_image.alt );
502
+
503
+ // Add the model to the collection
504
+ EnviraGalleryImages.add( new EnviraGalleryImage( envira_gallery_image ) );
505
+ } );
506
+
507
+ // Update the count in the UI
508
+ jQuery( '#envira-gallery-main span.count' ).text( jQuery( 'ul#envira-gallery-output li.envira-gallery-image' ).length );
509
+
510
+ }
511
+
512
+ /**
513
+ * Strips slashes from the given string, which may have been added to escape certain characters
514
+ *
515
+ * @since 1.4.2.0
516
+ *
517
+ * @param string str String
518
+ * @return string String without slashes
519
+ */
520
+ function EnviraGalleryStripslashes( str ) {
521
+
522
+ return (str + '').replace(/\\(.?)/g, function(s, n1) {
523
+ switch (n1) {
524
+ case '\\':
525
+ return '\\';
526
+ case '0':
527
+ return '\u0000';
528
+ case '':
529
+ return '';
530
+ default:
531
+ return n1;
532
+ }
533
+ });
534
+
535
+ }
assets/js/media-insert.js ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Creates and handles a wp.media instance for Envira Galleries, allowing
3
+ * the user to insert images from the WordPress Media Library into their Gallery
4
+ */
5
+ jQuery( document ).ready( function( $ ) {
6
+
7
+ // Select Files from Other Sources
8
+ $( 'a.envira-media-library' ).on( 'click', function( e ) {
9
+
10
+ // Prevent default action
11
+ e.preventDefault();
12
+
13
+ // If the wp.media.frames.envira instance already exists, reopen it
14
+ if ( wp.media.frames.envira ) {
15
+ wp.media.frames.envira.open();
16
+ return;
17
+ } else {
18
+ // Create the wp.media.frames.envira instance (one time)
19
+ wp.media.frames.envira = wp.media( {
20
+ frame: 'post',
21
+ title: wp.media.view.l10n.insertIntoPost,
22
+ button: {
23
+ text: wp.media.view.l10n.insertIntoPost,
24
+ },
25
+ multiple: true
26
+ } );
27
+ }
28
+
29
+ // Mark existing Gallery images as selected when the modal is opened
30
+ wp.media.frames.envira.on( 'open', function() {
31
+ // Get any previously selected images
32
+ var selection = wp.media.frames.envira.state().get( 'selection' );
33
+
34
+ // Get images that already exist in the gallery, and select each one in the modal
35
+ $( 'ul#envira-gallery-output li' ).each( function() {
36
+ var attachment = wp.media.attachment( $( this ).attr( 'id' ) );
37
+ selection.add( attachment ? [ attachment ] : [] );
38
+ } );
39
+ } );
40
+
41
+ // Insert into Gallery Button Clicked
42
+ wp.media.frames.envira.on( 'insert', function( selection ) {
43
+
44
+ // Get state
45
+ var state = wp.media.frames.envira.state(),
46
+ images = [];
47
+
48
+ // Iterate through selected images, building an images array
49
+ selection.each( function( attachment ) {
50
+ // Get the chosen options for this image (size, alignment, link type, link URL)
51
+ var display = state.display( attachment ).toJSON();
52
+
53
+ // Change the image link parameter based on the "Link To" setting the user chose in the media view
54
+ switch ( display.link ) {
55
+ case 'none':
56
+ // Because users cry when their images aren't linked, we need to actually set this to the attachment URL
57
+ attachment.set( 'link', attachment.get( 'url' ) );
58
+ break;
59
+ case 'file':
60
+ attachment.set( 'link', attachment.get( 'url' ) );
61
+ break;
62
+ case 'post':
63
+ // Already linked to post by default
64
+ break;
65
+ case 'custom':
66
+ attachment.set( 'link', display.linkUrl );
67
+ break;
68
+ }
69
+
70
+ // Add the image to the images array
71
+ images.push( attachment.toJSON() );
72
+ }, this );
73
+
74
+ // Send the ajax request with our data to be processed.
75
+ $.post(
76
+ envira_gallery_metabox.ajax,
77
+ {
78
+ action: 'envira_gallery_insert_images',
79
+ nonce: envira_gallery_metabox.insert_nonce,
80
+ post_id: envira_gallery_metabox.id,
81
+ images: images,
82
+ },
83
+ function( response ) {
84
+ // Response should be a JSON success with the HTML for the image grid
85
+ if ( response && response.success ) {
86
+ // Set the image grid to the HTML we received
87
+ $( '#envira-gallery-output' ).html( response.success );
88
+
89
+ // Repopulate the Envira Gallery Image Collection
90
+ EnviraGalleryImagesUpdate( false );
91
+ }
92
+ },
93
+ 'json'
94
+ );
95
+
96
+ } );
97
+
98
+ // Open the media frame
99
+ wp.media.frames.envira.open();
100
+
101
+ return;
102
+
103
+ } );
104
+
105
+ } );
assets/js/media-manage.js ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Handles:
3
+ * - Selection and deselection of media in an Envira Gallery
4
+ * - Toggling edit / delete button states when media is selected / deselected,
5
+ * - Toggling the media list / grid view
6
+ * - Storing the user's preferences for the list / grid view
7
+ */
8
+
9
+ // Setup some vars
10
+ var envira_gallery_output = '#envira-gallery-output',
11
+ envira_gallery_shift_key_pressed = false,
12
+ envira_gallery_last_selected_image = false;
13
+
14
+ jQuery( document ).ready( function( $ ) {
15
+
16
+ // Enable sortable functionality on images
17
+ envira_gallery_sortable( $ );
18
+
19
+ } );
20
+
21
+ /**
22
+ * Enables sortable functionality on a grid of Envira Gallery Images
23
+ *
24
+ * @since 1.5.0
25
+ */
26
+ function envira_gallery_sortable( $ ) {
27
+
28
+ // Add sortable support to Envira Gallery Media items
29
+ $( envira_gallery_output ).sortable( {
30
+ containment: envira_gallery_output,
31
+ items: 'li',
32
+ cursor: 'move',
33
+ forcePlaceholderSize: true,
34
+ placeholder: 'dropzone',
35
+ helper: function( e, item ) {
36
+
37
+ // Basically, if you grab an unhighlighted item to drag, it will deselect (unhighlight) everything else
38
+ if ( ! item.hasClass( 'selected' ) ) {
39
+ item.addClass( 'selected' ).siblings().removeClass( 'selected' );
40
+ }
41
+
42
+ // Clone the selected items into an array
43
+ var elements = item.parent().children( '.selected' ).clone();
44
+
45
+ // Add a property to `item` called 'multidrag` that contains the
46
+ // selected items, then remove the selected items from the source list
47
+ item.data( 'multidrag', elements ).siblings( '.selected' ).remove();
48
+
49
+ // Now the selected items exist in memory, attached to the `item`,
50
+ // so we can access them later when we get to the `stop()` callback
51
+
52
+ // Create the helper
53
+ var helper = $( '<li/>' );
54
+ return helper.append( elements );
55
+
56
+ },
57
+ stop: function( e, ui ) {
58
+ // Remove the helper so we just display the sorted items
59
+ var elements = ui.item.data( 'multidrag' );
60
+ ui.item.after(elements).remove();
61
+
62
+ // Remove the selected class from everything
63
+ $( 'li.selected', $( envira_gallery_output ) ).removeClass( 'selected' );
64
+
65
+ // Send AJAX request to store the new sort order
66
+ $.ajax( {
67
+ url: envira_gallery_metabox.ajax,
68
+ type: 'post',
69
+ async: true,
70
+ cache: false,
71
+ dataType: 'json',
72
+ data: {
73
+ action: 'envira_gallery_sort_images',
74
+ order: $( envira_gallery_output ).sortable( 'toArray' ).toString(),
75
+ post_id: envira_gallery_metabox.id,
76
+ nonce: envira_gallery_metabox.sort
77
+ },
78
+ success: function( response ) {
79
+ // Repopulate the Envira Gallery Backbone Image Collection
80
+ EnviraGalleryImagesUpdate( false );
81
+ return;
82
+ },
83
+ error: function( xhr, textStatus, e ) {
84
+ // Inject the error message into the tab settings area
85
+ $( envira_gallery_output ).before( '<div class="error"><p>' + textStatus.responseText + '</p></div>' );
86
+ }
87
+ } );
88
+ }
89
+ } );
90
+
91
+ }
assets/js/media-upload.js ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Hooks into the global Plupload instance ('uploader'), which is set when includes/admin/metaboxes.php calls media_form()
3
+ * We hook into this global instance and apply our own changes during and after the upload.
4
+ *
5
+ * @since 1.3.1.3
6
+ */
7
+ (function( $ ) {
8
+ $(function() {
9
+
10
+ if ( typeof uploader !== 'undefined' ) {
11
+
12
+ // Change "Select Files" button in the pluploader to "Select Files from Your Computer"
13
+ $( 'input#plupload-browse-button' ).val( envira_gallery_metabox.uploader_files_computer );
14
+
15
+ // Set a custom progress bar
16
+ $( '#envira-gallery .drag-drop-inside' ).append( '<div class="envira-progress-bar"><div></div></div>' );
17
+ var envira_bar = $( '#envira-gallery .envira-progress-bar' ),
18
+ envira_progress = $( '#envira-gallery .envira-progress-bar div' ),
19
+ envira_output = $( '#envira-gallery-output'),
20
+ envira_error = $( '#envira-gallery-upload-error' );
21
+
22
+ // Files Added for Uploading
23
+ uploader.bind( 'FilesAdded', function ( up, files ) {
24
+
25
+ // Hide any existing errors
26
+ $( envira_error ).html( '' );
27
+
28
+ // Fade in the upload progress bar
29
+ $( envira_bar ).fadeIn();
30
+
31
+ } );
32
+
33
+ // File Uploading - show progress bar
34
+ uploader.bind( 'UploadProgress', function( up, file ) {
35
+ $( envira_progress ).css({
36
+ 'width': up.total.percent + '%'
37
+ });
38
+ });
39
+
40
+ // File Uploaded - AJAX call to process image and add to screen.
41
+ uploader.bind( 'FileUploaded', function( up, file, info ) {
42
+
43
+ // AJAX call to Envira to store the newly uploaded image in the meta against this Gallery
44
+ $.post(
45
+ envira_gallery_metabox.ajax,
46
+ {
47
+ action: 'envira_gallery_load_image',
48
+ nonce: envira_gallery_metabox.load_image,
49
+ id: info.response,
50
+ post_id: envira_gallery_metabox.id
51
+ },
52
+ function(res){
53
+ // Prepend or append the new image to the existing grid of images,
54
+ // depending on the media_position setting
55
+ switch ( envira_gallery_metabox.media_position ) {
56
+ case 'before':
57
+ $(envira_output).prepend(res);
58
+ break;
59
+ case 'after':
60
+ default:
61
+ $(envira_output).append(res);
62
+ break;
63
+ }
64
+
65
+ // Repopulate the Envira Gallery Image Collection
66
+ EnviraGalleryImagesUpdate( false );
67
+
68
+ },
69
+ 'json'
70
+ );
71
+ });
72
+
73
+ // Files Uploaded
74
+ uploader.bind( 'UploadComplete', function() {
75
+
76
+ // Hide Progress Bar
77
+ $( envira_bar ).fadeOut();
78
+
79
+ });
80
+
81
+ // File Upload Error
82
+ uploader.bind('Error', function(up, err) {
83
+
84
+ // Show message
85
+ $('#envira-gallery-upload-error').html( '<div class="error fade"><p>' + err.file.name + ': ' + err.message + '</p></div>' );
86
+ up.refresh();
87
+
88
+ });
89
+
90
+ }
91
+
92
+ });
93
+ })( jQuery );
assets/js/metabox.js CHANGED
@@ -1,636 +1,12 @@
1
- /* ==========================================================
2
- * metabox.js
3
- * http://enviragallery.com/
4
- * ==========================================================
5
- * Copyright 2014 Thomas Griffin.
6
- *
7
- * Licensed under the GPL License, Version 2.0 or later (the "License");
8
- * you may not use this file except in compliance with the License.
9
- * You may obtain a copy of the License at
10
- *
11
- * http://www.gnu.org/licenses/gpl-2.0.html
12
- *
13
- * Unless required by applicable law or agreed to in writing, software
14
- * distributed under the License is distributed on an "AS IS" BASIS,
15
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- * See the License for the specific language governing permissions and
17
- * limitations under the License.
18
- * ========================================================== */
19
- ;(function($){
20
- $(function(){
21
- // Initialize the slider tabs.
22
- var envira_tabs = $('#envira-tabs'),
23
- envira_tabs_nav = $('#envira-tabs-nav'),
24
- envira_tabs_hash = window.location.hash,
25
- envira_tabs_hash_sani = window.location.hash.replace('!', '');
26
-
27
- // If we have a hash and it begins with "envira-tab", set the proper tab to be opened.
28
- if ( envira_tabs_hash && envira_tabs_hash.indexOf('envira-tab-') >= 0 ) {
29
- $('.envira-active').removeClass('envira-active');
30
- envira_tabs_nav.find('li a[href="' + envira_tabs_hash_sani + '"]').parent().addClass('envira-active');
31
- envira_tabs.find(envira_tabs_hash_sani).addClass('envira-active').show();
32
-
33
- // Update the post action to contain our hash so the proper tab can be loaded on save.
34
- var post_action = $('#post').attr('action');
35
- if ( post_action ) {
36
- post_action = post_action.split('#')[0];
37
- $('#post').attr('action', post_action + envira_tabs_hash);
38
- }
39
- }
40
-
41
- // Change tabs on click.
42
- $(document).on('click', '#envira-tabs-nav li a', function(e){
43
- e.preventDefault();
44
- var $this = $(this);
45
- if ( $this.parent().hasClass('envira-active') ) {
46
- return;
47
- } else {
48
- window.location.hash = envira_tabs_hash = this.hash.split('#').join('#!');
49
- var current = envira_tabs_nav.find('.envira-active').removeClass('envira-active').find('a').attr('href');
50
- $this.parent().addClass('envira-active');
51
- envira_tabs.find(current).removeClass('envira-active').hide();
52
- envira_tabs.find($this.attr('href')).addClass('envira-active').show();
53
-
54
- // Update the post action to contain our hash so the proper tab can be loaded on save.
55
- var post_action = $('#post').attr('action');
56
- if ( post_action ) {
57
- post_action = post_action.split('#')[0];
58
- $('#post').attr('action', post_action + envira_tabs_hash);
59
- }
60
- }
61
- });
62
-
63
- // Load plupload.
64
- var envira_uploader;
65
- enviraPlupload();
66
-
67
- // Conditionally show necessary fields.
68
- enviraConditionals();
69
-
70
- // Handle the meta icon helper.
71
- if ( 0 !== $('.envira-helper-needed').length ) {
72
- $('<div class="envira-meta-helper-overlay" />').prependTo('#envira-gallery');
73
- }
74
-
75
- $(document).on('click', '.envira-meta-icon', function(e){
76
- e.preventDefault();
77
- var $this = $(this),
78
- container = $this.parent(),
79
- helper = $this.next();
80
- if ( helper.is(':visible') ) {
81
- $('.envira-meta-helper-overlay').remove();
82
- container.removeClass('envira-helper-active');
83
- } else {
84
- if ( 0 === $('.envira-meta-helper-overlay').length ) {
85
- $('<div class="envira-meta-helper-overlay" />').prependTo('#envira-gallery');
86
- }
87
- container.addClass('envira-helper-active');
88
- }
89
- });
90
-
91
- // Open up the media manager modal.
92
- $(document).on('click', '.envira-media-library', function(e){
93
- e.preventDefault();
94
-
95
- // Show the modal.
96
- envira_main_frame = true;
97
- $('#envira-gallery-upload-ui').appendTo('body').show();
98
- });
99
-
100
- // Add the selected state to images when selected from the library view.
101
- $('.envira-gallery-gallery').on('click', '.thumbnail, .check, .media-modal-icon', function(e){
102
- e.preventDefault();
103
- if ( $(this).parent().parent().hasClass('envira-gallery-in-gallery') )
104
- return;
105
- if ( $(this).parent().parent().hasClass('selected') )
106
- $(this).parent().parent().removeClass('details selected');
107
- else
108
- $(this).parent().parent().addClass('details selected');
109
- });
110
-
111
- // Load more images into the library view when the 'Load More Images from Library'
112
- // button is pressed
113
- $(document).on('click', 'a.envira-gallery-load-library', function(e){
114
- enviraLoadLibraryImages( $('a.envira-gallery-load-library').attr('data-envira-gallery-offset') );
115
- });
116
-
117
- // Load more images into the library view when the user scrolls to the bottom of the view
118
- // Honours any search term(s) specified
119
- $('.envira-gallery-gallery').bind('scroll', function() {
120
- if( $(this).scrollTop() + $(this).innerHeight() >= this.scrollHeight ) {
121
- enviraLoadLibraryImages( $('a.envira-gallery-load-library').attr('data-envira-gallery-offset') );
122
- }
123
- });
124
-
125
- // Load images when the search term changes
126
- $(document).on('keyup keydown', '#envira-gallery-gallery-search', function() {
127
- delay(function() {
128
- enviraLoadLibraryImages( 0 );
129
- });
130
- });
131
-
132
- /**
133
- * Makes an AJAX call to get the next batch of images
134
- */
135
- function enviraLoadLibraryImages( offset ) {
136
- // Show spinner
137
- $('.media-toolbar-secondary span.envira-gallery-spinner').css('visibility','visible');
138
-
139
- // AJAX call to get next batch of images
140
- $.post(
141
- envira_gallery_metabox.ajax,
142
- {
143
- action: 'envira_gallery_load_library',
144
- offset: offset,
145
- post_id: envira_gallery_metabox.id,
146
- search: $('input#envira-gallery-gallery-search').val(),
147
- nonce: envira_gallery_metabox.load_gallery
148
- },
149
- function(response) {
150
- // Update offset
151
- $('a.envira-gallery-load-library').attr('data-envira-gallery-offset', ( Number(offset) + 20 ) );
152
-
153
- // Hide spinner
154
- $('.media-toolbar-secondary span.envira-gallery-spinner').css('visibility','hidden');
155
-
156
- // Append the response data.
157
- if ( offset === 0 ) {
158
- // New search, so replace results
159
- $('.envira-gallery-gallery').html( response.html );
160
- } else {
161
- // Append to end of results
162
- $('.envira-gallery-gallery').append( response.html );
163
- }
164
-
165
- },
166
- 'json'
167
- );
168
- }
169
-
170
- // Process inserting slides into slider when the Insert button is pressed.
171
- $(document).on('click', '.envira-gallery-media-insert', function(e){
172
- e.preventDefault();
173
- var $this = $(this),
174
- text = $(this).text(),
175
- data = {
176
- action: 'envira_gallery_insert_images',
177
- nonce: envira_gallery_metabox.insert_nonce,
178
- post_id: envira_gallery_metabox.id,
179
- images: {}
180
- },
181
- selected = false,
182
- insert_e = e;
183
- $this.text(envira_gallery_metabox.inserting);
184
-
185
- // Loop through potential data to send when inserting images.
186
- // First, we loop through the selected items and add them to the data var.
187
- $('.envira-gallery-media-frame').find('.attachment.selected:not(.envira-gallery-in-gallery)').each(function(i, el){
188
- data.images[i] = $(el).attr('data-attachment-id');
189
- selected = true;
190
- });
191
-
192
- // Send the ajax request with our data to be processed.
193
- $.post(
194
- envira_gallery_metabox.ajax,
195
- data,
196
- function(response){
197
- // Set small delay before closing modal.
198
- setTimeout(function(){
199
- // Re-append modal to correct spot and revert text back to default.
200
- append_and_hide(insert_e);
201
- $this.text(text);
202
-
203
- // If we have selected items, be sure to properly load first images back into view.
204
- if ( selected )
205
- $('.envira-gallery-load-library').attr('data-envira-gallery-offset', 0).addClass('has-search').trigger('click');
206
- }, 500);
207
- },
208
- 'json'
209
- );
210
-
211
- });
212
-
213
- // Make gallery items sortable.
214
- var gallery = $('#envira-gallery-output');
215
-
216
- // Use ajax to make the images sortable.
217
- gallery.sortable({
218
- containment: '#envira-gallery-output',
219
- items: 'li',
220
- cursor: 'move',
221
- forcePlaceholderSize: true,
222
- placeholder: 'dropzone',
223
- update: function(event, ui) {
224
- // Make ajax request to sort out items.
225
- var opts = {
226
- url: envira_gallery_metabox.ajax,
227
- type: 'post',
228
- async: true,
229
- cache: false,
230
- dataType: 'json',
231
- data: {
232
- action: 'envira_gallery_sort_images',
233
- order: gallery.sortable('toArray').toString(),
234
- post_id: envira_gallery_metabox.id,
235
- nonce: envira_gallery_metabox.sort
236
- },
237
- success: function(response) {
238
- return;
239
- },
240
- error: function(xhr, textStatus ,e) {
241
- return;
242
- }
243
- };
244
- $.ajax(opts);
245
- }
246
- });
247
-
248
- // Process image removal from a gallery.
249
- $('#envira-gallery').on('click', '.envira-gallery-remove-image', function(e){
250
- e.preventDefault();
251
-
252
- // Bail out if the user does not actually want to remove the image.
253
- var confirm_delete = confirm(envira_gallery_metabox.remove);
254
- if ( ! confirm_delete )
255
- return;
256
-
257
- // Prepare our data to be sent via Ajax.
258
- var attach_id = $(this).parent().attr('id'),
259
- remove = {
260
- action: 'envira_gallery_remove_image',
261
- attachment_id: attach_id,
262
- post_id: envira_gallery_metabox.id,
263
- nonce: envira_gallery_metabox.remove_nonce
264
- };
265
-
266
- // Process the Ajax response and output all the necessary data.
267
- $.post(
268
- envira_gallery_metabox.ajax,
269
- remove,
270
- function(response) {
271
- $('#' + attach_id).fadeOut('normal', function() {
272
- $(this).remove();
273
-
274
- // Refresh the modal view to ensure no items are still checked if they have been removed.
275
- $('.envira-gallery-load-library').attr('data-envira-gallery-offset', 0).addClass('has-search').trigger('click');
276
- });
277
- },
278
- 'json'
279
- );
280
- });
281
-
282
- // Open up the media modal area for modifying gallery metadata when clicking the info icon
283
- $('#envira-gallery').on('click', '.envira-gallery-modify-image', function(e){
284
- e.preventDefault();
285
- var attach_id = $(this).parent().data('envira-gallery-image'),
286
- formfield = 'envira-gallery-meta-' + attach_id;
287
-
288
- // Open modal
289
- openModal(attach_id, formfield);
290
- });
291
-
292
- // Open modal
293
- var modal;
294
- var openModal = function(attach_id, formfield) {
295
-
296
- // Show the modal.
297
- modal = $('#' + formfield).appendTo('body');
298
- $(modal).show();
299
-
300
- // Close modal on close button or background click
301
- $(document).on('click', '.media-modal-close, .media-modal-backdrop', function(e) {
302
- e.preventDefault();
303
- closeModal();
304
- });
305
-
306
- // Close modal on esc keypress
307
- $(document).on('keydown', function(e) {
308
- if ( 27 == e.keyCode ) {
309
- closeModal();
310
- }
311
- });
312
- }
313
-
314
- // Close modal
315
- var closeModal = function() {
316
- // Get modal
317
- var formfield = $(modal).attr('id');
318
- var formfieldArr = formfield.split('-');
319
- var attach_id = formfieldArr[(formfieldArr.length-1)];
320
-
321
- // Close modal
322
- $('#' + formfield).appendTo('#' + attach_id).hide();
323
- }
324
-
325
- // Save the gallery metadata.
326
- $(document).on('click', '.envira-gallery-meta-submit', function(e){
327
- e.preventDefault();
328
- var $this = $(this),
329
- default_t = $this.text(),
330
- attach_id = $this.data('envira-gallery-item'),
331
- formfield = 'envira-gallery-meta-' + attach_id,
332
- meta = {};
333
-
334
- // Output saving text...
335
- $this.text(envira_gallery_metabox.saving);
336
-
337
- // Add the title since it is a special field.
338
- meta.title = $('#envira-gallery-meta-table-' + attach_id).find('textarea[name="_envira_gallery[meta_title]"]').val();
339
-
340
- // Get all meta fields and values.
341
- $('#envira-gallery-meta-table-' + attach_id).find(':input').not('.ed_button').each(function(i, el){
342
- if ( $(this).data('envira-meta') )
343
- meta[$(this).data('envira-meta')] = $(this).val();
344
- });
345
-
346
- // Prepare the data to be sent.
347
- var data = {
348
- action: 'envira_gallery_save_meta',
349
- nonce: envira_gallery_metabox.save_nonce,
350
- attach_id: attach_id,
351
- post_id: envira_gallery_metabox.id,
352
- meta: meta
353
- };
354
-
355
- $.post(
356
- envira_gallery_metabox.ajax,
357
- data,
358
- function(res){
359
- setTimeout(function(){
360
- $('#' + formfield).appendTo('#' + attach_id).hide();
361
- $this.text(default_t);
362
- }, 500);
363
- },
364
- 'json'
365
- );
366
- });
367
-
368
- // Append spinner when importing a gallery.
369
- $('#envira-gallery-import-submit').on('click', function(e){
370
- $(this).next().css('display', 'inline-block');
371
- if ( $('#envira-config-import-gallery').val().length === 0 ) {
372
- e.preventDefault();
373
- $(this).next().hide();
374
- alert(envira_gallery_metabox.import);
375
- }
376
- });
377
-
378
- // Polling function for typing and other user centric items.
379
- var delay = (function() {
380
- var timer = 0;
381
- return function(callback, ms) {
382
- clearTimeout(timer);
383
- timer = setTimeout(callback, ms);
384
- };
385
- })();
386
-
387
- // Close the modal window on user action.
388
- var envira_main_frame = false;
389
- var append_and_hide = function(e){
390
- e.preventDefault();
391
- $('#envira-gallery-upload-ui').appendTo('#envira-gallery-upload-ui-wrapper').hide();
392
- enviraRefresh();
393
- envira_main_frame = false;
394
- };
395
- $(document).on('click', '#envira-gallery-upload-ui .media-modal-close, #envira-gallery-upload-ui .media-modal-backdrop', append_and_hide);
396
- $(document).on('keydown', function(e){
397
- if ( 27 == e.keyCode && envira_main_frame )
398
- append_and_hide(e);
399
- });
400
-
401
- // Function to refresh images in the gallery.
402
- function enviraRefresh(){
403
- var data = {
404
- action: 'envira_gallery_refresh',
405
- post_id: envira_gallery_metabox.id,
406
- nonce: envira_gallery_metabox.refresh_nonce
407
- };
408
-
409
- $('.envira-media-library').after('<span class="spinner envira-gallery-spinner envira-gallery-spinner-refresh"></span>');
410
- $('.envira-gallery-spinner-refresh').css({'display' : 'inline-block', 'margin-top' : '-3px'});
411
-
412
- $.post(
413
- envira_gallery_metabox.ajax,
414
- data,
415
- function(res){
416
- if ( res && res.success ) {
417
- $('#envira-gallery-output').html(res.success);
418
- $('#envira-gallery-output').find('.wp-editor-wrap').each(function(i, el){
419
- var qt = $(el).find('.quicktags-toolbar');
420
- if ( qt.length > 0 ) {
421
- return;
422
- }
423
-
424
- var arr = $(el).attr('id').split('-'),
425
- id = arr.slice(4, -1).join('-');
426
- quicktags({id: 'envira-gallery-caption-' + id, buttons: 'strong,em,link,ul,ol,li,close'});
427
- QTags._buttonsInit(); // Force buttons to initialize.
428
- });
429
-
430
- // Trigger a custom event for 3rd party scripts.
431
- $('#envira-gallery-output').trigger({ type: 'enviraRefreshed', html: res.success, id: envira_gallery_metabox.id });
432
- }
433
-
434
- // Remove the spinner.
435
- $('.envira-gallery-spinner-refresh').fadeOut(300, function(){
436
- $(this).remove();
437
- });
438
- },
439
- 'json'
440
- );
441
- }
442
-
443
- // Function to show conditional fields.
444
- function enviraConditionals() {
445
- var envira_crop_option = $('#envira-config-crop'),
446
- envira_mobile_option = $('#envira-config-mobile'),
447
- envira_toolbar_option = $('#envira-config-lightbox-toolbar');
448
- if ( envira_crop_option.is(':checked') )
449
- $('#envira-config-crop-size-box').fadeIn(300);
450
- envira_crop_option.on('change', function(){
451
- if ( $(this).is(':checked') )
452
- $('#envira-config-crop-size-box').fadeIn(300);
453
- else
454
- $('#envira-config-crop-size-box').fadeOut(300);
455
- });
456
- if ( envira_mobile_option.is(':checked') )
457
- $('#envira-config-mobile-size-box').fadeIn(300);
458
- envira_mobile_option.on('change', function(){
459
- if ( $(this).is(':checked') )
460
- $('#envira-config-mobile-size-box').fadeIn(300);
461
- else
462
- $('#envira-config-mobile-size-box').fadeOut(300);
463
- });
464
- if ( envira_toolbar_option.is(':checked') )
465
- $('#envira-config-lightbox-toolbar-position-box').fadeIn(300);
466
- envira_toolbar_option.on('change', function(){
467
- if ( $(this).is(':checked') )
468
- $('#envira-config-lightbox-toolbar-position-box').fadeIn(300);
469
- else
470
- $('#envira-config-lightbox-toolbar-position-box').fadeOut(300);
471
- });
472
- }
473
-
474
- // Function to initialize plupload.
475
- function enviraPlupload() {
476
- // Append the custom loading progress bar.
477
- $('#envira-gallery .drag-drop-inside').append('<div class="envira-progress-bar"><div></div></div>');
478
-
479
- // Prepare variables.
480
- envira_uploader = new plupload.Uploader(envira_gallery_metabox.plupload);
481
- var envira_bar = $('#envira-gallery .envira-progress-bar'),
482
- envira_progress = $('#envira-gallery .envira-progress-bar div'),
483
- envira_output = $('#envira-gallery-output');
484
-
485
- // Only move forward if the uploader is present.
486
- if ( envira_uploader ) {
487
- // Append a link to use images from the user's media library.
488
- $('#envira-gallery .max-upload-size').append(' <a class="envira-media-library button button-primary" href="#" title="' + envira_gallery_metabox.gallery + '" style="vertical-align: baseline;">' + envira_gallery_metabox.gallery + '</a>');
489
-
490
- envira_uploader.bind('Init', function(up) {
491
- var uploaddiv = $('#envira-gallery-plupload-upload-ui');
492
-
493
- // If drag and drop, make that happen.
494
- if ( up.features.dragdrop && ! $(document.body).hasClass('mobile') ) {
495
- uploaddiv.addClass('drag-drop');
496
- $('#envira-gallery-drag-drop-area').bind('dragover.wp-uploader', function(){
497
- uploaddiv.addClass('drag-over');
498
- }).bind('dragleave.wp-uploader, drop.wp-uploader', function(){
499
- uploaddiv.removeClass('drag-over');
500
- });
501
- } else {
502
- uploaddiv.removeClass('drag-drop');
503
- $('#envira-gallery-drag-drop-area').unbind('.wp-uploader');
504
- }
505
-
506
- // If we have an HTML4 runtime, hide the flash bypass.
507
- if ( up.runtime == 'html4' )
508
- $('.upload-flash-bypass').hide();
509
- });
510
-
511
- // Initialize the uploader.
512
- envira_uploader.init();
513
-
514
- // Bind to the FilesAdded event to show the progess bar.
515
- envira_uploader.bind('FilesAdded', function(up, files){
516
- var hundredmb = 100 * 1024 * 1024,
517
- max = parseInt(up.settings.max_file_size, 10);
518
-
519
- // Remove any errors.
520
- $('#envira-gallery-upload-error').html('');
521
-
522
- // Show the progress bar.
523
- $(envira_bar).show().css('display', 'block');
524
-
525
- // Upload the files.
526
- plupload.each(files, function(file){
527
- if ( max > hundredmb && file.size > hundredmb && up.runtime != 'html5' ) {
528
- enviraUploadError( up, file, true );
529
- }
530
- });
531
-
532
- // Refresh and start.
533
- up.refresh();
534
- up.start();
535
- });
536
-
537
- // Bind to the UploadProgress event to manipulate the progress bar.
538
- envira_uploader.bind('UploadProgress', function(up, file){
539
- $(envira_progress).css('width', up.total.percent + '%');
540
- });
541
-
542
- // Bind to the FileUploaded event to set proper UI display for slider.
543
- envira_uploader.bind('FileUploaded', function(up, file, info){
544
- // Make an ajax request to generate and output the image in the slider UI.
545
- $.post(
546
- envira_gallery_metabox.ajax,
547
- {
548
- action: 'envira_gallery_load_image',
549
- nonce: envira_gallery_metabox.load_image,
550
- id: info.response,
551
- post_id: envira_gallery_metabox.id
552
- },
553
- function(res){
554
- $(envira_output).append(res);
555
- $(res).find('.wp-editor-container').each(function(i, el){
556
- var id = $(el).attr('id').split('-')[4];
557
- quicktags({id: 'envira-gallery-caption-' + id, buttons: 'strong,em,link,ul,ol,li,close'});
558
- QTags._buttonsInit(); // Force buttons to initialize.
559
- });
560
- },
561
- 'json'
562
- );
563
- });
564
-
565
- // Bind to the UploadComplete event to hide and reset the progress bar.
566
- envira_uploader.bind('UploadComplete', function(){
567
- $(envira_bar).hide().css('display', 'none');
568
- $(envira_progress).removeAttr('style');
569
- });
570
-
571
- // Bind to any errors and output them on the screen.
572
- envira_uploader.bind('Error', function(up, error) {
573
- var hundredmb = 100 * 1024 * 1024,
574
- error_el = $('#envira-gallery-upload-error'),
575
- max;
576
- switch (error) {
577
- case plupload.FAILED:
578
- case plupload.FILE_EXTENSION_ERROR:
579
- error_el.html('<p class="error">' + pluploadL10n.upload_failed + '</p>');
580
- break;
581
- case plupload.FILE_SIZE_ERROR:
582
- enviraUploadError(up, error.file);
583
- break;
584
- case plupload.IMAGE_FORMAT_ERROR:
585
- wpFileError(fileObj, pluploadL10n.not_an_image);
586
- break;
587
- case plupload.IMAGE_MEMORY_ERROR:
588
- wpFileError(fileObj, pluploadL10n.image_memory_exceeded);
589
- break;
590
- case plupload.IMAGE_DIMENSIONS_ERROR:
591
- wpFileError(fileObj, pluploadL10n.image_dimensions_exceeded);
592
- break;
593
- case plupload.GENERIC_ERROR:
594
- wpQueueError(pluploadL10n.upload_failed);
595
- break;
596
- case plupload.IO_ERROR:
597
- max = parseInt(uploader.settings.max_file_size, 10);
598
-
599
- if ( max > hundredmb && fileObj.size > hundredmb )
600
- wpFileError(fileObj, pluploadL10n.big_upload_failed.replace('%1$s', '<a class="uploader-html" href="#">').replace('%2$s', '</a>'));
601
- else
602
- wpQueueError(pluploadL10n.io_error);
603
- break;
604
- case plupload.HTTP_ERROR:
605
- wpQueueError(pluploadL10n.http_error);
606
- break;
607
- case plupload.INIT_ERROR:
608
- $('.media-upload-form').addClass('html-uploader');
609
- break;
610
- case plupload.SECURITY_ERROR:
611
- wpQueueError(pluploadL10n.security_error);
612
- break;
613
- default:
614
- enviraUploadError(up, error.file);
615
- break;
616
- }
617
- up.refresh();
618
- });
619
- }
620
- }
621
-
622
- // Function for displaying file upload errors.
623
- function enviraUploadError( up, file, over100mb ) {
624
- var message;
625
-
626
- if ( over100mb ) {
627
- message = pluploadL10n.big_upload_queued.replace('%s', file.name) + ' ' + pluploadL10n.big_upload_failed.replace('%1$s', '<a class="uploader-html" href="#">').replace('%2$s', '</a>');
628
- } else {
629
- message = pluploadL10n.file_exceeds_size_limit.replace('%s', file.name);
630
- }
631
-
632
- $('#envira-gallery-upload-error').html('<div class="error fade"><p>' + message + '</p></div>');
633
- up.removeFile(file);
634
- }
635
- });
636
- }(jQuery));
1
+ /**
2
+ * You'll need to use CodeKit or similar, as this file is a placeholder to combine
3
+ * the following JS files into min/metabox-min.js:
4
+ *
5
+ * - conditional-fields.js
6
+ * - gallery-help.js
7
+ * - media-delete.js
8
+ * - media-edit.js
9
+ * - media-insert.js
10
+ * - media-manage.js
11
+ * - media-upload.js
12
+ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/js/min/admin-min.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery(document).ready(function($){if("undefined"!=typeof Clipboard){var i=new Clipboard(".envira-clipboard");$(document).on("click",".envira-clipboard",function(i){i.preventDefault()})}$("div.envira-notice").on("click",".notice-dismiss",function(i){i.preventDefault(),$(this).closest("div.envira-notice").fadeOut(),$(this).hasClass("is-dismissible")&&$.post(envira_gallery_admin.ajax,{action:"envira_gallery_ajax_dismiss_notice",nonce:envira_gallery_admin.dismiss_notice_nonce,notice:$(this).parent().data("notice")},function(i){},"json")})});
assets/js/min/clipboard-min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function o(t,e,n){function r(a,c){if(!e[a]){if(!t[a]){var s="function"==typeof require&&require;if(!c&&s)return s(a,!0);if(i)return i(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var l=e[a]={exports:{}};t[a][0].call(l.exports,function(e){var n=t[a][1][e];return r(n?n:e)},l,l.exports,o,t,e,n)}return e[a].exports}for(var i="function"==typeof require&&require,a=0;a<n.length;a++)r(n[a]);return r}({1:[function(t,e,n){var o=t("matches-selector");e.exports=function(t,e,n){for(var r=n?t:t.parentNode;r&&r!==document;){if(o(r,e))return r;r=r.parentNode}}},{"matches-selector":5}],2:[function(t,e,n){function o(t,e,n,o,i){var a=r.apply(this,arguments);return t.addEventListener(n,a,i),{destroy:function(){t.removeEventListener(n,a,i)}}}function r(t,e,n,o){return function(n){n.delegateTarget=i(n.target,e,!0),n.delegateTarget&&o.call(t,n)}}var i=t("closest");e.exports=o},{closest:1}],3:[function(t,e,n){n.node=function(t){return void 0!==t&&t instanceof HTMLElement&&1===t.nodeType},n.nodeList=function(t){var e=Object.prototype.toString.call(t);return void 0!==t&&("[object NodeList]"===e||"[object HTMLCollection]"===e)&&"length"in t&&(0===t.length||n.node(t[0]))},n.string=function(t){return"string"==typeof t||t instanceof String},n.fn=function(t){var e=Object.prototype.toString.call(t);return"[object Function]"===e}},{}],4:[function(t,e,n){function o(t,e,n){if(!t&&!e&&!n)throw new Error("Missing required arguments");if(!c.string(e))throw new TypeError("Second argument must be a String");if(!c.fn(n))throw new TypeError("Third argument must be a Function");if(c.node(t))return r(t,e,n);if(c.nodeList(t))return i(t,e,n);if(c.string(t))return a(t,e,n);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function r(t,e,n){return t.addEventListener(e,n),{destroy:function(){t.removeEventListener(e,n)}}}function i(t,e,n){return Array.prototype.forEach.call(t,function(t){t.addEventListener(e,n)}),{destroy:function(){Array.prototype.forEach.call(t,function(t){t.removeEventListener(e,n)})}}}function a(t,e,n){return s(document.body,t,e,n)}var c=t("./is"),s=t("delegate");e.exports=o},{"./is":3,delegate:2}],5:[function(t,e,n){function o(t,e){if(i)return i.call(t,e);for(var n=t.parentNode.querySelectorAll(e),o=0;o<n.length;++o)if(n[o]==t)return!0;return!1}var r=Element.prototype,i=r.matchesSelector||r.webkitMatchesSelector||r.mozMatchesSelector||r.msMatchesSelector||r.oMatchesSelector;e.exports=o},{}],6:[function(t,e,n){function o(t){var e;if("INPUT"===t.nodeName||"TEXTAREA"===t.nodeName)t.focus(),t.setSelectionRange(0,t.value.length),e=t.value;else{t.hasAttribute("contenteditable")&&t.focus();var n=window.getSelection(),o=document.createRange();o.selectNodeContents(t),n.removeAllRanges(),n.addRange(o),e=n.toString()}return e}e.exports=o},{}],7:[function(t,e,n){function o(){}o.prototype={on:function(t,e,n){var o=this.e||(this.e={});return(o[t]||(o[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){function o(){r.off(t,o),e.apply(n,arguments)}var r=this;return o._=e,this.on(t,o,n)},emit:function(t){var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),o=0,r=n.length;for(o;r>o;o++)n[o].fn.apply(n[o].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),o=n[t],r=[];if(o&&e)for(var i=0,a=o.length;a>i;i++)o[i].fn!==e&&o[i].fn._!==e&&r.push(o[i]);return r.length?n[t]=r:delete n[t],this}},e.exports=o},{}],8:[function(e,n,o){!function(r,i){if("function"==typeof t&&t.amd)t(["module","select"],i);else if("undefined"!=typeof o)i(n,e("select"));else{var a={exports:{}};i(a,r.select),r.clipboardAction=a.exports}}(this,function(t,e){"use strict";function n(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var r=n(e),i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},a=function(){function t(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}return function(e,n,o){return n&&t(e.prototype,n),o&&t(e,o),e}}(),c=function(){function t(e){o(this,t),this.resolveOptions(e),this.initSelection()}return t.prototype.resolveOptions=function e(){var t=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.action=t.action,this.emitter=t.emitter,this.target=t.target,this.text=t.text,this.trigger=t.trigger,this.selectedText=""},t.prototype.initSelection=function n(){this.text?this.selectFake():this.target&&this.selectTarget()},t.prototype.selectFake=function c(){var t=this,e="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandler=document.body.addEventListener("click",function(){return t.removeFake()}),this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="fixed",this.fakeElem.style[e?"right":"left"]="-9999px",this.fakeElem.style.top=(window.pageYOffset||document.documentElement.scrollTop)+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,document.body.appendChild(this.fakeElem),this.selectedText=(0,r["default"])(this.fakeElem),this.copyText()},t.prototype.removeFake=function s(){this.fakeHandler&&(document.body.removeEventListener("click"),this.fakeHandler=null),this.fakeElem&&(document.body.removeChild(this.fakeElem),this.fakeElem=null)},t.prototype.selectTarget=function u(){this.selectedText=(0,r["default"])(this.target),this.copyText()},t.prototype.copyText=function l(){var t=void 0;try{t=document.execCommand(this.action)}catch(e){t=!1}this.handleResult(t)},t.prototype.handleResult=function f(t){t?this.emitter.emit("success",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)}):this.emitter.emit("error",{action:this.action,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})},t.prototype.clearSelection=function d(){this.target&&this.target.blur(),window.getSelection().removeAllRanges()},t.prototype.destroy=function p(){this.removeFake()},a(t,[{key:"action",set:function h(){var t=arguments.length<=0||void 0===arguments[0]?"copy":arguments[0];if(this._action=t,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function y(){return this._action}},{key:"target",set:function g(t){if(void 0!==t){if(!t||"object"!==("undefined"==typeof t?"undefined":i(t))||1!==t.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&t.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(t.hasAttribute("readonly")||t.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=t}},get:function m(){return this._target}}]),t}();t.exports=c})},{select:6}],9:[function(e,n,o){!function(r,i){if("function"==typeof t&&t.amd)t(["module","./clipboard-action","tiny-emitter","good-listener"],i);else if("undefined"!=typeof o)i(n,e("./clipboard-action"),e("tiny-emitter"),e("good-listener"));else{var a={exports:{}};i(a,r.clipboardAction,r.tinyEmitter,r.goodListener),r.clipboard=a.exports}}(this,function(t,e,n,o){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function c(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function s(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}var u=r(e),l=r(n),f=r(o),d=function(t){function e(n,o){i(this,e);var r=a(this,t.call(this));return r.resolveOptions(o),r.listenClick(n),r}return c(e,t),e.prototype.resolveOptions=function n(){var t=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.action="function"==typeof t.action?t.action:this.defaultAction,this.target="function"==typeof t.target?t.target:this.defaultTarget,this.text="function"==typeof t.text?t.text:this.defaultText},e.prototype.listenClick=function o(t){var e=this;this.listener=(0,f["default"])(t,"click",function(t){return e.onClick(t)})},e.prototype.onClick=function r(t){var e=t.delegateTarget||t.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new u["default"]({action:this.action(e),target:this.target(e),text:this.text(e),trigger:e,emitter:this})},e.prototype.defaultAction=function l(t){return s("action",t)},e.prototype.defaultTarget=function d(t){var e=s("target",t);return e?document.querySelector(e):void 0},e.prototype.defaultText=function p(t){return s("text",t)},e.prototype.destroy=function h(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)},e}(l["default"]);t.exports=d})},{"./clipboard-action":8,"good-listener":4,"tiny-emitter":7}]},{},[9])(9)});
assets/js/min/editor-min.js CHANGED
@@ -1 +1 @@
1
- !function($){$(function(){var e=envira_editor_frame=!1,a=function(a){a.preventDefault(),$(".envira-gallery-default-ui .selected").removeClass("details selected"),$(".envira-gallery-default-ui").appendTo(".envira-gallery-default-ui-wrapper").hide(),e=envira_editor_frame=!1};$(document).on("click",".envira-gallery-choose-gallery, .envira-gallery-modal-trigger",function(l){l.preventDefault(),e=l.target,envira_editor_frame=!0,$(".envira-gallery-default-ui").appendTo("body").show(),$(document).on("click",".media-modal-close, .media-modal-backdrop, .envira-gallery-cancel-insertion",a),$(document).on("keydown",function(e){27==e.keyCode&&envira_editor_frame&&a(e)})}),$(document).on("click",".envira-gallery-default-ui .thumbnail, .envira-gallery-default-ui .check, .envira-gallery-default-ui .media-modal-icon",function(e){e.preventDefault(),$(this).parent().parent().hasClass("selected")?($(this).parent().parent().removeClass("details selected"),$(".envira-gallery-insert-gallery").attr("disabled","disabled")):($(this).parent().parent().parent().find(".selected").removeClass("details selected"),$(this).parent().parent().addClass("details selected"),$(".envira-gallery-insert-gallery").removeAttr("disabled"))}),$(document).on("click",".envira-gallery-default-ui .check",function(e){e.preventDefault(),$(this).parent().parent().removeClass("details selected"),$(".envira-gallery-insert-gallery").attr("disabled","disabled")}),$(document).on("click",".envira-gallery-default-ui .envira-gallery-insert-gallery",function(l){if(l.preventDefault(),$(e).hasClass("envira-gallery-choose-gallery"))wp.media.editor.insert('[envira-gallery id="'+$(".envira-gallery-default-ui .selected").data("envira-gallery-id")+'"]');else{var r={action:"envira_gallery_load_gallery_data",id:$(".envira-gallery-default-ui:first .selected").data("envira-gallery-id")};$.post(ajaxurl,r,function(e){$(document).trigger({type:"enviraGalleryModalData",gallery:e}),a(l)},"json")}a(l)})})}(jQuery);
1
+ if("undefined"==typeof EnviraGalleryModalWindow)var EnviraGalleryModalWindow=new wp.media.view.Modal({controller:{trigger:function(){}}});wp.media.view.EnviraGalleryError=wp.Backbone.View.extend({tagName:"div",className:"notice error envira-gallery-error",render:function(){return this.template=wp.media.template("envira-gallery-error"),this.$el.html(this.template(this.model)),this}});var EnviraGallerySelectionItemView=wp.Backbone.View.extend({tagName:"li",className:"attachment",template:wp.template("envira-selection-item"),initialize:function(e){this.model=e.model},render:function(){return this.$el.html(this.template(this.model.attributes)),this}}),EnviraGallerySelectionView=wp.Backbone.View.extend({tagName:"div",className:"media-frame mode-select wp-core-ui hide-router hide-menu",template:wp.template("envira-selection"),events:{"click .attachment":"click",keyup:"search",search:"search","click button.media-button-insert":"insert"},initialize:function(e){this.action=e.action,this.selection=new Backbone.Collection,this.collection=new Backbone.Collection,this.is_loading=!1,this.search_timeout=!1,this.on("loading",this.loading,this),this.on("loaded",this.loaded,this),this.getItems(!1,"")},click:function(e){var i=jQuery(e.currentTarget),t=jQuery("div.attachment-preview",i).attr("data-id");i.hasClass("selected")?this.removeFromSelection(i,t):this.addToSelection(i,t)},search:function(e){if(!this.is_loading){clearTimeout(this.search_timeout);var i=e.target.value;if(0==i.length)return void this.getItems(!1,"");if(!(i.length<3)){var t=this;this.search_timeout=setTimeout(function(){t.getItems(!0,i)},1e3)}}},getItems:function(e,i){if(!this.is_loading){this.clearSelection(),this.$el.find("ul.attachments").empty(),this.$el.find("div.envira-gallery-error").remove(),this.trigger("loading");var t="";switch(this.action){case"gallery":t="envira_gallery_editor_get_galleries";break;case"album":t="envira_albums_editor_get_albums"}wp.media.ajax(t,{context:this,data:{nonce:envira_gallery_editor.get_galleries_nonce,search:e,search_terms:i},success:function(e){var i=new Backbone.Collection(e);this.collection.reset(),this.collection.add(i.models),this.collection.each(function(e){var i=new EnviraGallerySelectionItemView({model:e});this.$el.find("ul.attachments").append(i.render().el)},this),this.trigger("loaded")},error:function(e){this.trigger("loaded",e)}})}},render:function(){return this.$el.html(this.template()),this},renderError:function(e){var i={};i.error=e;var t=new wp.media.view.EnviraGalleryError({model:i});return t.render().el},loading:function(){this.is_loading=!0,this.$el.find(".spinner").css("visibility","visible")},loaded:function(e){this.is_loading=!1,this.$el.find(".spinner").css("visibility","hidden"),"undefined"!=typeof e&&this.$el.find("ul.attachments").before(this.renderError(e))},addToSelection:function(e,i){this.trigger("loading"),this.collection.each(function(e){e.get("id")==i&&this.selection.add(e)},this),e.addClass("selected details"),this.selection.length>0&&this.$el.find("button.media-button-insert").attr("disabled",!1),this.trigger("loaded")},removeFromSelection:function(e,i){this.trigger("loading"),this.selection.each(function(e){this.selection.remove([{cid:e.cid}])},this),e.removeClass("selected details"),0==this.selection.length&&this.$el.find("button.media-button-insert").attr("disabled","disabled"),this.trigger("loaded")},clearSelection:function(){this.selection.each(function(e){this.$el.find('div[data-id="'+e.get("id")+'"]').parent().removeClass("selected details")},this),this.$el.find("button.media-button-insert").attr("disabled","disabled"),this.selection.reset()},insert:function(){this.trigger("loading"),this.selection.forEach(function(e){wp.media.editor.insert("[envira-"+this.action+' id="'+e.id+'"]')},this),this.trigger("loaded"),EnviraGalleryModalWindow.close()}});jQuery(document).ready(function($){$(document).on("click","a.envira-gallery-choose-gallery, a.envira-albums-choose-album",function(e){e.preventDefault();var i=$(this).data("action");EnviraGalleryModalWindow.content(new EnviraGallerySelectionView({action:i})),EnviraGalleryModalWindow.open()})});
assets/js/min/envira-min.js CHANGED
@@ -1,2 +1,3 @@
1
- function enviraGetColWidth(t,e){var i,n=jQuery(window).width(),o=t.data("envira-columns");switch(o){case 1:i=t.width();break;case 2:i=480>=n?t.width():t.width()/2;break;case 3:i=480>=n?t.width():768>=n?t.width()/2:t.width()/3;case 4:case 5:case 6:i=480>=n?t.width():768>=n?t.width()/2:1024>=n?t.width()/3:t.width()/o}return parseInt(i-e*(o-1)/o)}function enviraSetWidths(t,e){var i=enviraGetColWidth(t,e);t.children().css({width:i})}function enviraIsMobile(){var t=!1;return function(e){(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0,4)))&&(t=!0)}(navigator.userAgent||navigator.vendor||window.opera),t}function enviraThrottle(t,e){return function(){var i=this,n=[].slice(arguments);clearTimeout(t._throttleTimeout),t._throttleTimeout=setTimeout(function(){t.apply(i,n)},e)}}!function(t,e,i){var n=t.document,o=n.documentElement,s=t.Modernizr,r=function(t){return t.charAt(0).toUpperCase()+t.slice(1)},a="Moz Webkit O Ms".split(" "),l=function(t){var e=o.style,i;if("string"==typeof e[t])return t;t=r(t);for(var n=0,s=a.length;s>n;n++)if(i=a[n]+t,"string"==typeof e[i])return i},h=l("transform"),c=l("transitionProperty"),d={csstransforms:function(){return!!h},csstransforms3d:function(){var t=!!l("perspective");if(t&&"webkitPerspective"in o.style){var i=e("<style>@media (transform-3d),(-webkit-transform-3d){#modernizr{height:3px}}</style>").appendTo("head"),n=e('<div id="modernizr" />').appendTo("html");t=3===n.height(),n.remove(),i.remove()}return t},csstransitions:function(){return!!c}},u;if(s)for(u in d)s.hasOwnProperty(u)||s.addTest(u,d[u]);else{s=t.Modernizr={_version:"1.6ish: miniModernizr for Isotope"};var p=" ",f;for(u in d)f=d[u](),s[u]=f,p+=" "+(f?"":"no-")+u;e("html").addClass(p)}if(s.csstransforms){var m=s.csstransforms3d?{translate:function(t){return"translate3d("+t[0]+"px, "+t[1]+"px, 0) "},scale:function(t){return"scale3d("+t+", "+t+", 1) "}}:{translate:function(t){return"translate("+t[0]+"px, "+t[1]+"px) "},scale:function(t){return"scale("+t+") "}},g=function(t,i,n){var o=e.data(t,"isoTransform")||{},s={},r,a={},l;s[i]=n,e.extend(o,s);for(r in o)l=o[r],a[r]=m[r](l);var c=a.translate||"",d=a.scale||"",u=c+d;e.data(t,"isoTransform",o),t.style[h]=u};e.cssNumber.scale=!0,e.cssHooks.scale={set:function(t,e){g(t,"scale",e)},get:function(t,i){var n=e.data(t,"isoTransform");return n&&n.scale?n.scale:1}},e.fx.step.scale=function(t){e.cssHooks.scale.set(t.elem,t.now+t.unit)},e.cssNumber.translate=!0,e.cssHooks.translate={set:function(t,e){g(t,"translate",e)},get:function(t,i){var n=e.data(t,"isoTransform");return n&&n.translate?n.translate:[0,0]}}}var v,y;s.csstransitions&&(v={WebkitTransitionProperty:"webkitTransitionEnd",MozTransitionProperty:"transitionend",OTransitionProperty:"oTransitionEnd otransitionend",transitionProperty:"transitionend"}[c],y=l("transitionDuration"));var w=e.event,x=e.event.handle?"handle":"dispatch",b;w.special.smartresize={setup:function(){e(this).bind("resize",w.special.smartresize.handler)},teardown:function(){e(this).unbind("resize",w.special.smartresize.handler)},handler:function(t,e){var i=this,n=arguments;t.type="smartresize",b&&clearTimeout(b),b=setTimeout(function(){w[x].apply(i,n)},"execAsap"===e?0:100)}},e.fn.smartresize=function(t){return t?this.bind("smartresize",t):this.trigger("smartresize",["execAsap"])},e.Isotope=function(t,i,n){this.element=e(i),this._create(t),this._init(n)};var _=["width","height"],C=e(t);e.Isotope.settings={resizable:!0,layoutMode:"masonry",containerClass:"isotope",itemClass:"isotope-item",hiddenClass:"isotope-hidden",hiddenStyle:{opacity:0,scale:.001},visibleStyle:{opacity:1,scale:1},containerStyle:{position:"relative",overflow:"hidden"},animationEngine:"best-available",animationOptions:{queue:!1,duration:800},sortBy:"original-order",sortAscending:!0,resizesContainer:!0,transformsEnabled:!0,itemPositionDataEnabled:!1},e.Isotope.prototype={_create:function(t){this.options=e.extend({},e.Isotope.settings,t),this.styleQueue=[],this.elemCount=0;var i=this.element[0].style;this.originalStyle={};var n=_.slice(0);for(var o in this.options.containerStyle)n.push(o);for(var s=0,r=n.length;r>s;s++)o=n[s],this.originalStyle[o]=i[o]||"";this.element.css(this.options.containerStyle),this._updateAnimationEngine(),this._updateUsingTransforms();var a={"original-order":function(t,e){return e.elemCount++,e.elemCount},random:function(){return Math.random()}};this.options.getSortData=e.extend(this.options.getSortData,a),this.reloadItems(),this.offset={left:parseInt(this.element.css("padding-left")||0,10),top:parseInt(this.element.css("padding-top")||0,10)};var l=this;setTimeout(function(){l.element.addClass(l.options.containerClass)},0),this.options.resizable&&C.bind("smartresize.isotope",function(){l.resize()}),this.element.delegate("."+this.options.hiddenClass,"click",function(){return!1})},_getAtoms:function(t){var e=this.options.itemSelector,i=e?t.filter(e).add(t.find(e)):t,n={position:"absolute"};return i=i.filter(function(t,e){return 1===e.nodeType}),this.usingTransforms&&(n.left=0,n.top=0),i.css(n).addClass(this.options.itemClass),this.updateSortData(i,!0),i},_init:function(t){this.$filteredAtoms=this._filter(this.$allAtoms),this._sort(),this.reLayout(t)},option:function(t){if(e.isPlainObject(t)){this.options=e.extend(!0,this.options,t);var i;for(var n in t)i="_update"+r(n),this[i]&&this[i]()}},_updateAnimationEngine:function(){var t=this.options.animationEngine.toLowerCase().replace(/[ _\-]/g,""),e;switch(t){case"css":case"none":e=!1;break;case"jquery":e=!0;break;default:e=!s.csstransitions}this.isUsingJQueryAnimation=e,this._updateUsingTransforms()},_updateTransformsEnabled:function(){this._updateUsingTransforms()},_updateUsingTransforms:function(){var t=this.usingTransforms=this.options.transformsEnabled&&s.csstransforms&&s.csstransitions&&!this.isUsingJQueryAnimation;t||(delete this.options.hiddenStyle.scale,delete this.options.visibleStyle.scale),this.getPositionStyles=t?this._translate:this._positionAbs},_filter:function(t){var e=""===this.options.filter?"*":this.options.filter;if(!e)return t;var i=this.options.hiddenClass,n="."+i,o=t.filter(n),s=o;if("*"!==e){s=o.filter(e);var r=t.not(n).not(e).addClass(i);this.styleQueue.push({$el:r,style:this.options.hiddenStyle})}return this.styleQueue.push({$el:s,style:this.options.visibleStyle}),s.removeClass(i),t.filter(e)},updateSortData:function(t,i){var n=this,o=this.options.getSortData,s,r;t.each(function(){s=e(this),r={};for(var t in o)r[t]=i||"original-order"!==t?o[t](s,n):e.data(this,"isotope-sort-data")[t];e.data(this,"isotope-sort-data",r)})},_sort:function(){var t=this.options.sortBy,e=this._getSorter,i=this.options.sortAscending?1:-1,n=function(n,o){var s=e(n,t),r=e(o,t);return s===r&&"original-order"!==t&&(s=e(n,"original-order"),r=e(o,"original-order")),(s>r?1:r>s?-1:0)*i};this.$filteredAtoms.sort(n)},_getSorter:function(t,i){return e.data(t,"isotope-sort-data")[i]},_translate:function(t,e){return{translate:[t,e]}},_positionAbs:function(t,e){return{left:t,top:e}},_pushPosition:function(t,e,i){e=Math.round(e+this.offset.left),i=Math.round(i+this.offset.top);var n=this.getPositionStyles(e,i);this.styleQueue.push({$el:t,style:n}),this.options.itemPositionDataEnabled&&t.data("isotope-item-position",{x:e,y:i})},layout:function(t,e){var i=this.options.layoutMode;if(this["_"+i+"Layout"](t),this.options.resizesContainer){var n=this["_"+i+"GetContainerSize"]();this.styleQueue.push({$el:this.element,style:n})}this._processStyleQueue(t,e),this.isLaidOut=!0},_processStyleQueue:function(t,i){var n=this.isLaidOut&&this.isUsingJQueryAnimation?"animate":"css",o=this.options.animationOptions,r=this.options.onLayout,a,l,h,c;if(l=function(t,e){e.$el[n](e.style,o)},this._isInserting&&this.isUsingJQueryAnimation)l=function(t,e){a=e.$el.hasClass("no-transition")?"css":n,e.$el[a](e.style,o)};else if(i||r||o.complete){var d=!1,u=[i,r,o.complete],p=this;if(h=!0,c=function(){if(!d){for(var e,i=0,n=u.length;n>i;i++)e=u[i],"function"==typeof e&&e.call(p.element,t,p);d=!0}},this.isUsingJQueryAnimation&&"animate"===n)o.complete=c,h=!1;else if(s.csstransitions){for(var f=0,m=this.styleQueue[0],g=m&&m.$el,w;!g||!g.length;){if(w=this.styleQueue[f++],!w)return;g=w.$el}var x=parseFloat(getComputedStyle(g[0])[y]);x>0&&(l=function(t,e){e.$el[n](e.style,o).one(v,c)},h=!1)}}e.each(this.styleQueue,l),h&&c(),this.styleQueue=[]},resize:function(){this["_"+this.options.layoutMode+"ResizeChanged"]()&&this.reLayout()},reLayout:function(t){this["_"+this.options.layoutMode+"Reset"](),this.layout(this.$filteredAtoms,t)},addItems:function(t,e){var i=this._getAtoms(t);this.$allAtoms=this.$allAtoms.add(i),e&&e(i)},insert:function(t,e){this.element.append(t);var i=this;this.addItems(t,function(t){var n=i._filter(t);i._addHideAppended(n),i._sort(),i.reLayout(),i._revealAppended(n,e)})},appended:function(t,e){var i=this;this.addItems(t,function(t){i._addHideAppended(t),i.layout(t),i._revealAppended(t,e)})},_addHideAppended:function(t){this.$filteredAtoms=this.$filteredAtoms.add(t),t.addClass("no-transition"),this._isInserting=!0,this.styleQueue.push({$el:t,style:this.options.hiddenStyle})},_revealAppended:function(t,e){var i=this;setTimeout(function(){t.removeClass("no-transition"),i.styleQueue.push({$el:t,style:i.options.visibleStyle}),i._isInserting=!1,i._processStyleQueue(t,e)},10)},reloadItems:function(){this.$allAtoms=this._getAtoms(this.element.children())},remove:function(t,e){this.$allAtoms=this.$allAtoms.not(t),this.$filteredAtoms=this.$filteredAtoms.not(t);var i=this,n=function(){t.remove(),e&&e.call(i.element)};t.filter(":not(."+this.options.hiddenClass+")").length?(this.styleQueue.push({$el:t,style:this.options.hiddenStyle}),this._sort(),this.reLayout(n)):n()},shuffle:function(t){this.updateSortData(this.$allAtoms),this.options.sortBy="random",this._sort(),this.reLayout(t)},destroy:function(){var t=this.usingTransforms,e=this.options;this.$allAtoms.removeClass(e.hiddenClass+" "+e.itemClass).each(function(){var e=this.style;e.position="",e.top="",e.left="",e.opacity="",t&&(e[h]="")});var i=this.element[0].style;for(var n in this.originalStyle)i[n]=this.originalStyle[n];this.element.unbind(".isotope").undelegate("."+e.hiddenClass,"click").removeClass(e.containerClass).removeData("isotope"),C.unbind(".isotope")},_getSegments:function(t){var e=this.options.layoutMode,i=t?"rowHeight":"columnWidth",n=t?"height":"width",o=t?"rows":"cols",s=this.element[n](),a,l=this.options[e]&&this.options[e][i]||this.$filteredAtoms["outer"+r(n)](!0)||s;a=Math.floor(s/l),a=Math.max(a,1),this[e][o]=a,this[e][i]=l},_checkIfSegmentsChanged:function(t){var e=this.options.layoutMode,i=t?"rows":"cols",n=this[e][i];return this._getSegments(t),this[e][i]!==n},_masonryReset:function(){this.masonry={},this._getSegments();var t=this.masonry.cols;for(this.masonry.colYs=[];t--;)this.masonry.colYs.push(0)},_masonryLayout:function(t){var i=this,n=i.masonry;t.each(function(){var t=e(this),o=Math.ceil(t.outerWidth(!0)/n.columnWidth);if(o=Math.min(o,n.cols),1===o)i._masonryPlaceBrick(t,n.colYs);else{var s=n.cols+1-o,r=[],a,l;for(l=0;s>l;l++)a=n.colYs.slice(l,l+o),r[l]=Math.max.apply(Math,a);i._masonryPlaceBrick(t,r)}})},_masonryPlaceBrick:function(t,e){for(var i=Math.min.apply(Math,e),n=0,o=0,s=e.length;s>o;o++)if(e[o]===i){n=o;break}var r=this.masonry.columnWidth*n,a=i;this._pushPosition(t,r,a);var l=i+t.outerHeight(!0),h=this.masonry.cols+1-s;for(o=0;h>o;o++)this.masonry.colYs[n+o]=l},_masonryGetContainerSize:function(){var t=Math.max.apply(Math,this.masonry.colYs);return{height:t}},_masonryResizeChanged:function(){return this._checkIfSegmentsChanged()},_fitRowsReset:function(){this.fitRows={x:0,y:0,height:0}},_fitRowsLayout:function(t){var i=this,n=this.element.width(),o=this.fitRows;t.each(function(){var t=e(this),s=t.outerWidth(!0),r=t.outerHeight(!0);0!==o.x&&s+o.x>n&&(o.x=0,o.y=o.height),i._pushPosition(t,o.x,o.y),o.height=Math.max(o.y+r,o.height),o.x+=s})},_fitRowsGetContainerSize:function(){return{height:this.fitRows.height}},_fitRowsResizeChanged:function(){return!0},_cellsByRowReset:function(){this.cellsByRow={index:0},this._getSegments(),this._getSegments(!0)},_cellsByRowLayout:function(t){var i=this,n=this.cellsByRow;t.each(function(){var t=e(this),o=n.index%n.cols,s=Math.floor(n.index/n.cols),r=(o+.5)*n.columnWidth-t.outerWidth(!0)/2,a=(s+.5)*n.rowHeight-t.outerHeight(!0)/2;i._pushPosition(t,r,a),n.index++})},_cellsByRowGetContainerSize:function(){return{height:Math.ceil(this.$filteredAtoms.length/this.cellsByRow.cols)*this.cellsByRow.rowHeight+this.offset.top}},_cellsByRowResizeChanged:function(){return this._checkIfSegmentsChanged()},_straightDownReset:function(){this.straightDown={y:0}},_straightDownLayout:function(t){var i=this;t.each(function(t){var n=e(this);i._pushPosition(n,0,i.straightDown.y),i.straightDown.y+=n.outerHeight(!0)})},_straightDownGetContainerSize:function(){return{height:this.straightDown.y}},_straightDownResizeChanged:function(){return!0},_masonryHorizontalReset:function(){this.masonryHorizontal={},this._getSegments(!0);var t=this.masonryHorizontal.rows;for(this.masonryHorizontal.rowXs=[];t--;)this.masonryHorizontal.rowXs.push(0)},_masonryHorizontalLayout:function(t){var i=this,n=i.masonryHorizontal;t.each(function(){var t=e(this),o=Math.ceil(t.outerHeight(!0)/n.rowHeight);if(o=Math.min(o,n.rows),1===o)i._masonryHorizontalPlaceBrick(t,n.rowXs);else{var s=n.rows+1-o,r=[],a,l;for(l=0;s>l;l++)a=n.rowXs.slice(l,l+o),r[l]=Math.max.apply(Math,a);i._masonryHorizontalPlaceBrick(t,r)}})},_masonryHorizontalPlaceBrick:function(t,e){for(var i=Math.min.apply(Math,e),n=0,o=0,s=e.length;s>o;o++)if(e[o]===i){n=o;break}var r=i,a=this.masonryHorizontal.rowHeight*n;this._pushPosition(t,r,a);var l=i+t.outerWidth(!0),h=this.masonryHorizontal.rows+1-s;for(o=0;h>o;o++)this.masonryHorizontal.rowXs[n+o]=l},_masonryHorizontalGetContainerSize:function(){var t=Math.max.apply(Math,this.masonryHorizontal.rowXs);return{width:t}},_masonryHorizontalResizeChanged:function(){return this._checkIfSegmentsChanged(!0)},_fitColumnsReset:function(){this.fitColumns={x:0,y:0,width:0}},_fitColumnsLayout:function(t){var i=this,n=this.element.height(),o=this.fitColumns;t.each(function(){var t=e(this),s=t.outerWidth(!0),r=t.outerHeight(!0);0!==o.y&&r+o.y>n&&(o.x=o.width,o.y=0),i._pushPosition(t,o.x,o.y),o.width=Math.max(o.x+s,o.width),o.y+=r})},_fitColumnsGetContainerSize:function(){return{width:this.fitColumns.width}},_fitColumnsResizeChanged:function(){return!0},_cellsByColumnReset:function(){this.cellsByColumn={index:0},this._getSegments(),this._getSegments(!0)},_cellsByColumnLayout:function(t){var i=this,n=this.cellsByColumn;t.each(function(){var t=e(this),o=Math.floor(n.index/n.rows),s=n.index%n.rows,r=(o+.5)*n.columnWidth-t.outerWidth(!0)/2,a=(s+.5)*n.rowHeight-t.outerHeight(!0)/2;i._pushPosition(t,r,a),n.index++})},_cellsByColumnGetContainerSize:function(){return{width:Math.ceil(this.$filteredAtoms.length/this.cellsByColumn.rows)*this.cellsByColumn.columnWidth}},_cellsByColumnResizeChanged:function(){return this._checkIfSegmentsChanged(!0)},_straightAcrossReset:function(){this.straightAcross={x:0}},_straightAcrossLayout:function(t){var i=this;t.each(function(t){var n=e(this);i._pushPosition(n,i.straightAcross.x,0),i.straightAcross.x+=n.outerWidth(!0)})},_straightAcrossGetContainerSize:function(){return{width:this.straightAcross.x}},_straightAcrossResizeChanged:function(){return!0}},e.fn.imagesLoaded=function(t){function i(){t.call(o,s)}function n(t){var o=t.target;o.src!==a&&-1===e.inArray(o,l)&&(l.push(o),--r<=0&&(setTimeout(i),s.unbind(".imagesLoaded",n)))}var o=this,s=o.find("img").add(o.filter("img")),r=s.length,a="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==",l=[];return r||i(),s.bind("load.imagesLoaded error.imagesLoaded",n).each(function(){var t=this.src;this.src=a,this.src=t}),o};var k=function(e){t.console&&t.console.error(e)};e.fn.isotope=function(t,i){if("string"==typeof t){var n=Array.prototype.slice.call(arguments,1);this.each(function(){var i=e.data(this,"isotope");return i?e.isFunction(i[t])&&"_"!==t.charAt(0)?void i[t].apply(i,n):void k("no such method '"+t+"' for isotope instance"):void k("cannot call methods on isotope prior to initialization; attempted to call method '"+t+"'")})}else this.each(function(){var n=e.data(this,"isotope");n?(n.option(t),n._init(i)):e.data(this,"isotope",new e.Isotope(t,this,i))});return this}}(window,jQuery),jQuery.Isotope.prototype._getMasonryGutterColumns=function(){var t=this.options.masonry&&this.options.masonry.gutterWidth||0;containerWidth=this.element.width(),this.masonry.columnWidth=this.options.masonry&&this.options.masonry.columnWidth||this.$filteredAtoms.outerWidth(!0)||containerWidth,this.masonry.columnWidth+=t,this.masonry.cols=Math.floor((containerWidth+t)/this.masonry.columnWidth),this.masonry.cols=Math.max(this.masonry.cols,1)},jQuery.Isotope.prototype._masonryReset=function(){this.masonry={},this._getMasonryGutterColumns();var t=this.masonry.cols;for(this.masonry.colYs=[];t--;)this.masonry.colYs.push(0)},jQuery.Isotope.prototype._masonryResizeChanged=function(){var t=this.masonry.cols;return this._getMasonryGutterColumns(),this.masonry.cols!==t},function(t,e,$,i){"use strict";var n=$("html"),o=$(t),s=$(e),r=$.envirabox=function(){r.open.apply(this,arguments)},a=navigator.userAgent.match(/msie/i),l=null,h=e.createTouch!==i,c=function(t){return t&&t.hasOwnProperty&&t instanceof $},d=function(t){return t&&"string"===$.type(t)},u=function(t){return d(t)&&t.indexOf("%")>0},p=function(t){return t&&!(t.style.overflow&&"hidden"===t.style.overflow)&&(t.clientWidth&&t.scrollWidth>t.clientWidth||t.clientHeight&&t.scrollHeight>t.clientHeight)},f=function(t,e){var i=parseInt(t,10)||0;return e&&u(t)&&(i=r.getViewport()[e]/100*i),Math.ceil(i)},m=function(t,e){return f(t,e)+"px"};$.extend(r,{version:"2.1.5",defaults:{padding:15,margin:40,width:800,height:600,minWidth:100,minHeight:100,maxWidth:9999,maxHeight:9999,pixelRatio:1,autoSize:!0,autoHeight:!1,autoWidth:!1,autoResize:!0,autoCenter:!h,fitToView:!0,aspectRatio:!1,topRatio:.5,leftRatio:.5,scrolling:"auto",wrapCSS:"",arrows:!0,closeBtn:!0,closeClick:!1,nextClick:!1,mouseWheel:!0,autoPlay:!1,playSpeed:3e3,preload:3,modal:!1,loop:!0,ajax:{dataType:"html",headers:{"X-envirabox":!0}},iframe:{scrolling:"auto",preload:!0},swf:{wmode:"transparent",allowfullscreen:"true",allowscriptaccess:"always"},keys:{next:{13:"left",34:"up",39:"left",40:"up"},prev:{8:"right",33:"down",37:"right",38:"down"},close:[27],play:[32],toggle:[70]},direction:{next:"left",prev:"right"},scrollOutside:!0,index:0,type:null,href:null,content:null,title:null,tpl:{wrap:'<div class="envirabox-wrap" tabIndex="-1"><div class="envirabox-skin"><div class="envirabox-outer"><div class="envirabox-inner"></div></div></div></div>',image:'<img class="envirabox-image" src="{href}" alt="" />',iframe:'<iframe id="envirabox-frame{rnd}" name="envirabox-frame{rnd}" class="envirabox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen'+(a?' allowtransparency="true"':"")+"></iframe>",error:'<p class="envirabox-error">The requested content cannot be loaded.<br/>Please try again later.</p>',closeBtn:'<a title="Close" class="envirabox-item envirabox-close" href="javascript:;"></a>',next:'<a title="Next" class="envirabox-nav envirabox-next" href="javascript:;"><span></span></a>',prev:'<a title="Previous" class="envirabox-nav envirabox-prev" href="javascript:;"><span></span></a>'},openEffect:"fade",openSpeed:250,openEasing:"swing",openOpacity:!0,openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:$.noop,beforeLoad:$.noop,afterLoad:$.noop,beforeShow:$.noop,afterShow:$.noop,beforeChange:$.noop,beforeClose:$.noop,afterClose:$.noop},group:{},opts:{},previous:null,coming:null,current:null,isActive:!1,isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(t,e){return t&&($.isPlainObject(e)||(e={}),!1!==r.close(!0))?($.isArray(t)||(t=c(t)?$(t).get():[t]),$.each(t,function(n,o){var s={},a,l,h,u,p,f,m;"object"===$.type(o)&&(o.nodeType&&(o=$(o)),c(o)?(s={href:o.data("envirabox-href")||o.attr("href"),title:$("<div/>").text(o.data("envirabox-title")||o.attr("title")).html(),isDom:!0,element:o},$.metadata&&$.extend(!0,s,o.metadata())):s=o),a=e.href||s.href||(d(o)?o:null),l=e.title!==i?e.title:s.title||"",h=e.content||s.content,u=h?"html":e.type||s.type,!u&&s.isDom&&(u=o.data("envirabox-type"),u||(p=o.prop("class").match(/envirabox\.(\w+)/),u=p?p[1]:null)),d(a)&&(u||(r.isImage(a)?u="image":r.isSWF(a)?u="swf":"#"===a.charAt(0)?u="inline":d(o)&&(u="html",h=o)),"ajax"===u&&(f=a.split(/\s+/,2),a=f.shift(),m=f.shift())),h||("inline"===u?a?h=$(d(a)?a.replace(/.*(?=#[^\s]+$)/,""):a):s.isDom&&(h=o):"html"===u?h=a:u||a||!s.isDom||(u="inline",h=o)),$.extend(s,{href:a,type:u,content:h,title:l,selector:m}),t[n]=s}),r.opts=$.extend(!0,{},r.defaults,e),e.keys!==i&&(r.opts.keys=e.keys?$.extend({},r.defaults.keys,e.keys):!1),r.group=t,r._start(r.opts.index)):void 0},cancel:function(){var t=r.coming;t&&!1===r.trigger("onCancel")||(r.hideLoading(),t&&(r.ajaxLoad&&r.ajaxLoad.abort(),r.ajaxLoad=null,r.imgPreload&&(r.imgPreload.onload=r.imgPreload.onerror=null),t.wrap&&t.wrap.stop(!0,!0).trigger("onReset").remove(),r.coming=null,r.current||r._afterZoomOut(t)))},close:function(t){r.cancel(),!1!==r.trigger("beforeClose")&&(r.unbindEvents(),r.isActive&&(r.isOpen&&t!==!0?(r.isOpen=r.isOpened=!1,r.isClosing=!0,$(".envirabox-item, .envirabox-nav").remove(),r.wrap.stop(!0,!0).removeClass("envirabox-opened"),r.transitions[r.current.closeMethod]()):($(".envirabox-wrap").stop(!0).trigger("onReset").remove(),r._afterZoomOut())))},play:function(t){var e=function(){clearTimeout(r.player.timer)},i=function(){e(),r.current&&r.player.isActive&&(r.player.timer=setTimeout(r.next,r.current.playSpeed))},n=function(){e(),s.unbind(".player"),r.player.isActive=!1,r.trigger("onPlayEnd")},o=function(){r.current&&(r.current.loop||r.current.index<r.group.length-1)&&(r.player.isActive=!0,s.bind({"onCancel.player beforeClose.player":n,"onUpdate.player":i,"beforeLoad.player":e}),i(),r.trigger("onPlayStart"))};t===!0||!r.player.isActive&&t!==!1?o():n()},next:function(t){var e=r.current;e&&(d(t)||(t=e.direction.next),r.jumpto(e.index+1,t,"next"))},prev:function(t){var e=r.current;e&&(d(t)||(t=e.direction.prev),r.jumpto(e.index-1,t,"prev"))},jumpto:function(t,e,n){var o=r.current;o&&(t=f(t),r.direction=e||o.direction[t>=o.index?"next":"prev"],r.router=n||"jumpto",o.loop&&(0>t&&(t=o.group.length+t%o.group.length),t%=o.group.length),o.group[t]!==i&&(r.cancel(),r._start(t)))},reposition:function(t,e){var i=r.current,n=i?i.wrap:null,o;n&&(o=r._getPosition(e),t&&"scroll"===t.type?(delete o.position,n.stop(!0,!0).animate(o,200)):(n.css(o),i.pos=$.extend({},i.dim,o)))},update:function(t){var e=t&&t.originalEvent&&t.originalEvent.type,i=!e||"orientationchange"===e;i&&(clearTimeout(l),l=null),r.isOpen&&!l&&(l=setTimeout(function(){var n=r.current;n&&!r.isClosing&&(r.wrap.removeClass("envirabox-tmp"),(i||"load"===e||"resize"===e&&n.autoResize)&&r._setDimension(),"scroll"===e&&n.canShrink||r.reposition(t),r.trigger("onUpdate"),l=null)},i&&!h?0:300))},toggle:function(t){r.isOpen&&(r.current.fitToView="boolean"===$.type(t)?t:!r.current.fitToView,h&&(r.wrap.removeAttr("style").addClass("envirabox-tmp"),r.trigger("onUpdate")),r.update())},hideLoading:function(){s.unbind(".loading"),$("#envirabox-loading").remove()},showLoading:function(){var t,e;r.hideLoading(),t=$('<div id="envirabox-loading"><div></div></div>').click(r.cancel).appendTo("body"),s.bind("keydown.loading",function(t){27===(t.which||t.keyCode)&&(t.preventDefault(),r.cancel())}),r.defaults.fixed||(e=r.getViewport(),t.css({position:"absolute",top:.5*e.h+e.y,left:.5*e.w+e.x})),r.trigger("onLoading")},getViewport:function(){var e=r.current&&r.current.locked||!1,i={x:o.scrollLeft(),y:o.scrollTop()};return e&&e.length?(i.w=e[0].clientWidth,i.h=e[0].clientHeight):(i.w=h&&t.innerWidth?t.innerWidth:o.width(),i.h=h&&t.innerHeight?t.innerHeight:o.height()),i},unbindEvents:function(){r.wrap&&c(r.wrap)&&r.wrap.unbind(".fb"),s.unbind(".fb"),o.unbind(".fb")},bindEvents:function(){var t=r.current,e;t&&(o.bind("orientationchange.fb"+(h?"":" resize.fb")+(t.autoCenter&&!t.locked?" scroll.fb":""),r.update),e=t.keys,e&&s.bind("keydown.fb",function(n){var o=n.which||n.keyCode,s=n.target||n.srcElement;return 27===o&&r.coming?!1:void(n.ctrlKey||n.altKey||n.shiftKey||n.metaKey||s&&(s.type||$(s).is("[contenteditable]"))||$.each(e,function(e,s){return t.group.length>1&&s[o]!==i?(r[e](s[o]),n.preventDefault(),!1):$.inArray(o,s)>-1?(r[e](),n.preventDefault(),!1):void 0}))}),$.fn.mousewheel&&t.mouseWheel&&r.wrap.bind("mousewheel.fb",function(e,i,n,o){for(var s=e.target||null,a=$(s),l=!1;a.length&&!(l||a.is(".envirabox-skin")||a.is(".envirabox-wrap"));)l=p(a[0]),a=$(a).parent();0===i||l||r.group.length>1&&!t.canShrink&&(o>0||n>0?r.prev(o>0?"down":"left"):(0>o||0>n)&&r.next(0>o?"up":"right"),e.preventDefault())}))},trigger:function(t,e){var i,n=e||r.coming||r.current;if(n){if($.isFunction(n[t])&&(i=n[t].apply(n,Array.prototype.slice.call(arguments,1))),i===!1)return!1;n.helpers&&$.each(n.helpers,function(e,i){i&&r.helpers[e]&&$.isFunction(r.helpers[e][t])&&r.helpers[e][t]($.extend(!0,{},r.helpers[e].defaults,i),n)})}s.trigger(t)},isImage:function(t){return d(t)&&t.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)},isSWF:function(t){return d(t)&&t.match(/\.(swf)((\?|#).*)?$/i)},_start:function(t){var e={},i,n,o,s,a;if(t=f(t),i=r.group[t]||null,!i)return!1;if(e=$.extend(!0,{},r.opts,i),s=e.margin,a=e.padding,"number"===$.type(s)&&(e.margin=[s,s,s,s]),"number"===$.type(a)&&(e.padding=[a,a,a,a]),e.modal&&$.extend(!0,e,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1,mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}}),e.autoSize&&(e.autoWidth=e.autoHeight=!0),"auto"===e.width&&(e.autoWidth=!0),"auto"===e.height&&(e.autoHeight=!0),e.group=r.group,e.index=t,r.coming=e,!1===r.trigger("beforeLoad"))return void(r.coming=null);if(o=e.type,n=e.href,!o)return r.coming=null,r.current&&r.router&&"jumpto"!==r.router?(r.current.index=t,r[r.router](r.direction)):!1;if(r.isActive=!0,("image"===o||"swf"===o)&&(e.autoHeight=e.autoWidth=!1,e.scrolling="visible"),"image"===o&&(e.aspectRatio=!0),"iframe"===o&&h&&(e.scrolling="scroll"),e.wrap=$(e.tpl.wrap).addClass("envirabox-"+(h?"mobile":"desktop")+" envirabox-type-"+o+" envirabox-tmp "+e.wrapCSS).appendTo(e.parent||"body"),$.extend(e,{skin:$(".envirabox-skin",e.wrap),outer:$(".envirabox-outer",e.wrap),inner:$(".envirabox-inner",e.wrap)}),$.each(["Top","Right","Bottom","Left"],function(t,i){e.skin.css("padding"+i,m(e.padding[t]))}),r.trigger("onReady"),"inline"===o||"html"===o){if(!e.content||!e.content.length)return r._error("content")}else if(!n)return r._error("href");"image"===o?r._loadImage():"ajax"===o?r._loadAjax():"iframe"===o?r._loadIframe():r._afterLoad()},_error:function(t){$.extend(r.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:t,content:r.coming.tpl.error}),r._afterLoad()},_loadImage:function(){var t=r.imgPreload=new Image;t.onload=function(){this.onload=this.onerror=null,r.coming.width=this.width/r.opts.pixelRatio,r.coming.height=this.height/r.opts.pixelRatio,r._afterLoad()},t.onerror=function(){this.onload=this.onerror=null,r._error("image")},t.src=r.coming.href,t.complete!==!0&&r.showLoading()},_loadAjax:function(){var t=r.coming;r.showLoading(),r.ajaxLoad=$.ajax($.extend({},t.ajax,{url:t.href,error:function(t,e){r.coming&&"abort"!==e?r._error("ajax",t):r.hideLoading()},success:function(e,i){"success"===i&&(t.content=e,r._afterLoad())}}))},_loadIframe:function(){var t=r.coming,e=$(t.tpl.iframe.replace(/\{rnd\}/g,(new Date).getTime())).attr("scrolling",h?"auto":t.iframe.scrolling).attr("src",t.href);$(t.wrap).bind("onReset",function(){try{$(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(t){}}),t.iframe.preload&&(r.showLoading(),e.one("load",function(){$(this).data("ready",1),h||$(this).bind("load.fb",r.update),$(this).parents(".envirabox-wrap").width("100%").removeClass("envirabox-tmp").show(),r._afterLoad()})),t.content=e.appendTo(t.inner),t.iframe.preload||r._afterLoad()},_preloadImages:function(){var t=r.group,e=r.current,i=t.length,n=e.preload?Math.min(e.preload,i-1):0,o,s;for(s=1;n>=s;s+=1)o=t[(e.index+s)%i],"image"===o.type&&o.href&&((new Image).src=o.href)},_afterLoad:function(){var t=r.coming,e=r.current,i="envirabox-placeholder",n,o,s,a,l,h;if(r.hideLoading(),t&&r.isActive!==!1){if(!1===r.trigger("afterLoad",t,e))return t.wrap.stop(!0).trigger("onReset").remove(),void(r.coming=null);switch(e&&(r.trigger("beforeChange",e),e.wrap.stop(!0).removeClass("envirabox-opened").find(".envirabox-item, .envirabox-nav").remove()),r.unbindEvents(),n=t,o=t.content,s=t.type,a=t.scrolling,$.extend(r,{wrap:n.wrap,skin:n.skin,outer:n.outer,inner:n.inner,current:n,previous:e}),l=n.href,s){case"inline":case"ajax":case"html":n.selector?o=$("<div>").html(o).find(n.selector):c(o)&&(o.data(i)||o.data(i,$('<div class="'+i+'"></div>').insertAfter(o).hide()),o=o.show().detach(),n.wrap.bind("onReset",function(){$(this).find(o).length&&o.hide().replaceAll(o.data(i)).data(i,!1)}));break;case"image":o=n.tpl.image.replace(/\{href\}/g,l);break;case"swf":o='<object id="envirabox-swf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="'+l+'"></param>',h="",$.each(n.swf,function(t,e){o+='<param name="'+t+'" value="'+e+'"></param>',h+=" "+t+'="'+e+'"'}),o+='<embed src="'+l+'" type="application/x-shockwave-flash" width="100%" height="100%"'+h+"></embed></object>"}c(o)&&o.parent().is(n.inner)||n.inner.append(o),r.trigger("beforeShow"),n.inner.css("overflow","yes"===a?"scroll":"no"===a?"hidden":a),r._setDimension(),r.reposition(),r.isOpen=!1,r.coming=null,r.bindEvents(),r.isOpened?e.prevMethod&&r.transitions[e.prevMethod]():$(".envirabox-wrap").not(n.wrap).stop(!0).trigger("onReset").remove(),r.transitions[r.isOpened?n.nextMethod:n.openMethod](),r._preloadImages()
2
- }},_setDimension:function(){var t=r.getViewport(),e=0,i=!1,n=!1,o=r.wrap,s=r.skin,a=r.inner,l=r.current,h=l.width,c=l.height,d=l.minWidth,p=l.minHeight,g=l.maxWidth,v=l.maxHeight,y=l.scrolling,w=l.scrollOutside?l.scrollbarWidth:0,x=l.margin,b=f(x[1]+x[3]),_=f(x[0]+x[2]),C,k,A,S,M,z,H,R,T,W,P,L,O,I,D;if(o.add(s).add(a).width("auto").height("auto").removeClass("envirabox-tmp"),C=f(s.outerWidth(!0)-s.width()),k=f(s.outerHeight(!0)-s.height()),A=b+C,S=_+k,M=u(h)?(t.w-A)*f(h)/100:h,z=u(c)?(t.h-S)*f(c)/100:c,"iframe"===l.type){if(I=l.content,l.autoHeight&&1===I.data("ready"))try{I[0].contentWindow.document.location&&(a.width(M).height(9999),D=I.contents().find("body"),w&&D.css("overflow-x","hidden"),z=D.outerHeight(!0))}catch(E){}}else(l.autoWidth||l.autoHeight)&&(a.addClass("envirabox-tmp"),l.autoWidth||a.width(M),l.autoHeight||a.height(z),l.autoWidth&&(M=a.width()),l.autoHeight&&(z=a.height()),a.removeClass("envirabox-tmp"));if(h=f(M),c=f(z),T=M/z,d=f(u(d)?f(d,"w")-A:d),g=f(u(g)?f(g,"w")-A:g),p=f(u(p)?f(p,"h")-S:p),v=f(u(v)?f(v,"h")-S:v),H=g,R=v,l.fitToView&&(g=Math.min(t.w-A,g),v=Math.min(t.h-S,v)),L=t.w-b,O=t.h-_,l.aspectRatio?(h>g&&(h=g,c=f(h/T)),c>v&&(c=v,h=f(c*T)),d>h&&(h=d,c=f(h/T)),p>c&&(c=p,h=f(c*T))):(h=Math.max(d,Math.min(h,g)),l.autoHeight&&"iframe"!==l.type&&(a.width(h),c=a.height()),c=Math.max(p,Math.min(c,v))),l.fitToView)if(a.width(h).height(c),o.width(h+C),W=o.width(),P=o.height(),l.aspectRatio)for(;(W>L||P>O)&&h>d&&c>p&&!(e++>19);)c=Math.max(p,Math.min(v,c-10)),h=f(c*T),d>h&&(h=d,c=f(h/T)),h>g&&(h=g,c=f(h/T)),a.width(h).height(c),o.width(h+C),W=o.width(),P=o.height();else h=Math.max(d,Math.min(h,h-(W-L))),c=Math.max(p,Math.min(c,c-(P-O)));w&&"auto"===y&&z>c&&L>h+C+w&&(h+=w),a.width(h).height(c),o.width(h+C),W=o.width(),P=o.height(),i=(W>L||P>O)&&h>d&&c>p,n=l.aspectRatio?H>h&&R>c&&M>h&&z>c:(H>h||R>c)&&(M>h||z>c),$.extend(l,{dim:{width:m(W),height:m(P)},origWidth:M,origHeight:z,canShrink:i,canExpand:n,wPadding:C,hPadding:k,wrapSpace:P-s.outerHeight(!0),skinSpace:s.height()-c}),!I&&l.autoHeight&&c>p&&v>c&&!n&&a.height("auto")},_getPosition:function(t){var e=r.current,i=r.getViewport(),n=e.margin,o=r.wrap.width()+n[1]+n[3],s=r.wrap.height()+n[0]+n[2],a={position:"absolute",top:n[0],left:n[3]};return e.helpers.title.type&&"float"==e.helpers.title.type&&(s+=$(".envirabox-skin .envirabox-title").height()),e.autoCenter&&e.fixed&&!t&&s<=i.h&&o<=i.w?a.position="fixed":e.locked||(a.top+=i.y,a.left+=i.x),a.top=m(Math.max(a.top,a.top+(i.h-s)*e.topRatio)),a.left=m(Math.max(a.left,a.left+(i.w-o)*e.leftRatio)),a},_afterZoomIn:function(){var t=r.current;t&&(r.isOpen=r.isOpened=!0,r.wrap.css("overflow","visible").addClass("envirabox-opened").hide().show(0),r.update(),(t.closeClick||t.nextClick&&r.group.length>1)&&r.inner.css("cursor","pointer").bind("click.fb",function(e){$(e.target).is("a")||$(e.target).parent().is("a")||(e.preventDefault(),r[t.closeClick?"close":"next"]())}),t.closeBtn&&$(t.tpl.closeBtn).appendTo(r.skin).bind("click.fb",function(t){t.preventDefault(),r.close()}),t.arrows&&r.group.length>1&&((t.loop||t.index>0)&&$(t.tpl.prev).appendTo(r.outer).bind("click.fb",r.prev),(t.loop||t.index<r.group.length-1)&&$(t.tpl.next).appendTo(r.outer).bind("click.fb",r.next)),r.trigger("afterShow"),t.loop||t.index!==t.group.length-1?r.opts.autoPlay&&!r.player.isActive&&(r.opts.autoPlay=!1,r.play(!0)):r.play(!1))},_afterZoomOut:function(t){t=t||r.current,$(".envirabox-wrap").trigger("onReset").remove(),$.extend(r,{group:{},opts:{},router:!1,current:null,isActive:!1,isOpened:!1,isOpen:!1,isClosing:!1,wrap:null,skin:null,outer:null,inner:null}),r.trigger("afterClose",t)}}),r.transitions={getOrigPosition:function(){var t=r.current,e=t.element,i=t.orig,n={},o=50,s=50,a=t.hPadding,l=t.wPadding,h=r.getViewport();return!i&&t.isDom&&e.is(":visible")&&(i=e.find("img:first"),i.length||(i=e)),c(i)?(n=i.offset(),i.is("img")&&(o=i.outerWidth(),s=i.outerHeight())):(n.top=h.y+(h.h-s)*t.topRatio,n.left=h.x+(h.w-o)*t.leftRatio),("fixed"===r.wrap.css("position")||t.locked)&&(n.top-=h.y,n.left-=h.x),n={top:m(n.top-a*t.topRatio),left:m(n.left-l*t.leftRatio),width:m(o+l),height:m(s+a)}},step:function(t,e){var i,n,o,s=e.prop,a=r.current,l=a.wrapSpace,h=a.skinSpace;("width"===s||"height"===s)&&(i=e.end===e.start?1:(t-e.start)/(e.end-e.start),r.isClosing&&(i=1-i),n="width"===s?a.wPadding:a.hPadding,o=t-n,r.skin[s](f("width"===s?o:o-l*i)),r.inner[s](f("width"===s?o:o-l*i-h*i)))},zoomIn:function(){var t=r.current,e=t.pos,i=t.openEffect,n="elastic"===i,o=$.extend({opacity:1},e);delete o.position,n?(e=this.getOrigPosition(),t.openOpacity&&(e.opacity=.1)):"fade"===i&&(e.opacity=.1),r.wrap.css(e).animate(o,{duration:"none"===i?0:t.openSpeed,easing:t.openEasing,step:n?this.step:null,complete:r._afterZoomIn})},zoomOut:function(){var t=r.current,e=t.closeEffect,i="elastic"===e,n={opacity:.1};i&&(n=this.getOrigPosition(),t.closeOpacity&&(n.opacity=.1)),r.wrap.animate(n,{duration:"none"===e?0:t.closeSpeed,easing:t.closeEasing,step:i?this.step:null,complete:r._afterZoomOut})},changeIn:function(){var t=r.current,e=t.nextEffect,i=t.pos,n={opacity:1},o=r.direction,s=200,a;i.opacity=.1,"elastic"===e&&(a="down"===o||"up"===o?"top":"left","down"===o||"right"===o?(i[a]=m(f(i[a])-s),n[a]="+="+s+"px"):(i[a]=m(f(i[a])+s),n[a]="-="+s+"px")),"none"===e?r._afterZoomIn():r.wrap.css(i).animate(n,{duration:t.nextSpeed,easing:t.nextEasing,complete:r._afterZoomIn})},changeOut:function(){var t=r.previous,e=t.prevEffect,i={opacity:.1},n=r.direction,o=200;"elastic"===e&&(i["down"===n||"up"===n?"top":"left"]=("up"===n||"left"===n?"-":"+")+"="+o+"px"),t.wrap.animate(i,{duration:"none"===e?0:t.prevSpeed,easing:t.prevEasing,complete:function(){$(this).trigger("onReset").remove()}})}},r.helpers.overlay={defaults:{closeClick:!0,speedOut:200,showEarly:!0,css:{},locked:!h,fixed:!0},overlay:null,fixed:!1,el:$("html"),create:function(t){var e;t=$.extend({},this.defaults,t),this.overlay&&this.close(),e=r.coming?r.coming.parent:t.parent,this.overlay=$('<div class="envirabox-overlay"></div>').appendTo(e&&e.lenth?e:"body"),this.fixed=!1,t.fixed&&r.defaults.fixed&&(this.overlay.addClass("envirabox-overlay-fixed"),this.fixed=!0)},open:function(t){var e=this;t=$.extend({},this.defaults,t),this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(t),this.fixed||(o.bind("resize.overlay",$.proxy(this.update,this)),this.update()),t.closeClick&&this.overlay.bind("click.overlay",function(t){return $(t.target).hasClass("envirabox-overlay")?(r.isActive?r.close():e.close(),!1):void 0}),this.overlay.css(t.css).show()},close:function(){o.unbind("resize.overlay"),this.el.hasClass("envirabox-lock")&&($(".envirabox-margin").removeClass("envirabox-margin"),this.el.removeClass("envirabox-lock"),o.scrollTop(this.scrollV).scrollLeft(this.scrollH)),$(".envirabox-overlay").remove().hide(),$.extend(this,{overlay:null,fixed:!1})},update:function(){var t="100%",i;this.overlay.width(t).height("100%"),a?(i=Math.max(e.documentElement.offsetWidth,e.body.offsetWidth),s.width()>i&&(t=s.width())):s.width()>o.width()&&(t=s.width()),this.overlay.width(t).height(s.height())},onReady:function(t,e){var i=this.overlay;$(".envirabox-overlay").stop(!0,!0),i||this.create(t),t.locked&&this.fixed&&e.fixed&&(e.locked=this.overlay.append(e.wrap),e.fixed=!1),t.showEarly===!0&&this.beforeShow.apply(this,arguments)},beforeShow:function(t,e){e.locked&&!this.el.hasClass("envirabox-lock")&&(this.fixPosition!==!1&&$("*").filter(function(){return"fixed"===$(this).css("position")&&!$(this).hasClass("envirabox-overlay")&&!$(this).hasClass("envirabox-wrap")}).addClass("envirabox-margin"),this.el.addClass("envirabox-margin"),this.scrollV=o.scrollTop(),this.scrollH=o.scrollLeft(),this.el.addClass("envirabox-lock"),o.scrollTop(this.scrollV).scrollLeft(this.scrollH)),this.open(t)},onUpdate:function(){this.fixed||this.update()},afterClose:function(t){this.overlay&&!r.coming&&this.overlay.fadeOut(t.speedOut,$.proxy(this.close,this))}},r.helpers.title={defaults:{type:"float",position:"bottom"},beforeShow:function(t){var e=r.current,i=e.title,n=t.type,o,s;if($.isFunction(i)&&(i=i.call(e.element,e)),d(i)&&""!==$.trim(i)){switch(o=$('<div class="envirabox-title envirabox-title-'+n+'-wrap">'+i+"</div>"),n){case"inside":s=r.skin;break;case"outside":s=r.wrap;break;case"over":s=r.inner;break;default:s=r.skin,o.appendTo("body"),a&&o.width(o.width()),o.wrapInner('<span class="child"></span>'),r.current.margin[2]+=Math.abs(f(o.css("margin-bottom")))}o["top"===t.position?"prependTo":"appendTo"](s)}}},$.fn.envirabox=function(t){var e,i=$(this),n=this.selector||"",o=function(o){var s=$(this).blur(),a=e,l,h;o.ctrlKey||o.altKey||o.shiftKey||o.metaKey||s.is(".envirabox-wrap")||(l=t.groupAttr||"data-envirabox-group",h=s.attr(l),h||(l="rel",h=s.get(0)[l]),h&&""!==h&&"nofollow"!==h&&(s=n.length?$(n):i,s=s.filter("["+l+'="'+h+'"]'),a=s.index(this)),t.index=a,r.open(s,t)!==!1&&o.preventDefault())};return t=t||{},e=t.index||0,n&&t.live!==!1?s.undelegate(n,"click.fb-start").delegate(n+":not('.envirabox-item, .envirabox-nav')","click.fb-start",o):i.unbind("click.fb-start").bind("click.fb-start",o),this.filter("[data-envirabox-start=1]").trigger("click"),this},s.ready(function(){var e,o;$.scrollbarWidth===i&&($.scrollbarWidth=function(){var t=$('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo("body"),e=t.children(),i=e.innerWidth()-e.height(99).innerWidth();return t.remove(),i}),$.support.fixedPosition===i&&($.support.fixedPosition=function(){var t=$('<div style="position:fixed;top:20px;"></div>').appendTo("body"),e=20===t[0].offsetTop||15===t[0].offsetTop;return t.remove(),e}()),$.extend(r.defaults,{scrollbarWidth:$.scrollbarWidth(),fixed:$.support.fixedPosition,parent:$("body")}),e=$(t).width(),n.addClass("envirabox-lock-test"),o=$(t).width(),n.removeClass("envirabox-lock-test"),$("<style type='text/css'>.envirabox-margin{margin-right:"+(o-e)+"px;}</style>").appendTo("head")})}(window,document,jQuery),function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof exports?module.exports=t:t(jQuery)}(function($){function t(t){var n=t||window.event,o=s.call(arguments,1),l=0,c=0,d=0,u=0,p=0,f=0;if(t=$.event.fix(n),t.type="mousewheel","detail"in n&&(d=-1*n.detail),"wheelDelta"in n&&(d=n.wheelDelta),"wheelDeltaY"in n&&(d=n.wheelDeltaY),"wheelDeltaX"in n&&(c=-1*n.wheelDeltaX),"axis"in n&&n.axis===n.HORIZONTAL_AXIS&&(c=-1*d,d=0),l=0===d?c:d,"deltaY"in n&&(d=-1*n.deltaY,l=d),"deltaX"in n&&(c=n.deltaX,0===d&&(l=-1*c)),0!==d||0!==c){if(1===n.deltaMode){var m=$.data(this,"mousewheel-line-height");l*=m,d*=m,c*=m}else if(2===n.deltaMode){var g=$.data(this,"mousewheel-page-height");l*=g,d*=g,c*=g}if(u=Math.max(Math.abs(d),Math.abs(c)),(!a||a>u)&&(a=u,i(n,u)&&(a/=40)),i(n,u)&&(l/=40,c/=40,d/=40),l=Math[l>=1?"floor":"ceil"](l/a),c=Math[c>=1?"floor":"ceil"](c/a),d=Math[d>=1?"floor":"ceil"](d/a),h.settings.normalizeOffset&&this.getBoundingClientRect){var v=this.getBoundingClientRect();p=t.clientX-v.left,f=t.clientY-v.top}return t.deltaX=c,t.deltaY=d,t.deltaFactor=a,t.offsetX=p,t.offsetY=f,t.deltaMode=0,o.unshift(t,l,c,d),r&&clearTimeout(r),r=setTimeout(e,200),($.event.dispatch||$.event.handle).apply(this,o)}}function e(){a=null}function i(t,e){return h.settings.adjustOldDeltas&&"mousewheel"===t.type&&e%120===0}var n=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],o="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],s=Array.prototype.slice,r,a;if($.event.fixHooks)for(var l=n.length;l;)$.event.fixHooks[n[--l]]=$.event.mouseHooks;var h=$.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var e=o.length;e;)this.addEventListener(o[--e],t,!1);else this.onmousewheel=t;$.data(this,"mousewheel-line-height",h.getLineHeight(this)),$.data(this,"mousewheel-page-height",h.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var e=o.length;e;)this.removeEventListener(o[--e],t,!1);else this.onmousewheel=null;$.removeData(this,"mousewheel-line-height"),$.removeData(this,"mousewheel-page-height")},getLineHeight:function(t){var e=$(t),i=e["offsetParent"in $.fn?"offsetParent":"parent"]();return i.length||(i=$("body")),parseInt(i.css("fontSize"),10)||parseInt(e.css("fontSize"),10)||16},getPageHeight:function(t){return $(t).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};$.fn.extend({mousewheel:function(t){return t?this.bind("mousewheel",t):this.trigger("mousewheel")},unmousewheel:function(t){return this.unbind("mousewheel",t)}})}),jQuery(document).ready(function($){var t="ontouchstart"in document.documentElement;t&&$("body").addClass("envira-touch")});
 
1
+ !function(t,e,$,i){"use strict";var n=$("html"),o=$(t),r=$(e),s=$.envirabox=function(){s.open.apply(this,arguments)},a=navigator.userAgent.match(/msie/i),u=null,l=e.createTouch!==i,h=function(t){return t&&t.hasOwnProperty&&t instanceof $},p=function(t){return t&&"string"===$.type(t)},c=function(t){return p(t)&&t.indexOf("%")>0},d=function(t){return t&&!(t.style.overflow&&"hidden"===t.style.overflow)&&(t.clientWidth&&t.scrollWidth>t.clientWidth||t.clientHeight&&t.scrollHeight>t.clientHeight)},f=function(t,e){var i=parseInt(t,10)||0;return e&&c(t)&&(i=s.getViewport()[e]/100*i),Math.ceil(i)},m=function(t,e){return f(t,e)+"px"};$.extend(s,{version:"2.1.5",defaults:{padding:15,margin:40,width:800,height:600,minWidth:100,minHeight:100,maxWidth:9999,maxHeight:9999,pixelRatio:1,autoSize:!0,autoHeight:!1,autoWidth:!1,autoResize:!0,autoCenter:!l,fitToView:!0,aspectRatio:!1,topRatio:.5,leftRatio:.5,scrolling:"auto",wrapCSS:"",arrows:!0,closeBtn:!0,closeClick:!1,nextClick:!1,mouseWheel:!0,autoPlay:!1,playSpeed:3e3,preload:3,modal:!1,loop:!0,ajax:{dataType:"html",headers:{"X-envirabox":!0}},iframe:{scrolling:"auto",preload:!0},swf:{wmode:"transparent",allowfullscreen:"true",allowscriptaccess:"always"},keys:{next:{13:"left",34:"up",39:"left",40:"up"},prev:{8:"right",33:"down",37:"right",38:"down"},close:[27],play:[32],toggle:[70]},direction:{next:"left",prev:"right"},scrollOutside:!0,index:0,type:null,href:null,content:null,title:null,tpl:{wrap:'<div class="envirabox-wrap" tabIndex="-1"><div class="envirabox-skin"><div class="envirabox-outer"><div class="envirabox-inner"></div></div></div></div>',image:'<img class="envirabox-image" src="{href}" />',iframe:'<iframe id="envirabox-frame{rnd}" name="envirabox-frame{rnd}" class="envirabox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen'+(a?' allowtransparency="true"':"")+"></iframe>",error:'<p class="envirabox-error">The requested content cannot be loaded.<br/>Please try again later.</p>',closeBtn:'<a title="Close" class="envirabox-item envirabox-close" href="javascript:;"></a>',next:'<a title="Next" class="envirabox-nav envirabox-next" href="javascript:;"><span></span></a>',prev:'<a title="Previous" class="envirabox-nav envirabox-prev" href="javascript:;"><span></span></a>'},openEffect:"fade",openSpeed:250,openEasing:"swing",openOpacity:!0,openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:$.noop,beforeLoad:$.noop,afterLoad:$.noop,beforeShow:$.noop,afterShow:$.noop,beforeChange:$.noop,beforeClose:$.noop,afterClose:$.noop},group:{},opts:{},previous:null,coming:null,current:null,isActive:!1,isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(t,e){return t&&($.isPlainObject(e)||(e={}),!1!==s.close(!0))?($.isArray(t)||(t=h(t)?$(t).get():[t]),$.each(t,function(n,o){var r={},a,u,l,c,d,f,m;"object"===$.type(o)&&(o.nodeType&&(o=$(o)),h(o)?(r={href:o.data("envirabox-href")||o.attr("href"),title:$("<div/>").text(o.data("envirabox-title")||o.attr("title")).html(),isDom:!0,element:o},$.metadata&&$.extend(!0,r,o.metadata())):r=o),a=e.href||r.href||(p(o)?o:null),u=e.title!==i?e.title:r.title||"",l=e.content||r.content,c=l?"html":e.type||r.type,!c&&r.isDom&&(c=o.data("envirabox-type"),c||(d=o.prop("class").match(/envirabox\.(\w+)/),c=d?d[1]:null)),p(a)&&(c||(s.isImage(a)?c="image":s.isSWF(a)?c="swf":"#"===a.charAt(0)?c="inline":p(o)&&(c="html",l=o)),"ajax"===c&&(f=a.split(/\s+/,2),a=f.shift(),m=f.shift())),l||("inline"===c?a?l=$(p(a)?a.replace(/.*(?=#[^\s]+$)/,""):a):r.isDom&&(l=o):"html"===c?l=a:c||a||!r.isDom||(c="inline",l=o)),$.extend(r,{href:a,type:c,content:l,title:u,selector:m}),t[n]=r}),s.opts=$.extend(!0,{},s.defaults,e),e.keys!==i&&(s.opts.keys=e.keys?$.extend({},s.defaults.keys,e.keys):!1),s.group=t,s._start(s.opts.index)):void 0},cancel:function(){var t=s.coming;t&&!1===s.trigger("onCancel")||(s.hideLoading(),t&&(s.ajaxLoad&&s.ajaxLoad.abort(),s.ajaxLoad=null,s.imgPreload&&(s.imgPreload.onload=s.imgPreload.onerror=null),t.wrap&&t.wrap.stop(!0,!0).trigger("onReset").remove(),s.coming=null,s.current||s._afterZoomOut(t)))},close:function(t){s.cancel(),!1!==s.trigger("beforeClose")&&(s.unbindEvents(),s.isActive&&(s.isOpen&&t!==!0?(s.isOpen=s.isOpened=!1,s.isClosing=!0,$(".envirabox-item, .envirabox-nav").remove(),s.wrap.stop(!0,!0).removeClass("envirabox-opened"),s.transitions[s.current.closeMethod]()):($(".envirabox-wrap").stop(!0).trigger("onReset").remove(),s._afterZoomOut())))},play:function(t){var e=function(){clearTimeout(s.player.timer)},i=function(){e(),s.current&&s.player.isActive&&(s.player.timer=setTimeout(s.next,s.current.playSpeed))},n=function(){e(),r.unbind(".player"),s.player.isActive=!1,s.trigger("onPlayEnd")},o=function(){s.current&&(s.current.loop||s.current.index<s.group.length-1)&&(s.player.isActive=!0,r.bind({"onCancel.player beforeClose.player":n,"onUpdate.player":i,"beforeLoad.player":e}),i(),s.trigger("onPlayStart"))};t===!0||!s.player.isActive&&t!==!1?o():n()},next:function(t){var e=s.current;e&&(p(t)||(t=e.direction.next),s.jumpto(e.index+1,t,"next"))},prev:function(t){var e=s.current;e&&(p(t)||(t=e.direction.prev),s.jumpto(e.index-1,t,"prev"))},jumpto:function(t,e,n){var o=s.current;o&&(t=f(t),s.direction=e||o.direction[t>=o.index?"next":"prev"],s.router=n||"jumpto",o.loop&&(0>t&&(t=o.group.length+t%o.group.length),t%=o.group.length),o.group[t]!==i&&(s.cancel(),s._start(t)))},reposition:function(t,e){var i=s.current,n=i?i.wrap:null,o;n&&(o=s._getPosition(e),t&&"scroll"===t.type?(delete o.position,n.stop(!0,!0).animate(o,200)):(n.css(o),i.pos=$.extend({},i.dim,o)))},update:function(t){var e=t&&t.originalEvent&&t.originalEvent.type,i=!e||"orientationchange"===e;i&&(clearTimeout(u),u=null),s.isOpen&&!u&&(u=setTimeout(function(){var n=s.current;n&&!s.isClosing&&(s.wrap.removeClass("envirabox-tmp"),(i||"load"===e||"resize"===e&&n.autoResize)&&s._setDimension(),"scroll"===e&&n.canShrink||s.reposition(t),s.trigger("onUpdate"),u=null)},i&&!l?0:300))},toggle:function(t){s.isOpen&&(s.current.fitToView="boolean"===$.type(t)?t:!s.current.fitToView,l&&(s.wrap.removeAttr("style").addClass("envirabox-tmp"),s.trigger("onUpdate")),s.update())},hideLoading:function(){r.unbind(".loading"),$("#envirabox-loading").remove()},showLoading:function(){var t,e;s.hideLoading(),t=$('<div id="envirabox-loading"><div></div></div>').click(s.cancel).appendTo("body"),r.bind("keydown.loading",function(t){27===(t.which||t.keyCode)&&(t.preventDefault(),s.cancel())}),s.defaults.fixed||(e=s.getViewport(),t.css({position:"absolute",top:.5*e.h+e.y,left:.5*e.w+e.x})),s.trigger("onLoading")},getViewport:function(){var e=s.current&&s.current.locked||!1,i={x:o.scrollLeft(),y:o.scrollTop()};return e&&e.length?(i.w=e[0].clientWidth,i.h=e[0].clientHeight):(i.w=l&&t.innerWidth?t.innerWidth:o.width(),i.h=l&&t.innerHeight?t.innerHeight:o.height()),i},unbindEvents:function(){s.wrap&&h(s.wrap)&&s.wrap.unbind(".fb"),r.unbind(".fb"),o.unbind(".fb")},bindEvents:function(){var t=s.current,e;t&&(o.bind("orientationchange.fb"+(l?"":" resize.fb")+(t.autoCenter&&!t.locked?" scroll.fb":""),s.update),e=t.keys,e&&r.bind("keydown.fb",function(n){var o=n.which||n.keyCode,r=n.target||n.srcElement;return 27===o&&s.coming?!1:void(n.ctrlKey||n.altKey||n.shiftKey||n.metaKey||r&&(r.type||$(r).is("[contenteditable]"))||$.each(e,function(e,r){return t.group.length>1&&r[o]!==i?(s[e](r[o]),n.preventDefault(),!1):$.inArray(o,r)>-1?(s[e](),n.preventDefault(),!1):void 0}))}),$.fn.mousewheel&&t.mouseWheel&&s.wrap.bind("mousewheel.fb",function(e,i,n,o){for(var r=e.target||null,a=$(r),u=!1;a.length&&!(u||a.is(".envirabox-skin")||a.is(".envirabox-wrap"));)u=d(a[0]),a=$(a).parent();0===i||u||s.group.length>1&&!t.canShrink&&(o>0||n>0?s.prev(o>0?"down":"left"):(0>o||0>n)&&s.next(0>o?"up":"right"),e.preventDefault())}))},trigger:function(t,e){var i,n=e||s.coming||s.current;if(n){if($.isFunction(n[t])&&(i=n[t].apply(n,Array.prototype.slice.call(arguments,1))),i===!1)return!1;n.helpers&&$.each(n.helpers,function(e,i){i&&s.helpers[e]&&$.isFunction(s.helpers[e][t])&&s.helpers[e][t]($.extend(!0,{},s.helpers[e].defaults,i),n)})}r.trigger(t)},isImage:function(t){return p(t)&&t.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i)},isSWF:function(t){return p(t)&&t.match(/\.(swf)((\?|#).*)?$/i)},_start:function(t){var e={},i,n,o,r,a;if(t=f(t),i=s.group[t]||null,!i)return!1;if(e=$.extend(!0,{},s.opts,i),r=e.margin,a=e.padding,"number"===$.type(r)&&(e.margin=[r,r,r,r]),"number"===$.type(a)&&(e.padding=[a,a,a,a]),e.modal&&$.extend(!0,e,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1,mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}}),e.autoSize&&(e.autoWidth=e.autoHeight=!0),"auto"===e.width&&(e.autoWidth=!0),"auto"===e.height&&(e.autoHeight=!0),e.group=s.group,e.index=t,s.coming=e,!1===s.trigger("beforeLoad"))return void(s.coming=null);if(o=e.type,n=e.href,!o)return s.coming=null,s.current&&s.router&&"jumpto"!==s.router?(s.current.index=t,s[s.router](s.direction)):!1;if(s.isActive=!0,("image"===o||"swf"===o)&&(e.autoHeight=e.autoWidth=!1,e.scrolling="visible"),"image"===o&&(e.aspectRatio=!0),"iframe"===o&&l&&(e.scrolling="scroll"),e.wrap=$(e.tpl.wrap).addClass("envirabox-"+(l?"mobile":"desktop")+" envirabox-type-"+o+" envirabox-tmp "+e.wrapCSS).appendTo(e.parent||"body"),$.extend(e,{skin:$(".envirabox-skin",e.wrap),outer:$(".envirabox-outer",e.wrap),inner:$(".envirabox-inner",e.wrap)}),$.each(["Top","Right","Bottom","Left"],function(t,i){e.skin.css("padding"+i,m(e.padding[t]))}),s.trigger("onReady"),"inline"===o||"html"===o){if(!e.content||!e.content.length)return s._error("content")}else if(!n)return s._error("href");"image"===o?s._loadImage():"ajax"===o?s._loadAjax():"iframe"===o?s._loadIframe():s._afterLoad()},_error:function(t){$.extend(s.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:t,content:s.coming.tpl.error}),s._afterLoad()},_loadImage:function(){var t=s.imgPreload=new Image;t.onload=function(){this.onload=this.onerror=null,s.coming.width=this.width/s.opts.pixelRatio,s.coming.height=this.height/s.opts.pixelRatio,s._afterLoad()},t.onerror=function(){this.onload=this.onerror=null,s._error("image")},t.src=s.coming.href,t.complete!==!0&&s.showLoading()},_loadAjax:function(){var t=s.coming;s.showLoading(),s.ajaxLoad=$.ajax($.extend({},t.ajax,{url:t.href,error:function(t,e){s.coming&&"abort"!==e?s._error("ajax",t):s.hideLoading()},success:function(e,i){"success"===i&&(t.content=e,s._afterLoad())}}))},_loadIframe:function(){var t=s.coming,e=$(t.tpl.iframe.replace(/\{rnd\}/g,(new Date).getTime())).attr("scrolling",l?"auto":t.iframe.scrolling).attr("src",t.href);$(t.wrap).bind("onReset",function(){try{$(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(t){}}),t.iframe.preload&&(s.showLoading(),e.one("load",function(){$(this).data("ready",1),l||$(this).bind("load.fb",s.update),$(this).parents(".envirabox-wrap").width("100%").removeClass("envirabox-tmp").show(),s._afterLoad()})),t.content=e.appendTo(t.inner),t.iframe.preload||s._afterLoad()},_preloadImages:function(){var t=s.group,e=s.current,i=t.length,n=e.preload?Math.min(e.preload,i-1):0,o,r;for(r=1;n>=r;r+=1)o=t[(e.index+r)%i],"image"===o.type&&o.href&&((new Image).src=o.href)},_afterLoad:function(){var t=s.coming,e=s.current,i="envirabox-placeholder",n,o,r,a,u,l;if(s.hideLoading(),t&&s.isActive!==!1){if(!1===s.trigger("afterLoad",t,e))return t.wrap.stop(!0).trigger("onReset").remove(),void(s.coming=null);switch(e&&(s.trigger("beforeChange",e),e.wrap.stop(!0).removeClass("envirabox-opened").find(".envirabox-item, .envirabox-nav").remove()),s.unbindEvents(),n=t,o=t.content,r=t.type,a=t.scrolling,$.extend(s,{wrap:n.wrap,skin:n.skin,outer:n.outer,inner:n.inner,current:n,previous:e}),u=n.href,r){case"inline":case"ajax":case"html":n.selector?o=$("<div>").html(o).find(n.selector):h(o)&&(o.data(i)||o.data(i,$('<div class="'+i+'"></div>').insertAfter(o).hide()),o=o.show().detach(),n.wrap.bind("onReset",function(){$(this).find(o).length&&o.hide().replaceAll(o.data(i)).data(i,!1)}));break;case"image":o=n.tpl.image.replace(/\{href\}/g,u);break;case"swf":o='<object id="envirabox-swf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="'+u+'"></param>',l="",$.each(n.swf,function(t,e){o+='<param name="'+t+'" value="'+e+'"></param>',l+=" "+t+'="'+e+'"'}),o+='<embed src="'+u+'" type="application/x-shockwave-flash" width="100%" height="100%"'+l+"></embed></object>"}h(o)&&o.parent().is(n.inner)||n.inner.append(o),s.trigger("beforeShow"),n.inner.css("overflow","yes"===a?"scroll":"no"===a?"hidden":a),s._setDimension(),s.reposition(),s.isOpen=!1,s.coming=null,s.bindEvents(),s.isOpened?e.prevMethod&&s.transitions[e.prevMethod]():$(".envirabox-wrap").not(n.wrap).stop(!0).trigger("onReset").remove(),s.transitions[s.isOpened?n.nextMethod:n.openMethod](),s._preloadImages()}},_setDimension:function(){var t=s.getViewport(),e=0,i=!1,n=!1,o=s.wrap,r=s.skin,a=s.inner,u=s.current,l=u.width,h=u.height,p=u.minWidth,d=u.minHeight,g=u.maxWidth,v=u.maxHeight,y=u.scrolling,w=u.scrollOutside?u.scrollbarWidth:0,x=u.margin,b=f(x[1]+x[3]),E=f(x[0]+x[2]),_,L,T,S,I,z,O,C,M,R,k,j,P,W,D;if(o.add(r).add(a).width("auto").height("auto").removeClass("envirabox-tmp"),_=f(r.outerWidth(!0)-r.width()),L=f(r.outerHeight(!0)-r.height()),T=b+_,S=E+L,I=c(l)?(t.w-T)*f(l)/100:l,z=c(h)?(t.h-S)*f(h)/100:h,"iframe"===u.type){if(W=u.content,u.autoHeight&&1===W.data("ready"))try{W[0].contentWindow.document.location&&(a.width(I).height(9999),D=W.contents().find("body"),w&&D.css("overflow-x","hidden"),z=D.outerHeight(!0))}catch(A){}}else(u.autoWidth||u.autoHeight)&&(a.addClass("envirabox-tmp"),u.autoWidth||a.width(I),u.autoHeight||a.height(z),u.autoWidth&&(I=a.width()),u.autoHeight&&(z=a.height()),a.removeClass("envirabox-tmp"));if(l=f(I),h=f(z),M=I/z,p=f(c(p)?f(p,"w")-T:p),g=f(c(g)?f(g,"w")-T:g),d=f(c(d)?f(d,"h")-S:d),v=f(c(v)?f(v,"h")-S:v),O=g,C=v,u.fitToView&&(g=Math.min(t.w-T,g),v=Math.min(t.h-S,v)),j=t.w-b,P=t.h-E,u.aspectRatio?(l>g&&(l=g,h=f(l/M)),h>v&&(h=v,l=f(h*M)),p>l&&(l=p,h=f(l/M)),d>h&&(h=d,l=f(h*M))):(l=Math.max(p,Math.min(l,g)),u.autoHeight&&"iframe"!==u.type&&(a.width(l),h=a.height()),h=Math.max(d,Math.min(h,v))),u.fitToView)if(a.width(l).height(h),o.width(l+_),R=o.width(),k=o.height(),u.aspectRatio)for(;(R>j||k>P)&&l>p&&h>d&&!(e++>19);)h=Math.max(d,Math.min(v,h-10)),l=f(h*M),p>l&&(l=p,h=f(l/M)),l>g&&(l=g,h=f(l/M)),a.width(l).height(h),o.width(l+_),R=o.width(),k=o.height();else l=Math.max(p,Math.min(l,l-(R-j))),h=Math.max(d,Math.min(h,h-(k-P)));w&&"auto"===y&&z>h&&j>l+_+w&&(l+=w),a.width(l).height(h),o.width(l+_),R=o.width(),k=o.height(),i=(R>j||k>P)&&l>p&&h>d,n=u.aspectRatio?O>l&&C>h&&I>l&&z>h:(O>l||C>h)&&(I>l||z>h),$.extend(u,{dim:{width:m(R),height:m(k)},origWidth:I,origHeight:z,canShrink:i,canExpand:n,wPadding:_,hPadding:L,wrapSpace:k-r.outerHeight(!0),skinSpace:r.height()-h}),!W&&u.autoHeight&&h>d&&v>h&&!n&&a.height("auto")},_getPosition:function(t){var e=s.current,i=s.getViewport(),n=e.margin,o=s.wrap.width()+n[1]+n[3],r=s.wrap.height()+n[0]+n[2],a={position:"absolute",top:n[0],left:n[3]};return e.helpers.title.type&&"float"==e.helpers.title.type&&(r+=$(".envirabox-skin .envirabox-title").height()),e.autoCenter&&e.fixed&&!t&&r<=i.h&&o<=i.w?a.position="fixed":e.locked||(a.top+=i.y,a.left+=i.x),a.top=m(Math.max(a.top,a.top+(i.h-r)*e.topRatio)),a.left=m(Math.max(a.left,a.left+(i.w-o)*e.leftRatio)),a},_afterZoomIn:function(){var t=s.current;t&&(s.isOpen=s.isOpened=!0,s.wrap.css("overflow","visible").addClass("envirabox-opened").hide().show(0),s.update(),(t.closeClick||t.nextClick&&s.group.length>1)&&s.inner.css("cursor","pointer").bind("click.fb",function(e){$(e.target).is("a")||$(e.target).parent().is("a")||(e.preventDefault(),s[t.closeClick?"close":"next"]())}),t.closeBtn&&$(t.tpl.closeBtn).appendTo(s.skin).bind("click.fb",function(t){t.preventDefault(),s.close()}),t.arrows&&s.group.length>1&&((t.loop||t.index>0)&&$(t.tpl.prev).appendTo(s.outer).bind("click.fb",s.prev),(t.loop||t.index<s.group.length-1)&&$(t.tpl.next).appendTo(s.outer).bind("click.fb",s.next)),s.trigger("afterShow"),t.loop||t.index!==t.group.length-1?s.opts.autoPlay&&!s.player.isActive&&(s.opts.autoPlay=!1,s.play(!0)):s.play(!1))},_afterZoomOut:function(t){t=t||s.current,$(".envirabox-wrap").trigger("onReset").remove(),$.extend(s,{group:{},opts:{},router:!1,current:null,isActive:!1,isOpened:!1,isOpen:!1,isClosing:!1,wrap:null,skin:null,outer:null,inner:null}),s.trigger("afterClose",t)}}),s.transitions={getOrigPosition:function(){var t=s.current,e=t.element,i=t.orig,n={},o=50,r=50,a=t.hPadding,u=t.wPadding,l=s.getViewport();return!i&&t.isDom&&e.is(":visible")&&(i=e.find("img:first"),i.length||(i=e)),h(i)?(n=i.offset(),i.is("img")&&(o=i.outerWidth(),r=i.outerHeight())):(n.top=l.y+(l.h-r)*t.topRatio,n.left=l.x+(l.w-o)*t.leftRatio),("fixed"===s.wrap.css("position")||t.locked)&&(n.top-=l.y,n.left-=l.x),n={top:m(n.top-a*t.topRatio),left:m(n.left-u*t.leftRatio),width:m(o+u),height:m(r+a)}},step:function(t,e){var i,n,o,r=e.prop,a=s.current,u=a.wrapSpace,l=a.skinSpace;("width"===r||"height"===r)&&(i=e.end===e.start?1:(t-e.start)/(e.end-e.start),s.isClosing&&(i=1-i),n="width"===r?a.wPadding:a.hPadding,o=t-n,s.skin[r](f("width"===r?o:o-u*i)),s.inner[r](f("width"===r?o:o-u*i-l*i)))},zoomIn:function(){var t=s.current,e=t.pos,i=t.openEffect,n="elastic"===i,o=$.extend({opacity:1},e);delete o.position,n?(e=this.getOrigPosition(),t.openOpacity&&(e.opacity=.1)):"fade"===i&&(e.opacity=.1),s.wrap.css(e).animate(o,{duration:"none"===i?0:t.openSpeed,easing:t.openEasing,step:n?this.step:null,complete:s._afterZoomIn})},zoomOut:function(){var t=s.current,e=t.closeEffect,i="elastic"===e,n={opacity:.1};i&&(n=this.getOrigPosition(),t.closeOpacity&&(n.opacity=.1)),s.wrap.animate(n,{duration:"none"===e?0:t.closeSpeed,easing:t.closeEasing,step:i?this.step:null,complete:s._afterZoomOut})},changeIn:function(){var t=s.current,e=t.nextEffect,i=t.pos,n={opacity:1},o=s.direction,r=200,a;i.opacity=.1,"elastic"===e&&(a="down"===o||"up"===o?"top":"left","down"===o||"right"===o?(i[a]=m(f(i[a])-r),n[a]="+="+r+"px"):(i[a]=m(f(i[a])+r),n[a]="-="+r+"px")),"none"===e?s._afterZoomIn():s.wrap.css(i).animate(n,{duration:t.nextSpeed,easing:t.nextEasing,complete:s._afterZoomIn})},changeOut:function(){var t=s.previous,e=t.prevEffect,i={opacity:.1},n=s.direction,o=200;"elastic"===e&&(i["down"===n||"up"===n?"top":"left"]=("up"===n||"left"===n?"-":"+")+"="+o+"px"),t.wrap.animate(i,{duration:"none"===e?0:t.prevSpeed,easing:t.prevEasing,complete:function(){$(this).trigger("onReset").remove()}})}},s.helpers.overlay={defaults:{closeClick:!0,speedOut:200,showEarly:!0,css:{},locked:!l,fixed:!0},overlay:null,fixed:!1,el:$("html"),create:function(t){var e;t=$.extend({},this.defaults,t),this.overlay&&this.close(),e=s.coming?s.coming.parent:t.parent,this.overlay=$('<div class="envirabox-overlay"></div>').appendTo(e&&e.lenth?e:"body"),this.fixed=!1,t.fixed&&s.defaults.fixed&&(this.overlay.addClass("envirabox-overlay-fixed"),this.fixed=!0)},open:function(t){var e=this;t=$.extend({},this.defaults,t),this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(t),this.fixed||(o.bind("resize.overlay",$.proxy(this.update,this)),this.update()),t.closeClick&&this.overlay.bind("click.overlay",function(t){return $(t.target).hasClass("envirabox-overlay")?(s.isActive?s.close():e.close(),!1):void 0}),this.overlay.css(t.css).show()},close:function(){o.unbind("resize.overlay"),this.el.hasClass("envirabox-lock")&&($(".envirabox-margin").removeClass("envirabox-margin"),this.el.removeClass("envirabox-lock"),o.scrollTop(this.scrollV).scrollLeft(this.scrollH)),$(".envirabox-overlay").remove().hide(),$.extend(this,{overlay:null,fixed:!1})},update:function(){var t="100%",i;this.overlay.width(t).height("100%"),a?(i=Math.max(e.documentElement.offsetWidth,e.body.offsetWidth),r.width()>i&&(t=r.width())):r.width()>o.width()&&(t=r.width()),this.overlay.width(t).height(r.height())},onReady:function(t,e){var i=this.overlay;$(".envirabox-overlay").stop(!0,!0),i||this.create(t),t.locked&&this.fixed&&e.fixed&&(e.locked=this.overlay.append(e.wrap),e.fixed=!1),t.showEarly===!0&&this.beforeShow.apply(this,arguments)},beforeShow:function(t,e){e.locked&&!this.el.hasClass("envirabox-lock")&&(this.fixPosition!==!1&&$("*").filter(function(){return"fixed"===$(this).css("position")&&!$(this).hasClass("envirabox-overlay")&&!$(this).hasClass("envirabox-wrap")}).addClass("envirabox-margin"),this.el.addClass("envirabox-margin"),this.scrollV=o.scrollTop(),this.scrollH=o.scrollLeft(),this.el.addClass("envirabox-lock"),o.scrollTop(this.scrollV).scrollLeft(this.scrollH)),this.open(t)},onUpdate:function(){this.fixed||this.update()},afterClose:function(t){this.overlay&&!s.coming&&this.overlay.fadeOut(t.speedOut,$.proxy(this.close,this))}},s.helpers.title={defaults:{type:"float",position:"bottom"},beforeShow:function(t){var e=s.current,i=e.title,n=t.type,o,r;if($.isFunction(i)&&(i=i.call(e.element,e)),p(i)&&""!==$.trim(i)){switch(o=$('<div class="envirabox-title envirabox-title-'+n+'-wrap">'+i+"</div>"),n){case"inside":r=s.skin;break;case"outside":r=s.wrap;break;case"over":r=s.inner;break;default:r=s.skin,o.appendTo("body"),a&&o.width(o.width()),o.wrapInner('<span class="child"></span>'),s.current.margin[2]+=Math.abs(f(o.css("margin-bottom")))}o["top"===t.position?"prependTo":"appendTo"](r)}}},$.fn.envirabox=function(t){var e,i=$(this),n=this.selector||"",o=function(o){var r=$(this).blur(),a=e,u,l;o.ctrlKey||o.altKey||o.shiftKey||o.metaKey||r.is(".envirabox-wrap")||(u=t.groupAttr||"data-envirabox-group",l=r.attr(u),l||(u="rel",l=r.get(0)[u]),l&&""!==l&&"nofollow"!==l&&(r=n.length?$(n):i,r=r.filter("["+u+'="'+l+'"]'),a=r.index(this)),t.index=a,s.open(r,t)!==!1&&o.preventDefault())};return t=t||{},e=t.index||0,n&&t.live!==!1?r.undelegate(n,"click.fb-start").delegate(n+":not('.envirabox-item, .envirabox-nav')","click.fb-start",o):i.unbind("click.fb-start").bind("click.fb-start",o),this.filter("[data-envirabox-start=1]").trigger("click"),this},r.ready(function(){var e,o;$.scrollbarWidth===i&&($.scrollbarWidth=function(){var t=$('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo("body"),e=t.children(),i=e.innerWidth()-e.height(99).innerWidth();return t.remove(),i}),$.support.fixedPosition===i&&($.support.fixedPosition=function(){var t=$('<div style="position:fixed;top:20px;"></div>').appendTo("body"),e=20===t[0].offsetTop||15===t[0].offsetTop;return t.remove(),e}()),$.extend(s.defaults,{scrollbarWidth:$.scrollbarWidth(),fixed:$.support.fixedPosition,parent:$("body")}),e=$(t).width(),n.addClass("envirabox-lock-test"),o=$(t).width(),n.removeClass("envirabox-lock-test"),$("<style type='text/css'>.envirabox-margin{margin-right:"+(o-e)+"px;}</style>").appendTo("head")})}(window,document,jQuery),function(){function t(){}function e(t,e){for(var i=t.length;i--;)if(t[i].listener===e)return i;return-1}function i(t){return function e(){return this[t].apply(this,arguments)}}var n=t.prototype,o=this,r=o.EventEmitter;n.getListeners=function s(t){var e=this._getEvents(),i,n;if("object"==typeof t){i={};for(n in e)e.hasOwnProperty(n)&&t.test(n)&&(i[n]=e[n])}else i=e[t]||(e[t]=[]);return i},n.flattenListeners=function a(t){var e=[],i;for(i=0;i<t.length;i+=1)e.push(t[i].listener);return e},n.getListenersAsObject=function u(t){var e=this.getListeners(t),i;return e instanceof Array&&(i={},i[t]=e),i||e},n.addListener=function l(t,i){var n=this.getListenersAsObject(t),o="object"==typeof i,r;for(r in n)n.hasOwnProperty(r)&&-1===e(n[r],i)&&n[r].push(o?i:{listener:i,once:!1});return this},n.on=i("addListener"),n.addOnceListener=function h(t,e){return this.addListener(t,{listener:e,once:!0})},n.once=i("addOnceListener"),n.defineEvent=function p(t){return this.getListeners(t),this},n.defineEvents=function c(t){for(var e=0;e<t.length;e+=1)this.defineEvent(t[e]);return this},n.removeListener=function d(t,i){var n=this.getListenersAsObject(t),o,r;for(r in n)n.hasOwnProperty(r)&&(o=e(n[r],i),-1!==o&&n[r].splice(o,1));return this},n.off=i("removeListener"),n.addListeners=function f(t,e){return this.manipulateListeners(!1,t,e)},n.removeListeners=function m(t,e){return this.manipulateListeners(!0,t,e)},n.manipulateListeners=function g(t,e,i){var n,o,r=t?this.removeListener:this.addListener,s=t?this.removeListeners:this.addListeners;if("object"!=typeof e||e instanceof RegExp)for(n=i.length;n--;)r.call(this,e,i[n]);else for(n in e)e.hasOwnProperty(n)&&(o=e[n])&&("function"==typeof o?r.call(this,n,o):s.call(this,n,o));return this},n.removeEvent=function v(t){var e=typeof t,i=this._getEvents(),n;if("string"===e)delete i[t];else if("object"===e)for(n in i)i.hasOwnProperty(n)&&t.test(n)&&delete i[n];else delete this._events;return this},n.removeAllListeners=i("removeEvent"),n.emitEvent=function y(t,e){var i=this.getListenersAsObject(t),n,o,r,s;for(r in i)if(i.hasOwnProperty(r))for(o=i[r].length;o--;)n=i[r][o],n.once===!0&&this.removeListener(t,n.listener),s=n.listener.apply(this,e||[]),s===this._getOnceReturnValue()&&this.removeListener(t,n.listener);return this},n.trigger=i("emitEvent"),n.emit=function w(t){var e=Array.prototype.slice.call(arguments,1);return this.emitEvent(t,e)},n.setOnceReturnValue=function x(t){return this._onceReturnValue=t,this},n._getOnceReturnValue=function b(){return this.hasOwnProperty("_onceReturnValue")?this._onceReturnValue:!0},n._getEvents=function E(){return this._events||(this._events={})},t.noConflict=function _(){return o.EventEmitter=r,t},"function"==typeof define&&define.amd?define("eventEmitter/EventEmitter",[],function(){return t}):"object"==typeof module&&module.exports?module.exports=t:this.EventEmitter=t}.call(this),function(t){function e(e){var i=t.event;return i.target=i.target||i.srcElement||e,i}var i=document.documentElement,n=function(){};i.addEventListener?n=function(t,e,i){t.addEventListener(e,i,!1)}:i.attachEvent&&(n=function(t,i,n){t[i+n]=n.handleEvent?function(){var i=e(t);n.handleEvent.call(n,i)}:function(){var i=e(t);n.call(t,i)},t.attachEvent("on"+i,t[i+n])});var o=function(){};i.removeEventListener?o=function(t,e,i){t.removeEventListener(e,i,!1)}:i.detachEvent&&(o=function(t,e,i){t.detachEvent("on"+e,t[e+i]);try{delete t[e+i]}catch(n){t[e+i]=void 0}});var r={bind:n,unbind:o};"function"==typeof define&&define.amd?define("eventie/eventie",r):t.eventie=r}(this),function(t,e){"function"==typeof define&&define.amd?define(["eventEmitter/EventEmitter","eventie/eventie"],function(i,n){return e(t,i,n)}):"object"==typeof exports?module.exports=e(t,require("wolfy87-eventemitter"),require("eventie")):t.imagesLoaded=e(t,t.EventEmitter,t.eventie)}(window,function t(e,i,n){function o(t,e){for(var i in e)t[i]=e[i];return t}function r(t){return"[object Array]"===c.call(t)}function s(t){var e=[];if(r(t))e=t;else if("number"==typeof t.length)for(var i=0,n=t.length;n>i;i++)e.push(t[i]);else e.push(t);return e}function a(t,e,i){if(!(this instanceof a))return new a(t,e);"string"==typeof t&&(t=document.querySelectorAll(t)),this.elements=s(t),this.options=o({},this.options),"function"==typeof e?i=e:o(this.options,e),i&&this.on("always",i),this.getImages(),$&&(this.jqDeferred=new $.Deferred);var n=this;setTimeout(function(){n.check()})}function u(t){this.img=t}function l(t){this.src=t,d[t]=this}var $=e.jQuery,h=e.console,p="undefined"!=typeof h,c=Object.prototype.toString;a.prototype=new i,a.prototype.options={},a.prototype.getImages=function(){this.images=[];for(var t=0,e=this.elements.length;e>t;t++){var i=this.elements[t];"IMG"===i.nodeName&&this.addImage(i);var n=i.nodeType;if(n&&(1===n||9===n||11===n))for(var o=i.querySelectorAll("img"),r=0,s=o.length;s>r;r++){var a=o[r];this.addImage(a)}}},a.prototype.addImage=function(t){var e=new u(t);this.images.push(e)},a.prototype.check=function(){function t(t,o){return e.options.debug&&p&&h.log("confirm",t,o),e.progress(t),i++,i===n&&e.complete(),!0}var e=this,i=0,n=this.images.length;if(this.hasAnyBroken=!1,!n)return void this.complete();for(var o=0;n>o;o++){var r=this.images[o];r.on("confirm",t),r.check()}},a.prototype.progress=function(t){this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded;var e=this;setTimeout(function(){e.emit("progress",e,t),e.jqDeferred&&e.jqDeferred.notify&&e.jqDeferred.notify(e,t)})},a.prototype.complete=function(){var t=this.hasAnyBroken?"fail":"done";this.isComplete=!0;var e=this;setTimeout(function(){if(e.emit(t,e),e.emit("always",e),e.jqDeferred){var i=e.hasAnyBroken?"reject":"resolve";e.jqDeferred[i](e)}})},$&&($.fn.imagesLoaded=function(t,e){var i=new a(this,t,e);return i.jqDeferred.promise($(this))}),u.prototype=new i,u.prototype.check=function(){var t=d[this.img.src]||new l(this.img.src);if(t.isConfirmed)return void this.confirm(t.isLoaded,"cached was confirmed");if(this.img.complete&&void 0!==this.img.naturalWidth)return void this.confirm(0!==this.img.naturalWidth,"naturalWidth");var e=this;t.on("confirm",function(t,i){return e.confirm(t.isLoaded,i),!0}),t.check()},u.prototype.confirm=function(t,e){this.isLoaded=t,this.emit("confirm",this,e)};var d={};return l.prototype=new i,l.prototype.check=function(){if(!this.isChecked){var t=new Image;n.bind(t,"load",this),n.bind(t,"error",this),t.src=this.src,this.isChecked=!0}},l.prototype.handleEvent=function(t){var e="on"+t.type;this[e]&&this[e](t)},l.prototype.onload=function(t){this.confirm(!0,"onload"),this.unbindProxyEvents(t)},l.prototype.onerror=function(t){this.confirm(!1,"onerror"),this.unbindProxyEvents(t)},l.prototype.confirm=function(t,e){this.isConfirmed=!0,this.isLoaded=t,this.emit("confirm",this,e)},l.prototype.unbindProxyEvents=function(t){n.unbind(t.target,"load",this),n.unbind(t.target,"error",this)},a}),function(t){function e(){}function i($){function t(t){t.prototype.option||(t.prototype.option=function(t){$.isPlainObject(t)&&(this.options=$.extend(!0,this.options,t))})}function i(t,e){$.fn[t]=function(i){if("string"==typeof i){for(var r=n.call(arguments,1),s=0,a=this.length;a>s;s++){var u=this[s],l=$.data(u,t);if(l)if($.isFunction(l[i])&&"_"!==i.charAt(0)){var h=l[i].apply(l,r);if(void 0!==h)return h}else o("no such method '"+i+"' for "+t+" instance");else o("cannot call methods on "+t+" prior to initialization; attempted to call '"+i+"'")}return this}return this.each(function(){var n=$.data(this,t);n?(n.option(i),n._init()):(n=new e(this,i),$.data(this,t,n))})}}if($){var o="undefined"==typeof console?e:function(t){console.error(t)};return $.bridget=function(e,n){t(n),i(e,n)},$.bridget}}var n=Array.prototype.slice;"function"==typeof define&&define.amd?define("jquery-bridget/jquery.bridget",["jquery"],i):i("object"==typeof exports?require("jquery"):t.jQuery)}(window),function(t){function e(e){var i=t.event;return i.target=i.target||i.srcElement||e,i}var i=document.documentElement,n=function(){};i.addEventListener?n=function(t,e,i){t.addEventListener(e,i,!1)}:i.attachEvent&&(n=function(t,i,n){t[i+n]=n.handleEvent?function(){var i=e(t);n.handleEvent.call(n,i)}:function(){var i=e(t);n.call(t,i)},t.attachEvent("on"+i,t[i+n])});var o=function(){};i.removeEventListener?o=function(t,e,i){t.removeEventListener(e,i,!1)}:i.detachEvent&&(o=function(t,e,i){t.detachEvent("on"+e,t[e+i]);try{delete t[e+i]}catch(n){t[e+i]=void 0}});var r={bind:n,unbind:o};"function"==typeof define&&define.amd?define("eventie/eventie",r):"object"==typeof exports?module.exports=r:t.eventie=r}(window),function(){"use strict";function t(){}function e(t,e){for(var i=t.length;i--;)if(t[i].listener===e)return i;return-1}function i(t){return function e(){return this[t].apply(this,arguments);
2
+ }}var n=t.prototype,o=this,r=o.EventEmitter;n.getListeners=function s(t){var e=this._getEvents(),i,n;if(t instanceof RegExp){i={};for(n in e)e.hasOwnProperty(n)&&t.test(n)&&(i[n]=e[n])}else i=e[t]||(e[t]=[]);return i},n.flattenListeners=function a(t){var e=[],i;for(i=0;i<t.length;i+=1)e.push(t[i].listener);return e},n.getListenersAsObject=function u(t){var e=this.getListeners(t),i;return e instanceof Array&&(i={},i[t]=e),i||e},n.addListener=function l(t,i){var n=this.getListenersAsObject(t),o="object"==typeof i,r;for(r in n)n.hasOwnProperty(r)&&-1===e(n[r],i)&&n[r].push(o?i:{listener:i,once:!1});return this},n.on=i("addListener"),n.addOnceListener=function h(t,e){return this.addListener(t,{listener:e,once:!0})},n.once=i("addOnceListener"),n.defineEvent=function p(t){return this.getListeners(t),this},n.defineEvents=function c(t){for(var e=0;e<t.length;e+=1)this.defineEvent(t[e]);return this},n.removeListener=function d(t,i){var n=this.getListenersAsObject(t),o,r;for(r in n)n.hasOwnProperty(r)&&(o=e(n[r],i),-1!==o&&n[r].splice(o,1));return this},n.off=i("removeListener"),n.addListeners=function f(t,e){return this.manipulateListeners(!1,t,e)},n.removeListeners=function m(t,e){return this.manipulateListeners(!0,t,e)},n.manipulateListeners=function g(t,e,i){var n,o,r=t?this.removeListener:this.addListener,s=t?this.removeListeners:this.addListeners;if("object"!=typeof e||e instanceof RegExp)for(n=i.length;n--;)r.call(this,e,i[n]);else for(n in e)e.hasOwnProperty(n)&&(o=e[n])&&("function"==typeof o?r.call(this,n,o):s.call(this,n,o));return this},n.removeEvent=function v(t){var e=typeof t,i=this._getEvents(),n;if("string"===e)delete i[t];else if(t instanceof RegExp)for(n in i)i.hasOwnProperty(n)&&t.test(n)&&delete i[n];else delete this._events;return this},n.removeAllListeners=i("removeEvent"),n.emitEvent=function y(t,e){var i=this.getListenersAsObject(t),n,o,r,s;for(r in i)if(i.hasOwnProperty(r))for(o=i[r].length;o--;)n=i[r][o],n.once===!0&&this.removeListener(t,n.listener),s=n.listener.apply(this,e||[]),s===this._getOnceReturnValue()&&this.removeListener(t,n.listener);return this},n.trigger=i("emitEvent"),n.emit=function w(t){var e=Array.prototype.slice.call(arguments,1);return this.emitEvent(t,e)},n.setOnceReturnValue=function x(t){return this._onceReturnValue=t,this},n._getOnceReturnValue=function b(){return this.hasOwnProperty("_onceReturnValue")?this._onceReturnValue:!0},n._getEvents=function E(){return this._events||(this._events={})},t.noConflict=function _(){return o.EventEmitter=r,t},"function"==typeof define&&define.amd?define("eventEmitter/EventEmitter",[],function(){return t}):"object"==typeof module&&module.exports?module.exports=t:o.EventEmitter=t}.call(this),function(t){function e(t){if(t){if("string"==typeof n[t])return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e,o=0,r=i.length;r>o;o++)if(e=i[o]+t,"string"==typeof n[e])return e}}var i="Webkit Moz ms Ms O".split(" "),n=document.documentElement.style;"function"==typeof define&&define.amd?define("get-style-property/get-style-property",[],function(){return e}):"object"==typeof exports?module.exports=e:t.getStyleProperty=e}(window),function(t,e){function i(t){var e=parseFloat(t),i=-1===t.indexOf("%")&&!isNaN(e);return i&&e}function n(){}function o(){for(var t={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},e=0,i=a.length;i>e;e++){var n=a[e];t[n]=0}return t}function r(e){function n(){if(!l){l=!0;var n=t.getComputedStyle;if(h=function(){var t=n?function(t){return n(t,null)}:function(t){return t.currentStyle};return function e(i){var n=t(i);return n||s("Style returned "+n+". Are you running this code in a hidden iframe on Firefox? See http://bit.ly/getsizebug1"),n}}(),p=e("boxSizing")){var o=document.createElement("div");o.style.width="200px",o.style.padding="1px 2px 3px 4px",o.style.borderStyle="solid",o.style.borderWidth="1px 2px 3px 4px",o.style[p]="border-box";var r=document.body||document.documentElement;r.appendChild(o);var a=h(o);c=200===i(a.width),r.removeChild(o)}}}function r(t){if(n(),"string"==typeof t&&(t=document.querySelector(t)),t&&"object"==typeof t&&t.nodeType){var e=h(t);if("none"===e.display)return o();var r={};r.width=t.offsetWidth,r.height=t.offsetHeight;for(var s=r.isBorderBox=!(!p||!e[p]||"border-box"!==e[p]),l=0,d=a.length;d>l;l++){var f=a[l],m=e[f];m=u(t,m);var g=parseFloat(m);r[f]=isNaN(g)?0:g}var v=r.paddingLeft+r.paddingRight,y=r.paddingTop+r.paddingBottom,w=r.marginLeft+r.marginRight,x=r.marginTop+r.marginBottom,b=r.borderLeftWidth+r.borderRightWidth,E=r.borderTopWidth+r.borderBottomWidth,_=s&&c,L=i(e.width);L!==!1&&(r.width=L+(_?0:v+b));var T=i(e.height);return T!==!1&&(r.height=T+(_?0:y+E)),r.innerWidth=r.width-(v+b),r.innerHeight=r.height-(y+E),r.outerWidth=r.width+w,r.outerHeight=r.height+x,r}}function u(e,i){if(t.getComputedStyle||-1===i.indexOf("%"))return i;var n=e.style,o=n.left,r=e.runtimeStyle,s=r&&r.left;return s&&(r.left=e.currentStyle.left),n.left=i,i=n.pixelLeft,n.left=o,s&&(r.left=s),i}var l=!1,h,p,c;return r}var s="undefined"==typeof console?n:function(t){console.error(t)},a=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"];"function"==typeof define&&define.amd?define("get-size/get-size",["get-style-property/get-style-property"],r):"object"==typeof exports?module.exports=r(require("desandro-get-style-property")):t.getSize=r(t.getStyleProperty)}(window),function(t){function e(t){"function"==typeof t&&(e.isReady?t():s.push(t))}function i(t){var i="readystatechange"===t.type&&"complete"!==r.readyState;e.isReady||i||n()}function n(){e.isReady=!0;for(var t=0,i=s.length;i>t;t++){var n=s[t];n()}}function o(o){return"complete"===r.readyState?n():(o.bind(r,"DOMContentLoaded",i),o.bind(r,"readystatechange",i),o.bind(t,"load",i)),e}var r=t.document,s=[];e.isReady=!1,"function"==typeof define&&define.amd?define("doc-ready/doc-ready",["eventie/eventie"],o):"object"==typeof exports?module.exports=o(require("eventie")):t.docReady=o(t.eventie)}(window),function(t){"use strict";function e(t,e){return t[r](e)}function i(t){if(!t.parentNode){var e=document.createDocumentFragment();e.appendChild(t)}}function n(t,e){i(t);for(var n=t.parentNode.querySelectorAll(e),o=0,r=n.length;r>o;o++)if(n[o]===t)return!0;return!1}function o(t,n){return i(t),e(t,n)}var r=function(){if(t.matches)return"matches";if(t.matchesSelector)return"matchesSelector";for(var e=["webkit","moz","ms","o"],i=0,n=e.length;n>i;i++){var o=e[i],r=o+"MatchesSelector";if(t[r])return r}}(),s;if(r){var a=document.createElement("div"),u=e(a,"div");s=u?e:o}else s=n;"function"==typeof define&&define.amd?define("matches-selector/matches-selector",[],function(){return s}):"object"==typeof exports?module.exports=s:window.matchesSelector=s}(Element.prototype),function(t,e){"use strict";"function"==typeof define&&define.amd?define("fizzy-ui-utils/utils",["doc-ready/doc-ready","matches-selector/matches-selector"],function(i,n){return e(t,i,n)}):"object"==typeof exports?module.exports=e(t,require("doc-ready"),require("desandro-matches-selector")):t.fizzyUIUtils=e(t,t.docReady,t.matchesSelector)}(window,function e(t,i,n){var o={};o.extend=function(t,e){for(var i in e)t[i]=e[i];return t},o.modulo=function(t,e){return(t%e+e)%e};var r=Object.prototype.toString;o.isArray=function(t){return"[object Array]"==r.call(t)},o.makeArray=function(t){var e=[];if(o.isArray(t))e=t;else if(t&&"number"==typeof t.length)for(var i=0,n=t.length;n>i;i++)e.push(t[i]);else e.push(t);return e},o.indexOf=Array.prototype.indexOf?function(t,e){return t.indexOf(e)}:function(t,e){for(var i=0,n=t.length;n>i;i++)if(t[i]===e)return i;return-1},o.removeFrom=function(t,e){var i=o.indexOf(t,e);-1!=i&&t.splice(i,1)},o.isElement="function"==typeof HTMLElement||"object"==typeof HTMLElement?function a(t){return t instanceof HTMLElement}:function u(t){return t&&"object"==typeof t&&1==t.nodeType&&"string"==typeof t.nodeName},o.setText=function(){function t(t,i){e=e||(void 0!==document.documentElement.textContent?"textContent":"innerText"),t[e]=i}var e;return t}(),o.getParent=function(t,e){for(;t!=document.body;)if(t=t.parentNode,n(t,e))return t},o.getQueryElement=function(t){return"string"==typeof t?document.querySelector(t):t},o.handleEvent=function(t){var e="on"+t.type;this[e]&&this[e](t)},o.filterFindElements=function(t,e){t=o.makeArray(t);for(var i=[],r=0,s=t.length;s>r;r++){var a=t[r];if(o.isElement(a))if(e){n(a,e)&&i.push(a);for(var u=a.querySelectorAll(e),l=0,h=u.length;h>l;l++)i.push(u[l])}else i.push(a)}return i},o.debounceMethod=function(t,e,i){var n=t.prototype[e],o=e+"Timeout";t.prototype[e]=function(){var t=this[o];t&&clearTimeout(t);var e=arguments,r=this;this[o]=setTimeout(function(){n.apply(r,e),delete r[o]},i||100)}},o.toDashed=function(t){return t.replace(/(.)([A-Z])/g,function(t,e,i){return e+"-"+i}).toLowerCase()};var s=t.console;return o.htmlInit=function(e,n){i(function(){for(var i=o.toDashed(n),r=document.querySelectorAll(".js-"+i),a="data-"+i+"-options",u=0,l=r.length;l>u;u++){var h=r[u],p=h.getAttribute(a),c;try{c=p&&JSON.parse(p)}catch(d){s&&s.error("Error parsing "+a+" on "+h.nodeName.toLowerCase()+(h.id?"#"+h.id:"")+": "+d);continue}var f=new e(h,c),m=t.jQuery;m&&m.data(h,n,f)}})},o}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("outlayer/item",["eventEmitter/EventEmitter","get-size/get-size","get-style-property/get-style-property","fizzy-ui-utils/utils"],function(i,n,o,r){return e(t,i,n,o,r)}):"object"==typeof exports?module.exports=e(t,require("wolfy87-eventemitter"),require("get-size"),require("desandro-get-style-property"),require("fizzy-ui-utils")):(t.Outlayer={},t.Outlayer.Item=e(t,t.EventEmitter,t.getSize,t.getStyleProperty,t.fizzyUIUtils))}(window,function i(t,e,n,o,r){"use strict";function s(t){for(var e in t)return!1;return e=null,!0}function a(t,e){t&&(this.element=t,this.layout=e,this.position={x:0,y:0},this._create())}function u(t){return t.replace(/([A-Z])/g,function(t){return"-"+t.toLowerCase()})}var l=t.getComputedStyle,h=l?function(t){return l(t,null)}:function(t){return t.currentStyle},p=o("transition"),c=o("transform"),d=p&&c,f=!!o("perspective"),m={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"otransitionend",transition:"transitionend"}[p],g=["transform","transition","transitionDuration","transitionProperty"],v=function(){for(var t={},e=0,i=g.length;i>e;e++){var n=g[e],r=o(n);r&&r!==n&&(t[n]=r)}return t}();r.extend(a.prototype,e.prototype),a.prototype._create=function(){this._transn={ingProperties:{},clean:{},onEnd:{}},this.css({position:"absolute"})},a.prototype.handleEvent=function(t){var e="on"+t.type;this[e]&&this[e](t)},a.prototype.getSize=function(){this.size=n(this.element)},a.prototype.css=function(t){var e=this.element.style;for(var i in t){var n=v[i]||i;e[n]=t[i]}},a.prototype.getPosition=function(){var t=h(this.element),e=this.layout.options,i=e.isOriginLeft,n=e.isOriginTop,o=t[i?"left":"right"],r=t[n?"top":"bottom"],s=this.layout.size,a=-1!=o.indexOf("%")?parseFloat(o)/100*s.width:parseInt(o,10),u=-1!=r.indexOf("%")?parseFloat(r)/100*s.height:parseInt(r,10);a=isNaN(a)?0:a,u=isNaN(u)?0:u,a-=i?s.paddingLeft:s.paddingRight,u-=n?s.paddingTop:s.paddingBottom,this.position.x=a,this.position.y=u},a.prototype.layoutPosition=function(){var t=this.layout.size,e=this.layout.options,i={},n=e.isOriginLeft?"paddingLeft":"paddingRight",o=e.isOriginLeft?"left":"right",r=e.isOriginLeft?"right":"left",s=this.position.x+t[n];i[o]=this.getXValue(s),i[r]="";var a=e.isOriginTop?"paddingTop":"paddingBottom",u=e.isOriginTop?"top":"bottom",l=e.isOriginTop?"bottom":"top",h=this.position.y+t[a];i[u]=this.getYValue(h),i[l]="",this.css(i),this.emitEvent("layout",[this])},a.prototype.getXValue=function(t){var e=this.layout.options;return e.percentPosition&&!e.isHorizontal?t/this.layout.size.width*100+"%":t+"px"},a.prototype.getYValue=function(t){var e=this.layout.options;return e.percentPosition&&e.isHorizontal?t/this.layout.size.height*100+"%":t+"px"},a.prototype._transitionTo=function(t,e){this.getPosition();var i=this.position.x,n=this.position.y,o=parseInt(t,10),r=parseInt(e,10),s=o===this.position.x&&r===this.position.y;if(this.setPosition(t,e),s&&!this.isTransitioning)return void this.layoutPosition();var a=t-i,u=e-n,l={};l.transform=this.getTranslate(a,u),this.transition({to:l,onTransitionEnd:{transform:this.layoutPosition},isCleaning:!0})},a.prototype.getTranslate=function(t,e){var i=this.layout.options;return t=i.isOriginLeft?t:-t,e=i.isOriginTop?e:-e,f?"translate3d("+t+"px, "+e+"px, 0)":"translate("+t+"px, "+e+"px)"},a.prototype.goTo=function(t,e){this.setPosition(t,e),this.layoutPosition()},a.prototype.moveTo=d?a.prototype._transitionTo:a.prototype.goTo,a.prototype.setPosition=function(t,e){this.position.x=parseInt(t,10),this.position.y=parseInt(e,10)},a.prototype._nonTransition=function(t){this.css(t.to),t.isCleaning&&this._removeStyles(t.to);for(var e in t.onTransitionEnd)t.onTransitionEnd[e].call(this)},a.prototype._transition=function(t){if(!parseFloat(this.layout.options.transitionDuration))return void this._nonTransition(t);var e=this._transn;for(var i in t.onTransitionEnd)e.onEnd[i]=t.onTransitionEnd[i];for(i in t.to)e.ingProperties[i]=!0,t.isCleaning&&(e.clean[i]=!0);if(t.from){this.css(t.from);var n=this.element.offsetHeight;n=null}this.enableTransition(t.to),this.css(t.to),this.isTransitioning=!0};var y="opacity,"+u(v.transform||"transform");a.prototype.enableTransition=function(){this.isTransitioning||(this.css({transitionProperty:y,transitionDuration:this.layout.options.transitionDuration}),this.element.addEventListener(m,this,!1))},a.prototype.transition=a.prototype[p?"_transition":"_nonTransition"],a.prototype.onwebkitTransitionEnd=function(t){this.ontransitionend(t)},a.prototype.onotransitionend=function(t){this.ontransitionend(t)};var w={"-webkit-transform":"transform","-moz-transform":"transform","-o-transform":"transform"};a.prototype.ontransitionend=function(t){if(t.target===this.element){var e=this._transn,i=w[t.propertyName]||t.propertyName;if(delete e.ingProperties[i],s(e.ingProperties)&&this.disableTransition(),i in e.clean&&(this.element.style[t.propertyName]="",delete e.clean[i]),i in e.onEnd){var n=e.onEnd[i];n.call(this),delete e.onEnd[i]}this.emitEvent("transitionEnd",[this])}},a.prototype.disableTransition=function(){this.removeTransitionStyles(),this.element.removeEventListener(m,this,!1),this.isTransitioning=!1},a.prototype._removeStyles=function(t){var e={};for(var i in t)e[i]="";this.css(e)};var x={transitionProperty:"",transitionDuration:""};return a.prototype.removeTransitionStyles=function(){this.css(x)},a.prototype.removeElem=function(){this.element.parentNode.removeChild(this.element),this.css({display:""}),this.emitEvent("remove",[this])},a.prototype.remove=function(){if(!p||!parseFloat(this.layout.options.transitionDuration))return void this.removeElem();var t=this;this.once("transitionEnd",function(){t.removeElem()}),this.hide()},a.prototype.reveal=function(){delete this.isHidden,this.css({display:""});var t=this.layout.options,e={},i=this.getHideRevealTransitionEndProperty("visibleStyle");e[i]=this.onRevealTransitionEnd,this.transition({from:t.hiddenStyle,to:t.visibleStyle,isCleaning:!0,onTransitionEnd:e})},a.prototype.onRevealTransitionEnd=function(){this.isHidden||this.emitEvent("reveal")},a.prototype.getHideRevealTransitionEndProperty=function(t){var e=this.layout.options[t];if(e.opacity)return"opacity";for(var i in e)return i},a.prototype.hide=function(){this.isHidden=!0,this.css({display:""});var t=this.layout.options,e={},i=this.getHideRevealTransitionEndProperty("hiddenStyle");e[i]=this.onHideTransitionEnd,this.transition({from:t.visibleStyle,to:t.hiddenStyle,isCleaning:!0,onTransitionEnd:e})},a.prototype.onHideTransitionEnd=function(){this.isHidden&&(this.css({display:"none"}),this.emitEvent("hide"))},a.prototype.destroy=function(){this.css({position:"",left:"",right:"",top:"",bottom:"",transition:"",transform:""})},a}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("outlayer/outlayer",["eventie/eventie","eventEmitter/EventEmitter","get-size/get-size","fizzy-ui-utils/utils","./item"],function(i,n,o,r,s){return e(t,i,n,o,r,s)}):"object"==typeof exports?module.exports=e(t,require("eventie"),require("wolfy87-eventemitter"),require("get-size"),require("fizzy-ui-utils"),require("./item")):t.Outlayer=e(t,t.eventie,t.EventEmitter,t.getSize,t.fizzyUIUtils,t.Outlayer.Item)}(window,function n(t,e,i,o,r,s){"use strict";function a(t,e){var i=r.getQueryElement(t);if(!i)return void(u&&u.error("Bad element for "+this.constructor.namespace+": "+(i||t)));this.element=i,l&&(this.$element=l(this.element)),this.options=r.extend({},this.constructor.defaults),this.option(e);var n=++p;this.element.outlayerGUID=n,c[n]=this,this._create(),this.options.isInitLayout&&this.layout()}var u=t.console,l=t.jQuery,h=function(){},p=0,c={};return a.namespace="outlayer",a.Item=s,a.defaults={containerStyle:{position:"relative"},isInitLayout:!0,isOriginLeft:!0,isOriginTop:!0,isResizeBound:!0,isResizingContainer:!0,transitionDuration:"0.4s",hiddenStyle:{opacity:0,transform:"scale(0.001)"},visibleStyle:{opacity:1,transform:"scale(1)"}},r.extend(a.prototype,i.prototype),a.prototype.option=function(t){r.extend(this.options,t)},a.prototype._create=function(){this.reloadItems(),this.stamps=[],this.stamp(this.options.stamp),r.extend(this.element.style,this.options.containerStyle),this.options.isResizeBound&&this.bindResize()},a.prototype.reloadItems=function(){this.items=this._itemize(this.element.children)},a.prototype._itemize=function(t){for(var e=this._filterFindItemElements(t),i=this.constructor.Item,n=[],o=0,r=e.length;r>o;o++){var s=e[o],a=new i(s,this);n.push(a)}return n},a.prototype._filterFindItemElements=function(t){return r.filterFindElements(t,this.options.itemSelector)},a.prototype.getItemElements=function(){for(var t=[],e=0,i=this.items.length;i>e;e++)t.push(this.items[e].element);return t},a.prototype.layout=function(){this._resetLayout(),this._manageStamps();var t=void 0!==this.options.isLayoutInstant?this.options.isLayoutInstant:!this._isLayoutInited;this.layoutItems(this.items,t),this._isLayoutInited=!0},a.prototype._init=a.prototype.layout,a.prototype._resetLayout=function(){this.getSize()},a.prototype.getSize=function(){this.size=o(this.element)},a.prototype._getMeasurement=function(t,e){var i=this.options[t],n;i?("string"==typeof i?n=this.element.querySelector(i):r.isElement(i)&&(n=i),this[t]=n?o(n)[e]:i):this[t]=0},a.prototype.layoutItems=function(t,e){t=this._getItemsForLayout(t),this._layoutItems(t,e),this._postLayout()},a.prototype._getItemsForLayout=function(t){for(var e=[],i=0,n=t.length;n>i;i++){var o=t[i];o.isIgnored||e.push(o)}return e},a.prototype._layoutItems=function(t,e){if(this._emitCompleteOnItems("layout",t),t&&t.length){for(var i=[],n=0,o=t.length;o>n;n++){var r=t[n],s=this._getItemLayoutPosition(r);s.item=r,s.isInstant=e||r.isLayoutInstant,i.push(s)}this._processLayoutQueue(i)}},a.prototype._getItemLayoutPosition=function(){return{x:0,y:0}},a.prototype._processLayoutQueue=function(t){for(var e=0,i=t.length;i>e;e++){var n=t[e];this._positionItem(n.item,n.x,n.y,n.isInstant)}},a.prototype._positionItem=function(t,e,i,n){n?t.goTo(e,i):t.moveTo(e,i)},a.prototype._postLayout=function(){this.resizeContainer()},a.prototype.resizeContainer=function(){if(this.options.isResizingContainer){var t=this._getContainerSize();t&&(this._setContainerMeasure(t.width,!0),this._setContainerMeasure(t.height,!1))}},a.prototype._getContainerSize=h,a.prototype._setContainerMeasure=function(t,e){if(void 0!==t){var i=this.size;i.isBorderBox&&(t+=e?i.paddingLeft+i.paddingRight+i.borderLeftWidth+i.borderRightWidth:i.paddingBottom+i.paddingTop+i.borderTopWidth+i.borderBottomWidth),t=Math.max(t,0),this.element.style[e?"width":"height"]=t+"px"}},a.prototype._emitCompleteOnItems=function(t,e){function i(){o.dispatchEvent(t+"Complete",null,[e])}function n(){s++,s===r&&i()}var o=this,r=e.length;if(!e||!r)return void i();for(var s=0,a=0,u=e.length;u>a;a++){var l=e[a];l.once(t,n)}},a.prototype.dispatchEvent=function(t,e,i){var n=e?[e].concat(i):i;if(this.emitEvent(t,n),l)if(this.$element=this.$element||l(this.element),e){var o=l.Event(e);o.type=t,this.$element.trigger(o,i)}else this.$element.trigger(t,i)},a.prototype.ignore=function(t){var e=this.getItem(t);e&&(e.isIgnored=!0)},a.prototype.unignore=function(t){var e=this.getItem(t);e&&delete e.isIgnored},a.prototype.stamp=function(t){if(t=this._find(t)){this.stamps=this.stamps.concat(t);for(var e=0,i=t.length;i>e;e++){var n=t[e];this.ignore(n)}}},a.prototype.unstamp=function(t){if(t=this._find(t))for(var e=0,i=t.length;i>e;e++){var n=t[e];r.removeFrom(this.stamps,n),this.unignore(n)}},a.prototype._find=function(t){return t?("string"==typeof t&&(t=this.element.querySelectorAll(t)),t=r.makeArray(t)):void 0},a.prototype._manageStamps=function(){if(this.stamps&&this.stamps.length){this._getBoundingRect();for(var t=0,e=this.stamps.length;e>t;t++){var i=this.stamps[t];this._manageStamp(i)}}},a.prototype._getBoundingRect=function(){var t=this.element.getBoundingClientRect(),e=this.size;this._boundingRect={left:t.left+e.paddingLeft+e.borderLeftWidth,top:t.top+e.paddingTop+e.borderTopWidth,right:t.right-(e.paddingRight+e.borderRightWidth),bottom:t.bottom-(e.paddingBottom+e.borderBottomWidth)}},a.prototype._manageStamp=h,a.prototype._getElementOffset=function(t){var e=t.getBoundingClientRect(),i=this._boundingRect,n=o(t),r={left:e.left-i.left-n.marginLeft,top:e.top-i.top-n.marginTop,right:i.right-e.right-n.marginRight,bottom:i.bottom-e.bottom-n.marginBottom};return r},a.prototype.handleEvent=function(t){var e="on"+t.type;this[e]&&this[e](t)},a.prototype.bindResize=function(){this.isResizeBound||(e.bind(t,"resize",this),this.isResizeBound=!0)},a.prototype.unbindResize=function(){this.isResizeBound&&e.unbind(t,"resize",this),this.isResizeBound=!1},a.prototype.onresize=function(){function t(){e.resize(),delete e.resizeTimeout}this.resizeTimeout&&clearTimeout(this.resizeTimeout);var e=this;this.resizeTimeout=setTimeout(t,100)},a.prototype.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&this.layout()},a.prototype.needsResizeLayout=function(){var t=o(this.element),e=this.size&&t;return e&&t.innerWidth!==this.size.innerWidth},a.prototype.addItems=function(t){var e=this._itemize(t);return e.length&&(this.items=this.items.concat(e)),e},a.prototype.appended=function(t){var e=this.addItems(t);e.length&&(this.layoutItems(e,!0),this.reveal(e))},a.prototype.prepended=function(t){var e=this._itemize(t);if(e.length){var i=this.items.slice(0);this.items=e.concat(i),this._resetLayout(),this._manageStamps(),this.layoutItems(e,!0),this.reveal(e),this.layoutItems(i)}},a.prototype.reveal=function(t){this._emitCompleteOnItems("reveal",t);for(var e=t&&t.length,i=0;e&&e>i;i++){var n=t[i];n.reveal()}},a.prototype.hide=function(t){this._emitCompleteOnItems("hide",t);for(var e=t&&t.length,i=0;e&&e>i;i++){var n=t[i];n.hide()}},a.prototype.revealItemElements=function(t){var e=this.getItems(t);this.reveal(e)},a.prototype.hideItemElements=function(t){var e=this.getItems(t);this.hide(e)},a.prototype.getItem=function(t){for(var e=0,i=this.items.length;i>e;e++){var n=this.items[e];if(n.element===t)return n}},a.prototype.getItems=function(t){t=r.makeArray(t);for(var e=[],i=0,n=t.length;n>i;i++){var o=t[i],s=this.getItem(o);s&&e.push(s)}return e},a.prototype.remove=function(t){var e=this.getItems(t);if(this._emitCompleteOnItems("remove",e),e&&e.length)for(var i=0,n=e.length;n>i;i++){var o=e[i];o.remove(),r.removeFrom(this.items,o)}},a.prototype.destroy=function(){var t=this.element.style;t.height="",t.position="",t.width="";for(var e=0,i=this.items.length;i>e;e++){var n=this.items[e];n.destroy()}this.unbindResize();var o=this.element.outlayerGUID;delete c[o],delete this.element.outlayerGUID,l&&l.removeData(this.element,this.constructor.namespace)},a.data=function(t){t=r.getQueryElement(t);var e=t&&t.outlayerGUID;return e&&c[e]},a.create=function(t,e){function i(){a.apply(this,arguments)}return Object.create?i.prototype=Object.create(a.prototype):r.extend(i.prototype,a.prototype),i.prototype.constructor=i,i.defaults=r.extend({},a.defaults),r.extend(i.defaults,e),i.prototype.settings={},i.namespace=t,i.data=a.data,i.Item=function n(){s.apply(this,arguments)},i.Item.prototype=new s,r.htmlInit(i,t),l&&l.bridget&&l.bridget(t,i),i},a.Item=s,a}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("enviratope/js/item",["outlayer/outlayer"],e):"object"==typeof exports?module.exports=e(require("outlayer")):(t.Enviratope=t.Enviratope||{},t.Enviratope.Item=e(t.Outlayer))}(window,function o(t){"use strict";function e(){t.Item.apply(this,arguments)}e.prototype=new t.Item,e.prototype._create=function(){this.id=this.layout.itemGUID++,t.Item.prototype._create.call(this),this.sortData={}},e.prototype.updateSortData=function(){if(!this.isIgnored){this.sortData.id=this.id,this.sortData["original-order"]=this.id,this.sortData.random=Math.random();var t=this.layout.options.getSortData,e=this.layout._sorters;for(var i in t){var n=e[i];this.sortData[i]=n(this.element,this)}}};var i=e.prototype.destroy;return e.prototype.destroy=function(){i.apply(this,arguments),this.css({display:""})},e}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("enviratope/js/layout-mode",["get-size/get-size","outlayer/outlayer"],e):"object"==typeof exports?module.exports=e(require("get-size"),require("outlayer")):(t.Enviratope=t.Enviratope||{},t.Enviratope.LayoutMode=e(t.getSize,t.Outlayer))}(window,function r(t,e){"use strict";function i(t){this.enviratope=t,t&&(this.options=t.options[this.namespace],this.element=t.element,this.items=t.filteredItems,this.size=t.size)}return function(){function t(t){return function(){return e.prototype[t].apply(this.enviratope,arguments)}}for(var n=["_resetLayout","_getItemLayoutPosition","_manageStamp","_getContainerSize","_getElementOffset","needsResizeLayout"],o=0,r=n.length;r>o;o++){var s=n[o];i.prototype[s]=t(s)}}(),i.prototype.needsVerticalResizeLayout=function(){var e=t(this.enviratope.element),i=this.enviratope.size&&e;return i&&e.innerHeight!=this.enviratope.size.innerHeight},i.prototype._getMeasurement=function(){this.enviratope._getMeasurement.apply(this,arguments)},i.prototype.getColumnWidth=function(){this.getSegmentSize("column","Width")},i.prototype.getRowHeight=function(){this.getSegmentSize("row","Height")},i.prototype.getSegmentSize=function(t,e){var i=t+e,n="outer"+e;if(this._getMeasurement(i,n),!this[i]){var o=this.getFirstItemSize();this[i]=o&&o[n]||this.enviratope.size["inner"+e]}},i.prototype.getFirstItemSize=function(){var e=this.enviratope.filteredItems[0];return e&&e.element&&t(e.element)},i.prototype.layout=function(){this.enviratope.layout.apply(this.enviratope,arguments)},i.prototype.getSize=function(){this.enviratope.getSize(),this.size=this.enviratope.size},i.modes={},i.create=function(t,e){function n(){i.apply(this,arguments)}return n.prototype=new i,e&&(n.options=e),n.prototype.namespace=t,i.modes[t]=n,n},i}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("masonry/masonry",["outlayer/outlayer","get-size/get-size","fizzy-ui-utils/utils"],e):"object"==typeof exports?module.exports=e(require("outlayer"),require("get-size"),require("fizzy-ui-utils")):t.Masonry=e(t.Outlayer,t.getSize,t.fizzyUIUtils)}(window,function s(t,e,i){var n=t.create("masonry");return n.prototype._resetLayout=function(){this.getSize(),this._getMeasurement("columnWidth","outerWidth"),this._getMeasurement("gutter","outerWidth"),this.measureColumns();var t=this.cols;for(this.colYs=[];t--;)this.colYs.push(0);this.maxY=0},n.prototype.measureColumns=function(){if(this.getContainerWidth(),!this.columnWidth){var t=this.items[0],i=t&&t.element;this.columnWidth=i&&e(i).outerWidth||this.containerWidth}var n=this.columnWidth+=this.gutter,o=this.containerWidth+this.gutter,r=o/n,s=n-o%n,a=s&&1>s?"round":"floor";r=Math[a](r),this.cols=Math.max(r,1)},n.prototype.getContainerWidth=function(){var t=this.options.isFitWidth?this.element.parentNode:this.element,i=e(t);this.containerWidth=i&&i.innerWidth},n.prototype._getItemLayoutPosition=function(t){t.getSize();var e=t.size.outerWidth%this.columnWidth,n=e&&1>e?"round":"ceil",o=Math[n](t.size.outerWidth/this.columnWidth);o=Math.min(o,this.cols);for(var r=this._getColGroup(o),s=Math.min.apply(Math,r),a=i.indexOf(r,s),u={x:this.columnWidth*a,y:s},l=s+t.size.outerHeight,h=this.cols+1-r.length,p=0;h>p;p++)this.colYs[a+p]=l;return u},n.prototype._getColGroup=function(t){if(2>t)return this.colYs;for(var e=[],i=this.cols+1-t,n=0;i>n;n++){var o=this.colYs.slice(n,n+t);e[n]=Math.max.apply(Math,o)}return e},n.prototype._manageStamp=function(t){var i=e(t),n=this._getElementOffset(t),o=this.options.isOriginLeft?n.left:n.right,r=o+i.outerWidth,s=Math.floor(o/this.columnWidth);s=Math.max(0,s);var a=Math.floor(r/this.columnWidth);a-=r%this.columnWidth?0:1,a=Math.min(this.cols-1,a);for(var u=(this.options.isOriginTop?n.top:n.bottom)+i.outerHeight,l=s;a>=l;l++)this.colYs[l]=Math.max(u,this.colYs[l])},n.prototype._getContainerSize=function(){this.maxY=Math.max.apply(Math,this.colYs);var t={height:this.maxY};return this.options.isFitWidth&&(t.width=this._getContainerFitWidth()),t},n.prototype._getContainerFitWidth=function(){for(var t=0,e=this.cols;--e&&0===this.colYs[e];)t++;return(this.cols-t)*this.columnWidth-this.gutter},n.prototype.needsResizeLayout=function(){var t=this.containerWidth;return this.getContainerWidth(),t!==this.containerWidth},n}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("enviratope/js/layout-modes/masonry",["../layout-mode","masonry/masonry"],e):"object"==typeof exports?module.exports=e(require("../layout-mode"),require("masonry-layout")):e(t.Enviratope.LayoutMode,t.Masonry)}(window,function a(t,e){"use strict";function i(t,e){for(var i in e)t[i]=e[i];return t}var n=t.create("masonry"),o=n.prototype._getElementOffset,r=n.prototype.layout,s=n.prototype._getMeasurement;i(n.prototype,e.prototype),n.prototype._getElementOffset=o,n.prototype.layout=r,n.prototype._getMeasurement=s;var a=n.prototype.measureColumns;n.prototype.measureColumns=function(){this.items=this.enviratope.filteredItems,a.call(this)};var u=n.prototype._manageStamp;return n.prototype._manageStamp=function(){this.options.isOriginLeft=this.enviratope.options.isOriginLeft,this.options.isOriginTop=this.enviratope.options.isOriginTop,u.apply(this,arguments)},n}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("enviratope/js/layout-modes/fit-rows",["../layout-mode"],e):"object"==typeof exports?module.exports=e(require("../layout-mode")):e(t.Enviratope.LayoutMode)}(window,function u(t){"use strict";var e=t.create("fitRows");return e.prototype._resetLayout=function(){this.x=0,this.y=0,this.maxY=0,this._getMeasurement("gutter","outerWidth")},e.prototype._getItemLayoutPosition=function(t){t.getSize();var e=t.size.outerWidth+this.gutter,i=this.enviratope.size.innerWidth+this.gutter;0!==this.x&&e+this.x>i&&(this.x=0,this.y=this.maxY);var n={x:this.x,y:this.y};return this.maxY=Math.max(this.maxY,this.y+t.size.outerHeight),this.x+=e,n},e.prototype._getContainerSize=function(){return{height:this.maxY}},e}),function(t,e){"use strict";"function"==typeof define&&define.amd?define("enviratope/js/layout-modes/vertical",["../layout-mode"],e):"object"==typeof exports?module.exports=e(require("../layout-mode")):e(t.Enviratope.LayoutMode)}(window,function l(t){"use strict";var e=t.create("vertical",{horizontalAlignment:0});return e.prototype._resetLayout=function(){this.y=0},e.prototype._getItemLayoutPosition=function(t){t.getSize();var e=(this.enviratope.size.innerWidth-t.size.outerWidth)*this.options.horizontalAlignment,i=this.y;
3
+ return this.y+=t.size.outerHeight,{x:e,y:i}},e.prototype._getContainerSize=function(){return{height:this.y}},e}),function(t,e){"use strict";"function"==typeof define&&define.amd?define(["outlayer/outlayer","get-size/get-size","matches-selector/matches-selector","fizzy-ui-utils/utils","enviratope/js/item","enviratope/js/layout-mode","enviratope/js/layout-modes/masonry","enviratope/js/layout-modes/fit-rows","enviratope/js/layout-modes/vertical"],function(i,n,o,r,s,a){return e(t,i,n,o,r,s,a)}):"object"==typeof exports?module.exports=e(t,require("outlayer"),require("get-size"),require("desandro-matches-selector"),require("fizzy-ui-utils"),require("./item"),require("./layout-mode"),require("./layout-modes/masonry"),require("./layout-modes/fit-rows"),require("./layout-modes/vertical")):t.Enviratope=e(t,t.Outlayer,t.getSize,t.matchesSelector,t.fizzyUIUtils,t.Enviratope.Item,t.Enviratope.LayoutMode)}(window,function h(t,e,i,n,o,r,s){function a(t,e){return function i(n,o){for(var r=0,s=t.length;s>r;r++){var a=t[r],u=n.sortData[a],l=o.sortData[a];if(u>l||l>u){var h=void 0!==e[a]?e[a]:e,p=h?1:-1;return(u>l?1:-1)*p}}return 0}}var u=t.jQuery,l=String.prototype.trim?function(t){return t.trim()}:function(t){return t.replace(/^\s+|\s+$/g,"")},h=document.documentElement,p=h.textContent?function(t){return t.textContent}:function(t){return t.innerText},c=e.create("enviratope",{layoutMode:"masonry",isJQueryFiltering:!0,sortAscending:!0});c.Item=r,c.LayoutMode=s,c.prototype._create=function(){this.itemGUID=0,this._sorters={},this._getSorters(),e.prototype._create.call(this),this.modes={},this.filteredItems=this.items,this.sortHistory=["original-order"];for(var t in s.modes)this._initLayoutMode(t)},c.prototype.reloadItems=function(){this.itemGUID=0,e.prototype.reloadItems.call(this)},c.prototype._itemize=function(){for(var t=e.prototype._itemize.apply(this,arguments),i=0,n=t.length;n>i;i++){var o=t[i];o.id=this.itemGUID++}return this._updateItemsSortData(t),t},c.prototype._initLayoutMode=function(t){var e=s.modes[t],i=this.options[t]||{};this.options[t]=e.options?o.extend(e.options,i):i,this.modes[t]=new e(this)},c.prototype.layout=function(){return!this._isLayoutInited&&this.options.isInitLayout?void this.arrange():void this._layout()},c.prototype._layout=function(){var t=this._getIsInstant();this._resetLayout(),this._manageStamps(),this.layoutItems(this.filteredItems,t),this._isLayoutInited=!0},c.prototype.arrange=function(t){function e(){n.reveal(i.needReveal),n.hide(i.needHide)}this.option(t),this._getIsInstant();var i=this._filter(this.items);this.filteredItems=i.matches;var n=this;this._bindArrangeComplete(),this._isInstant?this._noTransition(e):e(),this._sort(),this._layout()},c.prototype._init=c.prototype.arrange,c.prototype._getIsInstant=function(){var t=void 0!==this.options.isLayoutInstant?this.options.isLayoutInstant:!this._isLayoutInited;return this._isInstant=t,t},c.prototype._bindArrangeComplete=function(){function t(){e&&i&&n&&o.dispatchEvent("arrangeComplete",null,[o.filteredItems])}var e,i,n,o=this;this.once("layoutComplete",function(){e=!0,t()}),this.once("hideComplete",function(){i=!0,t()}),this.once("revealComplete",function(){n=!0,t()})},c.prototype._filter=function(t){var e=this.options.filter;e=e||"*";for(var i=[],n=[],o=[],r=this._getFilterTest(e),s=0,a=t.length;a>s;s++){var u=t[s];if(!u.isIgnored){var l=r(u);l&&i.push(u),l&&u.isHidden?n.push(u):l||u.isHidden||o.push(u)}}return{matches:i,needReveal:n,needHide:o}},c.prototype._getFilterTest=function(t){return u&&this.options.isJQueryFiltering?function(e){return u(e.element).is(t)}:"function"==typeof t?function(e){return t(e.element)}:function(e){return n(e.element,t)}},c.prototype.updateSortData=function(t){var e;t?(t=o.makeArray(t),e=this.getItems(t)):e=this.items,this._getSorters(),this._updateItemsSortData(e)},c.prototype._getSorters=function(){var t=this.options.getSortData;for(var e in t){var i=t[e];this._sorters[e]=d(i)}},c.prototype._updateItemsSortData=function(t){for(var e=t&&t.length,i=0;e&&e>i;i++){var n=t[i];n.updateSortData()}};var d=function(){function t(t){if("string"!=typeof t)return t;var i=l(t).split(" "),n=i[0],o=n.match(/^\[(.+)\]$/),r=o&&o[1],s=e(r,n),a=c.sortDataParsers[i[1]];return t=a?function(t){return t&&a(s(t))}:function(t){return t&&s(t)}}function e(t,e){var i;return i=t?function(e){return e.getAttribute(t)}:function(t){var i=t.querySelector(e);return i&&p(i)}}return t}();c.sortDataParsers={parseInt:function(t){return parseInt(t,10)},parseFloat:function(t){return parseFloat(t)}},c.prototype._sort=function(){var t=this.options.sortBy;if(t){var e=[].concat.apply(t,this.sortHistory),i=a(e,this.options.sortAscending);this.filteredItems.sort(i),t!=this.sortHistory[0]&&this.sortHistory.unshift(t)}},c.prototype._mode=function(){var t=this.options.layoutMode,e=this.modes[t];if(!e)throw new Error("No layout mode: "+t);return e.options=this.options[t],e},c.prototype._resetLayout=function(){e.prototype._resetLayout.call(this),this._mode()._resetLayout()},c.prototype._getItemLayoutPosition=function(t){return this._mode()._getItemLayoutPosition(t)},c.prototype._manageStamp=function(t){this._mode()._manageStamp(t)},c.prototype._getContainerSize=function(){return this._mode()._getContainerSize()},c.prototype.needsResizeLayout=function(){return this._mode().needsResizeLayout()},c.prototype.appended=function(t){var e=this.addItems(t);if(e.length){var i=this._filterRevealAdded(e);this.filteredItems=this.filteredItems.concat(i)}},c.prototype.prepended=function(t){var e=this._itemize(t);if(e.length){this._resetLayout(),this._manageStamps();var i=this._filterRevealAdded(e);this.layoutItems(this.filteredItems),this.filteredItems=i.concat(this.filteredItems),this.items=e.concat(this.items)}},c.prototype._filterRevealAdded=function(t){var e=this._filter(t);return this.hide(e.needHide),this.reveal(e.matches),this.layoutItems(e.matches,!0),e.matches},c.prototype.insert=function(t){var e=this.addItems(t);if(e.length){var i,n,o=e.length;for(i=0;o>i;i++)n=e[i],this.element.appendChild(n.element);var r=this._filter(e).matches;for(i=0;o>i;i++)e[i].isLayoutInstant=!0;for(this.arrange(),i=0;o>i;i++)delete e[i].isLayoutInstant;this.reveal(r)}};var f=c.prototype.remove;return c.prototype.remove=function(t){t=o.makeArray(t);var e=this.getItems(t);f.call(this,t);var i=e&&e.length;if(i)for(var n=0;i>n;n++){var r=e[n];o.removeFrom(this.filteredItems,r)}},c.prototype.shuffle=function(){for(var t=0,e=this.items.length;e>t;t++){var i=this.items[t];i.sortData.random=Math.random()}this.options.sortBy="random",this._sort(),this._layout()},c.prototype._noTransition=function(t){var e=this.options.transitionDuration;this.options.transitionDuration=0;var i=t.call(this);return this.options.transitionDuration=e,i},c.prototype.getFilteredItemElements=function(){for(var t=[],e=0,i=this.filteredItems.length;i>e;e++)t.push(this.filteredItems[e].element);return t},c}),function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof exports?module.exports=t:t(jQuery)}(function($){function t(t){var n=t||window.event,o=r.call(arguments,1),u=0,h=0,p=0,c=0,d=0,f=0;if(t=$.event.fix(n),t.type="mousewheel","detail"in n&&(p=-1*n.detail),"wheelDelta"in n&&(p=n.wheelDelta),"wheelDeltaY"in n&&(p=n.wheelDeltaY),"wheelDeltaX"in n&&(h=-1*n.wheelDeltaX),"axis"in n&&n.axis===n.HORIZONTAL_AXIS&&(h=-1*p,p=0),u=0===p?h:p,"deltaY"in n&&(p=-1*n.deltaY,u=p),"deltaX"in n&&(h=n.deltaX,0===p&&(u=-1*h)),0!==p||0!==h){if(1===n.deltaMode){var m=$.data(this,"mousewheel-line-height");u*=m,p*=m,h*=m}else if(2===n.deltaMode){var g=$.data(this,"mousewheel-page-height");u*=g,p*=g,h*=g}if(c=Math.max(Math.abs(p),Math.abs(h)),(!a||a>c)&&(a=c,i(n,c)&&(a/=40)),i(n,c)&&(u/=40,h/=40,p/=40),u=Math[u>=1?"floor":"ceil"](u/a),h=Math[h>=1?"floor":"ceil"](h/a),p=Math[p>=1?"floor":"ceil"](p/a),l.settings.normalizeOffset&&this.getBoundingClientRect){var v=this.getBoundingClientRect();d=t.clientX-v.left,f=t.clientY-v.top}return t.deltaX=h,t.deltaY=p,t.deltaFactor=a,t.offsetX=d,t.offsetY=f,t.deltaMode=0,o.unshift(t,u,h,p),s&&clearTimeout(s),s=setTimeout(e,200),($.event.dispatch||$.event.handle).apply(this,o)}}function e(){a=null}function i(t,e){return l.settings.adjustOldDeltas&&"mousewheel"===t.type&&e%120===0}var n=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],o="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],r=Array.prototype.slice,s,a;if($.event.fixHooks)for(var u=n.length;u;)$.event.fixHooks[n[--u]]=$.event.mouseHooks;var l=$.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var e=o.length;e;)this.addEventListener(o[--e],t,!1);else this.onmousewheel=t;$.data(this,"mousewheel-line-height",l.getLineHeight(this)),$.data(this,"mousewheel-page-height",l.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var e=o.length;e;)this.removeEventListener(o[--e],t,!1);else this.onmousewheel=null;$.removeData(this,"mousewheel-line-height"),$.removeData(this,"mousewheel-page-height")},getLineHeight:function(t){var e=$(t),i=e["offsetParent"in $.fn?"offsetParent":"parent"]();return i.length||(i=$("body")),parseInt(i.css("fontSize"),10)||parseInt(e.css("fontSize"),10)||16},getPageHeight:function(t){return $(t).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};$.fn.extend({mousewheel:function(t){return t?this.bind("mousewheel",t):this.trigger("mousewheel")},unmousewheel:function(t){return this.unbind("mousewheel",t)}})}),jQuery(document).ready(function($){var t="ontouchstart"in document.documentElement;t&&$("body").addClass("envira-touch")}),function(t){"function"==typeof define&&define.amd&&define.amd.jQuery?define(["jquery"],t):t(jQuery)}(function($){"use strict";function t(t){return!t||void 0!==t.allowPageScroll||void 0===t.swipe&&void 0===t.swipeStatus||(t.allowPageScroll=u),void 0!==t.click&&void 0===t.tap&&(t.tap=t.click),t||(t={}),t=$.extend({},$.fn.swipe.defaults,t),this.each(function(){var i=$(this),n=i.data(I);n||(n=new e(this,t),i.data(I,n))})}function e(t,e){function m(t){if(!(lt()||$(t.target).closest(e.excludedElements,Ut).length>0)){var i=t.originalEvent?t.originalEvent:t,n,o=L?i.touches[0]:i;return Vt=x,L?Yt=i.touches.length:t.preventDefault(),Pt=0,Wt=null,Ft=null,Dt=0,At=0,Ht=0,qt=1,Bt=0,Qt=ft(),Nt=vt(),at(),!L||Yt===e.fingers||e.fingers===y||F()?(pt(0,o),Xt=St(),2==Yt&&(pt(1,i.touches[1]),At=Ht=xt(Qt[0].start,Qt[1].start)),(e.swipeStatus||e.pinchStatus)&&(n=j(i,Vt))):n=!1,n===!1?(Vt=_,j(i,Vt),n):(e.hold&&(te=setTimeout($.proxy(function(){Ut.trigger("hold",[i.target]),e.hold&&(n=e.hold.call(Ut,i,i.target))},this),e.longTapThreshold)),ht(!0),null)}}function z(t){var i=t.originalEvent?t.originalEvent:t;if(Vt!==E&&Vt!==_&&!ut()){var n,o=L?i.touches[0]:i,r=ct(o);if(Gt=St(),L&&(Yt=i.touches.length),e.hold&&clearTimeout(te),Vt=b,2==Yt&&(0==At?(pt(1,i.touches[1]),At=Ht=xt(Qt[0].start,Qt[1].start)):(ct(i.touches[1]),Ht=xt(Qt[0].end,Qt[1].end),Ft=Et(Qt[0].end,Qt[1].end)),qt=bt(At,Ht),Bt=Math.abs(At-Ht)),Yt===e.fingers||e.fingers===y||!L||F()){if(Wt=Tt(r.start,r.end),q(t,Wt),Pt=_t(r.start,r.end),Dt=wt(),mt(Wt,Pt),(e.swipeStatus||e.pinchStatus)&&(n=j(i,Vt)),!e.triggerOnTouchEnd||e.triggerOnTouchLeave){var s=!0;if(e.triggerOnTouchLeave){var a=It(this);s=zt(r.end,a)}!e.triggerOnTouchEnd&&s?Vt=k(b):e.triggerOnTouchLeave&&!s&&(Vt=k(E)),(Vt==_||Vt==E)&&j(i,Vt)}}else Vt=_,j(i,Vt);n===!1&&(Vt=_,j(i,Vt))}}function O(t){var i=t.originalEvent;return L&&i.touches.length>0?(st(),!0):(ut()&&(Yt=$t),Gt=St(),Dt=wt(),D()||!W()?(Vt=_,j(i,Vt)):e.triggerOnTouchEnd||0==e.triggerOnTouchEnd&&Vt===b?(t.preventDefault(),Vt=E,j(i,Vt)):!e.triggerOnTouchEnd&&G()?(Vt=E,P(i,Vt,c)):Vt===b&&(Vt=_,j(i,Vt)),ht(!1),null)}function C(){Yt=0,Gt=0,Xt=0,At=0,Ht=0,qt=1,at(),ht(!1)}function M(t){var i=t.originalEvent;e.triggerOnTouchLeave&&(Vt=k(E),j(i,Vt))}function R(){Ut.unbind(Ct,m),Ut.unbind(jt,C),Ut.unbind(Mt,z),Ut.unbind(Rt,O),kt&&Ut.unbind(kt,M),ht(!1)}function k(t){var i=t,n=H(),o=W(),r=D();return!n||r?i=_:!o||t!=b||e.triggerOnTouchEnd&&!e.triggerOnTouchLeave?!o&&t==E&&e.triggerOnTouchLeave&&(i=_):i=E,i}function j(t,e){var i=void 0;return Y()||V()?i=P(t,e,h):(N()||F())&&i!==!1&&(i=P(t,e,p)),ot()&&i!==!1?i=P(t,e,d):rt()&&i!==!1?i=P(t,e,f):nt()&&i!==!1&&(i=P(t,e,c)),e===_&&C(t),e===E&&(L?0==t.touches.length&&C(t):C(t)),i}function P(t,u,l){var m=void 0;if(l==h){if(Ut.trigger("swipeStatus",[u,Wt||null,Pt||0,Dt||0,Yt,Qt]),e.swipeStatus&&(m=e.swipeStatus.call(Ut,t,u,Wt||null,Pt||0,Dt||0,Yt,Qt),m===!1))return!1;if(u==E&&U()){if(Ut.trigger("swipe",[Wt,Pt,Dt,Yt,Qt]),e.swipe&&(m=e.swipe.call(Ut,t,Wt,Pt,Dt,Yt,Qt),m===!1))return!1;switch(Wt){case i:Ut.trigger("swipeLeft",[Wt,Pt,Dt,Yt,Qt]),e.swipeLeft&&(m=e.swipeLeft.call(Ut,t,Wt,Pt,Dt,Yt,Qt));break;case n:Ut.trigger("swipeRight",[Wt,Pt,Dt,Yt,Qt]),e.swipeRight&&(m=e.swipeRight.call(Ut,t,Wt,Pt,Dt,Yt,Qt));break;case o:Ut.trigger("swipeUp",[Wt,Pt,Dt,Yt,Qt]),e.swipeUp&&(m=e.swipeUp.call(Ut,t,Wt,Pt,Dt,Yt,Qt));break;case r:Ut.trigger("swipeDown",[Wt,Pt,Dt,Yt,Qt]),e.swipeDown&&(m=e.swipeDown.call(Ut,t,Wt,Pt,Dt,Yt,Qt))}}}if(l==p){if(Ut.trigger("pinchStatus",[u,Ft||null,Bt||0,Dt||0,Yt,qt,Qt]),e.pinchStatus&&(m=e.pinchStatus.call(Ut,t,u,Ft||null,Bt||0,Dt||0,Yt,qt,Qt),m===!1))return!1;if(u==E&&B())switch(Ft){case s:Ut.trigger("pinchIn",[Ft||null,Bt||0,Dt||0,Yt,qt,Qt]),e.pinchIn&&(m=e.pinchIn.call(Ut,t,Ft||null,Bt||0,Dt||0,Yt,qt,Qt));break;case a:Ut.trigger("pinchOut",[Ft||null,Bt||0,Dt||0,Yt,qt,Qt]),e.pinchOut&&(m=e.pinchOut.call(Ut,t,Ft||null,Bt||0,Dt||0,Yt,qt,Qt))}}return l==c?(u===_||u===E)&&(clearTimeout(Jt),clearTimeout(te),Z()&&!tt()?(Kt=St(),Jt=setTimeout($.proxy(function(){Kt=null,Ut.trigger("tap",[t.target]),e.tap&&(m=e.tap.call(Ut,t,t.target))},this),e.doubleTapThreshold)):(Kt=null,Ut.trigger("tap",[t.target]),e.tap&&(m=e.tap.call(Ut,t,t.target)))):l==d?(u===_||u===E)&&(clearTimeout(Jt),Kt=null,Ut.trigger("doubletap",[t.target]),e.doubleTap&&(m=e.doubleTap.call(Ut,t,t.target))):l==f&&(u===_||u===E)&&(clearTimeout(Jt),Kt=null,Ut.trigger("longtap",[t.target]),e.longTap&&(m=e.longTap.call(Ut,t,t.target))),m}function W(){var t=!0;return null!==e.threshold&&(t=Pt>=e.threshold),t}function D(){var t=!1;return null!==e.cancelThreshold&&null!==Wt&&(t=gt(Wt)-Pt>=e.cancelThreshold),t}function A(){return null!==e.pinchThreshold?Bt>=e.pinchThreshold:!0}function H(){var t;return t=e.maxTimeThreshold&&Dt>=e.maxTimeThreshold?!1:!0}function q(t,s){if(e.allowPageScroll===u||F())t.preventDefault();else{var a=e.allowPageScroll===l;switch(s){case i:(e.swipeLeft&&a||!a&&e.allowPageScroll!=g)&&t.preventDefault();break;case n:(e.swipeRight&&a||!a&&e.allowPageScroll!=g)&&t.preventDefault();break;case o:(e.swipeUp&&a||!a&&e.allowPageScroll!=v)&&t.preventDefault();break;case r:(e.swipeDown&&a||!a&&e.allowPageScroll!=v)&&t.preventDefault()}}}function B(){var t=Q(),e=X(),i=A();return t&&e&&i}function F(){return!!(e.pinchStatus||e.pinchIn||e.pinchOut)}function N(){return!(!B()||!F())}function U(){var t=H(),e=W(),i=Q(),n=X(),o=D(),r=!o&&n&&i&&e&&t;return r}function V(){return!!(e.swipe||e.swipeStatus||e.swipeLeft||e.swipeRight||e.swipeUp||e.swipeDown)}function Y(){return!(!U()||!V())}function Q(){return Yt===e.fingers||e.fingers===y||!L}function X(){return 0!==Qt[0].end.x}function G(){return!!e.tap}function Z(){return!!e.doubleTap}function K(){return!!e.longTap}function J(){if(null==Kt)return!1;var t=St();return Z()&&t-Kt<=e.doubleTapThreshold}function tt(){return J()}function et(){return(1===Yt||!L)&&(isNaN(Pt)||Pt<e.threshold)}function it(){return Dt>e.longTapThreshold&&w>Pt}function nt(){return!(!et()||!G())}function ot(){return!(!J()||!Z())}function rt(){return!(!it()||!K())}function st(){Zt=St(),$t=event.touches.length+1}function at(){Zt=0,$t=0}function ut(){var t=!1;if(Zt){var i=St()-Zt;i<=e.fingerReleaseThreshold&&(t=!0)}return t}function lt(){return!(Ut.data(I+"_intouch")!==!0)}function ht(t){t===!0?(Ut.bind(Mt,z),Ut.bind(Rt,O),kt&&Ut.bind(kt,M)):(Ut.unbind(Mt,z,!1),Ut.unbind(Rt,O,!1),kt&&Ut.unbind(kt,M,!1)),Ut.data(I+"_intouch",t===!0)}function pt(t,e){var i=void 0!==e.identifier?e.identifier:0;return Qt[t].identifier=i,Qt[t].start.x=Qt[t].end.x=e.pageX||e.clientX,Qt[t].start.y=Qt[t].end.y=e.pageY||e.clientY,Qt[t]}function ct(t){var e=void 0!==t.identifier?t.identifier:0,i=dt(e);return i.end.x=t.pageX||t.clientX,i.end.y=t.pageY||t.clientY,i}function dt(t){for(var e=0;e<Qt.length;e++)if(Qt[e].identifier==t)return Qt[e]}function ft(){for(var t=[],e=0;5>=e;e++)t.push({start:{x:0,y:0},end:{x:0,y:0},identifier:0});return t}function mt(t,e){e=Math.max(e,gt(t)),Nt[t].distance=e}function gt(t){return Nt[t]?Nt[t].distance:void 0}function vt(){var t={};return t[i]=yt(i),t[n]=yt(n),t[o]=yt(o),t[r]=yt(r),t}function yt(t){return{direction:t,distance:0}}function wt(){return Gt-Xt}function xt(t,e){var i=Math.abs(t.x-e.x),n=Math.abs(t.y-e.y);return Math.round(Math.sqrt(i*i+n*n))}function bt(t,e){var i=e/t*1;return i.toFixed(2)}function Et(){return 1>qt?a:s}function _t(t,e){return Math.round(Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2)))}function Lt(t,e){var i=t.x-e.x,n=e.y-t.y,o=Math.atan2(n,i),r=Math.round(180*o/Math.PI);return 0>r&&(r=360-Math.abs(r)),r}function Tt(t,e){var s=Lt(t,e);return 45>=s&&s>=0?i:360>=s&&s>=315?i:s>=135&&225>=s?n:s>45&&135>s?r:o}function St(){var t=new Date;return t.getTime()}function It(t){t=$(t);var e=t.offset(),i={left:e.left,right:e.left+t.outerWidth(),top:e.top,bottom:e.top+t.outerHeight()};return i}function zt(t,e){return t.x>e.left&&t.x<e.right&&t.y>e.top&&t.y<e.bottom}var Ot=L||S||!e.fallbackToMouseEvents,Ct=Ot?S?T?"MSPointerDown":"pointerdown":"touchstart":"mousedown",Mt=Ot?S?T?"MSPointerMove":"pointermove":"touchmove":"mousemove",Rt=Ot?S?T?"MSPointerUp":"pointerup":"touchend":"mouseup",kt=Ot?null:"mouseleave",jt=S?T?"MSPointerCancel":"pointercancel":"touchcancel",Pt=0,Wt=null,Dt=0,At=0,Ht=0,qt=1,Bt=0,Ft=0,Nt=null,Ut=$(t),Vt="start",Yt=0,Qt=null,Xt=0,Gt=0,Zt=0,$t=0,Kt=0,Jt=null,te=null;try{Ut.bind(Ct,m),Ut.bind(jt,C)}catch(ee){$.error("events not supported "+Ct+","+jt+" on jQuery.swipe")}this.enable=function(){return Ut.bind(Ct,m),Ut.bind(jt,C),Ut},this.disable=function(){return R(),Ut},this.destroy=function(){R(),Ut.data(I,null),Ut=null},this.option=function(t,i){if(void 0!==e[t]){if(void 0===i)return e[t];e[t]=i}else $.error("Option "+t+" does not exist on jQuery.swipe.options");return null}}var i="left",n="right",o="up",r="down",s="in",a="out",u="none",l="auto",h="swipe",p="pinch",c="tap",d="doubletap",f="longtap",m="hold",g="horizontal",v="vertical",y="all",w=10,x="start",b="move",E="end",_="cancel",L="ontouchstart"in window,T=window.navigator.msPointerEnabled&&!window.navigator.pointerEnabled,S=window.navigator.pointerEnabled||window.navigator.msPointerEnabled,I="TouchSwipe",z={fingers:1,threshold:75,cancelThreshold:null,pinchThreshold:20,maxTimeThreshold:null,fingerReleaseThreshold:250,longTapThreshold:500,doubleTapThreshold:200,swipe:null,swipeLeft:null,swipeRight:null,swipeUp:null,swipeDown:null,swipeStatus:null,pinchIn:null,pinchOut:null,pinchStatus:null,click:null,tap:null,doubleTap:null,longTap:null,hold:null,triggerOnTouchEnd:!0,triggerOnTouchLeave:!1,allowPageScroll:"auto",fallbackToMouseEvents:!0,excludedElements:"label, button, input, select, textarea, a, .noSwipe"};$.fn.swipe=function(e){var i=$(this),n=i.data(I);if(n&&"string"==typeof e){if(n[e])return n[e].apply(this,Array.prototype.slice.call(arguments,1));$.error("Method "+e+" does not exist on jQuery.swipe")}else if(!(n||"object"!=typeof e&&e))return t.apply(this,arguments);return i},$.fn.swipe.defaults=z,$.fn.swipe.phases={PHASE_START:x,PHASE_MOVE:b,PHASE_END:E,PHASE_CANCEL:_},$.fn.swipe.directions={LEFT:i,RIGHT:n,UP:o,DOWN:r,IN:s,OUT:a},$.fn.swipe.pageScroll={NONE:u,HORIZONTAL:g,VERTICAL:v,AUTO:l},$.fn.swipe.fingers={ONE:1,TWO:2,THREE:3,ALL:y}});
assets/js/min/metabox-min.js CHANGED
@@ -1 +1 @@
1
- !function($){$(function(){function e(e){$(".media-toolbar-secondary span.envira-gallery-spinner").css("visibility","visible"),$.post(envira_gallery_metabox.ajax,{action:"envira_gallery_load_library",offset:e,post_id:envira_gallery_metabox.id,search:$("input#envira-gallery-gallery-search").val(),nonce:envira_gallery_metabox.load_gallery},function(a){$("a.envira-gallery-load-library").attr("data-envira-gallery-offset",Number(e)+20),$(".media-toolbar-secondary span.envira-gallery-spinner").css("visibility","hidden"),0===e?$(".envira-gallery-gallery").html(a.html):$(".envira-gallery-gallery").append(a.html)},"json")}function a(){var e={action:"envira_gallery_refresh",post_id:envira_gallery_metabox.id,nonce:envira_gallery_metabox.refresh_nonce};$(".envira-media-library").after('<span class="spinner envira-gallery-spinner envira-gallery-spinner-refresh"></span>'),$(".envira-gallery-spinner-refresh").css({display:"inline-block","margin-top":"-3px"}),$.post(envira_gallery_metabox.ajax,e,function(e){e&&e.success&&($("#envira-gallery-output").html(e.success),$("#envira-gallery-output").find(".wp-editor-wrap").each(function(e,a){var r=$(a).find(".quicktags-toolbar");if(!(r.length>0)){var i=$(a).attr("id").split("-"),l=i.slice(4,-1).join("-");quicktags({id:"envira-gallery-caption-"+l,buttons:"strong,em,link,ul,ol,li,close"}),QTags._buttonsInit()}}),$("#envira-gallery-output").trigger({type:"enviraRefreshed",html:e.success,id:envira_gallery_metabox.id})),$(".envira-gallery-spinner-refresh").fadeOut(300,function(){$(this).remove()})},"json")}function r(){var e=$("#envira-config-crop"),a=$("#envira-config-mobile"),r=$("#envira-config-lightbox-toolbar");e.is(":checked")&&$("#envira-config-crop-size-box").fadeIn(300),e.on("change",function(){$(this).is(":checked")?$("#envira-config-crop-size-box").fadeIn(300):$("#envira-config-crop-size-box").fadeOut(300)}),a.is(":checked")&&$("#envira-config-mobile-size-box").fadeIn(300),a.on("change",function(){$(this).is(":checked")?$("#envira-config-mobile-size-box").fadeIn(300):$("#envira-config-mobile-size-box").fadeOut(300)}),r.is(":checked")&&$("#envira-config-lightbox-toolbar-position-box").fadeIn(300),r.on("change",function(){$(this).is(":checked")?$("#envira-config-lightbox-toolbar-position-box").fadeIn(300):$("#envira-config-lightbox-toolbar-position-box").fadeOut(300)})}function i(){$("#envira-gallery .drag-drop-inside").append('<div class="envira-progress-bar"><div></div></div>'),c=new plupload.Uploader(envira_gallery_metabox.plupload);var e=$("#envira-gallery .envira-progress-bar"),a=$("#envira-gallery .envira-progress-bar div"),r=$("#envira-gallery-output");c&&($("#envira-gallery .max-upload-size").append(' <a class="envira-media-library button button-primary" href="#" title="'+envira_gallery_metabox.gallery+'" style="vertical-align: baseline;">'+envira_gallery_metabox.gallery+"</a>"),c.bind("Init",function(e){var a=$("#envira-gallery-plupload-upload-ui");e.features.dragdrop&&!$(document.body).hasClass("mobile")?(a.addClass("drag-drop"),$("#envira-gallery-drag-drop-area").bind("dragover.wp-uploader",function(){a.addClass("drag-over")}).bind("dragleave.wp-uploader, drop.wp-uploader",function(){a.removeClass("drag-over")})):(a.removeClass("drag-drop"),$("#envira-gallery-drag-drop-area").unbind(".wp-uploader")),"html4"==e.runtime&&$(".upload-flash-bypass").hide()}),c.init(),c.bind("FilesAdded",function(a,r){var i=104857600,n=parseInt(a.settings.max_file_size,10);$("#envira-gallery-upload-error").html(""),$(e).show().css("display","block"),plupload.each(r,function(e){n>i&&e.size>i&&"html5"!=a.runtime&&l(a,e,!0)}),a.refresh(),a.start()}),c.bind("UploadProgress",function(e,r){$(a).css("width",e.total.percent+"%")}),c.bind("FileUploaded",function(e,a,i){$.post(envira_gallery_metabox.ajax,{action:"envira_gallery_load_image",nonce:envira_gallery_metabox.load_image,id:i.response,post_id:envira_gallery_metabox.id},function(e){$(r).append(e),$(e).find(".wp-editor-container").each(function(e,a){var r=$(a).attr("id").split("-")[4];quicktags({id:"envira-gallery-caption-"+r,buttons:"strong,em,link,ul,ol,li,close"}),QTags._buttonsInit()})},"json")}),c.bind("UploadComplete",function(){$(e).hide().css("display","none"),$(a).removeAttr("style")}),c.bind("Error",function(e,a){var r=104857600,i=$("#envira-gallery-upload-error"),n;switch(a){case plupload.FAILED:case plupload.FILE_EXTENSION_ERROR:i.html('<p class="error">'+pluploadL10n.upload_failed+"</p>");break;case plupload.FILE_SIZE_ERROR:l(e,a.file);break;case plupload.IMAGE_FORMAT_ERROR:wpFileError(fileObj,pluploadL10n.not_an_image);break;case plupload.IMAGE_MEMORY_ERROR:wpFileError(fileObj,pluploadL10n.image_memory_exceeded);break;case plupload.IMAGE_DIMENSIONS_ERROR:wpFileError(fileObj,pluploadL10n.image_dimensions_exceeded);break;case plupload.GENERIC_ERROR:wpQueueError(pluploadL10n.upload_failed);break;case plupload.IO_ERROR:n=parseInt(uploader.settings.max_file_size,10),n>r&&fileObj.size>r?wpFileError(fileObj,pluploadL10n.big_upload_failed.replace("%1$s",'<a class="uploader-html" href="#">').replace("%2$s","</a>")):wpQueueError(pluploadL10n.io_error);break;case plupload.HTTP_ERROR:wpQueueError(pluploadL10n.http_error);break;case plupload.INIT_ERROR:$(".media-upload-form").addClass("html-uploader");break;case plupload.SECURITY_ERROR:wpQueueError(pluploadL10n.security_error);break;default:l(e,a.file)}e.refresh()}))}function l(e,a,r){var i;i=r?pluploadL10n.big_upload_queued.replace("%s",a.name)+" "+pluploadL10n.big_upload_failed.replace("%1$s",'<a class="uploader-html" href="#">').replace("%2$s","</a>"):pluploadL10n.file_exceeds_size_limit.replace("%s",a.name),$("#envira-gallery-upload-error").html('<div class="error fade"><p>'+i+"</p></div>"),e.removeFile(a)}var n=$("#envira-tabs"),t=$("#envira-tabs-nav"),o=window.location.hash,s=window.location.hash.replace("!","");if(o&&o.indexOf("envira-tab-")>=0){$(".envira-active").removeClass("envira-active"),t.find('li a[href="'+s+'"]').parent().addClass("envira-active"),n.find(s).addClass("envira-active").show();var d=$("#post").attr("action");d&&(d=d.split("#")[0],$("#post").attr("action",d+o))}$(document).on("click","#envira-tabs-nav li a",function(e){e.preventDefault();var a=$(this);if(!a.parent().hasClass("envira-active")){window.location.hash=o=this.hash.split("#").join("#!");var r=t.find(".envira-active").removeClass("envira-active").find("a").attr("href");a.parent().addClass("envira-active"),n.find(r).removeClass("envira-active").hide(),n.find(a.attr("href")).addClass("envira-active").show();var i=$("#post").attr("action");i&&(i=i.split("#")[0],$("#post").attr("action",i+o))}});var c;i(),r(),0!==$(".envira-helper-needed").length&&$('<div class="envira-meta-helper-overlay" />').prependTo("#envira-gallery"),$(document).on("click",".envira-meta-icon",function(e){e.preventDefault();var a=$(this),r=a.parent(),i=a.next();i.is(":visible")?($(".envira-meta-helper-overlay").remove(),r.removeClass("envira-helper-active")):(0===$(".envira-meta-helper-overlay").length&&$('<div class="envira-meta-helper-overlay" />').prependTo("#envira-gallery"),r.addClass("envira-helper-active"))}),$(document).on("click",".envira-media-library",function(e){e.preventDefault(),f=!0,$("#envira-gallery-upload-ui").appendTo("body").show()}),$(".envira-gallery-gallery").on("click",".thumbnail, .check, .media-modal-icon",function(e){e.preventDefault(),$(this).parent().parent().hasClass("envira-gallery-in-gallery")||($(this).parent().parent().hasClass("selected")?$(this).parent().parent().removeClass("details selected"):$(this).parent().parent().addClass("details selected"))}),$(document).on("click","a.envira-gallery-load-library",function(a){e($("a.envira-gallery-load-library").attr("data-envira-gallery-offset"))}),$(".envira-gallery-gallery").bind("scroll",function(){$(this).scrollTop()+$(this).innerHeight()>=this.scrollHeight&&e($("a.envira-gallery-load-library").attr("data-envira-gallery-offset"))}),$(document).on("keyup keydown","#envira-gallery-gallery-search",function(){m(function(){e(0)})}),$(document).on("click",".envira-gallery-media-insert",function(e){e.preventDefault();var a=$(this),r=$(this).text(),i={action:"envira_gallery_insert_images",nonce:envira_gallery_metabox.insert_nonce,post_id:envira_gallery_metabox.id,images:{}},l=!1,n=e;a.text(envira_gallery_metabox.inserting),$(".envira-gallery-media-frame").find(".attachment.selected:not(.envira-gallery-in-gallery)").each(function(e,a){i.images[e]=$(a).attr("data-attachment-id"),l=!0}),$.post(envira_gallery_metabox.ajax,i,function(e){setTimeout(function(){y(n),a.text(r),l&&$(".envira-gallery-load-library").attr("data-envira-gallery-offset",0).addClass("has-search").trigger("click")},500)},"json")});var p=$("#envira-gallery-output");p.sortable({containment:"#envira-gallery-output",items:"li",cursor:"move",forcePlaceholderSize:!0,placeholder:"dropzone",update:function(e,a){var r={url:envira_gallery_metabox.ajax,type:"post",async:!0,cache:!1,dataType:"json",data:{action:"envira_gallery_sort_images",order:p.sortable("toArray").toString(),post_id:envira_gallery_metabox.id,nonce:envira_gallery_metabox.sort},success:function(e){},error:function(e,a,r){}};$.ajax(r)}}),$("#envira-gallery").on("click",".envira-gallery-remove-image",function(e){e.preventDefault();var a=confirm(envira_gallery_metabox.remove);if(a){var r=$(this).parent().attr("id"),i={action:"envira_gallery_remove_image",attachment_id:r,post_id:envira_gallery_metabox.id,nonce:envira_gallery_metabox.remove_nonce};$.post(envira_gallery_metabox.ajax,i,function(e){$("#"+r).fadeOut("normal",function(){$(this).remove(),$(".envira-gallery-load-library").attr("data-envira-gallery-offset",0).addClass("has-search").trigger("click")})},"json")}}),$("#envira-gallery").on("click",".envira-gallery-modify-image",function(e){e.preventDefault();var a=$(this).parent().data("envira-gallery-image"),r="envira-gallery-meta-"+a;u(a,r)});var v,u=function(e,a){v=$("#"+a).appendTo("body"),$(v).show(),$(document).on("click",".media-modal-close, .media-modal-backdrop",function(e){e.preventDefault(),g()}),$(document).on("keydown",function(e){27==e.keyCode&&g()})},g=function(){var e=$(v).attr("id"),a=e.split("-"),r=a[a.length-1];$("#"+e).appendTo("#"+r).hide()};$(document).on("click",".envira-gallery-meta-submit",function(e){e.preventDefault();var a=$(this),r=a.text(),i=a.data("envira-gallery-item"),l="envira-gallery-meta-"+i,n={};a.text(envira_gallery_metabox.saving),n.title=$("#envira-gallery-meta-table-"+i).find('textarea[name="_envira_gallery[meta_title]"]').val(),$("#envira-gallery-meta-table-"+i).find(":input").not(".ed_button").each(function(e,a){$(this).data("envira-meta")&&(n[$(this).data("envira-meta")]=$(this).val())});var t={action:"envira_gallery_save_meta",nonce:envira_gallery_metabox.save_nonce,attach_id:i,post_id:envira_gallery_metabox.id,meta:n};$.post(envira_gallery_metabox.ajax,t,function(e){setTimeout(function(){$("#"+l).appendTo("#"+i).hide(),a.text(r)},500)},"json")}),$("#envira-gallery-import-submit").on("click",function(e){$(this).next().css("display","inline-block"),0===$("#envira-config-import-gallery").val().length&&(e.preventDefault(),$(this).next().hide(),alert(envira_gallery_metabox["import"]))});var m=function(){var e=0;return function(a,r){clearTimeout(e),e=setTimeout(a,r)}}(),f=!1,y=function(e){e.preventDefault(),$("#envira-gallery-upload-ui").appendTo("#envira-gallery-upload-ui-wrapper").hide(),a(),f=!1};$(document).on("click","#envira-gallery-upload-ui .media-modal-close, #envira-gallery-upload-ui .media-modal-backdrop",y),$(document).on("keydown",function(e){27==e.keyCode&&f&&y(e)})})}(jQuery);
1
+ function EnviraGalleryImagesUpdate(e){EnviraGalleryImages.reset();var a="ul#envira-gallery-output li.envira-gallery-image"+(e?".selected":"");jQuery(a).each(function(){var e=jQuery.parseJSON(jQuery(this).attr("data-envira-gallery-image-model"));e.alt=EnviraGalleryStripslashes(e.alt),EnviraGalleryImages.add(new EnviraGalleryImage(e))}),jQuery("#envira-gallery-main span.count").text(jQuery("ul#envira-gallery-output li.envira-gallery-image").length)}function EnviraGalleryStripslashes(e){return(e+"").replace(/\\(.?)/g,function(e,a){switch(a){case"\\":return"\\";case"0":return"\x00";case"":return"";default:return a}})}function envira_gallery_sortable($){$(envira_gallery_output).sortable({containment:envira_gallery_output,items:"li",cursor:"move",forcePlaceholderSize:!0,placeholder:"dropzone",helper:function(e,a){a.hasClass("selected")||a.addClass("selected").siblings().removeClass("selected");var t=a.parent().children(".selected").clone();a.data("multidrag",t).siblings(".selected").remove();var i=$("<li/>");return i.append(t)},stop:function(e,a){var t=a.item.data("multidrag");a.item.after(t).remove(),$("li.selected",$(envira_gallery_output)).removeClass("selected"),$.ajax({url:envira_gallery_metabox.ajax,type:"post",async:!0,cache:!1,dataType:"json",data:{action:"envira_gallery_sort_images",order:$(envira_gallery_output).sortable("toArray").toString(),post_id:envira_gallery_metabox.id,nonce:envira_gallery_metabox.sort},success:function(e){EnviraGalleryImagesUpdate(!1)},error:function(e,a,t){$(envira_gallery_output).before('<div class="error"><p>'+a.responseText+"</p></div>")}})}})}jQuery(document).ready(function($){$("input, select").conditional({data:"envira-conditional",value:"envira-conditional-value",displayOnEnabled:"envira-conditional-display"})}),function($){"use strict";$.fn.conditional=function(e){var a=$.extend({data:"conditional",value:"conditional-value",displayOnEnabled:"conditional-display"},e);return this.each(function(){if("undefined"==typeof $(this).data(a.data))return!0;var e,t,i,n;$(this).on("change",function(){switch(e=$(this).data(a.data).split(","),t=$(this).data(a.displayOnEnabled),"undefined"==typeof t&&(t=!0),i=$(this).data(a.value),"undefined"==typeof i&&(i=""),n=!1,$(this).attr("type")){case"checkbox":n=t?$(this).is(":checked"):$(this).is(":checked")?!1:!0;break;default:n=t?""!==i?String($(this).val())!==String(i)?!1:!0:""===$(this).val()||"0"===$(this).val()?!1:!0:""!==i?$(this).val()!==i?!0:!1:""===$(this).val()||"0"===$(this).val()?!0:!1}for(var r=0;r<e.length;r++)n?$("#"+e[r]).fadeIn(300):$("#"+e[r]).fadeOut(300)}),$(this).trigger("change")}),this}}(jQuery);var envira_video_link="p.envira-intro a.envira-video",envira_close_video_link="a.envira-video-close";jQuery(document).ready(function($){$(document).on("click",envira_video_link,function(e){e.preventDefault();var a=$(this).attr("href");-1==a.search("autoplay=1")&&(a+=-1==a.search("rel=")?"?rel=0&autoplay=1":"&autoplay=1"),$("div.envira-video-help").remove();var t=$(this).closest("p.envira-intro");$(t).append('<div class="envira-video-help"><iframe src="'+a+'" /><a href="#" class="envira-video-close dashicons dashicons-no"></a></div>')}),$(document).on("click",envira_close_video_link,function(e){e.preventDefault(),$(this).closest(".envira-video-help").remove()})}),jQuery(document).ready(function($){$(document).on("click","a.envira-gallery-images-delete",function(e){e.preventDefault();var a=confirm(envira_gallery_metabox.remove_multiple);if(!a)return!1;var t=[];$("ul#envira-gallery-output > li.selected").each(function(){t.push($(this).attr("id"))});var i=$(this).parent().attr("id");$.ajax({url:envira_gallery_metabox.ajax,type:"post",dataType:"json",data:{action:"envira_gallery_remove_images",attachment_ids:t,post_id:envira_gallery_metabox.id,nonce:envira_gallery_metabox.remove_nonce},success:function(e){$("ul#envira-gallery-output > li.selected").remove(),$("nav.envira-select-options").fadeOut(),$(".envira-gallery-load-library").attr("data-envira-gallery-offset",0).addClass("has-search").trigger("click"),EnviraGalleryImagesUpdate(!1)},error:function(e,a,t){$(envira_gallery_output).before('<div class="error"><p>'+a.responseText+"</p></div>")}})}),$(document).on("click","#envira-gallery-main .envira-gallery-remove-image",function(e){e.preventDefault();var a=confirm(envira_gallery_metabox.remove);if(a){var t=$(this).parent().attr("id");$.ajax({url:envira_gallery_metabox.ajax,type:"post",dataType:"json",data:{action:"envira_gallery_remove_image",attachment_id:t,post_id:envira_gallery_metabox.id,nonce:envira_gallery_metabox.remove_nonce},success:function(e){$("#"+t).fadeOut("normal",function(){$(this).remove(),$(".envira-gallery-load-library").attr("data-envira-gallery-offset",0).addClass("has-search").trigger("click"),EnviraGalleryImagesUpdate(!1)})},error:function(e,a,t){$(envira_gallery_output).before('<div class="error"><p>'+a.responseText+"</p></div>")}})}})});var EnviraGalleryImage=Backbone.Model.extend({defaults:{id:"",title:"",caption:"",alt:"",link:""}}),EnviraGalleryImages=new Backbone.Collection;if("undefined"==typeof EnviraGalleryModalWindow)var EnviraGalleryModalWindow=new wp.media.view.Modal({controller:{trigger:function(){}}});var EnviraGalleryEditView=wp.Backbone.View.extend({tagName:"div",className:"edit-attachment-frame mode-select hide-menu hide-router",template:wp.template("envira-meta-editor"),events:{"click .edit-media-header .left":"loadPreviousItem","click .edit-media-header .right":"loadNextItem","keyup input":"updateItem","keyup textarea":"updateItem","change input":"updateItem","change textarea":"updateItem","blur textarea":"updateItem","change select":"updateItem","click .actions a.envira-gallery-meta-submit":"saveItem","keyup input#link-search":"searchLinks","click div.query-results li":"insertLink","click button.media-file":"insertMediaFileLink","click button.attachment-page":"insertAttachmentPageLink"},initialize:function(e){this.on("loading",this.loading,this),this.on("loaded",this.loaded,this),this.is_loading=!1,this.collection=e.collection,this.child_views=e.child_views,this.attachment_id=e.attachment_id,this.attachment_index=0,this.search_timer="";var a=0;this.collection.each(function(e){return e.get("id")==this.attachment_id?(this.model=e,this.attachment_index=a,!1):void a++},this)},render:function(){return this.$el.html(this.template(this.model.attributes)),this.child_views.length>0&&this.child_views.forEach(function(e){var a=new e({model:this.model});this.$el.find("div.addons").append(a.render().el)},this),this.$el.find("textarea[name=caption]").val(this.model.get("caption")),setTimeout(function(){quicktags({id:"caption",buttons:"strong,em,link,ul,ol,li,close"}),QTags._buttonsInit()},500),"undefined"!=typeof wpLink&&wpLink.init,0==this.attachment_index&&this.$el.find("button.left").addClass("disabled"),this.attachment_index==this.collection.length-1&&this.$el.find("button.right").addClass("disabled"),this},renderError:function(e){var a={};a.error=e;var t=new wp.media.view.EnviraGalleryError({model:a});return t.render().el},loading:function(){this.is_loading=!0,this.$el.find(".spinner").css("visibility","visible")},loaded:function(e){this.is_loading=!1,this.$el.find(".spinner").css("visibility","hidden"),"undefined"!=typeof e&&this.$el.find("div.media-toolbar").after(this.renderError(e))},loadPreviousItem:function(){this.attachment_index--,this.model=this.collection.at(this.attachment_index),this.attachment_id=this.model.get("id"),this.render()},loadNextItem:function(){this.attachment_index++,this.model=this.collection.at(this.attachment_index),this.attachment_id=this.model.get("id"),this.render()},updateItem:function(e){""!=e.target.name&&("checkbox"==e.target.type?value=e.target.checked?1:0:value=e.target.value,this.model.set(e.target.name,value))},saveItem:function(){this.trigger("loading"),wp.media.ajax("envira_gallery_save_meta",{context:this,data:{nonce:envira_gallery_metabox.save_nonce,post_id:envira_gallery_metabox.id,attach_id:this.model.get("id"),meta:this.model.attributes},success:function(e){this.trigger("loaded loaded:success");var a=JSON.stringify(this.model.attributes),t=jQuery("ul#envira-gallery-output li#"+this.model.get("id"));jQuery(t).attr("data-envira-gallery-image-model",a),jQuery("div.meta div.title span",t).text(this.model.get("title")),jQuery("div.meta div.title a.hint",t).attr("title",this.model.get("title")),this.model.get("title").length>20?jQuery("div.meta div.title a.hint",t).removeClass("hidden"):jQuery("div.meta div.title a.hint",t).addClass("hidden");var i=this.$el.find(".saved");i.fadeIn(),setTimeout(function(){i.fadeOut()},1500)},error:function(e){this.trigger("loaded loaded:error",e)}})},searchLinks:function(e){},insertLink:function(e){},insertMediaFileLink:function(e){this.trigger("loading"),wp.media.ajax("envira_gallery_get_attachment_links",{context:this,data:{nonce:envira_gallery_metabox.save_nonce,attachment_id:this.model.get("id")},success:function(e){this.model.set("link",e.media_link),this.trigger("loaded loaded:success"),this.render()},error:function(e){this.trigger("loaded loaded:error",e)}})},insertAttachmentPageLink:function(e){this.trigger("loading"),wp.media.ajax("envira_gallery_get_attachment_links",{context:this,data:{nonce:envira_gallery_metabox.save_nonce,attachment_id:this.model.get("id")},success:function(e){this.model.set("link",e.attachment_page),this.trigger("loaded loaded:success"),this.render()},error:function(e){this.trigger("loaded loaded:error",e)}})}}),EnviraGalleryChildViews=[];jQuery(document).ready(function($){$(document).on("click","#envira-gallery-main a.envira-gallery-modify-image",function(e){e.preventDefault(),EnviraGalleryImagesUpdate(!1);var a=$(this).parent().data("envira-gallery-image");EnviraGalleryModalWindow.content(new EnviraGalleryEditView({collection:EnviraGalleryImages,child_views:EnviraGalleryChildViews,attachment_id:a})),EnviraGalleryModalWindow.open()})}),jQuery(document).ready(function($){$("a.envira-media-library").on("click",function(e){return e.preventDefault(),wp.media.frames.envira?void wp.media.frames.envira.open():(wp.media.frames.envira=wp.media({frame:"post",title:wp.media.view.l10n.insertIntoPost,button:{text:wp.media.view.l10n.insertIntoPost},multiple:!0}),wp.media.frames.envira.on("open",function(){var e=wp.media.frames.envira.state().get("selection");$("ul#envira-gallery-output li").each(function(){var a=wp.media.attachment($(this).attr("id"));e.add(a?[a]:[])})}),wp.media.frames.envira.on("insert",function(e){var a=wp.media.frames.envira.state(),t=[];e.each(function(e){var i=a.display(e).toJSON();switch(i.link){case"none":e.set("link",e.get("url"));break;case"file":e.set("link",e.get("url"));break;case"post":break;case"custom":e.set("link",i.linkUrl)}t.push(e.toJSON())},this),$.post(envira_gallery_metabox.ajax,{action:"envira_gallery_insert_images",nonce:envira_gallery_metabox.insert_nonce,post_id:envira_gallery_metabox.id,images:t},function(e){e&&e.success&&($("#envira-gallery-output").html(e.success),EnviraGalleryImagesUpdate(!1))},"json")}),void wp.media.frames.envira.open())})});var envira_gallery_output="#envira-gallery-output",envira_gallery_shift_key_pressed=!1,envira_gallery_last_selected_image=!1;jQuery(document).ready(function($){envira_gallery_sortable($)}),function($){$(function(){if("undefined"!=typeof uploader){$("input#plupload-browse-button").val(envira_gallery_metabox.uploader_files_computer),$("#envira-gallery .drag-drop-inside").append('<div class="envira-progress-bar"><div></div></div>');var e=$("#envira-gallery .envira-progress-bar"),a=$("#envira-gallery .envira-progress-bar div"),t=$("#envira-gallery-output"),i=$("#envira-gallery-upload-error");uploader.bind("FilesAdded",function(a,t){$(i).html(""),$(e).fadeIn()}),uploader.bind("UploadProgress",function(e,t){$(a).css({width:e.total.percent+"%"})}),uploader.bind("FileUploaded",function(e,a,i){$.post(envira_gallery_metabox.ajax,{action:"envira_gallery_load_image",nonce:envira_gallery_metabox.load_image,id:i.response,post_id:envira_gallery_metabox.id},function(e){switch(envira_gallery_metabox.media_position){case"before":$(t).prepend(e);break;case"after":default:$(t).append(e)}EnviraGalleryImagesUpdate(!1)},"json")}),uploader.bind("UploadComplete",function(){$(e).fadeOut()}),uploader.bind("Error",function(e,a){$("#envira-gallery-upload-error").html('<div class="error fade"><p>'+a.file.name+": "+a.message+"</p></div>"),e.refresh()})}})}(jQuery);
assets/js/min/settings-min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function($){$(function(){})}(jQuery);
assets/js/min/tabs-min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function($){$(function(){var a=".envira-tabs-nav",i=window.location.hash,t=window.location.hash.replace("!","");if(i&&i.indexOf("envira-tab-")>=0){var e=$(t).parent(),n=$(e).data("navigation");$(n).find(".envira-active").removeClass("envira-active"),$(e).find(".envira-active").removeClass("envira-active"),$(n).find('a[href="'+t+'"]').addClass("envira-active"),$(t).addClass("envira-active");var r=$("#post").attr("action");r&&(r=r.split("#")[0],$("#post").attr("action",r+window.location.hash))}$(a).on("click",".nav-tab, a",function(i){i.preventDefault(),$("div.envira-video-help").remove();var t=$(this).closest(a),e=$(t).data("container"),n=$(t).data("update-hashbang"),r="undefined"!=typeof $(this).attr("href")?$(this).attr("href"):$(this).data("tab");if(!$(this).hasClass("envira-active")&&("undefined"!=typeof $(this).attr("for")&&($("input#"+$(this).attr("for")).prop("checked")||$("input#"+$(this).attr("for")).prop("checked",!0).trigger("change")),$(t).find(".envira-active").removeClass("envira-active"),$(e).find(".envira-active").removeClass("envira-active"),$(this).addClass("envira-active"),$(e).find(r).addClass("envira-active"),"1"==n)){window.location.hash=r.split("#").join("#!");var v=$("#post").attr("action");v&&(v=v.split("#")[0],$("#post").attr("action",v+window.location.hash))}})})}(jQuery);
assets/js/settings.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ==========================================================
2
+ * settings.js
3
+ * http://enviragallery.com/
4
+ * ==========================================================
5
+ * Copyright 2014 Thomas Griffin.
6
+ *
7
+ * Licensed under the GPL License, Version 2.0 or later (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.gnu.org/licenses/gpl-2.0.html
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ * ========================================================== */
19
+ ;(function($){
20
+ $(function(){
21
+
22
+ });
23
+ }(jQuery));
assets/js/tabs.js ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Handles tabbed interfaces within Envira:
3
+ * - Settings Screen
4
+ * - Add/Edit Screen: Native/External
5
+ * - Add/Edit Screen: Configuration Tabs
6
+ */
7
+
8
+ ;( function( $ ) {
9
+ $( function() {
10
+
11
+ // Define some general vars
12
+ var envira_tabs_nav = '.envira-tabs-nav', // Container of tab navigation items (typically an unordered list)
13
+ envira_tabs_hash = window.location.hash,
14
+ envira_tabs_current_tab = window.location.hash.replace( '!', '' );
15
+
16
+ // If the URL contains a hash beginning with envira-tab, mark that tab as open
17
+ // and display that tab's panel.
18
+ if ( envira_tabs_hash && envira_tabs_hash.indexOf( 'envira-tab-' ) >= 0 ) {
19
+ // Find the tab panel that the tab corresponds to
20
+ var envira_tabs_section = $( envira_tabs_current_tab ).parent(),
21
+ envira_tab_nav = $( envira_tabs_section ).data( 'navigation' );
22
+
23
+ // Remove the active class from everything in this tab navigation and section
24
+ $( envira_tab_nav ).find( '.envira-active' ).removeClass( 'envira-active' );
25
+ $( envira_tabs_section ).find( '.envira-active' ).removeClass( 'envira-active' );
26
+
27
+ // Add the active class to the chosen tab and section
28
+ $( envira_tab_nav ).find( 'a[href="' + envira_tabs_current_tab + '"]').addClass( 'envira-active' );
29
+ $( envira_tabs_current_tab ).addClass( 'envira-active' );
30
+
31
+ // Update the form action to contain the selected tab as a hash in the URL
32
+ // This means when the user saves their Gallery, they'll see the last selected
33
+ // tab 'open' on reload
34
+ var envira_post_action = $( '#post' ).attr( 'action' );
35
+ if ( envira_post_action ) {
36
+ // Remove any existing hash from the post action
37
+ envira_post_action = envira_post_action.split( '#' )[0];
38
+
39
+ // Append the selected tab as a hash to the post action
40
+ $( '#post' ).attr( 'action', envira_post_action + window.location.hash );
41
+ }
42
+ }
43
+
44
+ // Change tabs on click.
45
+ // Tabs should be clickable elements, such as an anchor or label.
46
+ $( envira_tabs_nav ).on( 'click', '.nav-tab, a', function( e ) {
47
+
48
+ // Prevent the default action
49
+ e.preventDefault();
50
+
51
+ // Destroy all instances of Envira Video iframes
52
+ $( 'div.envira-video-help' ).remove();
53
+
54
+ // Get the clicked element and the nav tabs
55
+ var envira_tabs = $( this ).closest( envira_tabs_nav ),
56
+ envira_tabs_section = $( envira_tabs ).data( 'container' ),
57
+ envira_tabs_update_hashbang = $( envira_tabs ).data( 'update-hashbang' ),
58
+ envira_tab = ( ( typeof $( this ).attr( 'href' ) !== 'undefined' ) ? $( this ).attr( 'href' ) : $( this ).data( 'tab' ) );
59
+
60
+ // Don't do anything if we're clicking the already active tab.
61
+ if ( $( this ).hasClass( 'envira-active' ) ) {
62
+ return;
63
+ }
64
+
65
+ // If the tab that was clicked is a label, check its corresponding input element, if it isn't already checked
66
+ if ( typeof $( this ).attr( 'for' ) !== 'undefined' ) {
67
+ if ( ! $( 'input#' + $( this ).attr( 'for' ) ).prop( 'checked' ) ) {
68
+ $( 'input#' + $( this ).attr( 'for' ) ).prop( 'checked', true ).trigger( 'change' );
69
+ }
70
+ }
71
+
72
+ // Remove the active class from everything in this tab navigation and section
73
+ $( envira_tabs ).find( '.envira-active' ).removeClass( 'envira-active' );
74
+ $( envira_tabs_section ).find( '.envira-active' ).removeClass( 'envira-active' );
75
+
76
+ // Add the active class to the chosen tab and section
77
+ $( this ).addClass( 'envira-active' );
78
+ $( envira_tabs_section ).find( envira_tab ).addClass( 'envira-active' );
79
+
80
+ // Update the window URL to contain the selected tab as a hash in the URL.
81
+ if ( envira_tabs_update_hashbang == '1' ) {
82
+ window.location.hash = envira_tab.split( '#' ).join( '#!' );
83
+
84
+ // Update the form action to contain the selected tab as a hash in the URL
85
+ // This means when the user saves their Gallery, they'll see the last selected
86
+ // tab 'open' on reload
87
+ var envira_post_action = $( '#post' ).attr( 'action' );
88
+ if ( envira_post_action ) {
89
+ // Remove any existing hash from the post action
90
+ envira_post_action = envira_post_action.split( '#' )[0];
91
+
92
+ // Append the selected tab as a hash to the post action
93
+ $( '#post' ).attr( 'action', envira_post_action + window.location.hash );
94
+ }
95
+ }
96
+
97
+ } );
98
+ } );
99
+ } ( jQuery ) );
assets/scss/attachment-details-modal-support.scss DELETED
@@ -1,304 +0,0 @@
1
- /* ==========================================================================
2
- 4.0 Attachment Details Modal
3
- ========================================================================== */
4
-
5
- .media-sidebar .setting,
6
- .attachment-details .setting {
7
- display: block;
8
- float: left;
9
- width: 100%;
10
- margin: 1px 0;
11
- }
12
-
13
- .media-sidebar .setting label,
14
- .attachment-details .setting label {
15
- display: block;
16
- }
17
-
18
- .media-sidebar .setting .link-to-custom,
19
- .attachment-details .setting .link-to-custom {
20
- margin: 3px 2px 0;
21
- }
22
-
23
- .media-sidebar .setting span,
24
- .attachment-details .setting span {
25
- min-width: 30%;
26
- margin-right: 4%;
27
- font-size: 12px;
28
- text-align: right;
29
- }
30
-
31
- .media-sidebar .setting select,
32
- .attachment-details .setting select {
33
- max-width: 65%;
34
- }
35
-
36
- .media-sidebar .setting input[type="checkbox"],
37
- .media-sidebar .field input[type="checkbox"],
38
- .media-sidebar .setting input[type="radio"],
39
- .media-sidebar .field input[type="radio"],
40
- .attachment-details .setting input[type="checkbox"],
41
- .attachment-details .field input[type="checkbox"],
42
- .attachment-details .setting input[type="radio"],
43
- .attachment-details .field input[type="radio"] {
44
- float: none;
45
- margin: 8px 3px 0;
46
- padding: 0;
47
- }
48
-
49
- .media-sidebar .setting span,
50
- .attachment-details .setting span,
51
- .compat-item label span {
52
- float: left;
53
- min-height: 22px;
54
- padding-top: 8px;
55
- line-height: 16px;
56
- font-weight: normal;
57
- color: #666;
58
- }
59
-
60
- .compat-item label span {
61
- text-align: right;
62
- }
63
-
64
- .media-sidebar .setting input[type="text"],
65
- .media-sidebar .setting input[type="password"],
66
- .media-sidebar .setting input[type="email"],
67
- .media-sidebar .setting input[type="number"],
68
- .media-sidebar .setting input[type="search"],
69
- .media-sidebar .setting input[type="tel"],
70
- .media-sidebar .setting input[type="url"],
71
- .media-sidebar .setting textarea,
72
- .media-sidebar .setting .value,
73
- .attachment-details .setting input[type="text"],
74
- .attachment-details .setting input[type="password"],
75
- .attachment-details .setting input[type="email"],
76
- .attachment-details .setting input[type="number"],
77
- .attachment-details .setting input[type="search"],
78
- .attachment-details .setting input[type="tel"],
79
- .attachment-details .setting input[type="url"],
80
- .attachment-details .setting textarea,
81
- .attachment-details .setting .value {
82
- -webkit-box-sizing: border-box;
83
- -moz-box-sizing: border-box;
84
- box-sizing: border-box;
85
- margin: 1px;
86
- width: 65%;
87
- float: right;
88
- }
89
-
90
- .media-sidebar .setting .value,
91
- .attachment-details .setting .value {
92
- margin: 0 1px;
93
- text-align: left;
94
- }
95
-
96
- .media-sidebar .setting textarea,
97
- .attachment-details .setting textarea,
98
- .compat-item .field textarea {
99
- height: 62px;
100
- resize: vertical;
101
- }
102
-
103
- .media-sidebar select,
104
- .attachment-details select {
105
- margin-top: 3px;
106
- }
107
-
108
- .edit-attachment-frame {
109
- display: block;
110
- height: 100%;
111
- width: 100%;
112
- }
113
-
114
- .edit-attachment-frame .edit-media-header {
115
- overflow: hidden;
116
- }
117
-
118
- .upload-php .media-modal-close .media-modal-icon:before {
119
- content: '\f335';
120
- font-size: 22px;
121
- }
122
-
123
- .upload-php .media-modal-close .media-modal-icon {
124
- margin: 14px;
125
- width: 22px;
126
- }
127
-
128
- .upload-php .media-modal-close,
129
- .edit-attachment-frame .edit-media-header .left,
130
- .edit-attachment-frame .edit-media-header .right {
131
- cursor: pointer;
132
- color: #777;
133
- background-color: transparent;
134
- height: 50px;
135
- width: 50px;
136
- padding: 0;
137
- position: absolute;
138
- text-align: center;
139
- border: 0;
140
- border-left: 1px solid #ddd;
141
- -webkit-transition: color .1s ease-in-out, background .1s ease-in-out;
142
- transition: color .1s ease-in-out, background .1s ease-in-out;
143
- }
144
-
145
- .upload-php .media-modal-close {
146
- top: 0;
147
- right: 0;
148
- }
149
-
150
- .edit-attachment-frame .edit-media-header .left {
151
- right: 102px;
152
- }
153
-
154
- .edit-attachment-frame .edit-media-header .right {
155
- right: 51px;
156
- }
157
-
158
- .edit-attachment-frame .media-frame-title {
159
- left: 0;
160
- right: 150px; /* leave space for prev/next/close */
161
- }
162
-
163
- .edit-attachment-frame .edit-media-header .right:before,
164
- .edit-attachment-frame .edit-media-header .left:before {
165
- font: normal 20px/50px 'dashicons' !important;
166
- display: inline;
167
- font-weight: 300;
168
- }
169
-
170
- .upload-php .media-modal-close:hover,
171
- .upload-php .media-modal-close:focus,
172
- .edit-attachment-frame .edit-media-header .left:hover,
173
- .edit-attachment-frame .edit-media-header .right:hover,
174
- .edit-attachment-frame .edit-media-header .left:focus,
175
- .edit-attachment-frame .edit-media-header .right:focus {
176
- background: #ddd;
177
- border-color: #ccc;
178
- color: #000;
179
- outline: none;
180
- }
181
-
182
- .upload-php .media-modal-close:focus .media-modal-icon:before,
183
- .upload-php .media-modal-close:hover .media-modal-icon:before {
184
- color: #000;
185
- }
186
-
187
- .edit-attachment-frame .edit-media-header .left:before,
188
- .rtl .edit-attachment-frame .edit-media-header .right:before {
189
- content: '\f341';
190
- }
191
-
192
- .edit-attachment-frame .edit-media-header .right:before,
193
- .rtl .edit-attachment-frame .edit-media-header .left:before {
194
- content: '\f345';
195
- }
196
-
197
- .edit-attachment-frame .edit-media-header .left.disabled,
198
- .edit-attachment-frame .edit-media-header .right.disabled,
199
- .edit-attachment-frame .edit-media-header .left.disabled:hover,
200
- .edit-attachment-frame .edit-media-header .right.disabled:hover {
201
- color: #ccc;
202
- background: inherit;
203
- cursor: default;
204
- pointer-events: none;
205
- }
206
-
207
- .edit-attachment-frame .media-frame-content,
208
- .edit-attachment-frame .media-frame-router {
209
- left: 0;
210
- }
211
-
212
- .edit-attachment-frame .media-frame-content {
213
- border-bottom: none;
214
- bottom: 0;
215
- top: 50px;
216
- }
217
-
218
- .edit-attachment-frame .attachment-details {
219
- position: absolute;
220
- overflow: auto;
221
- top: 0;
222
- bottom: 0;
223
- right: 0;
224
- left: 0;
225
- -webkit-box-shadow: inset 0px 4px 4px -4px rgba(0, 0, 0, 0.1);
226
- box-shadow: inset 0px 4px 4px -4px rgba(0, 0, 0, 0.1);
227
- }
228
-
229
- .edit-attachment-frame .attachment-media-view {
230
- float: left;
231
- width: 65%;
232
- height: 100%;
233
- }
234
-
235
- .edit-attachment-frame .attachment-media-view .thumbnail {
236
- -webkit-box-sizing: border-box;
237
- -moz-box-sizing: border-box;
238
- box-sizing: border-box;
239
- padding: 16px;
240
- height: 100%;
241
- }
242
-
243
- .edit-attachment-frame .attachment-media-view .details-image {
244
- display: block;
245
- margin-bottom: 16px;
246
- max-width: 100%;
247
- max-height: 90%;
248
- max-height: -webkit-calc( 100% - 42px );
249
- max-height: calc( 100% - 42px ); /* leave space for actions underneath */
250
- }
251
-
252
- .edit-attachment-frame .wp-media-wrapper {
253
- margin-bottom: 12px;
254
- }
255
-
256
- .edit-attachment-frame input,
257
- .edit-attachment-frame textarea {
258
- padding: 6px 8px;
259
- line-height: 16px;
260
- }
261
-
262
- .edit-attachment-frame .attachment-info {
263
- overflow: auto;
264
- -webkit-box-sizing: border-box;
265
- -moz-box-sizing: border-box;
266
- box-sizing: border-box;
267
- margin-bottom: 0;
268
- padding: 12px 16px 0;
269
- width: 35%;
270
- height: 100%;
271
- -webkit-box-shadow: inset 0px 4px 4px -4px rgba(0, 0, 0, 0.1);
272
- box-shadow: inset 0px 4px 4px -4px rgba(0, 0, 0, 0.1);
273
- border-bottom: 0;
274
- border-left: 1px solid #ddd;
275
- background: #f3f3f3;
276
- }
277
-
278
- .edit-attachment-frame .attachment-info .details,
279
- .edit-attachment-frame .attachment-info .settings {
280
- position: relative; /* RTL fix, #WP29352 */
281
- overflow: hidden;
282
- float: none;
283
- margin-bottom: 15px;
284
- padding-bottom: 15px;
285
- border-bottom: 1px solid #ddd;
286
- }
287
-
288
- .edit-attachment-frame .attachment-info .filename {
289
- font-weight: normal;
290
- color: #666;
291
- }
292
-
293
- .edit-attachment-frame .attachment-info .thumbnail {
294
- margin-bottom: 12px;
295
- }
296
-
297
- .attachment-info .actions {
298
- margin-bottom: 16px;
299
- }
300
-
301
- .attachment-info .actions a {
302
- display: inline;
303
- text-decoration: none;
304
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/scss/envira.scss DELETED
@@ -1,635 +0,0 @@
1
- /* ==========================================================================
2
- Envira Gallery Styles
3
- ========================================================================== */
4
-
5
- /**
6
- * Envira Gallery - Reset
7
- */
8
- .envira-gallery-wrap,
9
- .envira-gallery-wrap *,
10
- .envira-tags-filter-list,
11
- .envira-tags-filter-list * {
12
- background:none;
13
- border:0 none;
14
- border-radius:0;
15
- -webkit-border-radius:0;
16
- -moz-border-radius:0;
17
- float:none;
18
- font-size:100%;
19
- height:auto;
20
- letter-spacing:normal;
21
- list-style:none;
22
- outline:none;
23
- position:static;
24
- text-decoration:none;
25
- text-indent:0;
26
- text-shadow:none;
27
- text-transform:none;
28
- width:auto;
29
- visibility:visible;
30
- overflow:visible;
31
- margin:0;
32
- padding:0;
33
- line-height:1;
34
- box-sizing:border-box;
35
- -webkit-box-sizing:border-box;
36
- -moz-box-sizing:border-box;
37
- -webkit-box-shadow:none;
38
- -moz-box-shadow:none;
39
- -ms-box-shadow:none;
40
- -o-box-shadow:none;
41
- box-shadow:none;
42
- -webkit-appearance:none;
43
- transition: none;
44
- -webkit-transition: none;
45
- -moz-transition: none;
46
- -o-transition: none;
47
- -ms-transition: none;
48
- }
49
-
50
- /**
51
- * Main Wrapper
52
- */
53
- .envira-gallery-wrap {
54
- width: 100%;
55
- margin: 0 auto 20px auto;
56
-
57
- /**
58
- * Inner Wrapper
59
- */
60
- .envira-gallery-public {
61
- width: 100%;
62
- margin: 0 auto 20px auto;
63
- -webkit-box-sizing: border-box;
64
- -moz-box-sizing: border-box;
65
- box-sizing: border-box;
66
-
67
- /**
68
- * Clearing
69
- */
70
- &.envira-clear {
71
- clear: both;
72
-
73
- &:after {
74
- clear: both;
75
- content: '.';
76
- display: block;
77
- height: 0;
78
- line-height: 0;
79
- overflow: auto;
80
- visibility: hidden;
81
- zoom: 1;
82
- }
83
- }
84
-
85
- /**
86
- * Gallery Item
87
- */
88
- .envira-gallery-item {
89
- float: left;
90
-
91
- /**
92
- * Link
93
- */
94
- > .envira-gallery-link {
95
- display: block;
96
- outline: none;
97
- border: 0 none;
98
- position: relative;
99
- }
100
-
101
- /**
102
- * Image
103
- */
104
- img {
105
- display: block;
106
- margin: 0 auto;
107
- max-width: 100%;
108
- }
109
- }
110
- }
111
- }
112
-
113
- /**
114
- * RTL Support
115
- */
116
- .envira-gallery-wrap.envira-gallery-rtl {
117
- /**
118
- * Inner Wrapper
119
- */
120
- .envira-gallery-public {
121
- /**
122
- * Gallery Item
123
- */
124
- .envira-gallery-item {
125
- float: right;
126
- }
127
- }
128
- }
129
-
130
- /* ==========================================================================
131
- Envira Lightbox Gallery Styles
132
- ========================================================================== */
133
-
134
- /*! envirabox v2.1.5 fancyapps.com | fancyapps.com/envirabox/#license */
135
- .envirabox-wrap,
136
- .envirabox-skin,
137
- .envirabox-outer,
138
- .envirabox-inner,
139
- .envirabox-image,
140
- .envirabox-wrap iframe,
141
- .envirabox-wrap object,
142
- .envirabox-nav,
143
- .envirabox-nav span,
144
- .envirabox-tmp,
145
- .envirabox-buttons,
146
- .envirabox-thumbs,
147
- .envirabox-wrap *,
148
- .envirabox-thumbs *,
149
- .envirabox-buttons *
150
- {
151
- background:none;
152
- border:0 none;
153
- border-radius:0;
154
- -webkit-border-radius:0;
155
- -moz-border-radius:0;
156
- float:none;
157
- font-size:100%;
158
- height:auto;
159
- letter-spacing:normal;
160
- list-style:none;
161
- outline:none;
162
- position:static;
163
- text-decoration:none;
164
- text-indent:0;
165
- text-shadow:none;
166
- text-transform:none;
167
- width:auto;
168
- visibility:visible;
169
- overflow:visible;
170
- margin:0;
171
- padding:0;
172
- line-height:1;
173
- box-sizing:border-box;
174
- -webkit-box-sizing:border-box;
175
- -moz-box-sizing:border-box;
176
- -webkit-box-shadow:none;
177
- -moz-box-shadow:none;
178
- -ms-box-shadow:none;
179
- -o-box-shadow:none;
180
- box-shadow:none;
181
- -webkit-appearance:none;
182
- transition: none;
183
- -webkit-transition: none;
184
- -moz-transition: none;
185
- -o-transition: none;
186
- -ms-transition: none;
187
- }
188
-
189
- .envirabox-wrap {
190
- position: absolute;
191
- top: 0;
192
- left: 0;
193
- z-index: 988020;
194
- }
195
-
196
- .envirabox-skin {
197
- position: relative;
198
- background: #f9f9f9;
199
- color: #444;
200
- text-shadow: none;
201
- -webkit-border-radius: 4px;
202
- -moz-border-radius: 4px;
203
- border-radius: 4px;
204
- }
205
-
206
- .envirabox-opened {
207
- z-index: 988030;
208
- }
209
-
210
- .envirabox-opened .envirabox-skin {
211
- -webkit-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
212
- -moz-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
213
- box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
214
- }
215
-
216
- .envirabox-outer, .envirabox-inner {
217
- position: relative;
218
- }
219
-
220
- .envirabox-inner {
221
- overflow: hidden;
222
- }
223
-
224
- .envirabox-type-iframe .envirabox-inner {
225
- -webkit-overflow-scrolling: touch;
226
- }
227
-
228
- .envirabox-error {
229
- color: #444;
230
- font: 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;
231
- margin: 0;
232
- padding: 15px;
233
- white-space: nowrap;
234
- }
235
-
236
- .envirabox-image, .envirabox-iframe {
237
- display: block;
238
- width: 100%;
239
- height: 100%;
240
- }
241
-
242
- .envirabox-image {
243
- max-width: 100%;
244
- max-height: 100%;
245
- }
246
-
247
- #envirabox-loading, .envirabox-close, .envirabox-prev span, .envirabox-next span {
248
- background-image: url('images/envirabox_sprite.png');
249
- }
250
-
251
- #envirabox-loading {
252
- position: fixed;
253
- top: 50%;
254
- left: 50%;
255
- margin-top: -22px;
256
- margin-left: -22px;
257
- background-position: 0 -108px;
258
- opacity: 0.8;
259
- cursor: pointer;
260
- z-index: 988060;
261
- }
262
-
263
- #envirabox-loading div {
264
- width: 44px;
265
- height: 44px;
266
- background: url('images/envirabox_loading.gif') center center no-repeat;
267
- }
268
-
269
- .envirabox-close {
270
- position: absolute;
271
- top: -18px;
272
- right: -18px;
273
- width: 36px;
274
- height: 36px;
275
- cursor: pointer;
276
- z-index: 988040;
277
- }
278
-
279
- .envirabox-nav {
280
- position: absolute;
281
- top: 0;
282
- width: 40%;
283
- height: 100%;
284
- cursor: pointer;
285
- text-decoration: none;
286
- background: transparent url('images/blank.gif'); /* helps IE */
287
- -webkit-tap-highlight-color: rgba(0,0,0,0);
288
- z-index: 988040;
289
- }
290
-
291
- .envirabox-prev {
292
- left: 0;
293
- }
294
-
295
- .envirabox-next {
296
- right: 0;
297
- }
298
-
299
- .envirabox-nav span {
300
- position: absolute;
301
- top: 50%;
302
- width: 36px;
303
- height: 34px;
304
- margin-top: -18px;
305
- cursor: pointer;
306
- z-index: 988040;
307
- visibility: hidden;
308
- }
309
- body.envira-touch .envirabox-nav span {
310
- visibility: visible;
311
- }
312
-
313
- .envirabox-prev span {
314
- left: 10px;
315
- background-position: 0 -36px;
316
- }
317
-
318
- .envirabox-next span {
319
- right: 10px;
320
- background-position: 0 -72px;
321
- }
322
-
323
- .envirabox-nav:hover span {
324
- visibility: visible;
325
- }
326
-
327
- .envirabox-tmp {
328
- position: absolute;
329
- top: -99999px;
330
- left: -99999px;
331
- max-width: 99999px;
332
- max-height: 99999px;
333
- overflow: visible !important;
334
- }
335
-
336
- a.envirabox-close,
337
- a.envirabox-nav,
338
- a.fancy-close:hover,
339
- a.envirabox-nav:hover {
340
- border: 0;
341
- }
342
-
343
- /* Overlay helper */
344
-
345
- .envirabox-lock {
346
- overflow: visible !important;
347
- width: auto;
348
- }
349
-
350
- .envirabox-lock body {
351
- overflow: hidden !important;
352
- }
353
-
354
- .envirabox-lock-test {
355
- overflow-y: hidden !important;
356
- }
357
-
358
- .envirabox-overlay {
359
- position: absolute;
360
- top: 0;
361
- left: 0;
362
- overflow: hidden;
363
- display: none;
364
- z-index: 988010;
365
- background: url('images/envirabox_overlay.png');
366
- }
367
-
368
- .envirabox-overlay-fixed {
369
- position: fixed;
370
- bottom: 0;
371
- right: 0;
372
- }
373
-
374
- .envirabox-lock .envirabox-overlay {
375
- overflow: auto;
376
- overflow-y: scroll;
377
- }
378
-
379
- /* Title helper */
380
-
381
- .envirabox-title {
382
- visibility: hidden;
383
- font-size: 13px;
384
- line-height: 20px;
385
- font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
386
- position: relative;
387
- text-shadow: none;
388
- z-index: 988090;
389
-
390
- a {
391
- color: #fff;
392
- }
393
- }
394
-
395
- .envirabox-opened .envirabox-title {
396
- visibility: visible;
397
- }
398
-
399
- .envirabox-title-float-wrap {
400
- position: absolute;
401
- bottom: auto;
402
- right: 50%;
403
- margin-top: 20px;
404
- z-index: 988050;
405
- text-align: center;
406
- }
407
-
408
- .envirabox-title-float-wrap .child {
409
- display: inline-block;
410
- margin-right: -100%;
411
- padding: 2px 20px;
412
- background: transparent; /* Fallback for web browsers that doesn't support RGBa */
413
- background: rgba(0, 0, 0, 0.8);
414
- -webkit-border-radius: 15px;
415
- -moz-border-radius: 15px;
416
- border-radius: 15px;
417
- text-shadow: 0 1px 2px #222;
418
- color: #FFF;
419
- line-height: 24px;
420
- white-space: nowrap;
421
- }
422
- .envirabox-title-float-wrap.envirabox-title-text-wrap .child {
423
- white-space: normal;
424
- }
425
-
426
- .envirabox-title-outside-wrap {
427
- position: relative;
428
- margin-top: 10px;
429
- color: #fff;
430
- }
431
-
432
- .envirabox-title-inside-wrap {
433
- padding-top: 10px;
434
- }
435
-
436
- .envirabox-title-over-wrap {
437
- position: absolute;
438
- bottom: 0;
439
- left: 0;
440
- color: #fff;
441
- padding: 10px;
442
- background: #000;
443
- background: rgba(0, 0, 0, .8);
444
- }
445
-
446
- #envirabox-buttons {
447
- position: fixed;
448
- left: 0;
449
- width: 100%;
450
- z-index: 988050;
451
- }
452
-
453
- #envirabox-buttons.top {
454
- top: 10px;
455
- }
456
-
457
- #envirabox-buttons.bottom {
458
- bottom: 10px;
459
- }
460
-
461
- /* Allows for thumbnails to be displayed */
462
- #envirabox-buttons.bottom.has-padding {
463
- bottom: 80px;
464
- }
465
- #envirabox-buttons.top.has-padding {
466
- top: 80px;
467
- }
468
-
469
- #envirabox-buttons ul {
470
- display: block;
471
- width: auto;
472
- height: 30px;
473
- margin: 0 auto;
474
- padding: 0;
475
- list-style: none;
476
- border: 1px solid #111;
477
- border-radius: 3px;
478
- -webkit-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
479
- -moz-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
480
- box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
481
- background: rgb(50,50,50);
482
- background: -moz-linear-gradient(top, rgb(68,68,68) 0%, rgb(52,52,52) 50%, rgb(41,41,41) 50%, rgb(51,51,51) 100%);
483
- background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgb(68,68,68)), color-stop(50%,rgb(52,52,52)), color-stop(50%,rgb(41,41,41)), color-stop(100%,rgb(51,51,51)));
484
- background: -webkit-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%);
485
- background: -o-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%);
486
- background: -ms-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%);
487
- background: linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%);
488
- filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#444444', endColorstr='#222222',GradientType=0 );
489
- }
490
-
491
- #envirabox-buttons ul li {
492
- float: left;
493
- margin: 0;
494
- padding: 0;
495
- }
496
-
497
- #envirabox-buttons ul li#envirabox-buttons-title span {
498
- display: inline-block;
499
- padding: 0 10px;
500
- color: #fff;
501
- }
502
-
503
- #envirabox-buttons a {
504
- display: block;
505
- width: 30px;
506
- height: 30px;
507
- text-indent: -9999px;
508
- background-color: transparent;
509
- background-image: url('images/envirabox_buttons.png');
510
- background-repeat: no-repeat;
511
- outline: none;
512
- opacity: 0.8;
513
- }
514
-
515
- #envirabox-buttons a:hover {
516
- opacity: 1;
517
- }
518
-
519
- #envirabox-buttons a.btnPrev {
520
- background-position: 5px 0;
521
- }
522
-
523
- #envirabox-buttons a.btnNext {
524
- background-position: -33px 0;
525
- border-right: 1px solid #3e3e3e;
526
- }
527
-
528
- #envirabox-buttons a.btnPlay {
529
- background-position: 0 -30px;
530
- }
531
-
532
- #envirabox-buttons a.btnPlayOn {
533
- background-position: -30px -30px;
534
- }
535
-
536
- #envirabox-buttons a.btnToggle,
537
- #envirabox-buttons a.btnFullscreen {
538
- background-position: 3px -60px;
539
- border-left: 1px solid #111;
540
- border-right: 1px solid #3e3e3e;
541
- width: 35px
542
- }
543
-
544
- #envirabox-buttons a.btnToggleOn,
545
- #envirabox-buttons a.btnFullscreenOn {
546
- background-position: -27px -60px;
547
- }
548
-
549
- #envirabox-buttons a.btnClose {
550
- border-left: 1px solid #111;
551
- width: 35px;
552
- background-position: -56px 0px;
553
- }
554
-
555
- #envirabox-buttons a.btnDisabled {
556
- opacity : 0.4;
557
- cursor: default;
558
- }
559
-
560
- #envirabox-thumbs {
561
- position: fixed;
562
- left: 0;
563
- width: 100%;
564
- overflow: hidden;
565
- z-index: 988050;
566
- }
567
-
568
- #envirabox-thumbs.bottom {
569
- bottom: 2px;
570
- }
571
-
572
- #envirabox-thumbs.top {
573
- top: 2px;
574
- }
575
-
576
- #envirabox-thumbs ul {
577
- position: relative;
578
- list-style: none;
579
- margin: 0;
580
- padding: 0;
581
- }
582
-
583
- #envirabox-thumbs ul li {
584
- border: 3px solid #fff;
585
- float: left;
586
- margin: 5px;
587
- opacity: 1;
588
- }
589
-
590
- #envirabox-thumbs ul li.active {
591
- opacity: 0.75;
592
- border: 3px solid #888;
593
- }
594
-
595
- #envirabox-thumbs ul li:hover {
596
- opacity: 0.75;
597
- }
598
-
599
- #envirabox-thumbs ul li a {
600
- display: block;
601
- position: relative;
602
- overflow: hidden;
603
- border: 1px solid #222;
604
- background: #111;
605
- outline: none;
606
- }
607
-
608
- #envirabox-thumbs ul li img {
609
- display: block;
610
- position: relative;
611
- border: 0;
612
- padding: 0;
613
- max-width: none;
614
- }
615
-
616
- /* Retina stuff */
617
- @media
618
- only screen and (-webkit-min-device-pixel-ratio: 2),
619
- only screen and ( min--moz-device-pixel-ratio: 2),
620
- only screen and ( -o-min-device-pixel-ratio: 2/1),
621
- only screen and ( min-device-pixel-ratio: 2),
622
- only screen and ( min-resolution: 192dpi),
623
- only screen and ( min-resolution: 2dppx) {
624
-
625
- #envirabox-loading, .envirabox-close, .envirabox-prev span, .envirabox-next span {
626
- background-image: url('images/envirabox_sprite-2x.png');
627
- background-size: 44px 152px;
628
- }
629
-
630
- #envirabox-loading div {
631
- background-image: url('images/envirabox_loading-2x.gif');
632
- background-size: 24px 24px;
633
- }
634
-
635
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/scss/metabox.scss DELETED
@@ -1,805 +0,0 @@
1
- /* ==========================================================================
2
- Metabox Styles
3
- ========================================================================== */
4
-
5
- .envira-gallery-spinner {
6
- float: none;
7
- display: inline-block;
8
- margin-top: 0;
9
- }
10
-
11
- #envira-gallery {
12
- position: relative;
13
- }
14
-
15
- #envira-gallery .envira-clear {
16
- clear: both;
17
- }
18
-
19
- #envira-gallery .envira-clear:after {
20
- clear: both;
21
- content: '.';
22
- display: block;
23
- height: 0;
24
- line-height: 0;
25
- overflow: auto;
26
- visibility: hidden;
27
- zoom: 1;
28
- }
29
-
30
- #envira-gallery p.description {
31
- font-size: 13px;
32
- }
33
-
34
- #envira-gallery .inside {
35
- margin: 10px 0;
36
- padding: 0 10px;
37
- }
38
-
39
- #envira-gallery #envira-tabs {
40
- position: relative;
41
- }
42
-
43
- #envira-gallery #envira-tabs-nav {
44
- list-style: none;
45
- margin: 0 0 10px;
46
- padding: 0;
47
- border-bottom: 1px solid #cecece;
48
- }
49
-
50
- #envira-gallery #envira-tabs-nav li {
51
- float: left;
52
- margin: 0 10px -1px 0;
53
- }
54
-
55
- #envira-gallery #envira-tabs-nav li a {
56
- display: block;
57
- padding: 7px 10px 5px;
58
- font-size: 14px;
59
- color: #aaa;
60
- font-weight: 300;
61
- text-decoration: none;
62
- outline: none;
63
- }
64
-
65
- #envira-gallery #envira-tabs-nav li.envira-active a {
66
- border: 1px solid #cecece;
67
- border-bottom-color: #fff;
68
- -moz-border-radius: 3px 3px 0 0;
69
- -webkit-border-radius: 3px 3px 0 0;
70
- border-radius: 3px 3px 0 0;
71
- color: #21759b;
72
- padding-top: 6px;
73
- }
74
-
75
- #envira-gallery #envira-tabs-nav li a:hover {
76
- color: #21759b;
77
- }
78
-
79
- /**
80
- * Types Nav
81
- */
82
- #envira-gallery-types-nav {
83
- margin: 10px 0;
84
- padding: 10px 0;
85
- border-top: 1px solid #eee;
86
- border-bottom: 1px solid #eee;
87
-
88
- li {
89
- float: left;
90
- margin: 0 10px 0 0;
91
-
92
- &.envira-gallery-type-label {
93
- margin-right: 20px;
94
-
95
- span {
96
- font-weight: 700;
97
- font-size: 13px;
98
- vertical-align: middle;
99
- }
100
- }
101
- }
102
- }
103
-
104
- #envira-gallery .envira-meta-close-text {
105
- display: none;
106
- color: #fff;
107
- font-style: italic;
108
- font-size: 11px;
109
- position: absolute;
110
- z-index: 98;
111
- top: 6px;
112
- right: 27px;
113
- }
114
-
115
- #envira-gallery .envira-helper-active .envira-meta-close-text {
116
- display: inline;
117
- }
118
-
119
- #envira-gallery .envira-meta-icon {
120
- position: absolute;
121
- width: 19px;
122
- height: 16px;
123
- top: 6px;
124
- right: 0;
125
- background: url(images/meta.png) no-repeat scroll 0 0;
126
- display: block;
127
- outline: none;
128
- z-index: 98;
129
- }
130
-
131
- #envira-gallery .envira-helper-active .envira-meta-icon {
132
- background-image: url(images/meta-active.png);
133
- }
134
-
135
- #envira-gallery .envira-meta-information {
136
- display: none;
137
- padding: 0 1em 1em;
138
- position: absolute;
139
- right: 0;
140
- top: 30px;
141
- width: 278px;
142
- background: #fff;
143
- border: 1px solid #e5e5e5;
144
- -webkit-box-shadow: 0 5px 15px rgba(0,0,0,.7);
145
- box-shadow: 0 5px 15px rgba(0,0,0,.7);
146
- z-index: 98;
147
- }
148
-
149
- #envira-gallery .envira-helper-active .envira-meta-information {
150
- display: block;
151
- }
152
-
153
- #envira-gallery .envira-meta-helper-overlay {
154
- position: absolute;
155
- z-index: 97;
156
- background: #000;
157
- opacity: .7;
158
- filter: alpha(opacity=70);
159
- width: 100%;
160
- height: 100%;
161
- }
162
-
163
- #envira-gallery .envira-tab {
164
- display: none;
165
- }
166
-
167
- #envira-gallery .envira-tab.envira-active {
168
- display: block;
169
- }
170
-
171
- #envira-gallery .envira-tab p.envira-intro {
172
- margin: 1.5em 0 .5em;
173
- }
174
-
175
- #envira-gallery .envira-tab th,
176
- #envira-gallery .envira-tab input[type="text"],
177
- #envira-gallery .envira-tab input[type="number"],
178
- #envira-gallery .envira-tab input[type="password"],
179
- #envira-gallery .envira-tab select {
180
- width: 210px;
181
- padding-right: 0;
182
- }
183
-
184
- #envira-gallery .envira-tab tr {
185
- td {
186
- label {
187
- margin: 0 10px 0 0;
188
- }
189
- }
190
- }
191
-
192
- #envira-gallery .envira-progress-bar {
193
- display: none;
194
- width: 100%;
195
- position: relative;
196
- height: 10px;
197
- width: 100%;
198
- margin: 10px auto;
199
- border-radius: 10px;
200
- background: #dfdfdf;
201
- background: rgba(0,0,0,.1);
202
- }
203
-
204
- #envira-gallery .envira-progress-bar div {
205
- height: 10px;
206
- min-width: 20px;
207
- width: 0;
208
- background: #aaa;
209
- background: rgba(0,0,0,.2);
210
- border-radius: 10px;
211
- -webkit-transition: width 300ms;
212
- -moz-transition: width 300ms;
213
- -ms-transition: width 300ms;
214
- -o-transition: width 300ms;
215
- transition: width 300ms;
216
- }
217
-
218
- #envira-gallery .upload-flash-bypass {
219
- display: none;
220
- }
221
-
222
- #envira-gallery .max-upload-size {
223
- display: block;
224
- margin: 10px 0;
225
- }
226
-
227
- #envira-gallery .envira-tab {
228
- min-height: 320px;
229
- }
230
-
231
- #envira-gallery #envira-gallery-output {
232
- margin: 20px 0 10px;
233
- padding: 0;
234
- list-style: none;
235
- }
236
-
237
- #envira-gallery #envira-gallery-output li {
238
- background: #fff;
239
- display: block;
240
- float: left;
241
- margin: 0 10px 10px 0;
242
- padding: 4px;
243
- list-style: none;
244
- border: 1px solid #cecece;
245
- -moz-border-radius: 3px;
246
- -webkit-border-radius: 3px;
247
- border-radius: 3px;
248
- -moz-background-clip: padding;
249
- -webkit-background-clip: padding-box;
250
- background-clip: padding-box;
251
- -moz-box-shadow: 0 1px 2px rgba(0,0,0,.06);
252
- -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.06);
253
- box-shadow: 0 1px 2px rgba(0,0,0,.06);
254
- cursor: move;
255
- position: relative;
256
- width: 150px;
257
- height: 150px;
258
-
259
- /**
260
- * Selected Icon
261
- */
262
- a.check {
263
- display: none;
264
- position: absolute;
265
- right: 5px;
266
- top: 5px;
267
- width: 24px;
268
- height: 24px;
269
- background-color: #1e8cbe;
270
- -webkit-box-shadow: 0 0 0 1px #fff,0 0 0 2px #1e8cbe;
271
- box-shadow: 0 0 0 1px #fff,0 0 0 2px #1e8cbe;
272
-
273
- div.media-modal-icon {
274
- width: 15px;
275
- height: 15px;
276
- margin: 5px 0 0 5px;
277
- background-position: -21px 0;
278
- }
279
- }
280
-
281
- /**
282
- * Selected state
283
- */
284
- &.selected {
285
- width: 148px;
286
- height: 148px;
287
- border: 2px solid #1e8cbe;
288
- -webkit-box-shadow: inset 0 0 0 3px #fff,inset 0 0 0 7px #1e8cbe;
289
- box-shadow: inset 0 0 0 3px #fff,inset 0 0 0 7px #1e8cbe;
290
-
291
- a.check {
292
- display: block;
293
- }
294
- }
295
- }
296
-
297
- #envira-gallery #envira-gallery-output li.envira-gallery-status-pending {
298
- background-color: #faebcc;
299
- border-color: #8a6d3b;
300
- }
301
-
302
- #envira-gallery #envira-gallery-output li.envira-gallery-status-active {
303
- background-color: #dff0d8;
304
- border-color: #3c763d;
305
- }
306
-
307
- #envira-gallery #envira-gallery-output li.dropzone {
308
- background: transparent;
309
- border: 1px dashed #d5d5d5;
310
- -moz-box-shadow: none;
311
- -webkit-box-shadow: none;
312
- box-shadow: none;
313
- }
314
-
315
- #envira-gallery #envira-gallery-output li img {
316
- display: block;
317
- margin: auto;
318
- position: absolute;
319
- top: 0;
320
- left: 0;
321
- right: 0;
322
- bottom: 0;
323
- max-width: 150px;
324
- max-height: 150px;
325
- }
326
-
327
- #envira-gallery #envira-gallery-output li .envira-gallery-remove-image {
328
- background: url(images/delete.png) no-repeat scroll 0 0;
329
- display: block;
330
- height: 16px;
331
- left: -8px;
332
- outline: none;
333
- position: absolute;
334
- top: -8px;
335
- width: 16px;
336
- z-index: 20;
337
- }
338
-
339
- #envira-gallery #envira-gallery-output li .envira-gallery-modify-image {
340
- background: url(images/modify.png) no-repeat scroll 0 0;
341
- display: block;
342
- height: 16px;
343
- left: 12px;
344
- outline: none;
345
- position: absolute;
346
- top: -8px;
347
- width: 16px;
348
- z-index: 20;
349
- }
350
-
351
- #media-items .media-item .edit-attachment,
352
- .envira-gallery-media-frame .upload-flash-bypass {
353
- display: none !important;
354
- }
355
-
356
- #media-items {
357
- margin: 0 0 16px;
358
- overflow: hidden;
359
- width: 100%;
360
- }
361
-
362
- #media-items .media-item {
363
- width: auto;
364
- float: left;
365
- margin: 0 8px 8px 0;
366
- }
367
-
368
- #media-items .media-item img {
369
- max-width: 164px;
370
- max-height: 164px;
371
- float: none;
372
- margin: 4px;
373
- display: block;
374
- }
375
-
376
- .envira-gallery-gallery {
377
- padding-left: 7px;
378
- }
379
-
380
- .envira-gallery-gallery .attachment {
381
- margin: 8px;
382
- max-width: 164px;
383
- }
384
-
385
- .envira-gallery-gallery .attachment-preview,
386
- .envira-gallery-gallery .attachment-preview .thumbnail {
387
- max-width: 164px;
388
- max-height: 164px;
389
- }
390
-
391
- .envira-gallery-media-frame .max-upload-size {
392
- display: block;
393
- margin: 1em 0;
394
- }
395
-
396
- .envira-gallery-media-frame .envira-gallery-library-toolbar {
397
- top: 5px;
398
- }
399
-
400
- .envira-gallery-media-frame .attachment.envira-gallery-in-gallery {
401
- box-shadow: inset 0 0 0 3px #fff, inset 0 0 0 7px #519e0c;
402
- }
403
-
404
- .envira-gallery-media-frame .attachment.envira-gallery-in-gallery .attachment-preview,
405
- .envira-gallery-media-frame .attachment.envira-gallery-in-gallery .attachment-preview .check {
406
- cursor: default;
407
- }
408
-
409
- .envira-gallery-media-frame .attachment.envira-gallery-in-gallery .check {
410
- box-shadow: 0 0 0 1px #519e0c;
411
- background: #519e0c;
412
- background-image: -webkit-gradient(linear, left top, left bottom, from(#519e0c), to(#519e0c));
413
- background-image: -webkit-linear-gradient(top, #519e0c, #407f08);
414
- background-image: -moz-linear-gradient(top, #519e0c, #407f08);
415
- background-image: -o-linear-gradient(top, #519e0c, #407f08);
416
- background-image: linear-gradient(to bottom, #519e0c, #407f08);
417
- }
418
-
419
- .envira-gallery-media-frame .attachment.envira-gallery-in-gallery .check div,
420
- .envira-gallery-media-frame .attachment.envira-gallery-in-gallery .check:hover div {
421
- background-position: -21px 0;
422
- }
423
-
424
- .envira-gallery-meta-wrap .envira-gallery-meta-sidebar {
425
- overflow: auto;
426
- position: relative;
427
- }
428
-
429
- .envira-gallery-media-frame .media-sidebar h3 {
430
- margin: 1.1em 0 1em;
431
- }
432
-
433
- .envira-gallery-media-frame .media-sidebar p {
434
- margin: 0 0 1.5em;
435
- }
436
-
437
- .envira-gallery-meta {
438
- overflow: auto;
439
- padding: 0 16px;
440
- }
441
-
442
- .media-frame.envira-gallery-media-frame input:focus,
443
- .media-frame.envira-gallery-media-frame textarea:focus,
444
- .media-frame.envira-gallery-media-frame select:focus {
445
- border-color: #aaa;
446
- }
447
-
448
- .envira-gallery-meta-wrap .envira-gallery-meta.attachments {
449
- top: 0;
450
- }
451
-
452
- .envira-gallery-meta.attachments .attachment {
453
- width: 200px;
454
- height: 200px;
455
- border: none !important;
456
- }
457
-
458
- .envira-gallery-meta.attachments .attachment.selected {
459
- width: 200px;
460
- height: 200px;
461
- }
462
-
463
- .envira-gallery-meta.attachments .attachment .attachment-preview {
464
- width: 100%;
465
- height: 100%;
466
- border: none !important;
467
- }
468
-
469
- .envira-gallery-meta.attachments .attachment .attachment-preview:before {
470
- padding-top: 0;
471
- border: none !important;
472
- }
473
-
474
- .envira-gallery-meta.attachments .attachment .attachment-preview .thumbnail {
475
- display: table;
476
- position: relative;
477
- top: auto;
478
- right: auto;
479
- bottom: auto;
480
- left: auto;
481
- border: none !important;
482
- }
483
-
484
- .envira-gallery-meta.attachments .attachment .attachment-preview .thumbnail:after {
485
- box-shadow: none;
486
- -webkit-box-shadow: none;
487
- -moz-box-shadow: none;
488
- }
489
-
490
- .envira-gallery-meta.attachments .attachment .attachment-preview .thumbnail .inside {
491
- display: table-cell;
492
- width: 200px;
493
- height: 200px;
494
- text-align: center;
495
- vertical-align: middle;
496
- border: none !important;
497
- }
498
-
499
- .envira-gallery-ui-content {
500
- top: 16px !important;
501
- }
502
-
503
- .envira-gallery-meta-wrap .form-table {
504
- margin: 0;
505
- }
506
-
507
- .envira-gallery-meta-wrap .form-table input[type=text],
508
- .envira-gallery-meta-wrap .form-table textarea {
509
- width: 100%;
510
- }
511
-
512
- #envira-gallery .envira-gallery-import-form {
513
- margin-bottom: 20px;
514
- padding-bottom: 20px;
515
- border-bottom: 1px solid #ddd;
516
- }
517
-
518
- #envira-gallery .envira-unit {
519
- font-style: normal;
520
- font-weight: 700;
521
- font-size: 13px;
522
- }
523
-
524
- #envira-gallery textarea {
525
- width: 100%;
526
- }
527
-
528
- .envira-alert {
529
- padding: 15px;
530
- margin-bottom: 20px;
531
- border: 1px solid #faebcc;
532
- border-radius: 4px;
533
- background-color: #fcf8e3;
534
- color: #8a6d3b;
535
- }
536
-
537
- /* ==========================================================================
538
- Plupload Styles
539
- ========================================================================== */
540
-
541
- #envira-gallery-plupload-upload-ui {
542
- position: relative;
543
- }
544
-
545
- #envira-gallery-drag-drop-area {
546
- border: 4px dashed #bbb;
547
- height: 200px;
548
- }
549
-
550
- #envira-gallery-plupload-upload-ui.drag-over #envira-gallery-drag-drop-area {
551
- border-color: #83b4d8;
552
- }
553
-
554
- #envira-gallery .envira-gallery-progress-bar {
555
- display: none;
556
- width: 100%;
557
- position: relative;
558
- height: 10px;
559
- width: 100%;
560
- margin: 10px auto;
561
- border-radius: 10px;
562
- background: #dfdfdf;
563
- background: rgba(0,0,0,.1);
564
- }
565
-
566
- #envira-gallery .envira-gallery-progress-bar div {
567
- height: 10px;
568
- min-width: 20px;
569
- width: 0;
570
- background: #aaa;
571
- background: rgba(0,0,0,.2);
572
- border-radius: 10px;
573
- -webkit-transition: width 300ms;
574
- -moz-transition: width 300ms;
575
- -ms-transition: width 300ms;
576
- -o-transition: width 300ms;
577
- transition: width 300ms;
578
- }
579
-
580
- #envira-gallery .upload-flash-bypass {
581
- display: none;
582
- }
583
-
584
- #envira-gallery .max-upload-size {
585
- display: block;
586
- margin: 10px 0;
587
- }
588
-
589
- /* ==========================================================================
590
- Modal
591
- 4.3: Close links are replaced by buttons, which break styling on our close links - so we style our links in 4.3+
592
- ========================================================================== */
593
- body.branch-4-3,
594
- body.branch-4-4,
595
- body.branch-4-5 {
596
- div.media-modal {
597
- /**
598
- * Close Button
599
- */
600
- a.media-modal-close {
601
- text-align: center;
602
- text-decoration: none;
603
- display: inline-block;
604
-
605
- span {
606
- display: inline-block;
607
- margin-top: 17px;
608
- }
609
- }
610
- }
611
- }
612
-
613
- /* ==========================================================================
614
- Attachment Editor
615
- ========================================================================== */
616
-
617
- .envira-gallery-meta-container {
618
- /**
619
- * Navigation Buttons
620
- */
621
- button.right {
622
- border-right: 1px solid #ddd !important;
623
- }
624
-
625
- /**
626
- * Settings Labels + Fields
627
- * - left align labels
628
- * - increase width of text inputs
629
- * - force inputs to drop to new line below ~ 960px viewport
630
- */
631
- .setting {
632
- /**
633
- * Label
634
- */
635
- span.name {
636
- min-width: 20%;
637
- text-align: left;
638
- }
639
-
640
- /**
641
- * Inputs
642
- */
643
- input[type=text] {
644
- width: 75%;
645
- }
646
- textarea {
647
- height: 150px;
648
- }
649
-
650
- /**
651
- * Visual Editor
652
- */
653
- .wp-editor-wrap {
654
- float: right;
655
- width: 75%;
656
- }
657
- }
658
-
659
- /**
660
- * Links
661
- */
662
- #wp-link {
663
- float: left;
664
- width: 100%;
665
-
666
- #search-panel {
667
- display: block;
668
- float: left;
669
- width: 100%;
670
-
671
- /**
672
- * Search Box
673
- */
674
- .link-search-wrapper {
675
- float: left;
676
- width: 100%;
677
- margin: 0;
678
-
679
- label {
680
- display: block;
681
- float: left;
682
- width: 100%;
683
- margin: 1px 0;
684
-
685
- span.name {
686
- display: none;
687
- }
688
-
689
- input {
690
- float: right;
691
- width: 75%;
692
- max-width: 75%;
693
- }
694
- }
695
- }
696
-
697
- /**
698
- * Search Results
699
- */
700
- #search-results {
701
- position: relative;
702
- float: right;
703
- width: 75%;
704
- max-width: 75%;
705
- margin: -2px 0 0 0;
706
- display: block;
707
- top: 0;
708
- left: 0;
709
- right: 0;
710
- bottom: 0;
711
- border: none;
712
- border-left: 1px solid #dfdfdf;
713
- border-bottom: 1px solid #dfdfdf;
714
- border-right: 1px solid #dfdfdf;
715
- }
716
-
717
- /**
718
- * Most Recent Results
719
- */
720
- #most-recent-results {
721
- display: none;
722
- }
723
- }
724
- }
725
-
726
- /**
727
- * Actions
728
- */
729
- div.actions {
730
- a.button {
731
- display: inline-block;
732
- }
733
- }
734
- }
735
-
736
-
737
- /**
738
- * Responsive Media Queries
739
- */
740
- @media only screen and (max-width: 959px) {
741
- .envira-gallery-meta-container {
742
- .setting {
743
- /**
744
- * Label
745
- */
746
- span.name {
747
- width: 100%;
748
- max-width: 100%;
749
- min-width: 100%;
750
- }
751
-
752
- /**
753
- * Inputs
754
- */
755
- input[type=text] {
756
- width: 100%;
757
- }
758
- input[type=checkbox] {
759
- clear: both;
760
- }
761
-
762
- /**
763
- * Visual Editor
764
- */
765
- .wp-editor-wrap {
766
- float: left;
767
- width: 100%;
768
- }
769
- }
770
- }
771
- }
772
-
773
- /* ==========================================================================
774
- Retina Styles
775
- ========================================================================== */
776
-
777
- @media
778
- only screen and (-webkit-min-device-pixel-ratio: 2),
779
- only screen and ( min--moz-device-pixel-ratio: 2),
780
- only screen and ( -o-min-device-pixel-ratio: 2/1),
781
- only screen and ( min-device-pixel-ratio: 2),
782
- only screen and ( min-resolution: 192dpi),
783
- only screen and ( min-resolution: 2dppx) {
784
-
785
- #envira-gallery .envira-meta-icon {
786
- background-image: url(images/meta-2x.png);
787
- background-size: 19px 16px;
788
- }
789
-
790
- #envira-gallery .envira-helper-active .envira-meta-icon {
791
- background-image: url(images/meta-active-2x.png);
792
- background-size: 19px 16px;
793
- }
794
-
795
- #envira-gallery #envira-gallery-output li .envira-gallery-remove-image {
796
- background-image: url(images/delete-2x.png);
797
- background-size: 16px 16px;
798
- }
799
-
800
- #envira-gallery #envira-gallery-output li .envira-gallery-modify-image {
801
- background-image: url(images/modify-2x.png);
802
- background-size: 16px 16px;
803
- }
804
-
805
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
config.codekit DELETED
@@ -1,1307 +0,0 @@
1
- {
2
- "CodeKitInfo": "This is a CodeKit 2.x project configuration file. It is designed to sync project settings across multiple machines. MODIFYING THE CONTENTS OF THIS FILE IS A POOR LIFE DECISION. If you do so, you will likely cause CodeKit to crash. This file is not useful unless accompanied by the project that created it in CodeKit 2. This file is not backwards-compatible with CodeKit 1.x. For more information, see: http:\/\/incident57.com\/codekit",
3
- "creatorBuild": "19115",
4
- "files": {
5
- "\/assets\/css\/attachment-details-modal-support.css": {
6
- "fileType": 16,
7
- "ignore": 1,
8
- "ignoreWasSetByUser": 0,
9
- "inputAbbreviatedPath": "\/assets\/css\/attachment-details-modal-support.css",
10
- "outputAbbreviatedPath": "No Output Path",
11
- "outputPathIsOutsideProject": 0,
12
- "outputPathIsSetByUser": 0
13
- },
14
- "\/assets\/css\/envira.css": {
15
- "fileType": 16,
16
- "ignore": 1,
17
- "ignoreWasSetByUser": 0,
18
- "inputAbbreviatedPath": "\/assets\/css\/envira.css",
19
- "outputAbbreviatedPath": "No Output Path",
20
- "outputPathIsOutsideProject": 0,
21
- "outputPathIsSetByUser": 0
22
- },
23
- "\/assets\/css\/images\/delete-2x.png": {
24
- "fileType": 32768,
25
- "ignore": 0,
26
- "ignoreWasSetByUser": 0,
27
- "initialSize": 1618,
28
- "inputAbbreviatedPath": "\/assets\/css\/images\/delete-2x.png",
29
- "outputAbbreviatedPath": "\/assets\/css\/images\/delete-2x.png",
30
- "outputPathIsOutsideProject": 0,
31
- "outputPathIsSetByUser": 0,
32
- "processed": 1
33
- },
34
- "\/assets\/css\/images\/delete.png": {
35
- "fileType": 32768,
36
- "ignore": 0,
37
- "ignoreWasSetByUser": 0,
38
- "initialSize": 1222,
39
- "inputAbbreviatedPath": "\/assets\/css\/images\/delete.png",
40
- "outputAbbreviatedPath": "\/assets\/css\/images\/delete.png",
41
- "outputPathIsOutsideProject": 0,
42
- "outputPathIsSetByUser": 0,
43
- "processed": 1
44
- },
45
- "\/assets\/css\/images\/envirabox_buttons.png": {
46
- "fileType": 32768,
47
- "ignore": 0,
48
- "ignoreWasSetByUser": 0,
49
- "initialSize": 1080,
50
- "inputAbbreviatedPath": "\/assets\/css\/images\/envirabox_buttons.png",
51
- "outputAbbreviatedPath": "\/assets\/css\/images\/envirabox_buttons.png",
52
- "outputPathIsOutsideProject": 0,
53
- "outputPathIsSetByUser": 0,
54
- "processed": 1
55
- },
56
- "\/assets\/css\/images\/envirabox_overlay.png": {
57
- "fileType": 32768,
58
- "ignore": 0,
59
- "ignoreWasSetByUser": 0,
60
- "initialSize": 1003,
61
- "inputAbbreviatedPath": "\/assets\/css\/images\/envirabox_overlay.png",
62
- "outputAbbreviatedPath": "\/assets\/css\/images\/envirabox_overlay.png",
63
- "outputPathIsOutsideProject": 0,
64
- "outputPathIsSetByUser": 0,
65
- "processed": 1
66
- },
67
- "\/assets\/css\/images\/envirabox_sprite-2x.png": {
68
- "fileType": 32768,
69
- "ignore": 0,
70
- "ignoreWasSetByUser": 0,
71
- "initialSize": 6553,
72
- "inputAbbreviatedPath": "\/assets\/css\/images\/envirabox_sprite-2x.png",
73
- "outputAbbreviatedPath": "\/assets\/css\/images\/envirabox_sprite-2x.png",
74
- "outputPathIsOutsideProject": 0,
75
- "outputPathIsSetByUser": 0,
76
- "processed": 1
77
- },
78
- "\/assets\/css\/images\/envirabox_sprite.png": {
79
- "fileType": 32768,
80
- "ignore": 0,
81
- "ignoreWasSetByUser": 0,
82
- "initialSize": 1362,
83
- "inputAbbreviatedPath": "\/assets\/css\/images\/envirabox_sprite.png",
84
- "outputAbbreviatedPath": "\/assets\/css\/images\/envirabox_sprite.png",
85
- "outputPathIsOutsideProject": 0,
86
- "outputPathIsSetByUser": 0,
87
- "processed": 1
88
- },
89
- "\/assets\/css\/images\/menu-icon-2x.png": {
90
- "fileType": 32768,
91
- "ignore": 0,
92
- "ignoreWasSetByUser": 0,
93
- "initialSize": 1427,
94
- "inputAbbreviatedPath": "\/assets\/css\/images\/menu-icon-2x.png",
95
- "outputAbbreviatedPath": "\/assets\/css\/images\/menu-icon-2x.png",
96
- "outputPathIsOutsideProject": 0,
97
- "outputPathIsSetByUser": 0,
98
- "processed": 1
99
- },
100
- "\/assets\/css\/images\/menu-icon.png": {
101
- "fileType": 32768,
102
- "ignore": 0,
103
- "ignoreWasSetByUser": 0,
104
- "initialSize": 1158,
105
- "inputAbbreviatedPath": "\/assets\/css\/images\/menu-icon.png",
106
- "outputAbbreviatedPath": "\/assets\/css\/images\/menu-icon.png",
107
- "outputPathIsOutsideProject": 0,
108
- "outputPathIsSetByUser": 0,
109
- "processed": 1
110
- },
111
- "\/assets\/css\/images\/meta-2x.png": {
112
- "fileType": 32768,
113
- "ignore": 0,
114
- "ignoreWasSetByUser": 0,
115
- "initialSize": 1608,
116
- "inputAbbreviatedPath": "\/assets\/css\/images\/meta-2x.png",
117
- "outputAbbreviatedPath": "\/assets\/css\/images\/meta-2x.png",
118
- "outputPathIsOutsideProject": 0,
119
- "outputPathIsSetByUser": 0,
120
- "processed": 1
121
- },
122
- "\/assets\/css\/images\/meta-active-2x.png": {
123
- "fileType": 32768,
124
- "ignore": 0,
125
- "ignoreWasSetByUser": 0,
126
- "initialSize": 1521,
127
- "inputAbbreviatedPath": "\/assets\/css\/images\/meta-active-2x.png",
128
- "outputAbbreviatedPath": "\/assets\/css\/images\/meta-active-2x.png",
129
- "outputPathIsOutsideProject": 0,
130
- "outputPathIsSetByUser": 0,
131
- "processed": 1
132
- },
133
- "\/assets\/css\/images\/meta-active.png": {
134
- "fileType": 32768,
135
- "ignore": 0,
136
- "ignoreWasSetByUser": 0,
137
- "initialSize": 1219,
138
- "inputAbbreviatedPath": "\/assets\/css\/images\/meta-active.png",
139
- "outputAbbreviatedPath": "\/assets\/css\/images\/meta-active.png",
140
- "outputPathIsOutsideProject": 0,
141
- "outputPathIsSetByUser": 0,
142
- "processed": 1
143
- },
144
- "\/assets\/css\/images\/meta.png": {
145
- "fileType": 32768,
146
- "ignore": 0,
147
- "ignoreWasSetByUser": 0,
148
- "initialSize": 1256,
149
- "inputAbbreviatedPath": "\/assets\/css\/images\/meta.png",
150
- "outputAbbreviatedPath": "\/assets\/css\/images\/meta.png",
151
- "outputPathIsOutsideProject": 0,
152
- "outputPathIsSetByUser": 0,
153
- "processed": 1
154
- },
155
- "\/assets\/css\/images\/modify-2x.png": {
156
- "fileType": 32768,
157
- "ignore": 0,
158
- "ignoreWasSetByUser": 0,
159
- "initialSize": 1566,
160
- "inputAbbreviatedPath": "\/assets\/css\/images\/modify-2x.png",
161
- "outputAbbreviatedPath": "\/assets\/css\/images\/modify-2x.png",
162
- "outputPathIsOutsideProject": 0,
163
- "outputPathIsSetByUser": 0,
164
- "processed": 1
165
- },
166
- "\/assets\/css\/images\/modify.png": {
167
- "fileType": 32768,
168
- "ignore": 0,
169
- "ignoreWasSetByUser": 0,
170
- "initialSize": 1263,
171
- "inputAbbreviatedPath": "\/assets\/css\/images\/modify.png",
172
- "outputAbbreviatedPath": "\/assets\/css\/images\/modify.png",
173
- "outputPathIsOutsideProject": 0,
174
- "outputPathIsSetByUser": 0,
175
- "processed": 1
176
- },
177
- "\/assets\/css\/metabox.css": {
178
- "fileType": 16,
179
- "ignore": 1,
180
- "ignoreWasSetByUser": 0,
181
- "inputAbbreviatedPath": "\/assets\/css\/metabox.css",
182
- "outputAbbreviatedPath": "No Output Path",
183
- "outputPathIsOutsideProject": 0,
184
- "outputPathIsSetByUser": 0
185
- },
186
- "\/assets\/js\/editor.js": {
187
- "fileType": 64,
188
- "ignore": 0,
189
- "ignoreWasSetByUser": 0,
190
- "inputAbbreviatedPath": "\/assets\/js\/editor.js",
191
- "outputAbbreviatedPath": "\/assets\/js\/min\/editor-min.js",
192
- "outputPathIsOutsideProject": 0,
193
- "outputPathIsSetByUser": 0,
194
- "outputStyle": 1,
195
- "syntaxCheckerStyle": 1
196
- },
197
- "\/assets\/js\/envira.js": {
198
- "fileType": 64,
199
- "ignore": 0,
200
- "ignoreWasSetByUser": 0,
201
- "inputAbbreviatedPath": "\/assets\/js\/envira.js",
202
- "outputAbbreviatedPath": "\/assets\/js\/min\/envira-min.js",
203
- "outputPathIsOutsideProject": 0,
204
- "outputPathIsSetByUser": 0,
205
- "outputStyle": 1,
206
- "syntaxCheckerStyle": 0
207
- },
208
- "\/assets\/js\/lib\/fancybox.js": {
209
- "fileType": 64,
210
- "ignore": 1,
211
- "ignoreWasSetByUser": 0,
212
- "inputAbbreviatedPath": "\/assets\/js\/lib\/fancybox.js",
213
- "outputAbbreviatedPath": "\/assets\/js\/lib\/min\/fancybox-min.js",
214
- "outputPathIsOutsideProject": 0,
215
- "outputPathIsSetByUser": 0,
216
- "outputStyle": 1,
217
- "syntaxCheckerStyle": 1
218
- },
219
- "\/assets\/js\/lib\/isotope.js": {
220
- "fileType": 64,
221
- "ignore": 1,
222
- "ignoreWasSetByUser": 0,
223
- "inputAbbreviatedPath": "\/assets\/js\/lib\/isotope.js",
224
- "outputAbbreviatedPath": "\/assets\/js\/lib\/min\/isotope-min.js",
225
- "outputPathIsOutsideProject": 0,
226
- "outputPathIsSetByUser": 0,
227
- "outputStyle": 1,
228
- "syntaxCheckerStyle": 1
229
- },
230
- "\/assets\/js\/lib\/mousewheel.js": {
231
- "fileType": 64,
232
- "ignore": 1,
233
- "ignoreWasSetByUser": 0,
234
- "inputAbbreviatedPath": "\/assets\/js\/lib\/mousewheel.js",
235
- "outputAbbreviatedPath": "\/assets\/js\/lib\/min\/mousewheel-min.js",
236
- "outputPathIsOutsideProject": 0,
237
- "outputPathIsSetByUser": 0,
238
- "outputStyle": 1,
239
- "syntaxCheckerStyle": 1
240
- },
241
- "\/assets\/js\/lib\/touchsupport.js": {
242
- "fileType": 64,
243
- "ignore": 1,
244
- "ignoreWasSetByUser": 0,
245
- "inputAbbreviatedPath": "\/assets\/js\/lib\/touchsupport.js",
246
- "outputAbbreviatedPath": "\/assets\/js\/lib\/min\/touchsupport-min.js",
247
- "outputPathIsOutsideProject": 0,
248
- "outputPathIsSetByUser": 0,
249
- "outputStyle": 1,
250
- "syntaxCheckerStyle": 1
251
- },
252
- "\/assets\/js\/metabox.js": {
253
- "fileType": 64,
254
- "ignore": 0,
255
- "ignoreWasSetByUser": 0,
256
- "inputAbbreviatedPath": "\/assets\/js\/metabox.js",
257
- "outputAbbreviatedPath": "\/assets\/js\/min\/metabox-min.js",
258
- "outputPathIsOutsideProject": 0,
259
- "outputPathIsSetByUser": 0,
260
- "outputStyle": 1,
261
- "syntaxCheckerStyle": 0
262
- },
263
- "\/assets\/js\/min\/editor-min.js": {
264
- "fileType": 64,
265
- "ignore": 1,
266
- "ignoreWasSetByUser": 0,
267
- "inputAbbreviatedPath": "\/assets\/js\/min\/editor-min.js",
268
- "outputAbbreviatedPath": "\/assets\/js\/min\/min\/editor-min-min.js",
269
- "outputPathIsOutsideProject": 0,
270
- "outputPathIsSetByUser": 0,
271
- "outputStyle": 1,
272
- "syntaxCheckerStyle": 1
273
- },
274
- "\/assets\/js\/min\/envira-min.js": {
275
- "fileType": 64,
276
- "ignore": 1,
277
- "ignoreWasSetByUser": 0,
278
- "inputAbbreviatedPath": "\/assets\/js\/min\/envira-min.js",
279
- "outputAbbreviatedPath": "\/assets\/js\/min\/min\/envira-min-min.js",
280
- "outputPathIsOutsideProject": 0,
281
- "outputPathIsSetByUser": 0,
282
- "outputStyle": 1,
283
- "syntaxCheckerStyle": 1
284
- },
285
- "\/assets\/js\/min\/metabox-min.js": {
286
- "fileType": 64,
287
- "ignore": 1,
288
- "ignoreWasSetByUser": 0,
289
- "inputAbbreviatedPath": "\/assets\/js\/min\/metabox-min.js",
290
- "outputAbbreviatedPath": "\/assets\/js\/min\/min\/metabox-min-min.js",
291
- "outputPathIsOutsideProject": 0,
292
- "outputPathIsSetByUser": 0,
293
- "outputStyle": 1,
294
- "syntaxCheckerStyle": 1
295
- },
296
- "\/assets\/scss\/attachment-details-modal-support.scss": {
297
- "createSourceMap": 0,
298
- "debugStyle": 0,
299
- "decimalPrecision": 10,
300
- "fileType": 4,
301
- "ignore": 0,
302
- "ignoreWasSetByUser": 0,
303
- "inputAbbreviatedPath": "\/assets\/scss\/attachment-details-modal-support.scss",
304
- "outputAbbreviatedPath": "\/assets\/css\/attachment-details-modal-support.css",
305
- "outputPathIsOutsideProject": 0,
306
- "outputPathIsSetByUser": 0,
307
- "outputStyle": 3,
308
- "shouldRunAutoprefixer": 0,
309
- "shouldRunBless": 0,
310
- "useLibsass": 0
311
- },
312
- "\/assets\/scss\/envira.scss": {
313
- "createSourceMap": 0,
314
- "debugStyle": 0,
315
- "decimalPrecision": 10,
316
- "fileType": 4,
317
- "ignore": 0,
318
- "ignoreWasSetByUser": 0,
319
- "inputAbbreviatedPath": "\/assets\/scss\/envira.scss",
320
- "outputAbbreviatedPath": "\/assets\/css\/envira.css",
321
- "outputPathIsOutsideProject": 0,
322
- "outputPathIsSetByUser": 0,
323
- "outputStyle": 3,
324
- "shouldRunAutoprefixer": 0,
325
- "shouldRunBless": 0,
326
- "useLibsass": 0
327
- },
328
- "\/assets\/scss\/metabox.scss": {
329
- "createSourceMap": 0,
330
- "debugStyle": 0,
331
- "decimalPrecision": 10,
332
- "fileType": 4,
333
- "ignore": 0,
334
- "ignoreWasSetByUser": 0,
335
- "inputAbbreviatedPath": "\/assets\/scss\/metabox.scss",
336
- "outputAbbreviatedPath": "\/assets\/css\/metabox.css",
337
- "outputPathIsOutsideProject": 0,
338
- "outputPathIsSetByUser": 0,
339
- "outputStyle": 3,
340
- "shouldRunAutoprefixer": 0,
341
- "shouldRunBless": 0,
342
- "useLibsass": 0
343
- },
344
- "\/envira-gallery-lite.php": {
345
- "fileType": 8192,
346
- "ignore": 0,
347
- "ignoreWasSetByUser": 0,
348
- "inputAbbreviatedPath": "\/envira-gallery-lite.php",
349
- "outputAbbreviatedPath": "No Output Path",
350
- "outputPathIsOutsideProject": 0,
351
- "outputPathIsSetByUser": 0
352
- },
353
- "\/includes\/admin\/ajax.php": {
354
- "fileType": 8192,
355
- "ignore": 0,
356
- "ignoreWasSetByUser": 0,
357
- "inputAbbreviatedPath": "\/includes\/admin\/ajax.php",
358
- "outputAbbreviatedPath": "No Output Path",
359
- "outputPathIsOutsideProject": 0,
360
- "outputPathIsSetByUser": 0
361
- },
362
- "\/includes\/admin\/common.php": {
363
- "fileType": 8192,
364
- "ignore": 0,
365
- "ignoreWasSetByUser": 0,
366
- "inputAbbreviatedPath": "\/includes\/admin\/common.php",
367
- "outputAbbreviatedPath": "No Output Path",
368
- "outputPathIsOutsideProject": 0,
369
- "outputPathIsSetByUser": 0
370
- },
371
- "\/includes\/admin\/editor.php": {
372
- "fileType": 8192,
373
- "ignore": 0,
374
- "ignoreWasSetByUser": 0,
375
- "inputAbbreviatedPath": "\/includes\/admin\/editor.php",
376
- "outputAbbreviatedPath": "No Output Path",
377
- "outputPathIsOutsideProject": 0,
378
- "outputPathIsSetByUser": 0
379
- },
380
- "\/includes\/admin\/media.php": {
381
- "fileType": 8192,
382
- "ignore": 0,
383
- "ignoreWasSetByUser": 0,
384
- "inputAbbreviatedPath": "\/includes\/admin\/media.php",
385
- "outputAbbreviatedPath": "No Output Path",
386
- "outputPathIsOutsideProject": 0,
387
- "outputPathIsSetByUser": 0
388
- },
389
- "\/includes\/admin\/metaboxes.php": {
390
- "fileType": 8192,
391
- "ignore": 0,
392
- "ignoreWasSetByUser": 0,
393
- "inputAbbreviatedPath": "\/includes\/admin\/metaboxes.php",
394
- "outputAbbreviatedPath": "No Output Path",
395
- "outputPathIsOutsideProject": 0,
396
- "outputPathIsSetByUser": 0
397
- },
398
- "\/includes\/admin\/posttype.php": {
399
- "fileType": 8192,
400
- "ignore": 0,
401
- "ignoreWasSetByUser": 0,
402
- "inputAbbreviatedPath": "\/includes\/admin\/posttype.php",
403
- "outputAbbreviatedPath": "No Output Path",
404
- "outputPathIsOutsideProject": 0,
405
- "outputPathIsSetByUser": 0
406
- },
407
- "\/includes\/admin\/utils.php": {
408
- "fileType": 8192,
409
- "ignore": 0,
410
- "ignoreWasSetByUser": 0,
411
- "inputAbbreviatedPath": "\/includes\/admin\/utils.php",
412
- "outputAbbreviatedPath": "No Output Path",
413
- "outputPathIsOutsideProject": 0,
414
- "outputPathIsSetByUser": 0
415
- },
416
- "\/includes\/global\/common.php": {
417
- "fileType": 8192,
418
- "ignore": 0,
419
- "ignoreWasSetByUser": 0,
420
- "inputAbbreviatedPath": "\/includes\/global\/common.php",
421
- "outputAbbreviatedPath": "No Output Path",
422
- "outputPathIsOutsideProject": 0,
423
- "outputPathIsSetByUser": 0
424
- },
425
- "\/includes\/global\/posttype.php": {
426
- "fileType": 8192,
427
- "ignore": 0,
428
- "ignoreWasSetByUser": 0,
429
- "inputAbbreviatedPath": "\/includes\/global\/posttype.php",
430
- "outputAbbreviatedPath": "No Output Path",
431
- "outputPathIsOutsideProject": 0,
432
- "outputPathIsSetByUser": 0
433
- },
434
- "\/includes\/global\/shortcode.php": {
435
- "fileType": 8192,
436
- "ignore": 0,
437
- "ignoreWasSetByUser": 0,
438
- "inputAbbreviatedPath": "\/includes\/global\/shortcode.php",
439
- "outputAbbreviatedPath": "No Output Path",
440
- "outputPathIsOutsideProject": 0,
441
- "outputPathIsSetByUser": 0
442
- },
443
- "\/README.md": {
444
- "criticStyle": 0,
445
- "enableFootnotes": 0,
446
- "enableLabels": 1,
447
- "enableSmartQuotes": 1,
448
- "escapeLineBreaks": 0,
449
- "fileType": 4096,
450
- "ignore": 0,
451
- "ignoreWasSetByUser": 0,
452
- "inputAbbreviatedPath": "\/README.md",
453
- "maskEmailAddresses": 1,
454
- "outputAbbreviatedPath": "\/README.html",
455
- "outputFormat": 0,
456
- "outputPathIsOutsideProject": 0,
457
- "outputPathIsSetByUser": 0,
458
- "outputStyle": 0,
459
- "parseMetadata": 1,
460
- "processHTML": 0,
461
- "randomFootnoteNumbers": 0,
462
- "useCompatibilityMode": 0
463
- }
464
- },
465
- "hooks": [
466
- ],
467
- "lastSavedByUser": "Tim Carr",
468
- "manualImportLinks": {
469
- "\/assets\/js\/envira.js": [
470
- {
471
- "followForSyntaxChecking": 1,
472
- "linkedFileAbbreviatedPath": "\/assets\/js\/lib\/isotope.js",
473
- "position": 0,
474
- "type": 0
475
- },
476
- {
477
- "followForSyntaxChecking": 1,
478
- "linkedFileAbbreviatedPath": "\/assets\/js\/lib\/fancybox.js",
479
- "position": 1,
480
- "type": 0
481
- },
482
- {
483
- "followForSyntaxChecking": 1,
484
- "linkedFileAbbreviatedPath": "\/assets\/js\/lib\/mousewheel.js",
485
- "position": 2,
486
- "type": 0
487
- },
488
- {
489
- "followForSyntaxChecking": 1,
490
- "linkedFileAbbreviatedPath": "\/assets\/js\/lib\/touchsupport.js",
491
- "position": 3,
492
- "type": 0
493
- }
494
- ]
495
- },
496
- "projectAttributes": {
497
- "bowerAbbreviatedPath": "",
498
- "displayValue": "Envira Gallery Lite",
499
- "displayValueWasSetByUser": 1,
500
- "iconImageName": "compass_blue"
501
- },
502
- "projectSettings": {
503
- "alwaysUseExternalServer": 0,
504
- "animateCSSInjections": 1,
505
- "autoApplyPSLanguageSettingsStyle": 0,
506
- "autoprefixerBrowserString": "> 1%, last 2 versions, Firefox ESR, Opera 12.1",
507
- "autoSyncProjectSettingsFile": 1,
508
- "browserRefreshDelay": 0,
509
- "coffeeAutoOutputPathEnabled": 1,
510
- "coffeeAutoOutputPathFilenamePattern": "*.js",
511
- "coffeeAutoOutputPathRelativePath": "",
512
- "coffeeAutoOutputPathReplace1": "",
513
- "coffeeAutoOutputPathReplace2": "",
514
- "coffeeAutoOutputPathStyle": 0,
515
- "coffeeCreateSourceMap": 0,
516
- "coffeeLintFlags2": {
517
- "arrow_spacing": {
518
- "active": 0,
519
- "flagValue": -1
520
- },
521
- "camel_case_classes": {
522
- "active": 1,
523
- "flagValue": -1
524
- },
525
- "colon_assignment_spacing": {
526
- "active": 0,
527
- "flagValue": 1
528
- },
529
- "cyclomatic_complexity": {
530
- "active": 0,
531
- "flagValue": 10
532
- },
533
- "duplicate_key": {
534
- "active": 1,
535
- "flagValue": -1
536
- },
537
- "empty_constructor_needs_parens": {
538
- "active": 0,
539
- "flagValue": -1
540
- },
541
- "ensure_comprehensions": {
542
- "active": 1,
543
- "flagValue": -1
544
- },
545
- "indentation": {
546
- "active": 1,
547
- "flagValue": 2
548
- },
549
- "line_endings": {
550
- "active": 0,
551
- "flagValue": 0
552
- },
553
- "max_line_length": {
554
- "active": 0,
555
- "flagValue": 150
556
- },
557
- "missing_fat_arrows": {
558
- "active": 0,
559
- "flagValue": -1
560
- },
561
- "newlines_after_classes": {
562
- "active": 0,
563
- "flagValue": 3
564
- },
565
- "no_backticks": {
566
- "active": 1,
567
- "flagValue": -1
568
- },
569
- "no_debugger": {
570
- "active": 1,
571
- "flagValue": -1
572
- },
573
- "no_empty_functions": {
574
- "active": 0,
575
- "flagValue": -1
576
- },
577
- "no_empty_param_list": {
578
- "active": 0,
579
- "flagValue": -1
580
- },
581
- "no_implicit_braces": {
582
- "active": 1,
583
- "flagValue": -1
584
- },
585
- "no_implicit_parens": {
586
- "active": 0,
587
- "flagValue": -1
588
- },
589
- "no_interpolation_in_single_quotes": {
590
- "active": 0,
591
- "flagValue": -1
592
- },
593
- "no_nested_string_interpolation": {
594
- "active": 1,
595
- "flagValue": -1
596
- },
597
- "no_plusplus": {
598
- "active": 0,
599
- "flagValue": -1
600
- },
601
- "no_private_function_fat_arrows": {
602
- "active": 1,
603
- "flagValue": -1
604
- },
605
- "no_stand_alone_at": {
606
- "active": 1,
607
- "flagValue": -1
608
- },
609
- "no_tabs": {
610
- "active": 1,
611
- "flagValue": -1
612
- },
613
- "no_this": {
614
- "active": 0,
615
- "flagValue": -1
616
- },
617
- "no_throwing_strings": {
618
- "active": 1,
619
- "flagValue": -1
620
- },
621
- "no_trailing_semicolons": {
622
- "active": 1,
623
- "flagValue": -1
624
- },
625
- "no_trailing_whitespace": {
626
- "active": 1,
627
- "flagValue": -1
628
- },
629
- "no_unnecessary_double_quotes": {
630
- "active": 0,
631
- "flagValue": -1
632
- },
633
- "no_unnecessary_fat_arrows": {
634
- "active": 1,
635
- "flagValue": -1
636
- },
637
- "non_empty_constructor_needs_parens": {
638
- "active": 0,
639
- "flagValue": -1
640
- },
641
- "prefer_english_operator": {
642
- "active": 0,
643
- "flagValue": -1
644
- },
645
- "space_operators": {
646
- "active": 0,
647
- "flagValue": -1
648
- },
649
- "spacing_after_comma": {
650
- "active": 1,
651
- "flagValue": -1
652
- }
653
- },
654
- "coffeeMinifyOutput": 1,
655
- "coffeeOutputStyle": 0,
656
- "coffeeSyntaxCheckerStyle": 1,
657
- "externalServerAddress": "http:\/\/localhost:8888",
658
- "externalServerPreviewPathAddition": "",
659
- "genericWebpageFileExtensionsString": "html, htm, shtml, shtm, xhtml, php, jsp, asp, aspx, erb, ctp",
660
- "hamlAutoOutputPathEnabled": 1,
661
- "hamlAutoOutputPathFilenamePattern": "*.html",
662
- "hamlAutoOutputPathRelativePath": "",
663
- "hamlAutoOutputPathReplace1": "",
664
- "hamlAutoOutputPathReplace2": "",
665
- "hamlAutoOutputPathStyle": 0,
666
- "hamlEscapeHTMLCharacters": 0,
667
- "hamlNoEscapeInAttributes": 0,
668
- "hamlOutputFormat": 2,
669
- "hamlOutputStyle": 0,
670
- "hamlUseCDATA": 0,
671
- "hamlUseDoubleQuotes": 0,
672
- "hamlUseUnixNewlines": 0,
673
- "jadeAutoOutputPathEnabled": 1,
674
- "jadeAutoOutputPathFilenamePattern": "*.html",
675
- "jadeAutoOutputPathRelativePath": "",
676
- "jadeAutoOutputPathReplace1": "",
677
- "jadeAutoOutputPathReplace2": "",
678
- "jadeAutoOutputPathStyle": 0,
679
- "jadeCompileDebug": 1,
680
- "jadeOutputStyle": 0,
681
- "javascriptAutoOutputPathEnabled": 1,
682
- "javascriptAutoOutputPathFilenamePattern": "*-min.js",
683
- "javascriptAutoOutputPathRelativePath": "\/min",
684
- "javascriptAutoOutputPathReplace1": "",
685
- "javascriptAutoOutputPathReplace2": "",
686
- "javascriptAutoOutputPathStyle": 2,
687
- "javascriptCreateSourceMap": 1,
688
- "javascriptOutputStyle": 1,
689
- "javascriptSyntaxCheckerStyle": 1,
690
- "jsCheckerReservedNamesString": "",
691
- "jsHintFlags2": {
692
- "asi": {
693
- "active": 0,
694
- "flagValue": -1
695
- },
696
- "bitwise": {
697
- "active": 1,
698
- "flagValue": -1
699
- },
700
- "boss": {
701
- "active": 0,
702
- "flagValue": -1
703
- },
704
- "browser": {
705
- "active": 1,
706
- "flagValue": -1
707
- },
708
- "browserify": {
709
- "active": 0,
710
- "flagValue": -1
711
- },
712
- "camelcase": {
713
- "active": 0,
714
- "flagValue": -1
715
- },
716
- "couch": {
717
- "active": 0,
718
- "flagValue": -1
719
- },
720
- "curly": {
721
- "active": 1,
722
- "flagValue": -1
723
- },
724
- "debug": {
725
- "active": 0,
726
- "flagValue": -1
727
- },
728
- "devel": {
729
- "active": 0,
730
- "flagValue": -1
731
- },
732
- "dojo": {
733
- "active": 0,
734
- "flagValue": -1
735
- },
736
- "elision": {
737
- "active": 1,
738
- "flagValue": -1
739
- },
740
- "eqeqeq": {
741
- "active": 1,
742
- "flagValue": -1
743
- },
744
- "eqnull": {
745
- "active": 0,
746
- "flagValue": -1
747
- },
748
- "es3": {
749
- "active": 0,
750
- "flagValue": -1
751
- },
752
- "esnext": {
753
- "active": 0,
754
- "flagValue": -1
755
- },
756
- "evil": {
757
- "active": 0,
758
- "flagValue": -1
759
- },
760
- "expr": {
761
- "active": 0,
762
- "flagValue": -1
763
- },
764
- "forin": {
765
- "active": 0,
766
- "flagValue": -1
767
- },
768
- "freeze": {
769
- "active": 1,
770
- "flagValue": -1
771
- },
772
- "funcscope": {
773
- "active": 0,
774
- "flagValue": -1
775
- },
776
- "futurehostile": {
777
- "active": 0,
778
- "flagValue": -1
779
- },
780
- "globalstrict": {
781
- "active": 0,
782
- "flagValue": -1
783
- },
784
- "immed": {
785
- "active": 0,
786
- "flagValue": -1
787
- },
788
- "indent": {
789
- "active": 0,
790
- "flagValue": 4
791
- },
792
- "iterator": {
793
- "active": 0,
794
- "flagValue": -1
795
- },
796
- "jasmine": {
797
- "active": 0,
798
- "flagValue": -1
799
- },
800
- "jquery": {
801
- "active": 1,
802
- "flagValue": -1
803
- },
804
- "lastsemic": {
805
- "active": 0,
806
- "flagValue": -1
807
- },
808
- "latedef": {
809
- "active": 1,
810
- "flagValue": -1
811
- },
812
- "laxbreak": {
813
- "active": 0,
814
- "flagValue": -1
815
- },
816
- "laxcomma": {
817
- "active": 0,
818
- "flagValue": -1
819
- },
820
- "loopfunc": {
821
- "active": 0,
822
- "flagValue": -1
823
- },
824
- "maxcomplexity": {
825
- "active": 0,
826
- "flagValue": 10
827
- },
828
- "maxdepth": {
829
- "active": 0,
830
- "flagValue": 3
831
- },
832
- "maxlen": {
833
- "active": 0,
834
- "flagValue": 150
835
- },
836
- "maxparams": {
837
- "active": 0,
838
- "flagValue": 3
839
- },
840
- "maxstatements": {
841
- "active": 0,
842
- "flagValue": 4
843
- },
844
- "mocha": {
845
- "active": 0,
846
- "flagValue": -1
847
- },
848
- "mootools": {
849
- "active": 0,
850
- "flagValue": -1
851
- },
852
- "moz": {
853
- "active": 0,
854
- "flagValue": -1
855
- },
856
- "multistr": {
857
- "active": 0,
858
- "flagValue": -1
859
- },
860
- "newcap": {
861
- "active": 1,
862
- "flagValue": -1
863
- },
864
- "noarg": {
865
- "active": 1,
866
- "flagValue": -1
867
- },
868
- "nocomma": {
869
- "active": 0,
870
- "flagValue": -1
871
- },
872
- "node": {
873
- "active": 0,
874
- "flagValue": -1
875
- },
876
- "noempty": {
877
- "active": 0,
878
- "flagValue": -1
879
- },
880
- "nonbsp": {
881
- "active": 0,
882
- "flagValue": -1
883
- },
884
- "nonew": {
885
- "active": 1,
886
- "flagValue": -1
887
- },
888
- "nonstandard": {
889
- "active": 0,
890
- "flagValue": -1
891
- },
892
- "notypeof": {
893
- "active": 1,
894
- "flagValue": -1
895
- },
896
- "noyield": {
897
- "active": 0,
898
- "flagValue": -1
899
- },
900
- "onecase": {
901
- "active": 0,
902
- "flagValue": -1
903
- },
904
- "phantom": {
905
- "active": 0,
906
- "flagValue": -1
907
- },
908
- "plusplus": {
909
- "active": 0,
910
- "flagValue": -1
911
- },
912
- "proto": {
913
- "active": 0,
914
- "flagValue": -1
915
- },
916
- "prototypejs": {
917
- "active": 0,
918
- "flagValue": -1
919
- },
920
- "qunit": {
921
- "active": 0,
922
- "flagValue": -1
923
- },
924
- "regexp": {
925
- "active": 1,
926
- "flagValue": -1
927
- },
928
- "rhino": {
929
- "active": 0,
930
- "flagValue": -1
931
- },
932
- "scripturl": {
933
- "active": 0,
934
- "flagValue": -1
935
- },
936
- "shadow": {
937
- "active": 0,
938
- "flagValue": -1
939
- },
940
- "shelljs": {
941
- "active": 0,
942
- "flagValue": -1
943
- },
944
- "singleGroups": {
945
- "active": 0,
946
- "flagValue": -1
947
- },
948
- "strict": {
949
- "active": 0,
950
- "flagValue": -1
951
- },
952
- "sub": {
953
- "active": 0,
954
- "flagValue": -1
955
- },
956
- "supernew": {
957
- "active": 0,
958
- "flagValue": -1
959
- },
960
- "typed": {
961
- "active": 0,
962
- "flagValue": -1
963
- },
964
- "undef": {
965
- "active": 1,
966
- "flagValue": -1
967
- },
968
- "unused": {
969
- "active": 1,
970
- "flagValue": -1
971
- },
972
- "varstmt": {
973
- "active": 0,
974
- "flagValue": -1
975
- },
976
- "withstmt": {
977
- "active": 0,
978
- "flagValue": -1
979
- },
980
- "worker": {
981
- "active": 0,
982
- "flagValue": -1
983
- },
984
- "wsh": {
985
- "active": 0,
986
- "flagValue": -1
987
- },
988
- "yui": {
989
- "active": 0,
990
- "flagValue": -1
991
- }
992
- },
993
- "jsLintFlags2": {
994
- "bitwise": {
995
- "active": 0,
996
- "flagValue": -1
997
- },
998
- "browser": {
999
- "active": 1,
1000
- "flagValue": -1
1001
- },
1002
- "couch": {
1003
- "active": 0,
1004
- "flagValue": -1
1005
- },
1006
- "devel": {
1007
- "active": 0,
1008
- "flagValue": -1
1009
- },
1010
- "es6": {
1011
- "active": 0,
1012
- "flagValue": -1
1013
- },
1014
- "eval": {
1015
- "active": 0,
1016
- "flagValue": -1
1017
- },
1018
- "for": {
1019
- "active": 0,
1020
- "flagValue": -1
1021
- },
1022
- "maxlen": {
1023
- "active": 0,
1024
- "flagValue": 150
1025
- },
1026
- "node": {
1027
- "active": 0,
1028
- "flagValue": -1
1029
- },
1030
- "this": {
1031
- "active": 0,
1032
- "flagValue": -1
1033
- },
1034
- "white": {
1035
- "active": 0,
1036
- "flagValue": -1
1037
- }
1038
- },
1039
- "jsonAutoOutputPathEnabled": 0,
1040
- "jsonAutoOutputPathFilenamePattern": "*-min.json",
1041
- "jsonAutoOutputPathRelativePath": "",
1042
- "jsonAutoOutputPathReplace1": "",
1043
- "jsonAutoOutputPathReplace2": "",
1044
- "jsonAutoOutputPathStyle": 0,
1045
- "jsonOrderOutput": 0,
1046
- "jsonOutputStyle": 1,
1047
- "kitAutoOutputPathEnabled": 1,
1048
- "kitAutoOutputPathFilenamePattern": "*.html",
1049
- "kitAutoOutputPathRelativePath": "",
1050
- "kitAutoOutputPathReplace1": "",
1051
- "kitAutoOutputPathReplace2": "",
1052
- "kitAutoOutputPathStyle": 0,
1053
- "lessAllowInsecureImports": 0,
1054
- "lessAutoOutputPathEnabled": 1,
1055
- "lessAutoOutputPathFilenamePattern": "*.css",
1056
- "lessAutoOutputPathRelativePath": "..\/css",
1057
- "lessAutoOutputPathReplace1": "less",
1058
- "lessAutoOutputPathReplace2": "css",
1059
- "lessAutoOutputPathStyle": 2,
1060
- "lessCreateSourceMap": 0,
1061
- "lessDisableJavascript": 0,
1062
- "lessIeCompatibility": 1,
1063
- "lessOutputStyle": 0,
1064
- "lessRelativeURLS": 0,
1065
- "lessStrictImports": 0,
1066
- "lessStrictMath": 0,
1067
- "lessStrictUnits": 0,
1068
- "markdownAutoOutputPathEnabled": 1,
1069
- "markdownAutoOutputPathFilenamePattern": "*.html",
1070
- "markdownAutoOutputPathRelativePath": "",
1071
- "markdownAutoOutputPathReplace1": "",
1072
- "markdownAutoOutputPathReplace2": "",
1073
- "markdownAutoOutputPathStyle": 0,
1074
- "markdownCriticStyle": 0,
1075
- "markdownEnableFootnotes": 0,
1076
- "markdownEnableLabels": 1,
1077
- "markdownEnableSmartQuotes": 1,
1078
- "markdownEscapeLineBreaks": 0,
1079
- "markdownMaskEmailAddresses": 1,
1080
- "markdownOutputFormat": 0,
1081
- "markdownOutputStyle": 0,
1082
- "markdownParseMetadata": 1,
1083
- "markdownProcessHTML": 0,
1084
- "markdownRandomFootnoteNumbers": 0,
1085
- "markdownUseCompatibilityMode": 0,
1086
- "reloadFileURLs": 0,
1087
- "sassAutoOutputPathEnabled": 1,
1088
- "sassAutoOutputPathFilenamePattern": "*.css",
1089
- "sassAutoOutputPathRelativePath": "..\/css",
1090
- "sassAutoOutputPathReplace1": "sass",
1091
- "sassAutoOutputPathReplace2": "css",
1092
- "sassAutoOutputPathStyle": 2,
1093
- "sassCreateSourceMap": 0,
1094
- "sassDebugStyle": 0,
1095
- "sassDecimalPrecision": 10,
1096
- "sassOutputStyle": 0,
1097
- "sassUseLibsass": 0,
1098
- "shouldRunAutoprefixer": 0,
1099
- "shouldRunBless": 0,
1100
- "skippedItemsString": ".svn, .git, .hg, log, _logs, _cache, cache, logs, node_modules",
1101
- "slimAutoOutputPathEnabled": 1,
1102
- "slimAutoOutputPathFilenamePattern": "*.html",
1103
- "slimAutoOutputPathRelativePath": "",
1104
- "slimAutoOutputPathReplace1": "",
1105
- "slimAutoOutputPathReplace2": "",
1106
- "slimAutoOutputPathStyle": 0,
1107
- "slimCompileOnly": 0,
1108
- "slimLogicless": 0,
1109
- "slimOutputFormat": 0,
1110
- "slimOutputStyle": 1,
1111
- "slimRailsCompatible": 0,
1112
- "stylusAutoOutputPathEnabled": 1,
1113
- "stylusAutoOutputPathFilenamePattern": "*.css",
1114
- "stylusAutoOutputPathRelativePath": "..\/css",
1115
- "stylusAutoOutputPathReplace1": "stylus",
1116
- "stylusAutoOutputPathReplace2": "css",
1117
- "stylusAutoOutputPathStyle": 2,
1118
- "stylusCreateSourceMap": 0,
1119
- "stylusDebugStyle": 0,
1120
- "stylusImportCSS": 0,
1121
- "stylusOutputStyle": 0,
1122
- "stylusResolveRelativeURLS": 0,
1123
- "typescriptAutoOutputPathEnabled": 1,
1124
- "typescriptAutoOutputPathFilenamePattern": "*.js",
1125
- "typescriptAutoOutputPathRelativePath": "\/js",
1126
- "typescriptAutoOutputPathReplace1": "",
1127
- "typescriptAutoOutputPathReplace2": "",
1128
- "typescriptAutoOutputPathStyle": 2,
1129
- "typescriptCreateDeclarationFile": 0,
1130
- "typescriptCreateSourceMap": 0,
1131
- "typescriptJSXMode": 0,
1132
- "typescriptMinifyOutput": 0,
1133
- "typescriptModuleResolutionType": 0,
1134
- "typescriptModuleType": 0,
1135
- "typescriptNoImplicitAny": 0,
1136
- "typescriptPreserveConstEnums": 0,
1137
- "typescriptRemoveComments": 0,
1138
- "typescriptSuppressImplicitAnyIndexErrors": 0,
1139
- "typescriptTargetECMAVersion": 0,
1140
- "uglifyDefinesString": "",
1141
- "uglifyFlags2": {
1142
- "ascii-only": {
1143
- "active": 0,
1144
- "flagValue": -1
1145
- },
1146
- "bare-returns": {
1147
- "active": 0,
1148
- "flagValue": -1
1149
- },
1150
- "booleans": {
1151
- "active": 1,
1152
- "flagValue": -1
1153
- },
1154
- "bracketize": {
1155
- "active": 0,
1156
- "flagValue": -1
1157
- },
1158
- "cascade": {
1159
- "active": 1,
1160
- "flagValue": -1
1161
- },
1162
- "comments": {
1163
- "active": 1,
1164
- "flagValue": -1
1165
- },
1166
- "comparisons": {
1167
- "active": 1,
1168
- "flagValue": -1
1169
- },
1170
- "compress": {
1171
- "active": 1,
1172
- "flagValue": -1
1173
- },
1174
- "conditionals": {
1175
- "active": 1,
1176
- "flagValue": -1
1177
- },
1178
- "dead_code": {
1179
- "active": 0,
1180
- "flagValue": -1
1181
- },
1182
- "drop_console": {
1183
- "active": 0,
1184
- "flagValue": -1
1185
- },
1186
- "drop_debugger": {
1187
- "active": 1,
1188
- "flagValue": -1
1189
- },
1190
- "eval": {
1191
- "active": 0,
1192
- "flagValue": -1
1193
- },
1194
- "evaluate": {
1195
- "active": 1,
1196
- "flagValue": -1
1197
- },
1198
- "hoist_funs": {
1199
- "active": 1,
1200
- "flagValue": -1
1201
- },
1202
- "hoist_vars": {
1203
- "active": 0,
1204
- "flagValue": -1
1205
- },
1206
- "if_return": {
1207
- "active": 1,
1208
- "flagValue": -1
1209
- },
1210
- "indent-level": {
1211
- "active": 0,
1212
- "flagValue": 4
1213
- },
1214
- "indent-start": {
1215
- "active": 0,
1216
- "flagValue": 0
1217
- },
1218
- "inline-script": {
1219
- "active": 0,
1220
- "flagValue": -1
1221
- },
1222
- "join_vars": {
1223
- "active": 1,
1224
- "flagValue": -1
1225
- },
1226
- "keep_fargs": {
1227
- "active": 0,
1228
- "flagValue": -1
1229
- },
1230
- "keep_fnames": {
1231
- "active": 0,
1232
- "flagValue": -1
1233
- },
1234
- "loops": {
1235
- "active": 1,
1236
- "flagValue": -1
1237
- },
1238
- "mangle": {
1239
- "active": 1,
1240
- "flagValue": -1
1241
- },
1242
- "max-line-len": {
1243
- "active": 1,
1244
- "flagValue": 32000
1245
- },
1246
- "negate_iife": {
1247
- "active": 1,
1248
- "flagValue": -1
1249
- },
1250
- "properties": {
1251
- "active": 1,
1252
- "flagValue": -1
1253
- },
1254
- "pure_getters": {
1255
- "active": 0,
1256
- "flagValue": -1
1257
- },
1258
- "quote-keys": {
1259
- "active": 0,
1260
- "flagValue": -1
1261
- },
1262
- "screw-ie8": {
1263
- "active": 0,
1264
- "flagValue": -1
1265
- },
1266
- "semicolons": {
1267
- "active": 1,
1268
- "flagValue": -1
1269
- },
1270
- "sequences": {
1271
- "active": 1,
1272
- "flagValue": -1
1273
- },
1274
- "sort": {
1275
- "active": 0,
1276
- "flagValue": -1
1277
- },
1278
- "space-colon": {
1279
- "active": 1,
1280
- "flagValue": -1
1281
- },
1282
- "toplevel": {
1283
- "active": 0,
1284
- "flagValue": -1
1285
- },
1286
- "unsafe": {
1287
- "active": 0,
1288
- "flagValue": -1
1289
- },
1290
- "unused": {
1291
- "active": 0,
1292
- "flagValue": -1
1293
- },
1294
- "warnings": {
1295
- "active": 0,
1296
- "flagValue": -1
1297
- },
1298
- "width": {
1299
- "active": 1,
1300
- "flagValue": 80
1301
- }
1302
- },
1303
- "uglifyReservedNamesString": "$",
1304
- "websiteRelativeRoot": ""
1305
- },
1306
- "settingsFileVersion": "2"
1307
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
envira-gallery-lite.php CHANGED
@@ -5,8 +5,8 @@
5
  * Description: Envira Gallery is best responsive WordPress gallery plugin. This is the lite version.
6
  * Author: Thomas Griffin
7
  * Author URI: http://thomasgriffinmedia.com
8
- * Version: 1.3.5.9
9
- * Text Domain: envira-gallery-lite
10
  *
11
  * Envira Gallery is free software: you can redistribute it and/or modify
12
  * it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
24
 
25
  // Exit if accessed directly.
26
  if ( ! defined( 'ABSPATH' ) ) {
27
- exit;
28
  }
29
 
30
  /**
@@ -32,90 +32,102 @@ if ( ! defined( 'ABSPATH' ) ) {
32
  *
33
  * @since 1.0.0
34
  *
35
- * @package Envira_Gallery_Lite
36
  * @author Thomas Griffin
37
  */
38
  class Envira_Gallery_Lite {
39
 
40
- /**
41
- * Holds the class object.
42
- *
43
- * @since 1.0.0
44
- *
45
- * @var object
46
- */
47
- public static $instance;
48
-
49
- /**
50
- * Plugin version, used for cache-busting of style and script file references.
51
- *
52
- * @since 1.0.0
53
- *
54
- * @var string
55
- */
56
- public $version = '1.3.5.9';
57
-
58
- /**
59
- * Unique plugin slug identifier.
60
- *
61
- * @since 1.0.0
62
- *
63
- * @var string
64
- */
65
- public $plugin_slug = 'envira-gallery-lite';
66
-
67
- /**
68
- * Plugin file.
69
- *
70
- * @since 1.0.0
71
- *
72
- * @var string
73
- */
74
- public $file = __FILE__;
75
-
76
- /**
77
- * Primary class constructor.
78
- *
79
- * @since 1.0.0
80
- */
81
- public function __construct() {
82
-
83
- // Fire a hook before the class is setup.
84
- do_action( 'envira_gallery_pre_init' );
85
-
86
- // Load the plugin textdomain.
87
- add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ), 11 );
88
-
89
- // Load the plugin.
90
- add_action( 'init', array( $this, 'init' ), 1 );
91
-
92
- }
93
-
94
- /**
95
- * Loads the plugin textdomain for translation.
96
- *
97
- * @since 1.0.0
98
- */
99
- public function load_plugin_textdomain() {
100
-
101
- load_plugin_textdomain( 'envira-gallery-lite' );
102
-
103
- }
104
-
105
- /**
106
- * Loads the plugin into WordPress.
107
- *
108
- * @since 1.0.0
109
- */
110
- public function init() {
111
-
112
- // Do nothing if the full version of Envira Gallery is already active.
 
 
 
 
 
 
 
 
 
 
113
  if ( class_exists( 'Envira_Gallery' ) ) {
114
  return;
115
  }
116
 
117
  // Run hook once Envira has been initialized.
118
- do_action( 'envira_gallery_init' );
 
 
119
 
120
  // Load admin only components.
121
  if ( is_admin() ) {
@@ -125,220 +137,308 @@ class Envira_Gallery_Lite {
125
  // Load global components.
126
  $this->require_global();
127
 
128
- }
129
-
130
- /**
131
- * Loads all admin related files into scope.
132
- *
133
- * @since 1.0.0
134
- */
135
- public function require_admin() {
136
-
137
- require plugin_dir_path( __FILE__ ) . 'includes/admin/ajax.php';
138
- require plugin_dir_path( __FILE__ ) . 'includes/admin/common.php';
139
- require plugin_dir_path( __FILE__ ) . 'includes/admin/editor.php';
140
- require plugin_dir_path( __FILE__ ) . 'includes/admin/media.php';
141
- require plugin_dir_path( __FILE__ ) . 'includes/admin/metaboxes.php';
142
- require plugin_dir_path( __FILE__ ) . 'includes/admin/posttype.php';
143
- require plugin_dir_path( __FILE__ ) . 'includes/admin/utils.php';
144
-
145
- }
146
-
147
- /**
148
- * Loads all global files into scope.
149
- *
150
- * @since 1.0.0
151
- */
152
- public function require_global() {
153
-
154
- require plugin_dir_path( __FILE__ ) . 'includes/global/common.php';
155
- require plugin_dir_path( __FILE__ ) . 'includes/global/posttype.php';
156
- require plugin_dir_path( __FILE__ ) . 'includes/global/shortcode.php';
157
-
158
- }
159
-
160
- /**
161
- * Returns a gallery based on ID.
162
- *
163
- * @since 1.0.0
164
- *
165
- * @param int $id The gallery ID used to retrieve a gallery.
166
- * @return array|bool Array of gallery data or false if none found.
167
- */
168
- public function get_gallery( $id ) {
169
-
170
- // Attempt to return the transient first, otherwise generate the new query to retrieve the data.
171
- if ( false === ( $gallery = get_transient( '_eg_cache_' . $id ) ) ) {
172
- $gallery = $this->_get_gallery( $id );
173
- if ( $gallery ) {
174
- set_transient( '_eg_cache_' . $id, $gallery, DAY_IN_SECONDS );
175
- }
176
- }
177
-
178
- // Return the gallery data.
179
- return $gallery;
180
-
181
- }
182
-
183
- /**
184
- * Internal method that returns a gallery based on ID.
185
- *
186
- * @since 1.0.0
187
- *
188
- * @param int $id The gallery ID used to retrieve a gallery.
189
- * @return array|bool Array of gallery data or false if none found.
190
- */
191
- public function _get_gallery( $id ) {
192
-
193
- $gallery = get_post_meta( $id, '_eg_gallery_data', true );
194
- if ( empty( $gallery ) || empty( $gallery['gallery'] ) ) {
195
- return false;
196
- } else {
197
- return $gallery;
198
- }
199
-
200
- }
201
-
202
- /**
203
- * Returns a gallery based on slug.
204
- *
205
- * @since 1.0.0
206
- *
207
- * @param string $slug The gallery slug used to retrieve a gallery.
208
- * @return array|bool Array of gallery data or false if none found.
209
- */
210
- public function get_gallery_by_slug( $slug ) {
211
-
212
- // Attempt to return the transient first, otherwise generate the new query to retrieve the data.
213
- if ( false === ( $gallery = get_transient( '_eg_cache_' . $slug ) ) ) {
214
- $gallery = $this->_get_gallery_by_slug( $slug );
215
- if ( $gallery ) {
216
- set_transient( '_eg_cache_' . $slug, $gallery, DAY_IN_SECONDS );
217
- }
218
- }
219
-
220
- // Return the gallery data.
221
- return $gallery;
222
-
223
- }
224
-
225
- /**
226
- * Internal method that returns a gallery based on slug.
227
- *
228
- * @since 1.0.0
229
- *
230
- * @param string $slug The gallery slug used to retrieve a gallery.
231
- * @return array|bool Array of gallery data or false if none found.
232
- */
233
- public function _get_gallery_by_slug( $slug ) {
234
-
235
- $galleries = new WP_Query(
236
- array(
237
- 'post_type' => 'any',
238
- 'posts_per_page'=> -1,
239
- 'post_status' => 'publish',
240
- 'fields' => 'ids',
241
- 'meta_query' => array(
242
- array(
243
- 'key' => '_eg_gallery_data',
244
- 'value' => maybe_serialize( strval( $slug ) ),
245
- 'compare' => 'LIKE'
246
- )
247
- )
248
- )
249
- );
250
-
251
- if ( ! isset( $galleries->posts) || empty( $galleries->posts ) ) {
252
- return false;
253
- }
254
-
255
- return get_post_meta( $galleries->posts[0], '_eg_gallery_data', true );
256
-
257
- }
258
-
259
- /**
260
- * Returns all galleries created on the site.
261
- *
262
- * @since 1.0.0
263
- *
264
- * @return array|bool Array of gallery data or false if none found.
265
- */
266
- public function get_galleries() {
267
-
268
- // Attempt to return the transient first, otherwise generate the new query to retrieve the data.
269
- if ( false === ( $galleries = get_transient( '_eg_cache_all' ) ) ) {
270
- $galleries = $this->_get_galleries();
271
- if ( $galleries ) {
272
- set_transient( '_eg_cache_all', $galleries, DAY_IN_SECONDS );
273
- }
274
- }
275
-
276
- // Return the gallery data.
277
- return $galleries;
278
-
279
- }
280
-
281
- /**
282
- * Internal method that returns all galleries created on the site.
283
- *
284
- * @since 1.0.0
285
- *
286
- * @return array|bool Array of gallery data or false if none found.
287
- */
288
- public function _get_galleries() {
289
-
290
- $galleries = new WP_Query(
291
- array(
292
- 'post_type' => 'any',
293
- 'posts_per_page'=> -1,
294
- 'post_status' => 'publish',
295
- 'fields' => 'ids',
296
- 'meta_query' => array(
297
- array(
298
- 'key' => '_eg_gallery_data',
299
- 'compare' => 'EXISTS',
300
- )
301
- )
302
- )
303
- );
304
-
305
- if ( ! isset( $galleries->posts) || empty( $galleries->posts ) ) {
306
- return false;
307
- }
308
-
309
- // Now loop through all the galleries found and only use galleries that have images in them.
310
- $ret = array();
311
- foreach ( $galleries->posts as $id ) {
312
- $data = get_post_meta( $id, '_eg_gallery_data', true );
313
- if ( empty( $data['gallery'] ) ) {
314
- continue;
315
- }
316
-
317
- $ret[] = $data;
318
- }
319
-
320
- // Return the gallery data.
321
- return $ret;
322
-
323
- }
324
-
325
- /**
326
- * Returns the singleton instance of the class.
327
- *
328
- * @since 1.0.0
329
- *
330
- * @return object The Envira_Gallery_Lite object.
331
- */
332
- public static function get_instance() {
333
-
334
- if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Lite ) ) {
335
- self::$instance = new Envira_Gallery_Lite();
336
- }
337
-
338
- return self::$instance;
339
-
340
- }
341
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  }
343
 
344
  register_activation_hook( __FILE__, 'envira_gallery_lite_activation_hook' );
@@ -348,15 +448,16 @@ register_activation_hook( __FILE__, 'envira_gallery_lite_activation_hook' );
348
  * @since 1.0.0
349
  *
350
  * @global int $wp_version The version of WordPress for this install.
 
351
  * @param boolean $network_wide True if WPMU superadmin uses "Network Activate" action, false otherwise.
352
  */
353
  function envira_gallery_lite_activation_hook( $network_wide ) {
354
 
355
- global $wp_version;
356
- if ( version_compare( $wp_version, '3.8', '<' ) && ! defined( 'ENVIRA_FORCE_ACTIVATION' ) ) {
357
- deactivate_plugins( plugin_basename( __FILE__ ) );
358
- wp_die( sprintf( __( 'Sorry, but your version of WordPress does not meet Envira Gallery\'s required version of <strong>3.8</strong> to run properly. The plugin has been deactivated. <a href="%s">Click here to return to the Dashboard</a>.', 'envira-gallery-lite' ), get_admin_url() ) );
359
- }
360
 
361
  }
362
 
@@ -365,35 +466,35 @@ $envira_gallery_lite = Envira_Gallery_Lite::get_instance();
365
 
366
  // Conditionally load the template tag.
367
  if ( ! function_exists( 'envira_gallery' ) ) {
368
- /**
369
- * Primary template tag for outputting Envira galleries in templates.
370
- *
371
- * @since 1.0.0
372
- *
373
- * @param int $gallery_id The ID of the gallery to load.
374
- * @param string $type The type of field to query.
375
- * @param array $args Associative array of args to be passed.
376
- * @param bool $return Flag to echo or return the gallery HTML.
377
- */
378
- function envira_gallery( $id, $type = 'id', $args = array(), $return = false ) {
379
-
380
- // If we have args, build them into a shortcode format.
381
- $args_string = '';
382
- if ( ! empty( $args ) ) {
383
- foreach ( (array) $args as $key => $value ) {
384
- $args_string .= ' ' . $key . '="' . $value . '"';
385
- }
386
- }
387
-
388
- // Build the shortcode.
389
- $shortcode = ! empty( $args_string ) ? '[envira-gallery ' . $type . '="' . $id . '"' . $args_string . ']' : '[envira-gallery ' . $type . '="' . $id . '"]';
390
-
391
- // Return or echo the shortcode output.
392
- if ( $return ) {
393
- return do_shortcode( $shortcode );
394
- } else {
395
- echo do_shortcode( $shortcode );
396
- }
397
-
398
- }
399
- }
5
  * Description: Envira Gallery is best responsive WordPress gallery plugin. This is the lite version.
6
  * Author: Thomas Griffin
7
  * Author URI: http://thomasgriffinmedia.com
8
+ * Version: 1.5.0
9
+ * Text Domain: envira-gallery
10
  *
11
  * Envira Gallery is free software: you can redistribute it and/or modify
12
  * it under the terms of the GNU General Public License as published by
24
 
25
  // Exit if accessed directly.
26
  if ( ! defined( 'ABSPATH' ) ) {
27
+ exit;
28
  }
29
 
30
  /**
32
  *
33
  * @since 1.0.0
34
  *
35
+ * @package Envira_Gallery
36
  * @author Thomas Griffin
37
  */
38
  class Envira_Gallery_Lite {
39
 
40
+ /**
41
+ * Holds the class object.
42
+ *
43
+ * @since 1.0.0
44
+ *
45
+ * @var object
46
+ */
47
+ public static $instance;
48
+
49
+ /**
50
+ * Plugin version, used for cache-busting of style and script file references.
51
+ *
52
+ * @since 1.0.0
53
+ *
54
+ * @var string
55
+ */
56
+ public $version = '1.5.0';
57
+
58
+ /**
59
+ * The name of the plugin.
60
+ *
61
+ * @since 1.0.0
62
+ *
63
+ * @var string
64
+ */
65
+ public $plugin_name = 'Envira Gallery Lite';
66
+
67
+ /**
68
+ * Unique plugin slug identifier.
69
+ *
70
+ * @since 1.0.0
71
+ *
72
+ * @var string
73
+ */
74
+ public $plugin_slug = 'envira-gallery-lite';
75
+
76
+ /**
77
+ * Plugin file.
78
+ *
79
+ * @since 1.0.0
80
+ *
81
+ * @var string
82
+ */
83
+ public $file = __FILE__;
84
+
85
+ /**
86
+ * Primary class constructor.
87
+ *
88
+ * @since 1.0.0
89
+ */
90
+ public function __construct() {
91
+
92
+ // Fire a hook before the class is setup.
93
+ do_action( 'envira_gallery_pre_init' );
94
+
95
+ // Load the plugin textdomain.
96
+ add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ) );
97
+
98
+ // Load the plugin.
99
+ add_action( 'init', array( $this, 'init' ), 0 );
100
+
101
+ }
102
+
103
+ /**
104
+ * Loads the plugin textdomain for translation.
105
+ *
106
+ * @since 1.0.0
107
+ */
108
+ public function load_plugin_textdomain() {
109
+
110
+ load_plugin_textdomain( 'envira-gallery' );
111
+
112
+ }
113
+
114
+ /**
115
+ * Loads the plugin into WordPress.
116
+ *
117
+ * @since 1.0.0
118
+ */
119
+ public function init() {
120
+
121
+ // Don't load Lite if Envira Gallery is already active.
122
+ // Envira Gallery will display a notice telling the user to deactivate Lite.
123
  if ( class_exists( 'Envira_Gallery' ) ) {
124
  return;
125
  }
126
 
127
  // Run hook once Envira has been initialized.
128
+ // This hook is deliberately different from the Pro version, to prevent the entire site breaking
129
+ // if a user activates Lite with Pro Addons.
130
+ do_action( 'envira_gallery_lite_init' );
131
 
132
  // Load admin only components.
133
  if ( is_admin() ) {
137
  // Load global components.
138
  $this->require_global();
139
 
140
+ // Add hook for when Envira has loaded.
141
+ // This hook is deliberately different from the Pro version, to prevent the entire site breaking
142
+ // if a user activates Lite with Pro Addons.
143
+ do_action( 'envira_gallery_lite_loaded' );
144
+
145
+ }
146
+
147
+ /**
148
+ * Loads all admin related files into scope.
149
+ *
150
+ * @since 1.0.0
151
+ */
152
+ public function require_admin() {
153
+
154
+ require plugin_dir_path( __FILE__ ) . 'includes/admin/ajax.php';
155
+ require plugin_dir_path( __FILE__ ) . 'includes/admin/common.php';
156
+ require plugin_dir_path( __FILE__ ) . 'includes/admin/editor.php';
157
+ require plugin_dir_path( __FILE__ ) . 'includes/admin/media.php';
158
+ require plugin_dir_path( __FILE__ ) . 'includes/admin/media-view.php';
159
+ require plugin_dir_path( __FILE__ ) . 'includes/admin/metaboxes.php';
160
+ require plugin_dir_path( __FILE__ ) . 'includes/admin/notice.php';
161
+ require plugin_dir_path( __FILE__ ) . 'includes/admin/posttype.php';
162
+ require plugin_dir_path( __FILE__ ) . 'includes/admin/settings.php';
163
+ require plugin_dir_path( __FILE__ ) . 'includes/admin/table.php';
164
+
165
+ }
166
+
167
+ /**
168
+ * Loads a partial view for the Administration screen
169
+ *
170
+ * @since 1.5.0
171
+ *
172
+ * @param string $template PHP file at includes/admin/partials, excluding file extension
173
+ * @param array $data Any data to pass to the view
174
+ * @return void
175
+ */
176
+ public function load_admin_partial( $template, $data = array() ){
177
+
178
+ $dir = trailingslashit( plugin_dir_path( __FILE__ ) . 'includes/admin/partials' );
179
+
180
+ if ( file_exists( $dir . $template . '.php' ) ) {
181
+ require_once( $dir . $template . '.php' );
182
+ return true;
183
+ }
184
+
185
+ return false;
186
+
187
+ }
188
+
189
+ /**
190
+ * Loads all global files into scope.
191
+ *
192
+ * @since 1.0.0
193
+ */
194
+ public function require_global() {
195
+
196
+ require plugin_dir_path( __FILE__ ) . 'includes/global/common.php';
197
+ require plugin_dir_path( __FILE__ ) . 'includes/global/posttype.php';
198
+ require plugin_dir_path( __FILE__ ) . 'includes/global/shortcode.php';
199
+
200
+ }
201
+
202
+ /**
203
+ * Returns a gallery based on ID.
204
+ *
205
+ * @since 1.0.0
206
+ *
207
+ * @param int $id The gallery ID used to retrieve a gallery.
208
+ * @return array|bool Array of gallery data or false if none found.
209
+ */
210
+ public function get_gallery( $id ) {
211
+
212
+ // Attempt to return the transient first, otherwise generate the new query to retrieve the data.
213
+ if ( false === ( $gallery = get_transient( '_eg_cache_' . $id ) ) ) {
214
+ $gallery = $this->_get_gallery( $id );
215
+ if ( $gallery ) {
216
+ $expiration = Envira_Gallery_Common::get_instance()->get_transient_expiration_time();
217
+ set_transient( '_eg_cache_' . $id, $gallery, $expiration );
218
+ }
219
+ }
220
+
221
+ // Return the gallery data.
222
+ return $gallery;
223
+
224
+ }
225
+
226
+ /**
227
+ * Internal method that returns a gallery based on ID.
228
+ *
229
+ * @since 1.0.0
230
+ *
231
+ * @param int $id The gallery ID used to retrieve a gallery.
232
+ * @return array|bool Array of gallery data or false if none found.
233
+ */
234
+ public function _get_gallery( $id ) {
235
+
236
+ $meta = get_post_meta( $id, '_eg_gallery_data', true );
237
+
238
+ /**
239
+ * Version 1.2.1+: Check if $meta has a value - if not, we may be using a Post ID but the gallery
240
+ * has moved into the Envira CPT
241
+ */
242
+ if ( empty( $meta ) ) {
243
+ $gallery_id = get_post_meta( $id, '_eg_gallery_id', true );
244
+ $meta = get_post_meta( $gallery_id, '_eg_gallery_data', true );
245
+ }
246
+
247
+ return $meta;
248
+
249
+ }
250
+
251
+ /**
252
+ * Returns the number of images in a gallery.
253
+ *
254
+ * @since 1.2.1
255
+ *
256
+ * @param int $id The gallery ID used to retrieve a gallery.
257
+ * @return int The number of images in the gallery.
258
+ */
259
+ public function get_gallery_image_count( $id ) {
260
+
261
+ $gallery = $this->get_gallery( $id );
262
+ return isset( $gallery['gallery'] ) ? count( $gallery['gallery'] ) : 0;
263
+
264
+ }
265
+
266
+ /**
267
+ * Returns a gallery based on slug.
268
+ *
269
+ * @since 1.0.0
270
+ *
271
+ * @param string $slug The gallery slug used to retrieve a gallery.
272
+ * @return array|bool Array of gallery data or false if none found.
273
+ */
274
+ public function get_gallery_by_slug( $slug ) {
275
+
276
+ // Attempt to return the transient first, otherwise generate the new query to retrieve the data.
277
+ if ( false === ( $gallery = get_transient( '_eg_cache_' . $slug ) ) ) {
278
+ $gallery = $this->_get_gallery_by_slug( $slug );
279
+ if ( $gallery ) {
280
+ $expiration = Envira_Gallery_Common::get_instance()->get_transient_expiration_time();
281
+ set_transient( '_eg_cache_' . $slug, $gallery, $expiration );
282
+ }
283
+ }
284
+
285
+ // Return the gallery data.
286
+ return $gallery;
287
+
288
+ }
289
+
290
+ /**
291
+ * Internal method that returns a gallery based on slug.
292
+ *
293
+ * @since 1.0.0
294
+ *
295
+ * @param string $slug The gallery slug used to retrieve a gallery.
296
+ * @return array|bool Array of gallery data or false if none found.
297
+ */
298
+ public function _get_gallery_by_slug( $slug ) {
299
+
300
+ // Get Envira CPT by slug.
301
+ $galleries = new WP_Query( array(
302
+ 'post_type' => 'envira',
303
+ 'name' => $slug,
304
+ 'fields' => 'ids',
305
+ 'posts_per_page' => 1,
306
+ ) );
307
+ if ( $galleries->posts ) {
308
+ return get_post_meta( $galleries->posts[0], '_eg_gallery_data', true );
309
+ }
310
+
311
+ // If nothing found, get Envira CPT by _eg_gallery_old_slug.
312
+ // This covers Galleries migrated from Pages/Posts --> Envira CPTs.
313
+ $galleries = new WP_Query( array(
314
+ 'post_type' => 'envira',
315
+ 'no_found_rows' => true,
316
+ 'cache_results' => false,
317
+ 'fields' => 'ids',
318
+ 'meta_query' => array(
319
+ array(
320
+ 'key' => '_eg_gallery_old_slug',
321
+ 'value' => $slug,
322
+ ),
323
+ ),
324
+ 'posts_per_page' => 1,
325
+ ) );
326
+ if ( $galleries->posts ) {
327
+ return get_post_meta( $galleries->posts[0], '_eg_gallery_data', true );
328
+ }
329
+
330
+ // No galleries found.
331
+ return false;
332
+
333
+ }
334
+
335
+ /**
336
+ * Returns all galleries created on the site.
337
+ *
338
+ * @since 1.0.0
339
+ *
340
+ * @param bool $skip_empty Skip empty sliders.
341
+ * @param bool $ignore_cache Ignore Transient cache.
342
+ * @param string $search_terms Search for specified Galleries by Title
343
+ *
344
+ * @return array|bool Array of gallery data or false if none found.
345
+ */
346
+ public function get_galleries( $skip_empty = true, $ignore_cache = false, $search_terms = '' ) {
347
+
348
+ // Attempt to return the transient first, otherwise generate the new query to retrieve the data.
349
+ if ( $ignore_cache || ! empty( $search_terms ) || false === ( $galleries = get_transient( '_eg_cache_all' ) ) ) {
350
+ $galleries = $this->_get_galleries( $skip_empty, $search_terms );
351
+
352
+ // Cache the results if we're not performing a search and we have some results
353
+ if ( $galleries && empty( $search_terms ) ) {
354
+ $expiration = Envira_Gallery_Common::get_instance()->get_transient_expiration_time();
355
+ set_transient( '_eg_cache_all', $galleries, $expiration );
356
+ }
357
+ }
358
+
359
+ // Return the gallery data.
360
+ return $galleries;
361
+
362
+ }
363
+
364
+ /**
365
+ * Internal method that returns all galleries created on the site.
366
+ *
367
+ * @since 1.0.0
368
+ *
369
+ * @param bool $skip_empty Skip Empty Galleries.
370
+ * @param string $search_terms Search for specified Galleries by Title
371
+ * @return mixed Array of gallery data or false if none found.
372
+ */
373
+ public function _get_galleries( $skip_empty = true, $search_terms = '' ) {
374
+
375
+ // Build WP_Query arguments.
376
+ $args = array(
377
+ 'post_type' => 'envira',
378
+ 'post_status' => 'publish',
379
+ 'posts_per_page'=> 99,
380
+ 'no_found_rows' => true,
381
+ 'fields' => 'ids',
382
+ 'meta_query' => array(
383
+ array(
384
+ 'key' => '_eg_gallery_data',
385
+ 'compare' => 'EXISTS',
386
+ ),
387
+ ),
388
+ );
389
+
390
+ // If search terms exist, add a search parameter to the arguments.
391
+ if ( ! empty( $search_terms ) ) {
392
+ $args['s'] = $search_terms;
393
+ }
394
+
395
+ // Run WP_Query.
396
+ $galleries = new WP_Query( $args );
397
+ if ( ! isset( $galleries->posts ) || empty( $galleries->posts ) ) {
398
+ return false;
399
+ }
400
+
401
+ // Now loop through all the galleries found and only use galleries that have images in them.
402
+ $ret = array();
403
+ foreach ( $galleries->posts as $id ) {
404
+ $data = get_post_meta( $id, '_eg_gallery_data', true );
405
+
406
+ // Skip empty galleries.
407
+ if ( $skip_empty && empty( $data['gallery'] ) ) {
408
+ continue;
409
+ }
410
+
411
+ // Skip default/dynamic gallery types.
412
+ $type = Envira_Gallery_Shortcode::get_instance()->get_config( 'type', $data );
413
+ if ( 'defaults' === Envira_Gallery_Shortcode::get_instance()->get_config( 'type', $data ) || 'dynamic' === Envira_Gallery_Shortcode::get_instance()->get_config( 'type', $data ) ) {
414
+ continue;
415
+ }
416
+
417
+ // Add gallery to array of galleries.
418
+ $ret[] = $data;
419
+ }
420
+
421
+ // Return the gallery data.
422
+ return $ret;
423
+
424
+ }
425
+
426
+ /**
427
+ * Returns the singleton instance of the class.
428
+ *
429
+ * @since 1.0.0
430
+ *
431
+ * @return object The Envira_Gallery object.
432
+ */
433
+ public static function get_instance() {
434
+
435
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Lite ) ) {
436
+ self::$instance = new Envira_Gallery_Lite();
437
+ }
438
+
439
+ return self::$instance;
440
+
441
+ }
442
  }
443
 
444
  register_activation_hook( __FILE__, 'envira_gallery_lite_activation_hook' );
448
  * @since 1.0.0
449
  *
450
  * @global int $wp_version The version of WordPress for this install.
451
+ * @global object $wpdb The WordPress database object.
452
  * @param boolean $network_wide True if WPMU superadmin uses "Network Activate" action, false otherwise.
453
  */
454
  function envira_gallery_lite_activation_hook( $network_wide ) {
455
 
456
+ global $wp_version;
457
+ if ( version_compare( $wp_version, '4.0', '<' ) && ! defined( 'ENVIRA_FORCE_ACTIVATION' ) ) {
458
+ deactivate_plugins( plugin_basename( __FILE__ ) );
459
+ wp_die( sprintf( __( 'Sorry, but your version of WordPress does not meet Envira Gallery\'s required version of <strong>4.0</strong> to run properly. The plugin has been deactivated. <a href="%s">Click here to return to the Dashboard</a>.', 'envira-gallery' ), get_admin_url() ) );
460
+ }
461
 
462
  }
463
 
466
 
467
  // Conditionally load the template tag.
468
  if ( ! function_exists( 'envira_gallery' ) ) {
469
+ /**
470
+ * Primary template tag for outputting Envira galleries in templates.
471
+ *
472
+ * @since 1.0.0
473
+ *
474
+ * @param int $id The ID of the gallery to load.
475
+ * @param string $type The type of field to query.
476
+ * @param array $args Associative array of args to be passed.
477
+ * @param bool $return Flag to echo or return the gallery HTML.
478
+ */
479
+ function envira_gallery( $id, $type = 'id', $args = array(), $return = false ) {
480
+
481
+ // If we have args, build them into a shortcode format.
482
+ $args_string = '';
483
+ if ( ! empty( $args ) ) {
484
+ foreach ( (array) $args as $key => $value ) {
485
+ $args_string .= ' ' . $key . '="' . $value . '"';
486
+ }
487
+ }
488
+
489
+ // Build the shortcode.
490
+ $shortcode = ! empty( $args_string ) ? '[envira-gallery ' . $type . '="' . $id . '"' . $args_string . ']' : '[envira-gallery ' . $type . '="' . $id . '"]';
491
+
492
+ // Return or echo the shortcode output.
493
+ if ( $return ) {
494
+ return do_shortcode( $shortcode );
495
+ } else {
496
+ echo do_shortcode( $shortcode );
497
+ }
498
+
499
+ }
500
+ }
includes/admin/ajax.php CHANGED
@@ -4,17 +4,119 @@
4
  *
5
  * @since 1.0.0
6
  *
7
- * @package Envira_Gallery_Lite
8
  * @author Thomas Griffin
9
  */
10
 
11
- add_action( 'wp_ajax_envira_gallery_load_image', 'envira_gallery_lite_ajax_load_image' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  /**
13
  * Loads an image into a gallery.
14
  *
15
  * @since 1.0.0
16
  */
17
- function envira_gallery_lite_ajax_load_image() {
18
 
19
  // Run a security check first.
20
  check_ajax_referer( 'envira-gallery-load-image', 'nonce' );
@@ -53,110 +155,44 @@ function envira_gallery_lite_ajax_load_image() {
53
  }
54
 
55
  // Set data and update the meta information.
56
- $gallery_data = envira_gallery_lite_ajax_prepare_gallery_data( $gallery_data, $id );
57
  update_post_meta( $post_id, '_eg_gallery_data', $gallery_data );
58
 
59
  // Run hook before building out the item.
60
  do_action( 'envira_gallery_ajax_load_image', $id, $post_id );
61
 
62
  // Build out the individual HTML output for the gallery image that has just been uploaded.
63
- $html = Envira_Gallery_Metaboxes_Lite::get_instance()->get_gallery_item( $id, $gallery_data['gallery'][$id], $post_id );
 
 
 
64
 
65
  // Flush the gallery cache.
66
- Envira_Gallery_Common_Lite::get_instance()->flush_gallery_caches( $post_id );
67
 
68
  echo json_encode( $html );
69
  die;
70
 
71
  }
72
 
73
- add_action( 'wp_ajax_envira_gallery_load_library', 'envira_gallery_lite_ajax_load_library' );
74
- /**
75
- * Loads the Media Library images into the media modal window for selection.
76
- *
77
- * @since 1.0.0
78
- */
79
- function envira_gallery_lite_ajax_load_library() {
80
-
81
- // Run a security check first.
82
- check_ajax_referer( 'envira-gallery-load-gallery', 'nonce' );
83
-
84
- // Prepare variables.
85
- $offset = (int) $_POST['offset'];
86
- $search = trim( stripslashes( $_POST['search'] ) );
87
- $post_id = absint( $_POST['post_id'] );
88
- $html = '';
89
-
90
- // Build args
91
- $args = array(
92
- 'post_type' => 'attachment',
93
- 'post_mime_type'=> 'image',
94
- 'post_status' => 'any',
95
- 'posts_per_page'=> 20,
96
- 'offset' => $offset,
97
- );
98
-
99
- // Add search term to args if not empty
100
- if ( ! empty( $search ) ) {
101
- $args['s'] = $search;
102
- }
103
-
104
- // Grab the library contents
105
- $library = get_posts( $args );
106
- if ( $library ) {
107
- foreach ( (array) $library as $image ) {
108
- $has_gallery = get_post_meta( $image->ID, '_eg_has_gallery', true );
109
- $class = $has_gallery && in_array( $post_id, (array) $has_gallery ) ? ' selected envira-gallery-in-gallery' : '';
110
-
111
- $html .= '<li class="attachment' . $class . '" data-attachment-id="' . absint( $image->ID ) . '">';
112
- $html .= '<div class="attachment-preview landscape">';
113
- $html .= '<div class="thumbnail">';
114
- $html .= '<div class="centered">';
115
- $src = wp_get_attachment_image_src( $image->ID, 'thumbnail' );
116
- $html .= '<img src="' . esc_url( $src[0] ) . '" />';
117
- $html .= '</div>';
118
- $html .= '</div>';
119
- $html .= '<a class="check" href="#"><div class="media-modal-icon"></div></a>';
120
- $html .= '</div>';
121
- $html .= '</li>';
122
- }
123
- }
124
-
125
- echo json_encode( array( 'html' => stripslashes( $html ) ) );
126
- die;
127
-
128
- }
129
-
130
- add_action( 'wp_ajax_envira_gallery_library_search', 'envira_gallery_lite_ajax_library_search' );
131
- /**
132
- * Searches the Media Library for images matching the term specified in the search.
133
- *
134
- * @since 1.0.0
135
- * @deprecated 1.2.6
136
- */
137
- function envira_gallery_lite_ajax_library_search() {
138
-
139
- // Search is now performed by envira_gallery_lite_ajax_load_library()
140
- // Return the result of that function, so addons and custom code relying on this action
141
- // doesn't break
142
- envira_gallery_lite_ajax_load_library();
143
- die;
144
-
145
- }
146
-
147
- add_action( 'wp_ajax_envira_gallery_insert_images', 'envira_gallery_lite_ajax_insert_images' );
148
  /**
149
  * Inserts one or more images from the Media Library into a gallery.
150
  *
151
  * @since 1.0.0
152
  */
153
- function envira_gallery_lite_ajax_insert_images() {
154
 
155
  // Run a security check first.
156
  check_ajax_referer( 'envira-gallery-insert-images', 'nonce' );
157
 
158
  // Prepare variables.
159
- $images = stripslashes_deep( (array) $_POST['images'] );
 
 
 
 
 
160
  $post_id = absint( $_POST['post_id'] );
161
 
162
  // Grab and update any gallery data if necessary.
@@ -177,19 +213,19 @@ function envira_gallery_lite_ajax_insert_images() {
177
  }
178
 
179
  // Loop through the images and add them to the gallery.
180
- foreach ( (array) $images as $i => $id ) {
181
  // Update the attachment image post meta first.
182
- $has_gallery = get_post_meta( $id, '_eg_has_gallery', true );
183
  if ( empty( $has_gallery ) ) {
184
  $has_gallery = array();
185
  }
186
 
187
  $has_gallery[] = $post_id;
188
- update_post_meta( $id, '_eg_has_gallery', $has_gallery );
189
 
190
  // Now add the image to the gallery for this particular post.
191
- $in_gallery[] = $id;
192
- $gallery_data = envira_gallery_lite_ajax_prepare_gallery_data( $gallery_data, $id );
193
  }
194
 
195
  // Update the gallery data.
@@ -200,20 +236,27 @@ function envira_gallery_lite_ajax_insert_images() {
200
  do_action( 'envira_gallery_ajax_insert_images', $images, $post_id );
201
 
202
  // Flush the gallery cache.
203
- Envira_Gallery_Common_Lite::get_instance()->flush_gallery_caches( $post_id );
204
 
205
- echo json_encode( true );
 
 
 
 
 
 
 
206
  die;
207
 
208
  }
209
 
210
- add_action( 'wp_ajax_envira_gallery_sort_images', 'envira_gallery_lite_ajax_sort_images' );
211
  /**
212
  * Sorts images based on user-dragged position in the gallery.
213
  *
214
  * @since 1.0.0
215
  */
216
- function envira_gallery_lite_ajax_sort_images() {
217
 
218
  // Run a security check first.
219
  check_ajax_referer( 'envira-gallery-sort', 'nonce' );
@@ -238,20 +281,20 @@ function envira_gallery_lite_ajax_sort_images() {
238
  update_post_meta( $post_id, '_eg_gallery_data', $new_order );
239
 
240
  // Flush the gallery cache.
241
- Envira_Gallery_Common_Lite::get_instance()->flush_gallery_caches( $post_id );
242
 
243
  echo json_encode( true );
244
  die;
245
 
246
  }
247
 
248
- add_action( 'wp_ajax_envira_gallery_remove_image', 'envira_gallery_lite_ajax_remove_image' );
249
  /**
250
  * Removes an image from a gallery.
251
  *
252
  * @since 1.0.0
253
  */
254
- function envira_gallery_lite_ajax_remove_image() {
255
 
256
  // Run a security check first.
257
  check_ajax_referer( 'envira-gallery-remove-image', 'nonce' );
@@ -264,14 +307,14 @@ function envira_gallery_lite_ajax_remove_image() {
264
  $has_gallery = get_post_meta( $attach_id, '_eg_has_gallery', true );
265
 
266
  // Unset the image from the gallery, in_gallery and has_gallery checkers.
267
- unset( $gallery_data['gallery'][$attach_id] );
268
 
269
  if ( ( $key = array_search( $attach_id, (array) $in_gallery ) ) !== false ) {
270
- unset( $in_gallery[$key] );
271
  }
272
 
273
  if ( ( $key = array_search( $post_id, (array) $has_gallery ) ) !== false ) {
274
- unset( $has_gallery[$key] );
275
  }
276
 
277
  // Update the gallery data.
@@ -279,24 +322,87 @@ function envira_gallery_lite_ajax_remove_image() {
279
  update_post_meta( $post_id, '_eg_in_gallery', $in_gallery );
280
  update_post_meta( $attach_id, '_eg_has_gallery', $has_gallery );
281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  // Run hook before finishing the reponse.
283
  do_action( 'envira_gallery_ajax_remove_images', $attach_id, $post_id );
284
 
285
  // Flush the gallery cache.
286
- Envira_Gallery_Common_Lite::get_instance()->flush_gallery_caches( $post_id );
287
 
288
  echo json_encode( true );
289
  die;
290
 
291
  }
292
 
293
- add_action( 'wp_ajax_envira_gallery_save_meta', 'envira_gallery_lite_ajax_save_meta' );
294
  /**
295
  * Saves the metadata for an image in a gallery.
296
  *
297
  * @since 1.0.0
298
  */
299
- function envira_gallery_lite_ajax_save_meta() {
300
 
301
  // Run a security check first.
302
  check_ajax_referer( 'envira-gallery-save-meta', 'nonce' );
@@ -306,17 +412,25 @@ function envira_gallery_lite_ajax_save_meta() {
306
  $attach_id = absint( $_POST['attach_id'] );
307
  $meta = $_POST['meta'];
308
  $gallery_data = get_post_meta( $post_id, '_eg_gallery_data', true );
309
-
310
  if ( isset( $meta['title'] ) ) {
311
- $gallery_data['gallery'][$attach_id]['title'] = trim( $meta['title'] );
312
  }
313
 
314
  if ( isset( $meta['alt'] ) ) {
315
- $gallery_data['gallery'][$attach_id]['alt'] = trim( esc_html( $meta['alt'] ) );
316
  }
317
 
318
  if ( isset( $meta['link'] ) ) {
319
- $gallery_data['gallery'][$attach_id]['link'] = esc_url( $meta['link'] );
 
 
 
 
 
 
 
 
320
  }
321
 
322
  // Allow filtering of meta before saving.
@@ -326,20 +440,98 @@ function envira_gallery_lite_ajax_save_meta() {
326
  update_post_meta( $post_id, '_eg_gallery_data', $gallery_data );
327
 
328
  // Flush the gallery cache.
329
- Envira_Gallery_Common_Lite::get_instance()->flush_gallery_caches( $post_id );
330
 
331
- echo json_encode( true );
 
332
  die;
333
 
334
  }
335
 
336
- add_action( 'wp_ajax_envira_gallery_refresh', 'envira_gallery_lite_ajax_refresh' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337
  /**
338
  * Refreshes the DOM view for a gallery.
339
  *
340
  * @since 1.0.0
341
  */
342
- function envira_gallery_lite_ajax_refresh() {
343
 
344
  // Run a security check first.
345
  check_ajax_referer( 'envira-gallery-refresh', 'nonce' );
@@ -359,7 +551,7 @@ function envira_gallery_lite_ajax_refresh() {
359
 
360
  // Loop through the data and build out the gallery view.
361
  foreach ( (array) $gallery_data['gallery'] as $id => $data ) {
362
- $gallery .= Envira_Gallery_Metaboxes_Lite::get_instance()->get_gallery_item( $id, $data, $post_id );
363
  }
364
 
365
  echo json_encode( array( 'success' => $gallery ) );
@@ -367,13 +559,13 @@ function envira_gallery_lite_ajax_refresh() {
367
 
368
  }
369
 
370
- add_action( 'wp_ajax_envira_gallery_load_gallery_data', 'envira_gallery_lite_ajax_load_gallery_data' );
371
  /**
372
  * Retrieves and return gallery data for the specified ID.
373
  *
374
  * @since 1.0.0
375
  */
376
- function envira_gallery_lite_ajax_load_gallery_data() {
377
 
378
  // Prepare variables and grab the gallery data.
379
  $gallery_id = absint( $_POST['post_id'] );
@@ -385,31 +577,288 @@ function envira_gallery_lite_ajax_load_gallery_data() {
385
 
386
  }
387
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  /**
389
  * Helper function to prepare the metadata for an image in a gallery.
390
  *
391
  * @since 1.0.0
392
  *
393
- * @param array $gallery_data Array of data for the gallery.
394
- * @param int $id The attachment ID to prepare data for.
 
395
  * @return array $gallery_data Amended gallery data with updated image metadata.
396
  */
397
- function envira_gallery_lite_ajax_prepare_gallery_data( $gallery_data, $id ) {
398
 
 
399
  $attachment = get_post( $id );
400
- $url = wp_get_attachment_image_src( $id, 'full' );
401
- $alt_text = get_post_meta( $id, '_wp_attachment_image_alt', true );
402
- $gallery_data['gallery'][$id] = array(
403
- 'status' => 'pending',
404
- 'src' => isset( $url[0] ) ? esc_url( $url[0] ) : '',
405
- 'title' => get_the_title( $id ),
406
- 'link' => isset( $url[0] ) ? esc_url( $url[0] ) : '',
407
- 'alt' => ! empty( $alt_text ) ? $alt_text : '',
408
- 'thumb' => ''
409
- );
410
-
411
- $gallery_data = apply_filters( 'envira_gallery_ajax_item_data', $gallery_data, $attachment, $id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
412
 
413
  return $gallery_data;
414
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
415
  }
4
  *
5
  * @since 1.0.0
6
  *
7
+ * @package Envira_Gallery
8
  * @author Thomas Griffin
9
  */
10
 
11
+ add_action( 'wp_ajax_envira_gallery_change_type', 'envira_gallery_ajax_change_type' );
12
+ /**
13
+ * Changes the type of gallery to the user selection.
14
+ *
15
+ * @since 1.0.0
16
+ */
17
+ function envira_gallery_ajax_change_type() {
18
+
19
+ // Run a security check first.
20
+ check_ajax_referer( 'envira-gallery-change-type', 'nonce' );
21
+
22
+ // Prepare variables.
23
+ $post_id = absint( $_POST['post_id'] );
24
+ $post = get_post( $post_id );
25
+ $type = stripslashes( $_POST['type'] );
26
+
27
+ // Retrieve the data for the type selected.
28
+ ob_start();
29
+ $instance = Envira_Gallery_Metaboxes::get_instance();
30
+ $instance->images_display( $type, $post );
31
+ $html = ob_get_clean();
32
+
33
+ // Send back the response.
34
+ echo json_encode( array( 'type' => $type, 'html' => $html ) );
35
+ die;
36
+
37
+ }
38
+
39
+ add_action( 'wp_ajax_envira_gallery_change_preview', 'envira_gallery_ajax_change_preview' );
40
+ /**
41
+ * Returns the output for the Preview Metabox for the given Gallery Type.
42
+ *
43
+ * @since 1.5.0
44
+ */
45
+ function envira_gallery_ajax_change_preview() {
46
+
47
+ // Run a security check first.
48
+ check_ajax_referer( 'envira-gallery-change-preview', 'nonce' );
49
+
50
+ // Prepare variables.
51
+ $post_id = absint( $_POST['post_id'] );
52
+ $type = stripslashes( $_POST['type'] );
53
+
54
+ // Get the saved Gallery configuration.
55
+ $data = Envira_Gallery_Lite::get_instance()->get_gallery( $post_id );
56
+
57
+ // Iterate through the POSTed Gallery configuration (which comprises of index based fields),
58
+ // overwriting the above with the supplied values. This gives us the most up to date,
59
+ // unsaved configuration.
60
+ foreach ( $_POST['data'] as $index => $field ) {
61
+
62
+ // Skip if this isnt' a configuration field.
63
+ if ( strpos( $field['name'], '_envira_gallery[' ) === false ) {
64
+ continue;
65
+ }
66
+
67
+ // Extract the key from the field name.
68
+ preg_match_all( "/\[([^\]]*)\]/", $field['name'], $matches );
69
+ if ( ! isset( $matches[1] ) || count( $matches[1] ) == 0 ) {
70
+ continue;
71
+ }
72
+
73
+ // Add this field key/value pair to the configuration
74
+ $data['config'][ $matches[1][0] ] = $field['value'];
75
+
76
+ }
77
+
78
+ // Retrieve the preview for the type selected, using the now up-to-date gallery configuration.
79
+ ob_start();
80
+ do_action( 'envira_gallery_preview_' . $type, $data );
81
+ $html = ob_get_clean();
82
+
83
+ // Send back the response.
84
+ echo json_encode( $html );
85
+ die;
86
+
87
+ }
88
+
89
+ add_action( 'wp_ajax_envira_gallery_set_user_setting', 'envira_gallery_ajax_set_user_setting' );
90
+ /**
91
+ * Stores a user setting for the logged in WordPress User
92
+ *
93
+ * @since 1.5.0
94
+ */
95
+ function envira_gallery_ajax_set_user_setting() {
96
+
97
+ // Run a security check first.
98
+ check_ajax_referer( 'envira-gallery-set-user-setting', 'nonce' );
99
+
100
+ // Prepare variables.
101
+ $name = stripslashes( $_POST['name'] );
102
+ $value = stripslashes( $_POST['value'] );
103
+
104
+ // Set user setting.
105
+ set_user_setting( $name, $value );
106
+
107
+ // Send back the response.
108
+ wp_send_json_success();
109
+ die();
110
+
111
+ }
112
+
113
+ add_action( 'wp_ajax_envira_gallery_load_image', 'envira_gallery_ajax_load_image' );
114
  /**
115
  * Loads an image into a gallery.
116
  *
117
  * @since 1.0.0
118
  */
119
+ function envira_gallery_ajax_load_image() {
120
 
121
  // Run a security check first.
122
  check_ajax_referer( 'envira-gallery-load-image', 'nonce' );
155
  }
156
 
157
  // Set data and update the meta information.
158
+ $gallery_data = envira_gallery_ajax_prepare_gallery_data( $gallery_data, $id );
159
  update_post_meta( $post_id, '_eg_gallery_data', $gallery_data );
160
 
161
  // Run hook before building out the item.
162
  do_action( 'envira_gallery_ajax_load_image', $id, $post_id );
163
 
164
  // Build out the individual HTML output for the gallery image that has just been uploaded.
165
+ $html = Envira_Gallery_Metaboxes::get_instance()->get_gallery_item( $id, $gallery_data['gallery'][$id], $post_id );
166
+
167
+ // Allow addons to filter the HTML output
168
+ $html = apply_filters( 'envira_gallery_ajax_get_gallery_item_html', $html, $gallery_data, $id, $post_id );
169
 
170
  // Flush the gallery cache.
171
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $post_id );
172
 
173
  echo json_encode( $html );
174
  die;
175
 
176
  }
177
 
178
+ add_action( 'wp_ajax_envira_gallery_insert_images', 'envira_gallery_ajax_insert_images' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  /**
180
  * Inserts one or more images from the Media Library into a gallery.
181
  *
182
  * @since 1.0.0
183
  */
184
+ function envira_gallery_ajax_insert_images() {
185
 
186
  // Run a security check first.
187
  check_ajax_referer( 'envira-gallery-insert-images', 'nonce' );
188
 
189
  // Prepare variables.
190
+ $images = array();
191
+ if ( isset( $_POST['images'] ) ) {
192
+ $images = stripslashes_deep( (array) $_POST['images'] );
193
+ }
194
+
195
+ // Get the Envira Gallery ID
196
  $post_id = absint( $_POST['post_id'] );
197
 
198
  // Grab and update any gallery data if necessary.
213
  }
214
 
215
  // Loop through the images and add them to the gallery.
216
+ foreach ( (array) $images as $i => $image ) {
217
  // Update the attachment image post meta first.
218
+ $has_gallery = get_post_meta( $image['id'], '_eg_has_gallery', true );
219
  if ( empty( $has_gallery ) ) {
220
  $has_gallery = array();
221
  }
222
 
223
  $has_gallery[] = $post_id;
224
+ update_post_meta( $image['id'], '_eg_has_gallery', $has_gallery );
225
 
226
  // Now add the image to the gallery for this particular post.
227
+ $in_gallery[] = $image['id'];
228
+ $gallery_data = envira_gallery_ajax_prepare_gallery_data( $gallery_data, $image['id'], $image );
229
  }
230
 
231
  // Update the gallery data.
236
  do_action( 'envira_gallery_ajax_insert_images', $images, $post_id );
237
 
238
  // Flush the gallery cache.
239
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $post_id );
240
 
241
+ // Return a HTML string comprising of all gallery images, so the UI can be updated
242
+ $html = '';
243
+ foreach ( (array) $gallery_data['gallery'] as $id => $data ) {
244
+ $html .= Envira_Gallery_Metaboxes::get_instance()->get_gallery_item( $id, $data, $post_id );
245
+ }
246
+
247
+ // Output JSON and exit
248
+ echo json_encode( array( 'success' => $html ) );
249
  die;
250
 
251
  }
252
 
253
+ add_action( 'wp_ajax_envira_gallery_sort_images', 'envira_gallery_ajax_sort_images' );
254
  /**
255
  * Sorts images based on user-dragged position in the gallery.
256
  *
257
  * @since 1.0.0
258
  */
259
+ function envira_gallery_ajax_sort_images() {
260
 
261
  // Run a security check first.
262
  check_ajax_referer( 'envira-gallery-sort', 'nonce' );
281
  update_post_meta( $post_id, '_eg_gallery_data', $new_order );
282
 
283
  // Flush the gallery cache.
284
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $post_id );
285
 
286
  echo json_encode( true );
287
  die;
288
 
289
  }
290
 
291
+ add_action( 'wp_ajax_envira_gallery_remove_image', 'envira_gallery_ajax_remove_image' );
292
  /**
293
  * Removes an image from a gallery.
294
  *
295
  * @since 1.0.0
296
  */
297
+ function envira_gallery_ajax_remove_image() {
298
 
299
  // Run a security check first.
300
  check_ajax_referer( 'envira-gallery-remove-image', 'nonce' );
307
  $has_gallery = get_post_meta( $attach_id, '_eg_has_gallery', true );
308
 
309
  // Unset the image from the gallery, in_gallery and has_gallery checkers.
310
+ unset( $gallery_data['gallery'][ $attach_id ] );
311
 
312
  if ( ( $key = array_search( $attach_id, (array) $in_gallery ) ) !== false ) {
313
+ unset( $in_gallery[ $key ] );
314
  }
315
 
316
  if ( ( $key = array_search( $post_id, (array) $has_gallery ) ) !== false ) {
317
+ unset( $has_gallery[ $key ] );
318
  }
319
 
320
  // Update the gallery data.
322
  update_post_meta( $post_id, '_eg_in_gallery', $in_gallery );
323
  update_post_meta( $attach_id, '_eg_has_gallery', $has_gallery );
324
 
325
+ // Run hook before finishing the reponse.
326
+ do_action( 'envira_gallery_ajax_remove_image', $attach_id, $post_id );
327
+
328
+ // If the global setting for deleting images on gallery image deletion is enabled, check
329
+ // that the image doesn't belong to another gallery and isn't attached
330
+ $image_delete = Envira_Gallery_Settings::get_instance()->get_setting( 'image_delete' );
331
+ if ( $image_delete ) {
332
+ // Get attachment
333
+ $attachment = get_post( $attach_id );
334
+
335
+ // If post parent is the Gallery ID, and the image isn't in another gallery, we're OK to delete the image
336
+ if ( ( $attachment->post_parent == $post_id ) && ( count( $in_gallery ) == 0 ) ) {
337
+ wp_delete_attachment( $attach_id );
338
+ }
339
+ }
340
+
341
+ // Flush the gallery cache.
342
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $post_id );
343
+
344
+ echo json_encode( true );
345
+ die;
346
+
347
+ }
348
+
349
+ add_action( 'wp_ajax_envira_gallery_remove_images', 'envira_gallery_ajax_remove_images' );
350
+ /**
351
+ * Removes multiple images from a gallery.
352
+ *
353
+ * @since 1.3.2.4
354
+ */
355
+ function envira_gallery_ajax_remove_images() {
356
+
357
+ // Run a security check first.
358
+ check_ajax_referer( 'envira-gallery-remove-image', 'nonce' );
359
+
360
+ // Prepare variables.
361
+ $post_id = absint( $_POST['post_id'] );
362
+ $attach_ids = (array) $_POST['attachment_ids'];
363
+ $gallery_data = get_post_meta( $post_id, '_eg_gallery_data', true );
364
+ $in_gallery = get_post_meta( $post_id, '_eg_in_gallery', true );
365
+
366
+ foreach ( (array) $attach_ids as $attach_id ) {
367
+ $has_gallery = get_post_meta( $attach_id, '_eg_has_gallery', true );
368
+
369
+ // Unset the image from the gallery, in_gallery and has_gallery checkers.
370
+ unset( $gallery_data['gallery'][$attach_id] );
371
+
372
+ if ( ( $key = array_search( $attach_id, (array) $in_gallery ) ) !== false ) {
373
+ unset( $in_gallery[$key] );
374
+ }
375
+
376
+ if ( ( $key = array_search( $post_id, (array) $has_gallery ) ) !== false ) {
377
+ unset( $has_gallery[$key] );
378
+ }
379
+
380
+ // Update the attachment data.
381
+ update_post_meta( $attach_id, '_eg_has_gallery', $has_gallery );
382
+ }
383
+
384
+ // Update the gallery data
385
+ update_post_meta( $post_id, '_eg_gallery_data', $gallery_data );
386
+ update_post_meta( $post_id, '_eg_in_gallery', $in_gallery );
387
+
388
  // Run hook before finishing the reponse.
389
  do_action( 'envira_gallery_ajax_remove_images', $attach_id, $post_id );
390
 
391
  // Flush the gallery cache.
392
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $post_id );
393
 
394
  echo json_encode( true );
395
  die;
396
 
397
  }
398
 
399
+ add_action( 'wp_ajax_envira_gallery_save_meta', 'envira_gallery_ajax_save_meta' );
400
  /**
401
  * Saves the metadata for an image in a gallery.
402
  *
403
  * @since 1.0.0
404
  */
405
+ function envira_gallery_ajax_save_meta() {
406
 
407
  // Run a security check first.
408
  check_ajax_referer( 'envira-gallery-save-meta', 'nonce' );
412
  $attach_id = absint( $_POST['attach_id'] );
413
  $meta = $_POST['meta'];
414
  $gallery_data = get_post_meta( $post_id, '_eg_gallery_data', true );
415
+
416
  if ( isset( $meta['title'] ) ) {
417
+ $gallery_data['gallery'][ $attach_id ]['title'] = trim( $meta['title'] );
418
  }
419
 
420
  if ( isset( $meta['alt'] ) ) {
421
+ $gallery_data['gallery'][ $attach_id ]['alt'] = trim( esc_html( $meta['alt'] ) );
422
  }
423
 
424
  if ( isset( $meta['link'] ) ) {
425
+ $gallery_data['gallery'][ $attach_id ]['link'] = esc_url( $meta['link'] );
426
+ }
427
+
428
+ if ( isset( $meta['link_new_window'] ) ) {
429
+ $gallery_data['gallery'][ $attach_id ]['link_new_window'] = trim( $meta['link_new_window'] );
430
+ }
431
+
432
+ if ( isset( $meta['caption'] ) ) {
433
+ $gallery_data['gallery'][ $attach_id ]['caption'] = trim( $meta['caption'] );
434
  }
435
 
436
  // Allow filtering of meta before saving.
440
  update_post_meta( $post_id, '_eg_gallery_data', $gallery_data );
441
 
442
  // Flush the gallery cache.
443
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $post_id );
444
 
445
+ // Done
446
+ wp_send_json_success();
447
  die;
448
 
449
  }
450
 
451
+ add_action( 'wp_ajax_envira_gallery_save_bulk_meta', 'envira_gallery_ajax_save_bulk_meta' );
452
+ /**
453
+ * Saves the metadata for multiple images in a gallery (bulk edit).
454
+ *
455
+ * @since 1.4.2.2
456
+ */
457
+ function envira_gallery_ajax_save_bulk_meta() {
458
+
459
+ // Run a security check first.
460
+ check_ajax_referer( 'envira-gallery-save-meta', 'nonce' );
461
+
462
+ // Prepare variables.
463
+ $post_id = absint( $_POST['post_id'] );
464
+ $image_ids = $_POST['image_ids'];
465
+ $meta = $_POST['meta'];
466
+
467
+ // Check the required variables exist.
468
+ if ( empty( $post_id ) ) {
469
+ wp_send_json_error();
470
+ }
471
+ if ( empty( $image_ids ) || ! is_array( $image_ids ) ) {
472
+ wp_send_json_error();
473
+ }
474
+ if ( empty( $meta ) || ! is_array( $meta ) ) {
475
+ wp_send_json_error();
476
+ }
477
+
478
+ // Get gallery.
479
+ $gallery_data = get_post_meta( $post_id, '_eg_gallery_data', true );
480
+ if ( empty( $gallery_data ) || ! is_array( $gallery_data ) ) {
481
+ wp_send_json_error();
482
+ }
483
+
484
+ // Iterate through gallery images, updating the metadata.
485
+ foreach ( $image_ids as $image_id ) {
486
+ // If the image isn't in the gallery, something went wrong - so skip this image.
487
+ if ( ! isset( $gallery_data['gallery'][ $image_id ] ) ) {
488
+ continue;
489
+ }
490
+
491
+ // Update image metadata.
492
+ if ( isset( $meta['title'] ) && ! empty( $meta['title'] ) ) {
493
+ $gallery_data['gallery'][ $image_id ]['title'] = trim( $meta['title'] );
494
+ }
495
+
496
+ if ( isset( $meta['alt'] ) && ! empty( $meta['alt'] ) ) {
497
+ $gallery_data['gallery'][ $image_id ]['alt'] = trim( esc_html( $meta['alt'] ) );
498
+ }
499
+
500
+ if ( isset( $meta['link'] ) && ! empty( $meta['link'] ) ) {
501
+ $gallery_data['gallery'][ $image_id ]['link'] = esc_url( $meta['link'] );
502
+ }
503
+
504
+ if ( isset( $meta['link_new_window'] ) && ! empty( $meta['link_new_window'] ) ) {
505
+ $gallery_data['gallery'][ $image_id ]['link_new_window'] = trim( $meta['link_new_window'] );
506
+ }
507
+
508
+ if ( isset( $meta['caption'] ) && ! empty( $meta['caption'] ) ) {
509
+ $gallery_data['gallery'][ $image_id ]['caption'] = trim( $meta['caption'] );
510
+ }
511
+
512
+ // Allow filtering of meta before saving.
513
+ $gallery_data = apply_filters( 'envira_gallery_ajax_save_bulk_meta', $gallery_data, $meta, $image_id, $post_id );
514
+ }
515
+
516
+ // Update the gallery data.
517
+ update_post_meta( $post_id, '_eg_gallery_data', $gallery_data );
518
+
519
+ // Flush the gallery cache.
520
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $post_id );
521
+
522
+ // Done
523
+ wp_send_json_success();
524
+ die;
525
+
526
+ }
527
+
528
+ add_action( 'wp_ajax_envira_gallery_refresh', 'envira_gallery_ajax_refresh' );
529
  /**
530
  * Refreshes the DOM view for a gallery.
531
  *
532
  * @since 1.0.0
533
  */
534
+ function envira_gallery_ajax_refresh() {
535
 
536
  // Run a security check first.
537
  check_ajax_referer( 'envira-gallery-refresh', 'nonce' );
551
 
552
  // Loop through the data and build out the gallery view.
553
  foreach ( (array) $gallery_data['gallery'] as $id => $data ) {
554
+ $gallery .= Envira_Gallery_Metaboxes::get_instance()->get_gallery_item( $id, $data, $post_id );
555
  }
556
 
557
  echo json_encode( array( 'success' => $gallery ) );
559
 
560
  }
561
 
562
+ add_action( 'wp_ajax_envira_gallery_load_gallery_data', 'envira_gallery_ajax_load_gallery_data' );
563
  /**
564
  * Retrieves and return gallery data for the specified ID.
565
  *
566
  * @since 1.0.0
567
  */
568
+ function envira_gallery_ajax_load_gallery_data() {
569
 
570
  // Prepare variables and grab the gallery data.
571
  $gallery_id = absint( $_POST['post_id'] );
577
 
578
  }
579
 
580
+ add_action( 'wp_ajax_envira_gallery_install_addon', 'envira_gallery_ajax_install_addon' );
581
+ /**
582
+ * Installs an Envira addon.
583
+ *
584
+ * @since 1.0.0
585
+ */
586
+ function envira_gallery_ajax_install_addon() {
587
+
588
+ // Run a security check first.
589
+ check_ajax_referer( 'envira-gallery-install', 'nonce' );
590
+
591
+ // Install the addon.
592
+ if ( isset( $_POST['plugin'] ) ) {
593
+ $download_url = $_POST['plugin'];
594
+ global $hook_suffix;
595
+
596
+ // Set the current screen to avoid undefined notices.
597
+ set_current_screen();
598
+
599
+ // Prepare variables.
600
+ $method = '';
601
+ $url = add_query_arg(
602
+ array(
603
+ 'page' => 'envira-gallery-settings'
604
+ ),
605
+ admin_url( 'admin.php' )
606
+ );
607
+ $url = esc_url( $url );
608
+
609
+ // Start output bufferring to catch the filesystem form if credentials are needed.
610
+ ob_start();
611
+ if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, false, null ) ) ) {
612
+ $form = ob_get_clean();
613
+ echo json_encode( array( 'form' => $form ) );
614
+ die;
615
+ }
616
+
617
+ // If we are not authenticated, make it happen now.
618
+ if ( ! WP_Filesystem( $creds ) ) {
619
+ ob_start();
620
+ request_filesystem_credentials( $url, $method, true, false, null );
621
+ $form = ob_get_clean();
622
+ echo json_encode( array( 'form' => $form ) );
623
+ die;
624
+ }
625
+
626
+ // We do not need any extra credentials if we have gotten this far, so let's install the plugin.
627
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
628
+ require_once plugin_dir_path( Envira_Gallery_Lite::get_instance()->file ) . 'includes/admin/skin.php';
629
+
630
+ // Create the plugin upgrader with our custom skin.
631
+ $installer = new Plugin_Upgrader( $skin = new Envira_Gallery_Skin() );
632
+ $installer->install( $download_url );
633
+
634
+ // Flush the cache and return the newly installed plugin basename.
635
+ wp_cache_flush();
636
+ if ( $installer->plugin_info() ) {
637
+ $plugin_basename = $installer->plugin_info();
638
+ echo json_encode( array( 'plugin' => $plugin_basename ) );
639
+ die;
640
+ }
641
+ }
642
+
643
+ // Send back a response.
644
+ echo json_encode( true );
645
+ die;
646
+
647
+ }
648
+
649
+ add_action( 'wp_ajax_envira_gallery_activate_addon', 'envira_gallery_ajax_activate_addon' );
650
+ /**
651
+ * Activates an Envira addon.
652
+ *
653
+ * @since 1.0.0
654
+ */
655
+ function envira_gallery_ajax_activate_addon() {
656
+
657
+ // Run a security check first.
658
+ check_ajax_referer( 'envira-gallery-activate', 'nonce' );
659
+
660
+ // Activate the addon.
661
+ if ( isset( $_POST['plugin'] ) ) {
662
+ $activate = activate_plugin( $_POST['plugin'] );
663
+
664
+ if ( is_wp_error( $activate ) ) {
665
+ echo json_encode( array( 'error' => $activate->get_error_message() ) );
666
+ die;
667
+ }
668
+ }
669
+
670
+ echo json_encode( true );
671
+ die;
672
+
673
+ }
674
+
675
+ add_action( 'wp_ajax_envira_gallery_deactivate_addon', 'envira_gallery_ajax_deactivate_addon' );
676
+ /**
677
+ * Deactivates an Envira addon.
678
+ *
679
+ * @since 1.0.0
680
+ */
681
+ function envira_gallery_ajax_deactivate_addon() {
682
+
683
+ // Run a security check first.
684
+ check_ajax_referer( 'envira-gallery-deactivate', 'nonce' );
685
+
686
+ // Deactivate the addon.
687
+ if ( isset( $_POST['plugin'] ) ) {
688
+ $deactivate = deactivate_plugins( $_POST['plugin'] );
689
+ }
690
+
691
+ echo json_encode( true );
692
+ die;
693
+
694
+ }
695
+
696
  /**
697
  * Helper function to prepare the metadata for an image in a gallery.
698
  *
699
  * @since 1.0.0
700
  *
701
+ * @param array $gallery_data Array of data for the gallery.
702
+ * @param int $id The attachment ID to prepare data for.
703
+ * @param array $image Attachment image. Populated if inserting from the Media Library
704
  * @return array $gallery_data Amended gallery data with updated image metadata.
705
  */
706
+ function envira_gallery_ajax_prepare_gallery_data( $gallery_data, $id, $image = false ) {
707
 
708
+ // Get attachment
709
  $attachment = get_post( $id );
710
+
711
+ // Depending on whether we're inserting from the Media Library or not, prepare the image array
712
+ if ( ! $image ) {
713
+ $url = wp_get_attachment_image_src( $id, 'full' );
714
+ $alt_text = get_post_meta( $id, '_wp_attachment_image_alt', true );
715
+ $image = array(
716
+ 'status' => 'active',
717
+ 'src' => isset( $url[0] ) ? esc_url( $url[0] ) : '',
718
+ 'title' => get_the_title( $id ),
719
+ 'link' => ( isset( $url[0] ) ? esc_url( $url[0] ) : '' ),
720
+ 'alt' => ! empty( $alt_text ) ? $alt_text : '',
721
+ 'caption' => ! empty( $attachment->post_excerpt ) ? $attachment->post_excerpt : '',
722
+ 'thumb' => ''
723
+ );
724
+ } else {
725
+ $image = array(
726
+ 'status' => 'active',
727
+ 'src' => $image['url'],
728
+ 'title' => $image['title'],
729
+ 'link' => $image['link'],
730
+ 'alt' => $image['alt'],
731
+ 'caption' => $image['caption'],
732
+ 'thumb' => '',
733
+ );
734
+ }
735
+
736
+ // If gallery data is not an array (i.e. we have no images), just add the image to the array
737
+ if ( ! isset( $gallery_data['gallery'] ) || ! is_array( $gallery_data['gallery'] ) ) {
738
+ $gallery_data['gallery'] = array();
739
+ $gallery_data['gallery'][ $id ] = $image;
740
+ } else {
741
+ // Add this image to the start or end of the gallery, depending on the setting
742
+ $instance = Envira_Gallery_Settings::get_instance();
743
+ $media_position = $instance->get_setting( 'media_position' );
744
+
745
+ switch ( $media_position ) {
746
+ case 'before':
747
+ // Add image to start of images array
748
+ // Store copy of images, reset gallery array and rebuild
749
+ $images = $gallery_data['gallery'];
750
+ $gallery_data['gallery'] = array();
751
+ $gallery_data['gallery'][ $id ] = $image;
752
+ foreach ( $images as $old_image_id => $old_image ) {
753
+ $gallery_data['gallery'][ $old_image_id ] = $old_image;
754
+ }
755
+ break;
756
+ case 'after':
757
+ default:
758
+ // Add image, this will default to the end of the array
759
+ $gallery_data['gallery'][ $id ] = $image;
760
+ break;
761
+ }
762
+ }
763
+
764
+ // Filter and return
765
+ $gallery_data = apply_filters( 'envira_gallery_ajax_item_data', $gallery_data, $attachment, $id, $image );
766
 
767
  return $gallery_data;
768
 
769
+ }
770
+
771
+ /**
772
+ * Called whenever a notice is dismissed in Envira Gallery or its Addons.
773
+ *
774
+ * Updates a key's value in the options table to mark the notice as dismissed,
775
+ * preventing it from displaying again
776
+ *
777
+ * @since 1.3.5
778
+ */
779
+ function envira_gallery_ajax_dismiss_notice() {
780
+
781
+ // Run a security check first.
782
+ check_ajax_referer( 'envira-gallery-dismiss-notice', 'nonce' );
783
+
784
+ // Deactivate the notice
785
+ if ( isset( $_POST['notice'] ) ) {
786
+ // Init the notice class and mark notice as deactivated
787
+ $notice = Envira_Gallery_Notice_Admin::get_instance();
788
+ $notice->dismiss( $_POST['notice'] );
789
+
790
+ // Return true
791
+ echo json_encode( true );
792
+ die;
793
+ }
794
+
795
+ // If here, an error occured
796
+ echo json_encode( false );
797
+ die;
798
+
799
+ }
800
+ add_action( 'wp_ajax_envira_gallery_ajax_dismiss_notice', 'envira_gallery_ajax_dismiss_notice' );
801
+
802
+ /**
803
+ * Returns the media link (direct image URL) for the given attachment ID
804
+ *
805
+ * @since 1.4.1.4
806
+ */
807
+ add_action( 'wp_ajax_envira_gallery_get_attachment_links', 'envira_gallery_get_attachment_links' );
808
+ function envira_gallery_get_attachment_links() {
809
+
810
+ // Check nonce
811
+ check_ajax_referer( 'envira-gallery-save-meta', 'nonce' );
812
+
813
+ // Get required inputs
814
+ $attachment_id = absint( $_POST['attachment_id'] );
815
+
816
+ // Return the attachment's links
817
+ wp_send_json_success( array(
818
+ 'media_link' => wp_get_attachment_url( $attachment_id ),
819
+ 'attachment_page' => get_attachment_link( $attachment_id ),
820
+ ) );
821
+
822
+ }
823
+
824
+ /**
825
+ * Returns Galleries, with an optional search term
826
+ *
827
+ * @since 1.5.0
828
+ */
829
+ add_action( 'wp_ajax_envira_gallery_editor_get_galleries', 'envira_gallery_editor_get_galleries' );
830
+ function envira_gallery_editor_get_galleries() {
831
+
832
+ // Check nonce
833
+ check_ajax_referer( 'envira-gallery-editor-get-galleries', 'nonce' );
834
+
835
+ // Get POSTed fields
836
+ $search = (bool) $_POST['search'];
837
+ $search_terms = sanitize_text_field( $_POST['search_terms'] );
838
+
839
+ // Get galleries
840
+ $galleries = Envira_Gallery_Lite::get_instance()->get_galleries( false, true, ( $search ? $search_terms : '' ) );
841
+
842
+ // Build array of just the data we need.
843
+ foreach ( ( array ) $galleries as $gallery ) {
844
+ // Get the thumbnail of the first image
845
+ if ( isset( $gallery['gallery'] ) && ! empty( $gallery['gallery'] ) ) {
846
+ // Get the first image
847
+ reset( $gallery['gallery'] );
848
+ $key = key( $gallery['gallery'] );
849
+ $thumbnail = wp_get_attachment_image_src( $key, 'thumbnail' );
850
+ }
851
+
852
+ // Add gallery to results
853
+ $results[] = array(
854
+ 'id' => $gallery['id'],
855
+ 'title' => $gallery['config']['title'],
856
+ 'thumbnail' => ( ( isset( $thumbnail ) && is_array( $thumbnail ) ) ? $thumbnail[0] : '' ),
857
+ 'action' => 'gallery', // Tells the editor modal whether this is a Gallery or Album for the shortcode output
858
+ );
859
+ }
860
+
861
+ // Return galleries
862
+ wp_send_json_success( $results );
863
+
864
  }
includes/admin/common.php CHANGED
@@ -4,10 +4,10 @@
4
  *
5
  * @since 1.0.0
6
  *
7
- * @package Envira_Gallery_Lite
8
  * @author Thomas Griffin
9
  */
10
- class Envira_Gallery_Common_Admin_Lite {
11
 
12
  /**
13
  * Holds the class object.
@@ -35,6 +35,15 @@ class Envira_Gallery_Common_Admin_Lite {
35
  * @var object
36
  */
37
  public $base;
 
 
 
 
 
 
 
 
 
38
 
39
  /**
40
  * Primary class constructor.
@@ -46,6 +55,13 @@ class Envira_Gallery_Common_Admin_Lite {
46
  // Load the base class object.
47
  $this->base = Envira_Gallery_Lite::get_instance();
48
 
 
 
 
 
 
 
 
49
  // Delete any gallery association on attachment deletion. Also delete any extra cropped images.
50
  add_action( 'delete_attachment', array( $this, 'delete_gallery_association' ) );
51
  add_action( 'delete_attachment', array( $this, 'delete_cropped_image' ) );
@@ -54,8 +70,237 @@ class Envira_Gallery_Common_Admin_Lite {
54
  add_action( 'wp_trash_post', array( $this, 'trash_gallery' ) );
55
  add_action( 'untrash_post', array( $this, 'untrash_gallery' ) );
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  }
58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  /**
60
  * Deletes the Envira gallery association for the image being deleted.
61
  *
@@ -90,7 +335,7 @@ class Envira_Gallery_Common_Admin_Lite {
90
  update_post_meta( $post_id, '_eg_gallery_data', $gallery_data );
91
 
92
  // Flush necessary gallery caches.
93
- Envira_Gallery_Common_Lite::get_instance()->flush_gallery_caches( $post_id, ( ! empty( $gallery_data['config']['slug'] ) ? $gallery_data['config']['slug'] : '' ) );
94
  }
95
  }
96
 
@@ -150,22 +395,26 @@ class Envira_Gallery_Common_Admin_Lite {
150
  $gallery = get_post( $id );
151
 
152
  // Flush necessary gallery caches to ensure trashed galleries are not showing.
153
- Envira_Gallery_Common_Lite::get_instance()->flush_gallery_caches( $id );
154
 
155
  // Return early if not an Envira gallery.
156
  if ( 'envira' !== $gallery->post_type ) {
157
  return;
158
  }
159
 
160
- // Set the gallery status to inactive.
161
  $gallery_data = get_post_meta( $id, '_eg_gallery_data', true );
162
  if ( empty( $gallery_data ) ) {
163
  return;
164
  }
165
 
 
166
  $gallery_data['status'] = 'inactive';
167
  update_post_meta( $id, '_eg_gallery_data', $gallery_data );
168
 
 
 
 
169
  }
170
 
171
  /**
@@ -181,7 +430,7 @@ class Envira_Gallery_Common_Admin_Lite {
181
  $gallery = get_post( $id );
182
 
183
  // Flush necessary gallery caches to ensure untrashed galleries are showing.
184
- Envira_Gallery_Common_Lite::get_instance()->flush_gallery_caches( $id );
185
 
186
  // Return early if not an Envira gallery.
187
  if ( 'envira' !== $gallery->post_type ) {
@@ -200,6 +449,96 @@ class Envira_Gallery_Common_Admin_Lite {
200
 
201
  update_post_meta( $id, '_eg_gallery_data', $gallery_data );
202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  }
204
 
205
  /**
@@ -207,12 +546,12 @@ class Envira_Gallery_Common_Admin_Lite {
207
  *
208
  * @since 1.0.0
209
  *
210
- * @return object The Envira_Gallery_Common_Admin_Lite object.
211
  */
212
  public static function get_instance() {
213
 
214
- if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Common_Admin_Lite ) ) {
215
- self::$instance = new Envira_Gallery_Common_Admin_Lite();
216
  }
217
 
218
  return self::$instance;
@@ -222,4 +561,4 @@ class Envira_Gallery_Common_Admin_Lite {
222
  }
223
 
224
  // Load the common admin class.
225
- $envira_gallery_common_admin_lite = Envira_Gallery_Common_Admin_Lite::get_instance();
4
  *
5
  * @since 1.0.0
6
  *
7
+ * @package Envira_Gallery
8
  * @author Thomas Griffin
9
  */
10
+ class Envira_Gallery_Common_Admin {
11
 
12
  /**
13
  * Holds the class object.
35
  * @var object
36
  */
37
  public $base;
38
+
39
+ /**
40
+ * Holds the metabox class object.
41
+ *
42
+ * @since 1.3.1
43
+ *
44
+ * @var object
45
+ */
46
+ public $metabox;
47
 
48
  /**
49
  * Primary class constructor.
55
  // Load the base class object.
56
  $this->base = Envira_Gallery_Lite::get_instance();
57
 
58
+ // Handle any necessary DB upgrades.
59
+ add_action( 'admin_init', array( $this, 'db_upgrade' ) );
60
+
61
+ // Load admin assets.
62
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_styles' ) );
63
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
64
+
65
  // Delete any gallery association on attachment deletion. Also delete any extra cropped images.
66
  add_action( 'delete_attachment', array( $this, 'delete_gallery_association' ) );
67
  add_action( 'delete_attachment', array( $this, 'delete_cropped_image' ) );
70
  add_action( 'wp_trash_post', array( $this, 'trash_gallery' ) );
71
  add_action( 'untrash_post', array( $this, 'untrash_gallery' ) );
72
 
73
+ // Delete attachments, if setting enabled, when a gallery is permanently deleted
74
+ add_action( 'before_delete_post', array( $this, 'delete_gallery' ) );
75
+
76
+ }
77
+
78
+ /**
79
+ * Handles any necessary DB upgrades for Envira.
80
+ *
81
+ * @since 1.0.0
82
+ */
83
+ public function db_upgrade() {
84
+
85
+ // Upgrade to allow captions (v1.1.6).
86
+ $captions = get_option( 'envira_gallery_116' );
87
+ if ( ! $captions ) {
88
+ $galleries = Envira_Gallery_Lite::get_instance()->_get_galleries();
89
+ if ( $galleries ) {
90
+ foreach ( $galleries as $gallery ) {
91
+ foreach ( (array) $gallery['gallery'] as $id => $item ) {
92
+ $gallery['gallery'][$id]['caption'] = ! empty( $item['title'] ) ? $item['title'] : '';
93
+ update_post_meta( $gallery['id'], '_eg_gallery_data', $gallery );
94
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $gallery['id'], $gallery['config']['slug'] );
95
+ }
96
+ }
97
+ }
98
+
99
+ update_option( 'envira_gallery_116', true );
100
+ }
101
+
102
+ // 1.2.1: Convert all non-Envira Post Type galleries into Envira CPT galleries.
103
+ $cptGalleries = get_option( 'envira_gallery_121' );
104
+ if ( ! $cptGalleries ) {
105
+ // Get Post Types, excluding our own
106
+ // We don't use post_status => 'any', as this doesn't include CPTs where exclude_from_search = true.
107
+ $postTypes = get_post_types( array(
108
+ 'public' => true,
109
+ ) );
110
+ $excludedPostTypes = array( 'envira', 'envira_album', 'attachment' );
111
+ foreach ( $postTypes as $key=>$postType ) {
112
+ if ( in_array( $postType, $excludedPostTypes ) ) {
113
+ unset( $postTypes[ $key ] );
114
+ }
115
+ }
116
+
117
+ // Get all Posts that have _eg_gallery_data set
118
+ $inPostGalleries = new WP_Query( array(
119
+ 'post_type' => $postTypes,
120
+ 'post_status' => 'any',
121
+ 'posts_per_page'=> -1,
122
+ 'meta_query' => array(
123
+ array(
124
+ 'key' => '_eg_gallery_data',
125
+ 'compare' => 'EXISTS',
126
+ ),
127
+ )
128
+ ) );
129
+
130
+ // Check if any Posts with galleries exist
131
+ if ( count( $inPostGalleries->posts ) > 0 ) {
132
+ $migrated_galleries = 0;
133
+
134
+ // Iterate through Posts with Galleries
135
+ foreach ( $inPostGalleries->posts as $post ) {
136
+ // Check if this is an Envira or Envira Album CPT
137
+ // If so, skip it
138
+ if ( $post->post_type == 'envira' || $post->post_type == 'envira_album' ) {
139
+ continue;
140
+ }
141
+
142
+ // Get metadata
143
+ $data = get_post_meta( $post->ID, '_eg_gallery_data', true);
144
+ $in = get_post_meta( $post->ID, '_eg_in_gallery', true);
145
+
146
+ // Check if there is at least one image in the gallery
147
+ // Some Posts save Envira config data but don't have images - we don't want to migrate those,
148
+ // as we would end up with blank Envira CPT galleries
149
+ if ( ! isset( $data['gallery'] ) || ! is_array( $data['gallery']) ) {
150
+ continue;
151
+ }
152
+
153
+ // If here, we need to create a new Envira CPT
154
+ $cpt_args = array(
155
+ 'post_title' => ( !empty( $data['config']['title'] ) ? $data['config']['title'] : $post->post_title ),
156
+ 'post_status' => $post->post_status,
157
+ 'post_type' => 'envira',
158
+ 'post_author' => $post->post_author,
159
+ );
160
+ if ( ! empty( $data['config']['slug'] ) ) {
161
+ $cpt_args['post_name'] = $data['config']['slug'];
162
+ }
163
+ $enviraGalleryID = wp_insert_post( $cpt_args );
164
+
165
+ // Check gallery creation was successful
166
+ if ( is_wp_error( $enviraGalleryID ) ) {
167
+ // @TODO how to handle errors?
168
+ continue;
169
+ }
170
+
171
+ // Get Envira Gallery Post
172
+ $enviraPost = get_post( $enviraGalleryID );
173
+
174
+ // Map the title and slug of the post object to the custom fields if no value exists yet.
175
+ $data['config']['title'] = trim( strip_tags( $enviraPost->post_title ) );
176
+ $data['config']['slug'] = sanitize_text_field( $enviraPost->post_name );
177
+
178
+ // Store post metadata
179
+ update_post_meta( $enviraGalleryID, '_eg_gallery_data', $data );
180
+ update_post_meta( $enviraGalleryID, '_eg_in_gallery', $in );
181
+ update_post_meta( $enviraGalleryID, '_eg_gallery_old', $post->ID );
182
+ if ( ! empty( $data['config']['slug'] ) ) {
183
+ update_post_meta( $enviraGalleryID, '_eg_gallery_old_slug', $data['config']['slug'] );
184
+ }
185
+
186
+ // Remove post metadata from the original Post
187
+ delete_post_meta( $post->ID, '_eg_gallery_data' );
188
+ delete_post_meta( $post->ID, '_eg_in_gallery' );
189
+
190
+ // Search for the envira shortcode in the Post content, and change its ID to the new Envira Gallery ID
191
+ if ( has_shortcode ( $post->post_content, 'envira-gallery' ) ) {
192
+ $pattern = get_shortcode_regex();
193
+ if ( preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches ) ) {
194
+ foreach ( $matches[2] as $key => $shortcode ) {
195
+ if ( $shortcode == 'envira-gallery' ) {
196
+ // Found an envira-gallery shortcode
197
+ // Change the ID
198
+ $originalShortcode = $matches[0][ $key ];
199
+ $replacementShortcode = str_replace( 'id="' . $post->ID . '"', 'id="' . $enviraGalleryID . '"', $originalShortcode );
200
+ $post->post_content = str_replace( $originalShortcode, $replacementShortcode, $post->post_content );
201
+ wp_update_post( $post );
202
+ }
203
+ }
204
+ }
205
+ }
206
+
207
+ // Store a relationship between the gallery and this Post
208
+ update_post_meta( $post->ID, '_eg_gallery_id', $enviraGalleryID );
209
+
210
+ // Increment the counter
211
+ $migrated_galleries++;
212
+ }
213
+
214
+ // Display a one time admin notice so the user knows their in-page galleries were migrated.
215
+ if ( $migrated_galleries > 0 ) {
216
+ add_action( 'admin_notices', array( $this, 'notice_galleries_migrated' ) );
217
+ }
218
+ }
219
+
220
+ // Force the tags addon to convert any tags to the new CPT system for any galleries that have been converted to Envira post type.
221
+ delete_option( 'envira_tags_taxonomy_migrated' );
222
+
223
+ // Mark upgrade as complete
224
+ update_option( 'envira_gallery_121', true );
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Displays a notice on screen when a user upgrades from Lite to Pro or Lite to Lite 1.5.x,
230
+ * telling them that their in-page galleries have been migrated.
231
+ *
232
+ * @since 1.5.0
233
+ */
234
+ public function notice_galleries_migrated() {
235
+
236
+ ?>
237
+ <div class="notice updated">
238
+ <p><?php _e( '<strong>Envira Gallery:</strong> Your existing in-page Galleries can now be found by clicking on Envira Gallery in the WordPress Admin menu.', 'envira-gallery' ); ?></p>
239
+ </div>
240
+ <?php
241
+
242
+ }
243
+
244
+ /**
245
+ * Loads styles for all Envira-based Administration Screens.
246
+ *
247
+ * @since 1.3.1
248
+ *
249
+ * @return null Return early if not on the proper screen.
250
+ */
251
+ public function admin_styles() {
252
+
253
+ // Get current screen.
254
+ $screen = get_current_screen();
255
+
256
+ // Bail if we're not on the Envira Post Type screen.
257
+ if ( 'envira' !== $screen->post_type && 'envira_album' !== $screen->post_type ) {
258
+ return;
259
+ }
260
+
261
+ // Load necessary admin styles.
262
+ wp_register_style( $this->base->plugin_slug . '-admin-style', plugins_url( 'assets/css/admin.css', $this->base->file ), array(), $this->base->version );
263
+ wp_enqueue_style( $this->base->plugin_slug . '-admin-style' );
264
+
265
+ // Fire a hook to load in custom admin styles.
266
+ do_action( 'envira_gallery_admin_styles' );
267
+
268
  }
269
 
270
+ /**
271
+ * Loads scripts for all Envira-based Administration Screens.
272
+ *
273
+ * @since 1.3.5
274
+ *
275
+ * @return null Return early if not on the proper screen.
276
+ */
277
+ public function admin_scripts() {
278
+
279
+ // Get current screen.
280
+ $screen = get_current_screen();
281
+
282
+ // Bail if we're not on the Envira Post Type screen.
283
+ if ( 'envira' !== $screen->post_type && 'envira_album' !== $screen->post_type ) {
284
+ return;
285
+ }
286
+
287
+ // Load necessary admin scripts
288
+ wp_register_script( $this->base->plugin_slug . '-admin-script', plugins_url( 'assets/js/min/admin-min.js', $this->base->file ), array( 'jquery' ), $this->base->version );
289
+ wp_enqueue_script( $this->base->plugin_slug . '-admin-script' );
290
+ wp_localize_script(
291
+ $this->base->plugin_slug . '-admin-script',
292
+ 'envira_gallery_admin',
293
+ array(
294
+ 'ajax' => admin_url( 'admin-ajax.php' ),
295
+ 'dismiss_notice_nonce' => wp_create_nonce( 'envira-gallery-dismiss-notice' ),
296
+ )
297
+ );
298
+
299
+ // Fire a hook to load in custom admin scripts.
300
+ do_action( 'envira_gallery_admin_scripts' );
301
+
302
+ }
303
+
304
  /**
305
  * Deletes the Envira gallery association for the image being deleted.
306
  *
335
  update_post_meta( $post_id, '_eg_gallery_data', $gallery_data );
336
 
337
  // Flush necessary gallery caches.
338
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $post_id, ( ! empty( $gallery_data['config']['slug'] ) ? $gallery_data['config']['slug'] : '' ) );
339
  }
340
  }
341
 
395
  $gallery = get_post( $id );
396
 
397
  // Flush necessary gallery caches to ensure trashed galleries are not showing.
398
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $id );
399
 
400
  // Return early if not an Envira gallery.
401
  if ( 'envira' !== $gallery->post_type ) {
402
  return;
403
  }
404
 
405
+ // Check some gallery data exists
406
  $gallery_data = get_post_meta( $id, '_eg_gallery_data', true );
407
  if ( empty( $gallery_data ) ) {
408
  return;
409
  }
410
 
411
+ // Set the gallery status to inactive.
412
  $gallery_data['status'] = 'inactive';
413
  update_post_meta( $id, '_eg_gallery_data', $gallery_data );
414
 
415
+ // Allow other addons to run routines when a Gallery is trashed
416
+ do_action( 'envira_gallery_trash', $id, $gallery_data );
417
+
418
  }
419
 
420
  /**
430
  $gallery = get_post( $id );
431
 
432
  // Flush necessary gallery caches to ensure untrashed galleries are showing.
433
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $id );
434
 
435
  // Return early if not an Envira gallery.
436
  if ( 'envira' !== $gallery->post_type ) {
449
 
450
  update_post_meta( $id, '_eg_gallery_data', $gallery_data );
451
 
452
+ // Allow other addons to run routines when a Gallery is untrashed
453
+ do_action( 'envira_gallery_untrash', $id, $gallery_data );
454
+
455
+ }
456
+
457
+ /**
458
+ * Fired when a gallery is about to be permanently deleted from Trash
459
+ *
460
+ * Checks if the media_delete setting is enabled, and if so safely deletes
461
+ * media that isn't being used elsewhere on the site
462
+ *
463
+ * @since 1.3.6.1
464
+ *
465
+ * @param int $post_id Post ID
466
+ * @return null
467
+ */
468
+ public function delete_gallery( $id ) {
469
+
470
+ // Check if the media_delete setting is enabled
471
+ $media_delete = Envira_Gallery_Settings::get_instance()->get_setting( 'media_delete' );
472
+ if ( $media_delete != '1' ) {
473
+ return;
474
+ }
475
+
476
+ // Get post
477
+ $gallery = get_post( $id );
478
+
479
+ // Flush necessary gallery caches to ensure untrashed galleries are showing.
480
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $id );
481
+
482
+ // Return early if not an Envira gallery.
483
+ if ( 'envira' !== $gallery->post_type ) {
484
+ return;
485
+ }
486
+
487
+ // Get attached media
488
+ $media = get_attached_media( 'image', $id );
489
+ if ( ! is_array( $media ) ) {
490
+ return;
491
+ }
492
+
493
+ // Iterate through media, deleting
494
+ foreach ( $media as $image ) {
495
+ wp_delete_attachment( $image->ID );
496
+ }
497
+
498
+ }
499
+
500
+ /**
501
+ * Called whenever an upgrade button / link is displayed in Lite, this function will
502
+ * check if there's a shareasale ID specified.
503
+ *
504
+ * There are three ways to specify an ID, ordered by highest to lowest priority
505
+ * - add_filter( 'envira_gallery_shareasale_id', function() { return 1234; } );
506
+ * - define( 'ENVIRA_GALLERY_SHAREASALE_ID', 1234 );
507
+ * - get_option( 'envira_gallery_shareasale_id' ); (with the option being in the wp_options table)
508
+ *
509
+ * If an ID is present, returns the ShareASale link with the affiliate ID, and tells
510
+ * ShareASale to then redirect to enviragallery.com/lite
511
+ *
512
+ * If no ID is present, just returns the enviragallery.com/lite URL with UTM tracking.
513
+ *
514
+ * @since 1.5.0
515
+ */
516
+ public function get_upgrade_link() {
517
+
518
+ // Check if there's a constant.
519
+ $shareasale_id = '';
520
+ if ( defined( 'ENVIRA_GALLERY_SHAREASALE_ID' ) ) {
521
+ $shareasale_id = ENVIRA_GALLERY_SHAREASALE_ID;
522
+ }
523
+
524
+ // If there's no constant, check if there's an option.
525
+ if ( empty( $shareasale_id ) ) {
526
+ $shareasale_id = get_option( 'envira_gallery_shareasale_id', '' );
527
+ }
528
+
529
+ // Whether we have an ID or not, filter the ID.
530
+ $shareasale_id = apply_filters( 'envira_gallery_shareasale_id', $shareasale_id );
531
+
532
+ // If at this point we still don't have an ID, we really don't have one!
533
+ // Just return the standard upgrade URL.
534
+ if ( empty( $shareasale_id ) ) {
535
+ return 'http://enviragallery.com/lite/?utm_source=liteplugin&utm_medium=link&utm_campaign=WordPress';
536
+ }
537
+
538
+ // If here, we have a ShareASale ID
539
+ // Return ShareASale URL with redirect.
540
+ return 'http://www.shareasale.com/r.cfm?u=' . $shareasale_id . '&b=566240&m=51693&afftrack=&urllink=enviragallery%2Ecom%2Flite%2F';
541
+
542
  }
543
 
544
  /**
546
  *
547
  * @since 1.0.0
548
  *
549
+ * @return object The Envira_Gallery_Common_Admin object.
550
  */
551
  public static function get_instance() {
552
 
553
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Common_Admin ) ) {
554
+ self::$instance = new Envira_Gallery_Common_Admin();
555
  }
556
 
557
  return self::$instance;
561
  }
562
 
563
  // Load the common admin class.
564
+ $envira_gallery_common_admin = Envira_Gallery_Common_Admin::get_instance();
includes/admin/editor.php CHANGED
@@ -4,10 +4,10 @@
4
  *
5
  * @since 1.0.0
6
  *
7
- * @package Envira_Gallery_Lite
8
  * @author Thomas Griffin
9
  */
10
- class Envira_Gallery_Editor_Lite {
11
 
12
  /**
13
  * Holds the class object.
@@ -57,6 +57,8 @@ class Envira_Gallery_Editor_Lite {
57
 
58
  // Add a custom media button to the editor.
59
  add_filter( 'media_buttons_context', array( $this, 'media_button' ) );
 
 
60
 
61
  }
62
 
@@ -70,15 +72,24 @@ class Envira_Gallery_Editor_Lite {
70
  */
71
  public function media_button( $buttons ) {
72
 
73
- // Create the media button.
74
- $button = '<style type="text/css">@media only screen and (-webkit-min-device-pixel-ratio: 2),only screen and (min--moz-device-pixel-ratio: 2),only screen and (-o-min-device-pixel-ratio: 2/1),only screen and (min-device-pixel-ratio: 2),only screen and (min-resolution: 192dpi),only screen and (min-resolution: 2dppx) { #envira-media-modal-button .envira-media-icon[style] { background-image: url(' . plugins_url( 'assets/css/images/menu-icon-2x.png', $this->base->file ) . ') !important; background-size: 16px 16px !important; } }</style>';
75
- $button .= '<a id="envira-media-modal-button" href="#" class="button envira-gallery-choose-gallery" title="' . esc_attr__( 'Add Gallery', 'envira-gallery-lite' ) . '" style="padding-left: .4em;"><span class="envira-media-icon" style="background: transparent url(' . plugins_url( 'assets/css/images/menu-icon.png', $this->base->file ) . ') no-repeat scroll 0 0; width: 16px; height: 16px; display: inline-block; vertical-align: text-top;"></span> ' . __( 'Add Gallery', 'envira-gallery-lite' ) . '</a>';
76
 
77
  // Enqueue the script that will trigger the editor button.
78
- wp_enqueue_script( $this->base->plugin_slug . '-editor-script', plugins_url( 'assets/js/min/editor-min.js', $this->base->file ), array( 'jquery' ), $this->base->version, true );
 
 
 
 
 
 
 
 
 
79
 
80
- // Add the action to the footer to output the modal window.
81
- add_action( 'admin_footer', array( $this, 'gallery_selection_modal' ) );
82
 
83
  // Append the button.
84
  return $buttons . $button;
@@ -86,127 +97,113 @@ class Envira_Gallery_Editor_Lite {
86
  }
87
 
88
  /**
89
- * Outputs the gallery selection modal to insert a gallery into an editor.
 
90
  *
91
- * @since 1.0.0
 
 
 
 
 
92
  */
93
- public function gallery_selection_modal() {
94
 
95
- echo $this->get_gallery_selection_modal();
96
 
97
  }
98
 
99
  /**
100
- * Returns the gallery selection modal to insert a gallery into an editor.
101
  *
102
- * @since 1.0.0
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  *
104
- * @global object $post The current post object.
105
- * @return string Empty string if no galleries are found, otherwise modal UI.
 
 
 
106
  */
107
- public function get_gallery_selection_modal() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
- // Return early if already loaded.
110
- if ( $this->loaded ) {
111
- return '';
112
  }
113
 
114
- // Set the loaded flag to true.
115
- $this->loaded = true;
116
-
117
- global $post;
118
- $galleries = $this->base->get_galleries();
119
-
120
- ob_start();
121
- ?>
122
- <div class="envira-gallery-default-ui-wrapper" style="display: none;">
123
- <div class="envira-gallery-default-ui envira-gallery-image-meta">
124
- <div class="media-modal wp-core-ui">
125
- <a class="media-modal-close" href="#"><span class="media-modal-icon"></span>
126
- </a>
127
- <div class="media-modal-content">
128
- <div class="media-frame wp-core-ui hide-menu hide-router envira-gallery-meta-wrap">
129
- <div class="media-frame-title">
130
- <h1><?php _e( 'Choose Your Gallery', 'envira-gallery-lite' ); ?></h1>
131
- </div>
132
- <div class="media-frame-content">
133
- <div class="attachments-browser">
134
- <ul class="envira-gallery-meta attachments" style="padding-left: 8px; top: 1em;">
135
- <li class="attachment" data-envira-gallery-id="<?php echo absint( $post->ID ); ?>" style="margin: 8px;">
136
- <div class="attachment-preview landscape">
137
- <div class="thumbnail" style="display: table;">
138
- <div class="inside">
139
- <h3 style="margin: 0;color: #7ad03a;"><?php _e( 'This Post\'s Gallery', 'envira-gallery-lite' ); ?></h3>
140
- <code style="color: #7ad03a;">[envira-gallery id="<?php echo absint( $post->ID ); ?>"]</code>
141
- </div>
142
- </div>
143
- <a class="check" href="#"><div class="media-modal-icon"></div></a>
144
- </div>
145
- </li>
146
-
147
- <?php foreach ( (array) $galleries as $gallery ) : if ( $post->ID == $gallery['id'] ) continue; ?>
148
- <li class="attachment" data-envira-gallery-id="<?php echo absint( $gallery['id'] ); ?>" style="margin: 8px;">
149
- <div class="attachment-preview landscape">
150
- <div class="thumbnail" style="display: table;">
151
- <div class="inside">
152
- <?php
153
- if ( ! empty( $gallery['config']['title'] ) ) {
154
- $title = $gallery['config']['title'];
155
- } else if ( ! empty( $gallery['config']['slug'] ) ) {
156
- $title = $gallery['config']['title'];
157
- } else {
158
- $title = sprintf( __( 'Gallery ID #%s', 'envira-gallery-lite' ), $gallery['id'] );
159
- }
160
- ?>
161
- <h3 style="margin: 0;"><?php echo $title; ?></h3>
162
- <code>[envira-gallery id="<?php echo absint( $gallery['id'] ); ?>"]</code>
163
- </div>
164
- </div>
165
- <a class="check" href="#"><div class="media-modal-icon"></div></a>
166
- </div>
167
- </li>
168
- <?php endforeach; ?>
169
- </ul>
170
- <!-- end .envira-gallery-meta -->
171
- <div class="media-sidebar">
172
- <div class="envira-gallery-meta-sidebar">
173
- <h3 style="margin: 1.4em 0 1em;"><?php _e( 'Helpful Tips', 'envira-gallery-lite' ); ?></h3>
174
- <strong><?php _e( 'Choosing Your Gallery', 'envira-gallery-lite' ); ?></strong>
175
- <p style="margin: 0 0 1.5em;"><?php _e( 'To choose your gallery, simply click on one of the boxes to the left. The "Insert Gallery" button will be activated once you have selected a gallery.', 'envira-gallery-lite' ); ?></p>
176
- <strong><?php _e( 'Inserting Your Gallery', 'envira-gallery-lite' ); ?></strong>
177
- <p style="margin: 0 0 1.5em;"><?php _e( 'To insert your gallery into the editor, click on the "Insert Gallery" button below.', 'envira-gallery-lite' ); ?></p>
178
- </div>
179
- <!-- end .envira-gallery-meta-sidebar -->
180
- </div>
181
- <!-- end .media-sidebar -->
182
- </div>
183
- <!-- end .attachments-browser -->
184
- </div>
185
- <!-- end .media-frame-content -->
186
- <div class="media-frame-toolbar">
187
- <div class="media-toolbar">
188
- <div class="media-toolbar-secondary">
189
- <a href="#" class="envira-gallery-cancel-insertion button media-button button-large button-secondary media-button-insert" title="<?php esc_attr_e( 'Cancel Gallery Insertion', 'envira-gallery-lite' ); ?>"><?php _e( 'Cancel Gallery Insertion', 'envira-gallery-lite' ); ?></a>
190
- </div>
191
- <div class="media-toolbar-primary">
192
- <a href="#" class="envira-gallery-insert-gallery button media-button button-large button-primary media-button-insert" disabled="disabled" title="<?php esc_attr_e( 'Insert Gallery', 'envira-gallery-lite' ); ?>"><?php _e( 'Insert Gallery', 'envira-gallery-lite' ); ?></a>
193
- </div>
194
- <!-- end .media-toolbar-primary -->
195
- </div>
196
- <!-- end .media-toolbar -->
197
- </div>
198
- <!-- end .media-frame-toolbar -->
199
- </div>
200
- <!-- end .media-frame -->
201
- </div>
202
- <!-- end .media-modal-content -->
203
- </div>
204
- <!-- end .media-modal -->
205
- <div class="media-modal-backdrop"></div>
206
- </div><!-- end #envira-gallery-default-ui -->
207
- </div><!-- end #envira-gallery-default-ui-wrapper -->
208
- <?php
209
- return ob_get_clean();
210
 
211
  }
212
 
@@ -215,12 +212,12 @@ class Envira_Gallery_Editor_Lite {
215
  *
216
  * @since 1.0.0
217
  *
218
- * @return object The Envira_Gallery_Editor_Lite object.
219
  */
220
  public static function get_instance() {
221
 
222
- if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Editor_Lite ) ) {
223
- self::$instance = new Envira_Gallery_Editor_Lite();
224
  }
225
 
226
  return self::$instance;
@@ -230,4 +227,4 @@ class Envira_Gallery_Editor_Lite {
230
  }
231
 
232
  // Load the editor class.
233
- $envira_gallery_editor_lite = Envira_Gallery_Editor_Lite::get_instance();
4
  *
5
  * @since 1.0.0
6
  *
7
+ * @package Envira_Gallery
8
  * @author Thomas Griffin
9
  */
10
+ class Envira_Gallery_Editor {
11
 
12
  /**
13
  * Holds the class object.
57
 
58
  // Add a custom media button to the editor.
59
  add_filter( 'media_buttons_context', array( $this, 'media_button' ) );
60
+ add_action( 'save_post', array( $this, 'save_gallery_ids' ), 9999 );
61
+ add_action( 'before_delete_post', array( $this, 'remove_gallery_ids' ) );
62
 
63
  }
64
 
72
  */
73
  public function media_button( $buttons ) {
74
 
75
+ // Enqueue styles.
76
+ wp_register_style( $this->base->plugin_slug . '-editor-style', plugins_url( 'assets/css/editor.css', $this->base->file ), array(), $this->base->version );
77
+ wp_enqueue_style( $this->base->plugin_slug . '-editor-style' );
78
 
79
  // Enqueue the script that will trigger the editor button.
80
+ wp_enqueue_script( $this->base->plugin_slug . '-editor-script', plugins_url( 'assets/js/editor.js', $this->base->file ), array( 'jquery' ), $this->base->version, true );
81
+ wp_localize_script( $this->base->plugin_slug . '-editor-script', 'envira_gallery_editor', array(
82
+ 'get_galleries_nonce' => wp_create_nonce( 'envira-gallery-editor-get-galleries' ),
83
+ ) );
84
+
85
+ // Create the media button.
86
+ $button = '<a id="envira-media-modal-button" href="#" class="button envira-gallery-choose-gallery" data-action="gallery" title="' . esc_attr__( 'Add Gallery', 'envira-gallery' ) . '" >
87
+ <span class="envira-media-icon"></span> ' .
88
+ __( 'Add Gallery', 'envira-gallery' ) .
89
+ '</a>';
90
 
91
+ // Filter the button.
92
+ $button = apply_filters( 'envira_gallery_media_button', $button, $buttons );
93
 
94
  // Append the button.
95
  return $buttons . $button;
97
  }
98
 
99
  /**
100
+ * Checks for the existience of any Envira Gallery shortcodes in the Post's content,
101
+ * storing this Post's ID in each Envira Gallery.
102
  *
103
+ * This allows Envira's WP_List_Table to tell the user which Post(s) the Gallery is
104
+ * included in.
105
+ *
106
+ * @since 1.3.3.6
107
+ *
108
+ * @param int $post_id Post ID
109
  */
110
+ public function save_gallery_ids( $post_id ) {
111
 
112
+ $this->update_gallery_post_ids( $post_id, false );
113
 
114
  }
115
 
116
  /**
117
+ * Removes the given Post ID from all Envira Galleries that contain the Post ID
118
  *
119
+ * @since 1.3.3.6
120
+ *
121
+ * @param int $post_id Post ID
122
+ */
123
+ public function remove_gallery_ids( $post_id ) {
124
+
125
+ $this->update_gallery_post_ids( $post_id, true );
126
+
127
+ }
128
+
129
+ /**
130
+ * Checks for Envira Gallery shortcodes in the given content.
131
+ *
132
+ * If found, adds or removes those shortcode IDs to the given Post ID
133
  *
134
+ * @since 1.3.3.6
135
+ *
136
+ * @param int $post_id Post ID
137
+ * @param bool $remove Remove Post ID from Gallery Meta (false)
138
+ * @return bool
139
  */
140
+ private function update_gallery_post_ids( $post_id, $remove = false ) {
141
+
142
+ // Get post
143
+ $post = get_post( $post_id );
144
+ if ( ! $post ) {
145
+ return;
146
+ }
147
+
148
+ // Don't do anything if we are saving a Gallery or Album
149
+ if ( in_array( $post->post_type, array( 'envira', 'envira_album' ) ) ) {
150
+ return;
151
+ }
152
+
153
+ // Don't do anything if this is a Post Revision
154
+ if ( wp_is_post_revision( $post ) ) {
155
+ return false;
156
+ }
157
 
158
+ // Check content for shortcodes
159
+ if ( ! has_shortcode( $post->post_content, 'envira-gallery' ) ) {
160
+ return false;
161
  }
162
 
163
+ // Content has Envira shortcode(s)
164
+ // Extract them to get Gallery IDs
165
+ $pattern = '\[(\[?)(envira\-gallery)(?![\w-])([^\]\/]*(?:\/(?!\])[^\]\/]*)*?)(?:(\/)\]|\](?:([^\[]*+(?:\[(?!\/\2\])[^\[]*+)*+)\[\/\2\])?)(\]?)';
166
+ if ( ! preg_match_all( '/'. $pattern .'/s', $post->post_content, $matches ) ) {
167
+ return false;
168
+ }
169
+ if ( ! is_array( $matches[3] ) ) {
170
+ return false;
171
+ }
172
+
173
+ // Iterate through shortcode matches, extracting the gallery ID and storing it in the meta
174
+ $gallery_ids = array();
175
+ foreach ( $matches[3] as $shortcode ) {
176
+ // Grab ID
177
+ $gallery_ids[] = preg_replace( "/[^0-9]/", "", $shortcode );
178
+ }
179
+
180
+ // Check we found gallery IDs
181
+ if ( ! $gallery_ids ) {
182
+ return false;
183
+ }
184
+
185
+ // Iterate through each gallery
186
+ foreach ( $gallery_ids as $gallery_id ) {
187
+ // Get Post IDs this Gallery is included in
188
+ $post_ids = get_post_meta( $gallery_id, '_eg_in_posts', true );
189
+ if ( ! is_array( $post_ids ) ) {
190
+ $post_ids = array();
191
+ }
192
+
193
+
194
+ if ( $remove ) {
195
+ // Remove the Post ID
196
+ if ( isset( $post_ids[ $post_id ] ) ) {
197
+ unset( $post_ids[ $post_id ] );
198
+ }
199
+ } else {
200
+ // Add the Post ID
201
+ $post_ids[ $post_id ] = $post_id;
202
+ }
203
+
204
+ // Save
205
+ update_post_meta( $gallery_id, '_eg_in_posts', $post_ids );
206
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
 
208
  }
209
 
212
  *
213
  * @since 1.0.0
214
  *
215
+ * @return object The Envira_Gallery_Editor object.
216
  */
217
  public static function get_instance() {
218
 
219
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Editor ) ) {
220
+ self::$instance = new Envira_Gallery_Editor();
221
  }
222
 
223
  return self::$instance;
227
  }
228
 
229
  // Load the editor class.
230
+ $envira_gallery_editor = Envira_Gallery_Editor::get_instance();
includes/admin/media-view.php ADDED
@@ -0,0 +1,300 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Media View class.
4
+ *
5
+ * @since 1.0.3
6
+ *
7
+ * @package Envira_Gallery
8
+ * @author Tim Carr
9
+ */
10
+ class Envira_Gallery_Media_View {
11
+
12
+ /**
13
+ * Holds the class object.
14
+ *
15
+ * @since 1.0.0
16
+ *
17
+ * @var object
18
+ */
19
+ public static $instance;
20
+
21
+ /**
22
+ * Path to the file.
23
+ *
24
+ * @since 1.0.0
25
+ *
26
+ * @var string
27
+ */
28
+ public $file = __FILE__;
29
+
30
+ /**
31
+ * Holds the base class object.
32
+ *
33
+ * @since 1.0.0
34
+ *
35
+ * @var object
36
+ */
37
+ public $base;
38
+
39
+ /**
40
+ * Primary class constructor.
41
+ *
42
+ * @since 1.0.0
43
+ */
44
+ public function __construct() {
45
+
46
+ // Base
47
+ $this->base = Envira_Gallery_Lite::get_instance();
48
+
49
+ // Modals
50
+ add_filter( 'envira_gallery_media_view_strings', array( $this, 'media_view_strings' ) );
51
+ add_action( 'print_media_templates', array( $this, 'print_media_templates' ) );
52
+
53
+ }
54
+
55
+ /**
56
+ * Adds media view (modal) strings
57
+ *
58
+ * @since 1.0.3
59
+ *
60
+ * @param array $strings Media View Strings
61
+ * @return array Media View Strings
62
+ */
63
+ public function media_view_strings( $strings ) {
64
+
65
+ return $strings;
66
+
67
+ }
68
+
69
+ /**
70
+ * Outputs backbone.js wp.media compatible templates, which are loaded into the modal
71
+ * view
72
+ *
73
+ * @since 1.0.3
74
+ */
75
+ public function print_media_templates() {
76
+
77
+ // Always output certain print media templates
78
+ // Insert Gallery (into Visual / Text Editor)
79
+ // Use: wp.media.template( 'envira-selection' )
80
+ ?>
81
+ <script type="text/html" id="tmpl-envira-selection">
82
+ <div class="media-frame-title">
83
+ <h1><?php _e( 'Insert', 'envira-gallery' ); ?></h1>
84
+ </div>
85
+ <div class="media-frame-content">
86
+ <div class="attachments-browser envira-gallery envira-gallery-editor">
87
+ <ul class="attachments">
88
+ </ul>
89
+
90
+ <!-- Helpful Tips -->
91
+ <div class="media-sidebar">
92
+ <h3><?php _e( 'Helpful Tips', 'envira-gallery' ); ?></h3>
93
+ <strong><?php _e( 'Choosing Your Gallery', 'envira-gallery' ); ?></strong>
94
+ <p>
95
+ <?php _e( 'To choose your gallery, simply click on one of the boxes to the left. The "Insert Gallery" button will be activated once you have selected a gallery.', 'envira-gallery' ); ?>
96
+ </p>
97
+
98
+ <strong><?php _e( 'Inserting Your Gallery', 'envira-gallery' ); ?></strong>
99
+ <p>
100
+ <?php _e( 'To insert your gallery into the editor, click on the "Insert Gallery" button below.', 'envira-gallery' ); ?>
101
+ </p>
102
+ </div>
103
+
104
+ <!-- Search -->
105
+ <div class="media-toolbar">
106
+ <div class="media-toolbar-secondary">
107
+ <span class="spinner"></span>
108
+ </div>
109
+ <div class="media-toolbar-primary search-form">
110
+ <label for="envira-gallery-search" class="screen-reader-text"><?php _e( 'Search', 'envira-gallery' ); ?></label>
111
+ <input type="search" placeholder="<?php _e( 'Search', 'envira-gallery' ); ?>" id="envira-gallery-search" class="search" />
112
+ </div>
113
+ </div>
114
+ </div>
115
+ </div>
116
+
117
+ <!-- Footer Bar -->
118
+ <div class="media-frame-toolbar">
119
+ <div class="media-toolbar">
120
+ <div class="media-toolbar-primary search-form">
121
+ <button type="button" class="button media-button button-primary button-large media-button-insert" disabled="disabled">
122
+ <?php _e( 'Insert', 'envira-gallery' ); ?>
123
+ </button>
124
+ </div>
125
+ </div>
126
+ </div>
127
+ </script>
128
+ <?php
129
+
130
+ // Single Selection Item (Gallery or Album)
131
+ // Use: wp.media.template( 'envira-selection-item' )
132
+ ?>
133
+ <script type="text/html" id="tmpl-envira-selection-item">
134
+ <div class="attachment-preview" data-id="{{ data.id }}">
135
+ <div class="thumbnail">
136
+ <#
137
+ if ( data.thumbnail != '' ) {
138
+ #>
139
+ <img src="{{ data.thumbnail }}" alt="{{ data.title }}" />
140
+ <#
141
+ }
142
+ #>
143
+ <strong>
144
+ <span>{{ data.title }}</span>
145
+ </strong>
146
+ <code>
147
+ [envira-{{ data.action }} id="{{ data.id }}"]
148
+ </code>
149
+ </div>
150
+ </div>
151
+
152
+ <a class="check">
153
+ <div class="media-modal-icon"></div>
154
+ </a>
155
+ </script>
156
+ <?php
157
+
158
+ // Error
159
+ // Use: wp.media.template( 'envira-gallery-error' )
160
+ ?>
161
+ <script type="text/html" id="tmpl-envira-gallery-error">
162
+ <p>
163
+ {{ data.error }}
164
+ </p>
165
+ </script>
166
+
167
+ <?php
168
+ // Only load other Backbone templates if we're on an Envira CPT.
169
+ global $post;
170
+ if ( isset( $post ) ) {
171
+ $post_id = absint( $post->ID );
172
+ } else {
173
+ $post_id = 0;
174
+ }
175
+
176
+ // Bail if we're not editing an Envira Gallery
177
+ if ( get_post_type( $post_id ) != 'envira' ) {
178
+ return;
179
+ }
180
+
181
+ // Single Image Editor
182
+ // Use: wp.media.template( 'envira-meta-editor' )
183
+ ?>
184
+ <script type="text/html" id="tmpl-envira-meta-editor">
185
+ <div class="edit-media-header">
186
+ <button class="left dashicons"><span class="screen-reader-text"><?php _e( 'Edit previous media item' ); ?></span></button>
187
+ <button class="right dashicons"><span class="screen-reader-text"><?php _e( 'Edit next media item' ); ?></span></button>
188
+ </div>
189
+ <div class="media-frame-title">
190
+ <h1><?php _e( 'Edit Metadata', 'envira-gallery' ); ?></h1>
191
+ </div>
192
+ <div class="media-frame-content">
193
+ <div class="attachment-details save-ready">
194
+ <!-- Left -->
195
+ <div class="attachment-media-view portrait">
196
+ <div class="thumbnail thumbnail-image">
197
+ <img class="details-image" src="{{ data.src }}" draggable="false" />
198
+ </div>
199
+ </div>
200
+
201
+ <!-- Right -->
202
+ <div class="attachment-info">
203
+ <!-- Settings -->
204
+ <div class="settings">
205
+ <!-- Attachment ID -->
206
+ <input type="hidden" name="id" value="{{ data.id }}" />
207
+
208
+ <!-- Image Title -->
209
+ <label class="setting">
210
+ <span class="name"><?php _e( 'Title', 'envira-gallery' ); ?></span>
211
+ <input type="text" name="title" value="{{ data.title }}" />
212
+ <div class="description">
213
+ <?php _e( 'Image titles can take any type of HTML. You can adjust the position of the titles in the main Lightbox settings.', 'envira-gallery' ); ?>
214
+ </div>
215
+ </label>
216
+
217
+ <!-- Alt Text -->
218
+ <label class="setting">
219
+ <span class="name"><?php _e( 'Alt Text', 'envira-gallery' ); ?></span>
220
+ <input type="text" name="alt" value="{{ data.alt }}" />
221
+ <div class="description">
222
+ <?php _e( 'Very important for SEO, the Alt Text describes the image.', 'envira-gallery' ); ?>
223
+ </div>
224
+ </label>
225
+
226
+ <!-- Link -->
227
+ <label class="setting">
228
+ <span class="name"><?php _e( 'URL', 'envira-gallery' ); ?></span>
229
+ <input type="text" name="link" value="{{ data.link }}" />
230
+ <# if ( typeof( data.id ) === 'number' ) { #>
231
+ <span class="buttons">
232
+ <button class="button button-small media-file"><?php _e( 'Media File', 'envira-gallery' ); ?></button>
233
+ <button class="button button-small attachment-page"><?php _e( 'Attachment Page', 'envira-gallery' ); ?></button>
234
+ </span>
235
+ <# } #>
236
+ <span class="description">
237
+ <?php _e( 'Enter a hyperlink if you wish to link this image to somewhere other than its full size image.', 'envira-gallery' ); ?>
238
+ </span>
239
+ </label>
240
+
241
+ <label class="setting">
242
+ <!-- Upgrade -->
243
+ <?php
244
+ Envira_Gallery_Notice_Admin::get_instance()->display_inline_notice(
245
+ 'envira_gallery_edit_metadata',
246
+ __( 'Want Captions and more options?', 'envira-gallery' ),
247
+ __( 'By upgrading to Envira Pro, you can get access to numerous other features, including: HTML captions, open links in new windows, WooCommerce product integration and so much more!', 'envira-gallery' ),
248
+ 'warning',
249
+ __( 'Click here to Upgrade', 'envira-gallery' ),
250
+ Envira_Gallery_Common_Admin::get_instance()->get_upgrade_link(),
251
+ false
252
+ );
253
+ ?>
254
+ </label>
255
+ </div>
256
+ <!-- /.settings -->
257
+
258
+ <!-- Actions -->
259
+ <div class="actions">
260
+ <a href="#" class="envira-gallery-meta-submit button media-button button-large button-primary media-button-insert" title="<?php esc_attr_e( 'Save Metadata', 'envira-gallery' ); ?>">
261
+ <?php _e( 'Save Metadata', 'envira-gallery' ); ?>
262
+ </a>
263
+
264
+ <!-- Save Spinner -->
265
+ <span class="settings-save-status">
266
+ <span class="spinner"></span>
267
+ <span class="saved"><?php _e( 'Saved.', 'envira-gallery' ); ?></span>
268
+ </span>
269
+ </div>
270
+ <!-- /.actions -->
271
+ </div>
272
+ </div>
273
+ </div>
274
+ </script>
275
+
276
+ <?php
277
+
278
+ }
279
+
280
+ /**
281
+ * Returns the singleton instance of the class.
282
+ *
283
+ * @since 1.0.0
284
+ *
285
+ * @return object The Envira_Gallery_Media_View object.
286
+ */
287
+ public static function get_instance() {
288
+
289
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Media_View ) ) {
290
+ self::$instance = new Envira_Gallery_Media_View();
291
+ }
292
+
293
+ return self::$instance;
294
+
295
+ }
296
+
297
+ }
298
+
299
+ // Load the media class.
300
+ $envira_gallery_media_view = Envira_Gallery_Media_View::get_instance();
includes/admin/media.php CHANGED
@@ -4,10 +4,10 @@
4
  *
5
  * @since 1.0.0
6
  *
7
- * @package Envira_Gallery_Lite
8
  * @author Thomas Griffin
9
  */
10
- class Envira_Gallery_Media_Lite {
11
 
12
  /**
13
  * Holds the class object.
@@ -273,195 +273,17 @@ class Envira_Gallery_Media_Lite {
273
 
274
  }
275
 
276
- /**
277
- * Prepares a custom media upload form that allows multiple forms on one page.
278
- *
279
- * @since 1.0.0
280
- *
281
- * @return null Return early if the form cannot be output.
282
- */
283
- public function media_upload_form() {
284
-
285
- do_action( 'pre-upload-ui' );
286
-
287
- if ( ! $this->device_can_upload() ) {
288
- echo '<p>' . sprintf( __( 'The web browser on your device cannot be used to upload files. You may be able to use the <a href="%s">native app for your device</a> instead.', 'envira-gallery-lite' ), 'http://wordpress.org/mobile/' ) . '</p>';
289
- return;
290
- }
291
-
292
- if ( ! $this->has_upload_capacity() ) {
293
- do_action( 'upload_ui_over_quota' );
294
- return;
295
- }
296
-
297
- // Get both resize width and height for the media form.
298
- $width = $this->get_resize_width();
299
- $height = $this->get_resize_height();
300
-
301
- // Output the media form.
302
- $this->do_media_upload_form( $width, $height );
303
-
304
- }
305
-
306
- /**
307
- * Outputs a custom media upload form that allows multiple forms on one page.
308
- *
309
- * @since 1.0.0
310
- *
311
- * @global bool $ie_IE Flag for Internet Explorer.
312
- * @global bool $is_opera Flag for Opera.
313
- * @param int $width The media resize width.
314
- * @param int $height The media resize height.
315
- */
316
- public function do_media_upload_form( $width, $height ) {
317
-
318
- // Prepare globals and variables.
319
- global $is_IE, $is_opera;
320
- $sizes = array( 'KB', 'MB', 'GB' );
321
- $max_upload_size = wp_max_upload_size();
322
-
323
- ?>
324
- <script type="text/javascript">var resize_width = <?php echo $width; ?>, resize_height = <?php echo $height; ?>;</script>
325
- <div id="envira-gallery-upload-error"></div>
326
- <div id="envira-gallery-plupload-upload-ui" class="hide-if-no-js">
327
- <?php do_action( 'pre-plupload-upload-ui' ); ?>
328
- <div id="envira-gallery-drag-drop-area">
329
- <div class="drag-drop-inside">
330
- <p class="drag-drop-info"><?php _e( 'Drop images here', 'envira-gallery-lite' ); ?></p>
331
- <p><?php _ex( 'or', 'Uploader: Drop images here - or - Select Images', 'envira-gallery-lite' ); ?></p>
332
- <p class="drag-drop-buttons">
333
- <input id="envira-gallery-plupload-browse-button" type="button" value="<?php esc_attr_e( 'Select Images', 'envira-gallery-lite' ); ?>" class="button" />
334
- </p>
335
- </div>
336
- </div>
337
- <?php do_action( 'post-plupload-upload-ui' ); ?>
338
- </div>
339
-
340
- <div id="envira-gallery-html-upload-ui" class="hide-if-js">
341
- <?php do_action('pre-html-upload-ui'); ?>
342
- <p id="envira-gallery-async-upload-wrap">
343
- <label class="screen-reader-text" for="envira-gallery-async-upload"><?php _e( 'Upload', 'envira-gallery-lite' ); ?></label>
344
- <input type="file" name="async-upload" id="envira-gallery-async-upload" />
345
- <?php submit_button( __( 'Upload', 'envira-gallery-lite' ), 'button', 'html-upload', false ); ?>
346
- <a href="#" onclick="try{top.tb_remove();}catch(e){};return false;"><?php _e( 'Cancel', 'envira-gallery-lite' ); ?></a>
347
- </p>
348
- <div class="clear"></div>
349
- <?php do_action( 'post-html-upload-ui' ); ?>
350
- </div>
351
-
352
- <span class="max-upload-size"><?php printf( __( 'Maximum upload file size: %d%s.', 'envira-gallery-lite' ), esc_html( $this->get_upload_size_unit( $sizes ) ), esc_html( $sizes[$this->get_upload_size_unit( $sizes, 'unit' )] ) ); ?></span>
353
- <?php
354
-
355
- // Output a notice if the browser may have trouble with uploading large images.
356
- if ( ( $is_IE || $is_opera ) && $max_upload_size > 100 * 1024 * 1024 ) {
357
- echo '<span class="big-file-warning">' . __( 'Your browser has some limitations uploading large files with the multi-file uploader. Please use the browser uploader for files over 100MB.', 'envira-gallery-lite' ) . '</span>';
358
- }
359
-
360
- do_action( 'post-upload-ui' );
361
-
362
- }
363
-
364
- /**
365
- * Flag if the device can upload images.
366
- *
367
- * @since 1.0.0
368
- *
369
- * @return bool True if it can, false otherwise.
370
- */
371
- public function device_can_upload() {
372
-
373
- // Why is this method internal? It is quite useful.
374
- return _device_can_upload();
375
-
376
- }
377
-
378
- /**
379
- * Flag if the site has the capacity to receive an upload.
380
- *
381
- * @since 1.0.0
382
- *
383
- * @return bool True if it can, false otherwise.
384
- */
385
- public function has_upload_capacity() {
386
-
387
- return ! ( is_multisite() && ! is_upload_space_available() );
388
-
389
- }
390
-
391
- /**
392
- * Returns the resize width for the media form.
393
- *
394
- * @since 1.0.0
395
- *
396
- * @return int $width The resize width.
397
- */
398
- public function get_resize_width() {
399
-
400
- $width = absint( get_option( 'large_size_w' ) );
401
- if ( ! $width ) {
402
- $width = 1024;
403
- }
404
-
405
- return $width;
406
-
407
- }
408
-
409
- /**
410
- * Returns the resize height for the media form.
411
- *
412
- * @since 1.0.0
413
- *
414
- * @return int $width The resize height.
415
- */
416
- public function get_resize_height() {
417
-
418
- $height = absint( get_option( 'large_size_h' ) );
419
- if ( ! $height ) {
420
- $height = 1024;
421
- }
422
-
423
- return $height;
424
-
425
- }
426
-
427
- /**
428
- * Returns the upload unit for the media uploader.
429
- *
430
- * @since 1.0.0
431
- *
432
- * @param array $sizes Array of sizes to use for units.
433
- * @param string $type Type of unit to retrieve ('size' or 'unit').
434
- */
435
- public function get_upload_size_unit( $sizes, $type = 'size' ) {
436
-
437
- $upload_size_unit = wp_max_upload_size();
438
- for ( $u = -1; $upload_size_unit > 1024 && $u < count( $sizes ) - 1; $u++ ) {
439
- $upload_size_unit /= 1024;
440
- }
441
-
442
- // If the upload size is 0, disable uploading, otherwise allow uploading to continue.
443
- if ( $u < 0 ) {
444
- $upload_size_unit = 0;
445
- $u = 0;
446
- } else {
447
- $upload_size_unit = (int) $upload_size_unit;
448
- }
449
-
450
- return 'unit' == $type ? $u : $upload_size_unit;
451
-
452
- }
453
-
454
  /**
455
  * Returns the singleton instance of the class.
456
  *
457
  * @since 1.0.0
458
  *
459
- * @return object The Envira_Gallery_Media_Lite object.
460
  */
461
  public static function get_instance() {
462
 
463
- if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Media_Lite ) ) {
464
- self::$instance = new Envira_Gallery_Media_Lite();
465
  }
466
 
467
  return self::$instance;
@@ -471,4 +293,4 @@ class Envira_Gallery_Media_Lite {
471
  }
472
 
473
  // Load the media class.
474
- $envira_gallery_media_lite = Envira_Gallery_Media_Lite::get_instance();
4
  *
5
  * @since 1.0.0
6
  *
7
+ * @package Envira_Gallery
8
  * @author Thomas Griffin
9
  */
10
+ class Envira_Gallery_Media {
11
 
12
  /**
13
  * Holds the class object.
273
 
274
  }
275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  /**
277
  * Returns the singleton instance of the class.
278
  *
279
  * @since 1.0.0
280
  *
281
+ * @return object The Envira_Gallery_Media object.
282
  */
283
  public static function get_instance() {
284
 
285
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Media ) ) {
286
+ self::$instance = new Envira_Gallery_Media();
287
  }
288
 
289
  return self::$instance;
293
  }
294
 
295
  // Load the media class.
296
+ $envira_gallery_media = Envira_Gallery_Media::get_instance();
includes/admin/metaboxes.php CHANGED
@@ -4,10 +4,10 @@
4
  *
5
  * @since 1.0.0
6
  *
7
- * @package Envira_Gallery_Lite
8
  * @author Thomas Griffin
9
  */
10
- class Envira_Gallery_Metaboxes_Lite {
11
 
12
  /**
13
  * Holds the class object.
@@ -46,12 +46,23 @@ class Envira_Gallery_Metaboxes_Lite {
46
  // Load the base class object.
47
  $this->base = Envira_Gallery_Lite::get_instance();
48
 
49
- // Load metabox assets.
50
- add_action( 'admin_enqueue_scripts', array( $this, 'meta_box_styles' ) );
51
- add_action( 'admin_enqueue_scripts', array( $this, 'meta_box_scripts' ) );
 
 
 
 
 
 
 
 
 
 
 
52
 
53
- // Load the metabox hooks and filters.
54
- add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 100 );
55
 
56
  // Load all tabs.
57
  add_action( 'envira_gallery_tab_images', array( $this, 'images_tab' ) );
@@ -59,11 +70,95 @@ class Envira_Gallery_Metaboxes_Lite {
59
  add_action( 'envira_gallery_tab_lightbox', array( $this, 'lightbox_tab' ) );
60
  add_action( 'envira_gallery_tab_misc', array( $this, 'misc_tab' ) );
61
 
62
- // Add action to save metabox config options.
 
 
 
 
 
 
 
 
 
 
63
  add_action( 'save_post', array( $this, 'save_meta_boxes' ), 10, 2 );
64
 
65
  }
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  /**
68
  * Loads styles for our metaboxes.
69
  *
@@ -71,19 +166,27 @@ class Envira_Gallery_Metaboxes_Lite {
71
  *
72
  * @return null Return early if not on the proper screen.
73
  */
74
- public function meta_box_styles() {
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
  // Load necessary metabox styles.
77
  wp_register_style( $this->base->plugin_slug . '-metabox-style', plugins_url( 'assets/css/metabox.css', $this->base->file ), array(), $this->base->version );
78
  wp_enqueue_style( $this->base->plugin_slug . '-metabox-style' );
79
 
80
- // If WordPress version < 4.0, add attachment-details-modal-support.css
81
- // This contains the 4.0 CSS to make the attachment window display correctly
82
- $version = (float) get_bloginfo( 'version' );
83
- if ( $version < 4 ) {
84
- wp_register_style( $this->base->plugin_slug . '-attachment-details-modal-support', plugins_url( 'assets/css/attachment-details-modal-support.css', $this->base->file ), array(), $this->base->version );
85
- wp_enqueue_style( $this->base->plugin_slug . '-attachment-details-modal-support' );
86
- }
87
 
88
  }
89
 
@@ -93,127 +196,116 @@ class Envira_Gallery_Metaboxes_Lite {
93
  * @since 1.0.0
94
  *
95
  * @global int $id The current post ID.
96
- * @global object $post The current post object..
97
  * @return null Return early if not on the proper screen.
98
  */
99
- public function meta_box_scripts( $hook ) {
100
 
101
  global $id, $post;
102
 
103
- if ( isset( get_current_screen()->base ) && 'post' !== get_current_screen()->base ) {
 
 
 
 
104
  return;
105
  }
106
 
107
- if ( isset( get_current_screen()->post_type ) && in_array( get_current_screen()->post_type, $this->get_skipped_posttypes() ) ) {
 
108
  return;
109
  }
110
 
111
  // Set the post_id for localization.
112
  $post_id = isset( $post->ID ) ? $post->ID : (int) $id;
113
 
114
- // Load WordPress necessary scripts.
115
- wp_enqueue_script( 'plupload-handlers' );
116
  wp_enqueue_script( 'jquery-ui-sortable' );
117
- wp_enqueue_media( array( 'post' => $post_id ) );
118
-
119
- // Load necessary metabox scripts.
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  wp_register_script( $this->base->plugin_slug . '-metabox-script', plugins_url( 'assets/js/min/metabox-min.js', $this->base->file ), array( 'jquery', 'plupload-handlers', 'quicktags', 'jquery-ui-sortable' ), $this->base->version, true );
121
  wp_enqueue_script( $this->base->plugin_slug . '-metabox-script' );
122
  wp_localize_script(
123
  $this->base->plugin_slug . '-metabox-script',
124
  'envira_gallery_metabox',
125
  array(
126
- 'ajax' => admin_url( 'admin-ajax.php' ),
127
- 'gallery' => esc_attr__( 'Click Here to Insert from Other Image Sources', 'envira-gallery-lite' ),
128
- 'id' => $post_id,
129
- 'import' => __( 'You must select a file to import before continuing.', 'envira-gallery-lite' ),
130
- 'insert_nonce' => wp_create_nonce( 'envira-gallery-insert-images' ),
131
- 'inserting' => __( 'Inserting...', 'envira-gallery-lite' ),
132
- 'library_search' => wp_create_nonce( 'envira-gallery-library-search' ),
133
- 'load_image' => wp_create_nonce( 'envira-gallery-load-image' ),
134
- 'load_gallery' => wp_create_nonce( 'envira-gallery-load-gallery' ),
135
- 'plupload' => $this->get_plupload_init( $post_id ),
136
- 'refresh_nonce' => wp_create_nonce( 'envira-gallery-refresh' ),
137
- 'remove' => __( 'Are you sure you want to remove this image from the gallery?', 'envira-gallery-lite' ),
138
- 'remove_nonce' => wp_create_nonce( 'envira-gallery-remove-image' ),
139
- 'save_nonce' => wp_create_nonce( 'envira-gallery-save-meta' ),
140
- 'saving' => __( 'Saving...', 'envira-gallery-lite' ),
141
- 'sort' => wp_create_nonce( 'envira-gallery-sort' )
 
 
 
 
142
  )
143
  );
144
 
145
- // If on an Envira post type, add custom CSS for hiding specific things.
146
- if ( isset( get_current_screen()->post_type ) && 'envira' == get_current_screen()->post_type ) {
147
- add_action( 'admin_head', array( $this, 'meta_box_css' ) );
148
- }
 
 
 
 
149
 
150
  }
151
 
152
  /**
153
- * Returns custom plupload init properties for the media uploader.
154
- *
155
- * @since 1.0.0
156
- *
157
- * @param int $post_id The current post ID.
158
- * @return array Array of plupload init data.
159
- */
160
- public function get_plupload_init( $post_id ) {
161
-
162
- // Prepare $_POST form variables and apply backwards compat filter.
163
- $post_params = array(
164
- 'post_id' => $post_id,
165
- '_wpnonce' => wp_create_nonce( 'media-form' ),
166
- 'type' => '',
167
- 'tab' => '',
168
- 'short' => 3
169
- );
170
- $post_params = apply_filters( 'upload_post_params', $post_params );
171
-
172
- // Prepare upload size parameters.
173
- $max_upload_size = wp_max_upload_size();
174
-
175
- // Prepare the plupload init array.
176
- $plupload_init = array(
177
- 'runtimes' => 'html5,silverlight,flash,html4',
178
- 'browse_button' => 'envira-gallery-plupload-browse-button',
179
- 'container' => 'envira-gallery-plupload-upload-ui',
180
- 'drop_element' => 'envira-gallery-drag-drop-area',
181
- 'file_data_name' => 'async-upload',
182
- 'multiple_queues' => true,
183
- 'max_file_size' => $max_upload_size . 'b',
184
- 'url' => admin_url( 'async-upload.php' ),
185
- 'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ),
186
- 'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
187
- 'filters' => array(
188
- array(
189
- 'title' => __( 'Allowed Files', 'envira-gallery-lite' ),
190
- 'extensions' => '*'
191
- ),
192
- ),
193
- 'multipart' => true,
194
- 'urlstream_upload' => true,
195
- 'multipart_params' => $post_params,
196
- 'resize' => array(
197
- 'width' => Envira_Gallery_Media_Lite::get_instance()->get_resize_width(),
198
- 'height' => Envira_Gallery_Media_Lite::get_instance()->get_resize_height(),
199
- 'quality' => 100,
200
- 'enabled' => true
201
- )
202
- );
203
 
204
- // If we are on a mobile device, disable multi selection.
205
- if ( wp_is_mobile() ) {
206
- $plupload_init['multi_selection'] = false;
207
- }
208
 
209
- // Apply backwards compat filter.
210
- $plupload_init = apply_filters( 'plupload_init', $plupload_init );
 
 
 
 
 
 
 
211
 
212
  // Return and apply a custom filter to our init data.
213
- return apply_filters( 'envira_gallery_plupload_init', $plupload_init, $post_id );
 
214
 
215
  }
216
-
217
  /**
218
  * Hides unnecessary meta box items on Envira post type screens.
219
  *
@@ -225,6 +317,9 @@ class Envira_Gallery_Metaboxes_Lite {
225
  <style type="text/css">.misc-pub-section:not(.misc-pub-post-status) { display: none; }</style>
226
  <?php
227
 
 
 
 
228
  }
229
 
230
  /**
@@ -234,25 +329,43 @@ class Envira_Gallery_Metaboxes_Lite {
234
  */
235
  public function add_meta_boxes() {
236
 
237
- // Let's remove all of those dumb metaboxes from our post type screen to control the experience.
238
- $this->remove_all_the_metaboxes();
239
-
240
- // Get all public post types.
241
- $post_types = get_post_types( array( 'public' => true ) );
242
 
243
- // Splice the envira post type since it is not visible to the public by default.
244
- $post_types[] = 'envira';
 
 
245
 
246
- // Loops through the post types and add the metaboxes.
247
- foreach ( (array) $post_types as $post_type ) {
248
- // Don't output boxes on these post types.
249
- if ( in_array( $post_type, $this->get_skipped_posttypes() ) ) {
250
- continue;
251
- }
 
 
 
 
 
 
252
 
253
- add_meta_box( 'envira-gallery', __( 'Envira Gallery Settings', 'envira-gallery-lite' ), array( $this, 'meta_box_callback' ), $post_type, 'normal', 'high' );
 
 
 
 
 
 
 
 
 
 
254
  }
255
 
 
 
 
 
256
  }
257
 
258
  /**
@@ -271,13 +384,16 @@ class Envira_Gallery_Metaboxes_Lite {
271
  $post_type = 'envira';
272
 
273
  // These are the metabox IDs you want to pass over. They don't have to match exactly. preg_match will be run on them.
274
- $pass_over = apply_filters( 'envira_gallery_metabox_ids', array( 'submitdiv', 'envira' ) );
 
275
 
276
  // All the metabox contexts you want to check.
277
- $contexts = apply_filters( 'envira_gallery_metabox_contexts', array( 'normal', 'advanced', 'side' ) );
 
278
 
279
  // All the priorities you want to check.
280
- $priorities = apply_filters( 'envira_gallery_metabox_priorities', array( 'high', 'core', 'default', 'low' ) );
 
281
 
282
  // Loop through and target each context.
283
  foreach ( $contexts as $context ) {
@@ -308,7 +424,44 @@ class Envira_Gallery_Metaboxes_Lite {
308
  }
309
 
310
  /**
311
- * Callback for displaying content in the registered metabox.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
  *
313
  * @since 1.0.0
314
  *
@@ -317,36 +470,75 @@ class Envira_Gallery_Metaboxes_Lite {
317
  public function meta_box_callback( $post ) {
318
 
319
  // Keep security first.
320
- wp_nonce_field( 'envira-gallery-lite', 'envira-gallery-lite' );
321
 
322
- // Check for our meta overlay helper.
323
- $gallery_data = get_post_meta( $post->ID, '_eg_gallery_data', true );
324
- $helper = get_post_meta( $post->ID, '_eg_just_published', true );
325
- $class = '';
326
- if ( $helper ) {
327
- $class = 'envira-helper-needed';
328
- }
329
 
330
- ?>
331
- <div id="envira-tabs" class="envira-clear <?php echo $class; ?>">
332
- <?php $this->meta_helper( $post, $gallery_data ); ?>
333
- <ul id="envira-tabs-nav" class="envira-clear">
334
- <?php $i = 0; foreach ( (array) $this->get_envira_tab_nav() as $id => $title ) : $class = 0 === $i ? 'envira-active' : ''; ?>
335
- <li class="<?php echo $class; ?>"><a href="#envira-tab-<?php echo $id; ?>" title="<?php echo $title; ?>"><?php echo $title; ?></a></li>
336
- <?php $i++; endforeach; ?>
337
- </ul>
338
- <?php $i = 0; foreach ( (array) $this->get_envira_tab_nav() as $id => $title ) : $class = 0 === $i ? 'envira-active' : ''; ?>
339
- <div id="envira-tab-<?php echo $id; ?>" class="envira-tab envira-clear <?php echo $class; ?>">
340
- <?php do_action( 'envira_gallery_tab_' . $id, $post ); ?>
341
- </div>
342
- <?php $i++; endforeach; ?>
343
- </div>
344
- <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
 
346
  }
347
 
348
  /**
349
- * Callback for getting all of the tabs for Envira galleries.
350
  *
351
  * @since 1.0.0
352
  *
@@ -355,21 +547,21 @@ class Envira_Gallery_Metaboxes_Lite {
355
  public function get_envira_tab_nav() {
356
 
357
  $tabs = array(
358
- 'images' => __( 'Images', 'envira-gallery-lite' ),
359
- 'config' => __( 'Config', 'envira-gallery-lite' ),
360
- 'lightbox' => __( 'Lightbox', 'envira-gallery-lite' )
361
  );
362
  $tabs = apply_filters( 'envira_gallery_tab_nav', $tabs );
363
 
364
  // "Misc" tab is required.
365
- $tabs['misc'] = __( 'Misc', 'envira-gallery-lite' );
366
 
367
  return $tabs;
368
 
369
  }
370
 
371
  /**
372
- * Callback for displaying the UI for main images tab.
373
  *
374
  * @since 1.0.0
375
  *
@@ -377,161 +569,127 @@ class Envira_Gallery_Metaboxes_Lite {
377
  */
378
  public function images_tab( $post ) {
379
 
380
- ?>
381
- <div class="envira-alert envira-clear" style="margin-bottom:10px;">
382
- <?php _e( '<em>Want to make your gallery workflow even better?</em> By upgrading to Envira Pro, you can get access to numerous other features, including: <strong>a fully featured gallery widget</strong>, <strong>complete gallery API</strong>, <strong>powerful gallery documentation</strong>, <strong>full mobile and Retina support</strong>, <strong>dedicated customer support</strong> and so much more! <a href="http://enviragallery.com/lite/?utm_source=liteplugin&utm_medium=link&utm_campaign=WordPress" title="Click here to upgrade to Envira Pro!" target="_blank">Click here to upgrade to Envira Pro!</a>', 'envira-gallery-lite' ); ?>
383
- </div>
384
- <?php
385
 
386
- // Output the custom media upload form.
387
- Envira_Gallery_Media_Lite::get_instance()->media_upload_form();
388
 
389
- // Prepare output data.
390
- $gallery_data = get_post_meta( $post->ID, '_eg_gallery_data', true );
391
 
392
- ?>
393
- <ul id="envira-gallery-output" class="envira-clear">
394
- <?php if ( ! empty( $gallery_data['gallery'] ) ) : ?>
395
- <?php foreach ( $gallery_data['gallery'] as $id => $data ) : ?>
396
- <?php echo $this->get_gallery_item( $id, $data, $post->ID ); ?>
397
- <?php endforeach; ?>
398
- <?php endif; ?>
399
- </ul>
400
- <?php $this->media_library( $post );
401
 
402
  }
403
 
404
  /**
405
- * Inserts the meta icon for displaying useful gallery meta like shortcode and template tag.
406
  *
407
  * @since 1.0.0
408
  *
409
- * @param object $post The current post object.
410
- * @param array $gallery_data Array of gallery data for the current post.
411
- * @return null Return early if this is an auto-draft.
412
  */
413
- public function meta_helper( $post, $gallery_data ) {
414
-
415
- if ( isset( $post->post_status ) && 'auto-draft' == $post->post_status ) {
416
- return;
 
 
 
 
 
 
 
 
 
417
  }
418
 
419
- // Check for our meta overlay helper.
420
- $helper = get_post_meta( $post->ID, '_eg_just_published', true );
421
- $class = '';
422
- if ( $helper ) {
423
- $class = 'envira-helper-active';
424
- delete_post_meta( $post->ID, '_eg_just_published' );
425
- }
426
 
427
- ?>
428
- <div class="envira-meta-helper <?php echo $class; ?>">
429
- <span class="envira-meta-close-text"><?php _e( '(click the icon to open and close the overlay dialog)', 'envira-gallery-lite' ); ?></span>
430
- <a href="#" class="envira-meta-icon" title="<?php esc_attr__( 'Click here to view meta information about this gallery.', 'envira-gallery-lite' ); ?>"></a>
431
- <div class="envira-meta-information">
432
- <p><?php _e( 'You can place this gallery anywhere into your posts, pages, custom post types or widgets by using the shortcode(s) below:', 'envira-gallery-lite' ); ?></p>
433
- <code><?php echo '[envira-gallery id="' . $post->ID . '"]'; ?></code>
434
- <?php if ( ! empty( $gallery_data['config']['slug'] ) ) : ?>
435
- <br><code><?php echo '[envira-gallery slug="' . $gallery_data['config']['slug'] . '"]'; ?></code>
436
- <?php endif; ?>
437
- <p><?php _e( 'You can also place this gallery into your template files by using the template tag(s) below:', 'envira-gallery-lite' ); ?></p>
438
- <code><?php echo 'if ( function_exists( \'envira_gallery\' ) ) { envira_gallery( \'' . $post->ID . '\' ); }'; ?></code>
439
- <?php if ( ! empty( $gallery_data['config']['slug'] ) ) : ?>
440
- <br><code><?php echo 'if ( function_exists( \'envira_gallery\' ) ) { envira_gallery( \'' . $gallery_data['config']['slug'] . '\', \'slug\' ); }'; ?></code>
441
- <?php endif; ?>
442
- </div>
443
- </div>
444
- <?php
 
445
 
446
  }
447
 
448
  /**
449
- * Callback for displaying the UI for selecting images from the media library to insert.
450
  *
451
  * @since 1.0.0
452
  *
453
  * @param object $post The current post object.
454
  */
455
- public function media_library( $post ) {
 
 
 
456
 
 
 
457
  ?>
458
- <div id="envira-gallery-upload-ui-wrapper">
459
- <div id="envira-gallery-upload-ui" class="envira-gallery-image-meta" style="display: none;">
460
- <div class="media-modal wp-core-ui">
461
- <a class="media-modal-close" href="#"><span class="media-modal-icon"></span></a>
462
- <div class="media-modal-content">
463
- <div class="media-frame envira-gallery-media-frame wp-core-ui hide-menu envira-gallery-meta-wrap">
464
- <div class="media-frame-title">
465
- <h1><?php _e( 'Insert Images into Gallery', 'envira-gallery-lite' ); ?></h1>
466
- </div>
467
- <div class="media-frame-router">
468
- <div class="media-router">
469
- <a href="#" class="media-menu-item active"><?php _e( 'Images', 'envira-gallery-lite' ); ?></a>
470
- <?php do_action( 'envira_gallery_modal_router', $post ); ?>
471
- </div><!-- end .media-router -->
472
- </div><!-- end .media-frame-router -->
473
- <!-- begin content for inserting slides from media library -->
474
- <div id="envira-gallery-select-images">
475
- <div class="media-frame-content">
476
- <div class="attachments-browser">
477
- <div class="media-toolbar envira-gallery-library-toolbar">
478
- <div class="media-toolbar-primary">
479
- <input type="search" placeholder="<?php esc_attr_e( 'Search', 'envira-gallery-lite' ); ?>" id="envira-gallery-gallery-search" class="search" value="" />
480
- </div>
481
- <div class="media-toolbar-secondary">
482
- <a class="button media-button button-large button-secodary envira-gallery-load-library" href="#" data-envira-gallery-offset="20"><?php _e( 'Load More Images from Library', 'envira-gallery-lite' ); ?></a></a><span class="spinner envira-gallery-spinner"></span>
483
- </div>
484
- </div>
485
- <?php $library = get_posts( array( 'post_type' => 'attachment', 'post_mime_type' => 'image', 'post_status' => 'inherit', 'posts_per_page' => 20 ) ); ?>
486
- <?php if ( $library ) : ?>
487
- <ul class="attachments envira-gallery-gallery">
488
- <?php foreach ( (array) $library as $image ) :
489
- $has_gallery = get_post_meta( $image->ID, '_eg_has_gallery', true );
490
- $class = $has_gallery && in_array( $post->ID, (array) $has_gallery ) ? ' selected envira-gallery-in-gallery' : ''; ?>
491
- <li class="attachment<?php echo $class; ?>" data-attachment-id="<?php echo absint( $image->ID ); ?>">
492
- <div class="attachment-preview landscape">
493
- <div class="thumbnail">
494
- <div class="centered">
495
- <?php $src = wp_get_attachment_image_src( $image->ID, 'thumbnail' ); ?>
496
- <img src="<?php echo esc_url( $src[0] ); ?>" />
497
- </div>
498
- </div>
499
- <a class="check" href="#"><div class="media-modal-icon"></div></a>
500
- </div>
501
- </li>
502
- <?php endforeach; ?>
503
- </ul><!-- end .envira-gallery-meta -->
504
- <?php endif; ?>
505
- <div class="media-sidebar">
506
- <div class="envira-gallery-meta-sidebar">
507
- <h3><?php _e( 'Helpful Tips', 'envira-gallery-lite' ); ?></h3>
508
- <strong><?php _e( 'Selecting Images', 'envira-gallery-lite' ); ?></strong>
509
- <p><?php _e( 'You can insert any image from your Media Library into your gallery. If the image you want to insert is not shown on the screen, you can either click on the "Load More Images from Library" button to load more images or use the search box to find the images you are looking for.', 'envira-gallery-lite' ); ?></p>
510
- </div><!-- end .envira-gallery-meta-sidebar -->
511
- </div><!-- end .media-sidebar -->
512
- </div><!-- end .attachments-browser -->
513
- </div><!-- end .media-frame-content -->
514
- </div><!-- end #envira-gallery-image-slides -->
515
- <!-- end content for inserting slides from media library -->
516
- <div class="media-frame-toolbar">
517
- <div class="media-toolbar">
518
- <div class="media-toolbar-primary">
519
- <a href="#" class="envira-gallery-media-insert button media-button button-large button-primary media-button-insert" title="<?php esc_attr_e( 'Insert Images into Gallery', 'envira-gallery-lite' ); ?>"><?php _e( 'Insert Images into Gallery', 'envira-gallery-lite' ); ?></a>
520
- </div><!-- end .media-toolbar-primary -->
521
- </div><!-- end .media-toolbar -->
522
- </div><!-- end .media-frame-toolbar -->
523
- </div><!-- end .media-frame -->
524
- </div><!-- end .media-modal-content -->
525
- </div><!-- end .media-modal -->
526
- <div class="media-modal-backdrop"></div>
527
- </div><!-- end .envira-gallery-image-meta -->
528
- </div><!-- end #envira-gallery-upload-ui-wrapper-->
529
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
530
 
531
  }
532
 
533
  /**
534
- * Callback for displaying the UI for setting gallery config options.
535
  *
536
  * @since 1.0.0
537
  *
@@ -541,12 +699,25 @@ class Envira_Gallery_Metaboxes_Lite {
541
 
542
  ?>
543
  <div id="envira-config">
544
- <p class="envira-intro"><?php _e( 'The settings below adjust the basic configuration options for the gallery lightbox display.', 'envira-gallery-lite' ); ?></p>
 
 
 
 
 
 
 
 
 
 
 
 
 
545
  <table class="form-table">
546
  <tbody>
547
  <tr id="envira-config-columns-box">
548
  <th scope="row">
549
- <label for="envira-config-columns"><?php _e( 'Number of Gallery Columns', 'envira-gallery-lite' ); ?></label>
550
  </th>
551
  <td>
552
  <select id="envira-config-columns" name="_envira_gallery[columns]">
@@ -554,12 +725,13 @@ class Envira_Gallery_Metaboxes_Lite {
554
  <option value="<?php echo $data['value']; ?>"<?php selected( $data['value'], $this->get_config( 'columns', $this->get_config_default( 'columns' ) ) ); ?>><?php echo $data['name']; ?></option>
555
  <?php endforeach; ?>
556
  </select>
557
- <p class="description"><?php _e( 'Determines the number of columns in the gallery.', 'envira-gallery-lite' ); ?></p>
558
  </td>
559
  </tr>
560
- <tr id="envira-config-gallery-theme-box" class="envira-lite-disabled">
 
561
  <th scope="row">
562
- <label for="envira-config-gallery-theme"><?php _e( 'Gallery Theme', 'envira-gallery-lite' ); ?></label>
563
  </th>
564
  <td>
565
  <select id="envira-config-gallery-theme" name="_envira_gallery[gallery_theme]">
@@ -567,60 +739,91 @@ class Envira_Gallery_Metaboxes_Lite {
567
  <option value="<?php echo $data['value']; ?>"<?php selected( $data['value'], $this->get_config( 'gallery_theme', $this->get_config_default( 'gallery_theme' ) ) ); ?>><?php echo $data['name']; ?></option>
568
  <?php endforeach; ?>
569
  </select>
570
- <p class="description"><?php _e( 'Sets the theme for the gallery display.', 'envira-gallery-lite' ); ?></p>
571
  </td>
572
  </tr>
 
 
573
  <tr id="envira-config-gutter-box">
574
  <th scope="row">
575
- <label for="envira-config-gutter"><?php _e( 'Column Gutter Width', 'envira-gallery-lite' ); ?></label>
576
  </th>
577
  <td>
578
- <input id="envira-config-gutter" type="number" name="_envira_gallery[gutter]" value="<?php echo $this->get_config( 'gutter', $this->get_config_default( 'gutter' ) ); ?>" />
579
- <span class="envira-unit"><?php _e( 'px', 'envira-gallery-lite' ); ?></span>
580
- <p class="description"><?php _e( 'Sets the space between the columns (defaults to 10).', 'envira-gallery-lite' ); ?></p>
581
  </td>
582
  </tr>
 
583
  <tr id="envira-config-margin-box">
584
  <th scope="row">
585
- <label for="envira-config-margin"><?php _e( 'Margin Below Each Image', 'envira-gallery-lite' ); ?></label>
586
  </th>
587
  <td>
588
- <input id="envira-config-margin" type="number" name="_envira_gallery[margin]" value="<?php echo $this->get_config( 'margin', $this->get_config_default( 'margin' ) ); ?>" />
589
- <span class="envira-unit"><?php _e( 'px', 'envira-gallery-lite' ); ?></span>
590
- <p class="description"><?php _e( 'Sets the space below each item in the gallery.', 'envira-gallery-lite' ); ?></p>
591
  </td>
592
  </tr>
593
- <tr id="envira-config-crop-box">
 
 
594
  <th scope="row">
595
- <label for="envira-config-crop"><?php _e( 'Crop Images in Gallery?', 'envira-gallery-lite' ); ?></label>
596
  </th>
597
  <td>
598
- <input id="envira-config-crop" type="checkbox" name="_envira_gallery[crop]" value="<?php echo $this->get_config( 'crop', $this->get_config_default( 'crop' ) ); ?>" <?php checked( $this->get_config( 'crop', $this->get_config_default( 'crop' ) ), 1 ); ?> />
599
- <span class="description"><?php _e( 'Enables or disables image cropping for the main gallery images.', 'envira-gallery-lite' ); ?></span>
 
 
 
 
 
 
 
 
600
  </td>
601
  </tr>
602
- <tr id="envira-config-crop-size-box" style="display:none;">
603
  <th scope="row">
604
- <label for="envira-config-crop-width"><?php _e( 'Crop Dimensions', 'envira-gallery-lite' ); ?></label>
605
  </th>
606
  <td>
607
- <input id="envira-config-crop-width" type="number" name="_envira_gallery[crop_width]" value="<?php echo $this->get_config( 'crop_width', $this->get_config_default( 'crop_width' ) ); ?>" <?php checked( $this->get_config( 'crop_width', $this->get_config_default( 'crop_width' ) ), 1 ); ?> /> &#215; <input id="envira-config-crop-height" type="number" name="_envira_gallery[crop_height]" value="<?php echo $this->get_config( 'crop_height', $this->get_config_default( 'crop_height' ) ); ?>" <?php checked( $this->get_config( 'crop_height', $this->get_config_default( 'crop_height' ) ), 1 ); ?> />
608
- <p class="description"><?php _e( 'You should adjust these dimensions based on the number of columns in your gallery.', 'envira-gallery-lite' ); ?></p>
609
  </td>
610
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
611
  <?php do_action( 'envira_gallery_config_box', $post ); ?>
612
  </tbody>
613
  </table>
614
- <div class="envira-alert envira-clear">
615
- <?php _e( '<em>Want to do even more with your gallery display?</em> By upgrading to Envira Pro, you can get access to numerous other gallery display features, including: <strong>custom image tagging and filtering</strong>, <strong>mobile specific image assets for blazing fast load times</strong>, <strong>dedicated and unique gallery URLs</strong>, <strong>custom gallery themes</strong>, <strong>gallery thumbnail support</strong> and so much more! <a href="http://enviragallery.com/lite/?utm_source=liteplugin&utm_medium=link&utm_campaign=WordPress" title="Click here to upgrade to Envira Pro!" target="_blank">Click here to upgrade to Envira Pro!</a>', 'envira-gallery-lite' ); ?>
616
- </div>
617
  </div>
618
  <?php
619
 
 
 
 
 
 
 
 
 
 
 
 
620
  }
621
 
622
  /**
623
- * Callback for displaying the UI for setting gallery lightbox options.
624
  *
625
  * @since 1.0.0
626
  *
@@ -630,57 +833,101 @@ class Envira_Gallery_Metaboxes_Lite {
630
 
631
  ?>
632
  <div id="envira-lightbox">
633
- <p class="envira-intro"><?php _e( 'The settings below adjust the lightbox outputs and displays.', 'envira-gallery-lite' ); ?></p>
634
- <table class="form-table">
 
 
 
 
 
 
 
 
 
 
 
 
 
635
  <tbody>
636
  <tr id="envira-config-lightbox-enabled-box">
637
  <th scope="row">
638
- <label for="envira-config-lightbox-enabled"><?php _e( 'Enable Lightbox?', 'envira-gallery-lite' ); ?></label>
639
  </th>
640
  <td>
641
- <input id="envira-config-lightbox-enabled" type="checkbox" name="_envira_gallery[lightbox_enabled]" value="<?php echo $this->get_config( 'lightbox_enabled', $this->get_config_default( 'lightbox_enabled' ) ); ?>" <?php checked( $this->get_config( 'lightbox_enabled', $this->get_config_default( 'lightbox_enabled' ) ), 1 ); ?> />
642
- <span class="description"><?php _e( 'Enables or disables the gallery lightbox.', 'envira-gallery-lite' ); ?></span>
643
  </td>
644
  </tr>
645
- <tr id="envira-config-lightbox-theme-box">
646
- <th scope="row">
647
- <label for="envira-config-lightbox-theme"><?php _e( 'Gallery Lightbox Theme', 'envira-gallery-lite' ); ?></label>
648
- </th>
649
- <td>
650
- <select id="envira-config-lightbox-theme" name="_envira_gallery[lightbox_theme]">
651
- <?php foreach ( (array) $this->get_lightbox_themes() as $i => $data ) : ?>
652
- <option value="<?php echo $data['value']; ?>"<?php selected( $data['value'], $this->get_config( 'lightbox_theme', $this->get_config_default( 'lightbox_theme' ) ) ); ?>><?php echo $data['name']; ?></option>
653
- <?php endforeach; ?>
654
- </select>
655
- <p class="description"><?php _e( 'Sets the theme for the gallery lightbox display.', 'envira-gallery-lite' ); ?></p>
656
- </td>
657
- </tr>
658
- <tr id="envira-config-lightbox-title-display-box">
659
- <th scope="row">
660
- <label for="envira-config-lightbox-title-display"><?php _e( 'Caption Position', 'envira-gallery-lite' ); ?></label>
661
- </th>
662
- <td>
663
- <select id="envira-config-lightbox-title-display" name="_envira_gallery[title_display]">
664
- <?php foreach ( (array) $this->get_title_displays() as $i => $data ) : ?>
665
- <option value="<?php echo $data['value']; ?>"<?php selected( $data['value'], $this->get_config( 'title_display', $this->get_config_default( 'title_display' ) ) ); ?>><?php echo $data['name']; ?></option>
666
- <?php endforeach; ?>
667
- </select>
668
- <p class="description"><?php _e( 'Sets the display of the lightbox image\'s caption.', 'envira-gallery-lite' ); ?></p>
669
- </td>
670
- </tr>
671
- <?php do_action( 'envira_gallery_lightbox_box', $post ); ?>
672
  </tbody>
673
  </table>
674
- <div class="envira-alert envira-clear">
675
- <?php _e( '<em>Want even more fine tuned control over your lightbox display?</em> By upgrading to Envira Pro, you can get access to numerous other lightbox features, including: <strong>custom lightbox titles</strong>, <strong>enable/disable lightbox controls (arrow, keyboard and mousehweel navigation)</strong>, <strong>custom lightbox transition effects</strong>, <strong>native fullscreen support</strong>, <strong>gallery deeplinking</strong>, <strong>image protection</strong>, <strong>lightbox supersize effects</strong>, <strong>lightbox slideshows</strong> and so much more! <a href="http://enviragallery.com/lite/?utm_source=liteplugin&utm_medium=link&utm_campaign=WordPress" title="Click here to upgrade to Envira Pro!" target="_blank">Click here to upgrade to Envira Pro!</a>', 'envira-gallery-lite' ); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
676
  </div>
677
  </div>
678
  <?php
679
 
 
 
 
 
 
 
 
 
 
 
 
680
  }
681
 
682
  /**
683
- * Callback for displaying the UI for setting gallery miscellaneous options.
684
  *
685
  * @since 1.0.0
686
  *
@@ -690,54 +937,203 @@ class Envira_Gallery_Metaboxes_Lite {
690
 
691
  ?>
692
  <div id="envira-misc">
693
- <p class="envira-intro"><?php _e( 'The settings below adjust the miscellaneous settings for the gallery lightbox display.', 'envira-gallery-lite' ); ?></p>
 
 
 
 
 
 
 
 
 
 
 
 
694
  <table class="form-table">
695
  <tbody>
696
  <tr id="envira-config-title-box">
697
  <th scope="row">
698
- <label for="envira-config-title"><?php _e( 'Gallery Title', 'envira-gallery-lite' ); ?></label>
699
  </th>
700
  <td>
701
  <input id="envira-config-title" type="text" name="_envira_gallery[title]" value="<?php echo $this->get_config( 'title', $this->get_config_default( 'title' ) ); ?>" />
702
- <p class="description"><?php _e( 'Internal gallery title for identification in the admin.', 'envira-gallery-lite' ); ?></p>
703
  </td>
704
  </tr>
705
  <tr id="envira-config-slug-box">
706
  <th scope="row">
707
- <label for="envira-config-slug"><?php _e( 'Gallery Slug', 'envira-gallery-lite' ); ?></label>
708
  </th>
709
  <td>
710
  <input id="envira-config-slug" type="text" name="_envira_gallery[slug]" value="<?php echo $this->get_config( 'slug', $this->get_config_default( 'slug' ) ); ?>" />
711
- <p class="description"><?php _e( '<strong>Unique</strong> internal gallery slug for identification and advanced gallery queries.', 'envira-gallery-lite' ); ?></p>
712
  </td>
713
  </tr>
714
  <tr id="envira-config-classes-box">
715
  <th scope="row">
716
- <label for="envira-config-classes"><?php _e( 'Custom Gallery Classes', 'envira-gallery-lite' ); ?></label>
717
  </th>
718
  <td>
719
- <textarea id="envira-config-classes" rows="5" cols="75" name="_envira_gallery[classes]" placeholder="<?php _e( 'Enter custom gallery CSS classes here, one per line.', 'envira-gallery-lite' ); ?>"><?php echo implode( "\n", (array) $this->get_config( 'classes', $this->get_config_default( 'classes' ) ) ); ?></textarea>
720
- <p class="description"><?php _e( 'Adds custom CSS classes to this gallery. Enter one class per line.', 'envira-gallery-lite' ); ?></p>
721
  </td>
722
  </tr>
723
  <tr id="envira-config-rtl-box">
724
  <th scope="row">
725
- <label for="envira-config-rtl"><?php _e( 'Enable RTL Support?', 'envira-gallery-lite' ); ?></label>
726
  </th>
727
  <td>
728
  <input id="envira-config-rtl" type="checkbox" name="_envira_gallery[rtl]" value="<?php echo $this->get_config( 'rtl', $this->get_config_default( 'rtl' ) ); ?>" <?php checked( $this->get_config( 'rtl', $this->get_config_default( 'rtl' ) ), 1 ); ?> />
729
- <span class="description"><?php _e( 'Enables or disables RTL support in Envira for right-to-left languages.', 'envira-gallery-lite' ); ?></span>
730
  </td>
731
  </tr>
732
  <?php do_action( 'envira_gallery_misc_box', $post ); ?>
733
  </tbody>
734
  </table>
735
- <div class="envira-alert envira-clear">
736
- <?php _e( '<em>Want to take your galleries further?</em> By upgrading to Envira Pro, you can get access to numerous other features, including: <strong>a fully-integrated import/export module for your galleries</strong>, <strong>custom CSS controls for each gallery</strong> and so much more! <a href="http://enviragallery.com/lite/?utm_source=liteplugin&utm_medium=link&utm_campaign=WordPress" title="Click here to upgrade to Envira Pro!" target="_blank">Click here to upgrade to Envira Pro!</a>', 'envira-gallery-lite' ); ?>
737
- </div>
738
  </div>
739
  <?php
740
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
741
  }
742
 
743
  /**
@@ -751,7 +1147,7 @@ class Envira_Gallery_Metaboxes_Lite {
751
  public function save_meta_boxes( $post_id, $post ) {
752
 
753
  // Bail out if we fail a security check.
754
- if ( ! isset( $_POST['envira-gallery-lite'] ) || ! wp_verify_nonce( $_POST['envira-gallery-lite'], 'envira-gallery-lite' ) || ! isset( $_POST['_envira_gallery'] ) ) {
755
  return;
756
  }
757
 
@@ -761,6 +1157,36 @@ class Envira_Gallery_Metaboxes_Lite {
761
  }
762
 
763
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
764
  return;
765
  }
766
 
@@ -776,7 +1202,7 @@ class Envira_Gallery_Metaboxes_Lite {
776
  if ( ! current_user_can( 'edit_post', $post_id ) ) {
777
  return;
778
  }
779
-
780
  // If the post has just been published for the first time, set meta field for the gallery meta overlay helper.
781
  if ( isset( $post->post_date ) && isset( $post->post_modified ) && $post->post_date === $post->post_modified ) {
782
  update_post_meta( $post_id, '_eg_just_published', true );
@@ -788,28 +1214,33 @@ class Envira_Gallery_Metaboxes_Lite {
788
  $settings = array();
789
  }
790
 
791
- // Force gallery ID to match Post ID. This is deliberate; if a gallery is duplicated (either using a duplication)
792
  // plugin or WPML, the ID remains as the original gallery ID, which breaks things for translations etc.
793
  $settings['id'] = $post_id;
794
 
795
- // Save the config settings.
796
- $settings['config']['columns'] = preg_replace( '#[^a-z0-9-_]#', '', $_POST['_envira_gallery']['columns'] );
797
- $settings['config']['gutter'] = absint( $_POST['_envira_gallery']['gutter'] );
798
- $settings['config']['margin'] = absint( $_POST['_envira_gallery']['margin'] );
799
- $settings['config']['crop'] = isset( $_POST['_envira_gallery']['crop'] ) ? 1 : 0;
800
- $settings['config']['crop_width'] = absint( $_POST['_envira_gallery']['crop_width'] );
801
- $settings['config']['crop_height'] = absint( $_POST['_envira_gallery']['crop_height'] );
 
 
 
802
 
803
  // Lightbox
804
- $settings['config']['lightbox_enabled'] = isset( $_POST['_envira_gallery']['lightbox_enabled'] ) ? 1 : 0;
805
- $settings['config']['title_display'] = preg_replace( '#[^a-z0-9-_]#', '', $_POST['_envira_gallery']['title_display'] );
806
-
 
 
807
  // Misc
808
- $settings['config']['classes'] = explode( "\n", $_POST['_envira_gallery']['classes'] );
809
- $settings['config']['title'] = trim( strip_tags( $_POST['_envira_gallery']['title'] ) );
810
- $settings['config']['slug'] = sanitize_text_field( $_POST['_envira_gallery']['slug'] );
811
- $settings['config']['rtl'] = isset( $_POST['_envira_gallery']['rtl'] ) ? 1 : 0;
812
-
813
  // If on an envira post type, map the title and slug of the post object to the custom fields if no value exists yet.
814
  if ( isset( $post->post_type ) && 'envira' == $post->post_type ) {
815
  if ( empty( $settings['config']['title'] ) ) {
@@ -831,136 +1262,80 @@ class Envira_Gallery_Metaboxes_Lite {
831
 
832
  // If the crop option is checked, crop images accordingly.
833
  if ( isset( $settings['config']['crop'] ) && $settings['config']['crop'] ) {
834
- $args = apply_filters( 'envira_gallery_crop_image_args',
835
- array(
836
- 'position' => 'c',
837
- 'width' => $this->get_config( 'crop_width', $this->get_config_default( 'crop_width' ) ),
838
- 'height' => $this->get_config( 'crop_height', $this->get_config_default( 'crop_height' ) ),
839
- 'quality' => 100,
840
- 'retina' => false
841
- )
842
  );
 
843
  $this->crop_images( $args, $post_id );
844
  }
845
 
 
 
 
846
  // Finally, flush all gallery caches to ensure everything is up to date.
847
- $this->flush_gallery_caches( $post_id, $settings['config']['slug'] );
848
 
849
  }
850
 
851
  /**
852
  * Helper method for retrieving the gallery layout for an item in the admin.
853
  *
 
 
854
  * @since 1.0.0
855
  *
856
- * @param int $id The ID of the item to retrieve.
857
- * @param array $data Array of data for the item.
858
- * @param int $post_id The current post ID.
859
- * @return string The HTML output for the gallery item.
860
  */
861
- public function get_gallery_item( $id, $data, $post_id = 0 ) {
862
-
863
- $thumbnail = wp_get_attachment_image_src( $id, 'thumbnail' ); ob_start(); ?>
864
- <li id="<?php echo $id; ?>" class="envira-gallery-image envira-gallery-status-<?php echo $data['status']; ?>" data-envira-gallery-image="<?php echo $id; ?>">
865
- <img src="<?php echo esc_url( $thumbnail[0] ); ?>" alt="<?php esc_attr_e( $data['alt'] ); ?>" />
866
- <a href="#" class="envira-gallery-remove-image" title="<?php esc_attr_e( 'Remove Image from Gallery?', 'envira-gallery-lite' ); ?>"></a>
867
- <a href="#" class="envira-gallery-modify-image" title="<?php esc_attr_e( 'Modify Image', 'envira-gallery-lite' ); ?>"></a>
868
- <?php echo $this->get_gallery_item_meta( $id, $data, $post_id ); ?>
869
- </li>
870
- <?php
871
- return ob_get_clean();
872
 
873
- }
 
874
 
875
- /**
876
- * Helper method for retrieving the gallery metadata editing modal.
877
- *
878
- * @since 1.0.0
879
- *
880
- * @param int $id The ID of the item to retrieve.
881
- * @param array $data Array of data for the item.
882
- * @param int $post_id The current post ID.
883
- * @return string The HTML output for the gallery item.
884
- */
885
- public function get_gallery_item_meta( $id, $data, $post_id ) {
886
-
887
- ob_start(); ?>
888
- <div id="envira-gallery-meta-<?php echo $id; ?>" class="envira-gallery-meta-container" style="display:none;">
889
- <div class="media-modal wp-core-ui">
890
- <a class="media-modal-close" href="#"><span class="media-modal-icon"></span></a>
891
- <div class="media-modal-content">
892
- <div class="media-frame envira-gallery-media-frame wp-core-ui hide-menu hide-router envira-gallery-meta-wrap">
893
- <div class="media-frame-title">
894
- <h1><?php _e( 'Edit Metadata', 'envira-gallery-lite' ); ?></h1>
895
- </div>
896
- <div class="media-frame-content">
897
- <div class="attachments-browser">
898
- <div class="envira-gallery-meta attachments">
899
- <?php do_action( 'envira_gallery_before_meta_table', $id, $data, $post_id ); ?>
900
- <table id="envira-gallery-meta-table-<?php echo $id; ?>" class="form-table envira-gallery-meta-table" data-envira-meta-id="<?php echo $id; ?>">
901
- <tbody>
902
- <?php do_action( 'envira_gallery_before_meta_settings', $id, $data, $post_id ); ?>
903
- <tr id="envira-gallery-title-box-<?php echo $id; ?>" valign="middle">
904
- <th scope="row"><label for="envira-gallery-title-<?php echo $id; ?>"><?php _e( 'Image Title', 'envira-gallery-lite' ); ?></label></th>
905
- <td>
906
- <?php
907
- wp_editor( $data['title'], 'envira-gallery-title-' . $id, array(
908
- 'media_buttons' => false,
909
- 'tinymce' => false,
910
- 'textarea_name' => '_envira_gallery[meta_title]',
911
- 'quicktags' => array( 'buttons' => 'strong,em,link,ul,ol,li,close' ),
912
- 'textarea_rows' => 5,
913
- ) );
914
- ?>
915
- <p class="description"><?php _e( 'Image titles can take any type of HTML.', 'envira-gallery-lite' ); ?></p>
916
- </td>
917
- </tr>
918
- <tr id="envira-gallery-alt-box-<?php echo $id; ?>" valign="middle">
919
- <th scope="row"><label for="envira-gallery-alt-<?php echo $id; ?>"><?php _e( 'Image Alt Text', 'envira-gallery-lite' ); ?></label></th>
920
- <td>
921
- <input id="envira-gallery-alt-<?php echo $id; ?>" class="envira-gallery-alt" type="text" name="_envira_gallery[meta_alt]" value="<?php echo esc_attr( $data['alt'] ); ?>" data-envira-meta="alt" />
922
- <p class="description"><?php _e( 'The image alt text is used for SEO. You should probably fill this one out!', 'envira-gallery-lite' ); ?></p>
923
- </td>
924
- </tr>
925
- <tr id="envira-gallery-link-box-<?php echo $id; ?>" class="envira-gallery-link-cell" valign="middle">
926
- <th scope="row"><label for="envira-gallery-link-<?php echo $id; ?>"><?php _e( 'Image Hyperlink', 'envira-gallery-lite' ); ?></label></th>
927
- <td>
928
- <input id="envira-gallery-link-<?php echo $id; ?>" class="envira-gallery-link" type="text" name="_envira_gallery[meta_link]" value="<?php echo esc_url( $data['link'] ); ?>" data-envira-meta="link" />
929
- <p class="description"><?php _e( 'The image hyperlink determines what opens up in the lightbox once the image is clicked. If this link is set to a regular web page, it will go to that page. Defaults to a larger version of the image itself.', 'envira-gallery-lite' ); ?></p>
930
- </td>
931
- </tr>
932
- <?php do_action( 'envira_gallery_after_meta_settings', $id, $data, $post_id ); ?>
933
- </tbody>
934
- </table>
935
- <?php do_action( 'envira_gallery_after_meta_table', $id, $data, $post_id ); ?>
936
- </div><!-- end .envira-gallery-meta -->
937
- <div class="media-sidebar">
938
- <div class="envira-gallery-meta-sidebar">
939
- <h3><?php _e( 'Helpful Tips', 'envira-gallery-lite' ); ?></h3>
940
- <strong><?php _e( 'Image Titles', 'envira-gallery-lite' ); ?></strong>
941
- <p><?php _e( 'Image titles can take any type of HTML. You can adjust the position of the titles in the main Lightbox settings.', 'envira-gallery-lite' ); ?></p>
942
- <strong><?php _e( 'Image Alt Text', 'envira-gallery-lite' ); ?></strong>
943
- <p><?php _e( 'The image alt text field is used for accessibility and SEO, and describes your image.', 'envira-gallery-lite' ); ?></p>
944
- <strong><?php _e( 'Image Hyperlinks', 'envira-gallery-lite' ); ?></strong>
945
- <p><?php _e( 'The image hyperlink field is used when you click on an image in the gallery. It determines what is displayed in the lightbox view. It could be a larger version of the image, a video, or some other form of content.', 'envira-gallery-lite' ); ?></p>
946
- <strong><?php _e( 'Saving and Exiting', 'envira-gallery-lite' ); ?></strong>
947
- <p class="no-margin"><?php _e( 'Click on the button below to save your image metadata. You can close this window by either clicking on the "X" above or hitting the <code>esc</code> key on your keyboard.', 'envira-gallery-lite' ); ?></p>
948
- </div><!-- end .envira-gallery-meta-sidebar -->
949
- </div><!-- end .media-sidebar -->
950
- </div><!-- end .attachments-browser -->
951
- </div><!-- end .media-frame-content -->
952
- <div class="media-frame-toolbar">
953
- <div class="media-toolbar">
954
- <div class="media-toolbar-primary">
955
- <a href="#" class="envira-gallery-meta-submit button media-button button-large button-primary media-button-insert" title="<?php esc_attr_e( 'Save Metadata', 'envira-gallery-lite' ); ?>" data-envira-gallery-item="<?php echo $id; ?>"><?php _e( 'Save Metadata', 'envira-gallery-lite' ); ?></a>
956
- </div><!-- end .media-toolbar-primary -->
957
- </div><!-- end .media-toolbar -->
958
- </div><!-- end .media-frame-toolbar -->
959
- </div><!-- end .media-frame -->
960
- </div><!-- end .media-modal-content -->
961
- </div><!-- end .media-modal -->
962
- <div class="media-modal-backdrop"></div>
963
- </div>
964
  <?php
965
  return ob_get_clean();
966
 
@@ -981,7 +1356,7 @@ class Envira_Gallery_Metaboxes_Lite {
981
  $gallery_data = get_post_meta( $post_id, '_eg_gallery_data', true );
982
  if ( ! empty( $gallery_data['gallery'] ) ) {
983
  foreach ( (array) $gallery_data['gallery'] as $id => $item ) {
984
- $gallery_data['gallery'][$id]['status'] = 'active';
985
  }
986
  }
987
 
@@ -990,66 +1365,122 @@ class Envira_Gallery_Metaboxes_Lite {
990
  }
991
 
992
  /**
993
- * Helper method to crop gallery images to the specified sizes.
994
  *
995
  * @since 1.0.0
996
  *
997
  * @param array $args Array of args used when cropping the images.
998
  * @param int $post_id The current post ID.
999
  */
1000
- public function crop_images( $args, $post_id ) {
1001
 
1002
  // Gather all available images to crop.
1003
  $gallery_data = get_post_meta( $post_id, '_eg_gallery_data', true );
1004
  $images = ! empty( $gallery_data['gallery'] ) ? $gallery_data['gallery'] : false;
1005
- $common = Envira_Gallery_Common_Lite::get_instance();
1006
 
1007
  // Loop through the images and crop them.
1008
  if ( $images ) {
1009
  // Increase the time limit to account for large image sets and suspend cache invalidations.
1010
- set_time_limit( 0 );
 
 
1011
  wp_suspend_cache_invalidation( true );
1012
 
1013
  foreach ( $images as $id => $item ) {
1014
  // Get the full image attachment. If it does not return the data we need, skip over it.
1015
  $image = wp_get_attachment_image_src( $id, 'full' );
 
1016
  if ( ! is_array( $image ) ) {
1017
  continue;
1018
  }
1019
 
 
 
 
 
 
 
1020
  // Generate the cropped image.
1021
  $cropped_image = $common->resize_image( $image[0], $args['width'], $args['height'], true, $args['position'], $args['quality'], $args['retina'] );
1022
-
1023
  // If there is an error, possibly output error message, otherwise woot!
1024
  if ( is_wp_error( $cropped_image ) ) {
1025
  // If WP_DEBUG is enabled, and we're logged in, output an error to the user
1026
  if ( defined( 'WP_DEBUG' ) && WP_DEBUG && is_user_logged_in() ) {
1027
  echo '<pre>Envira: Error occured resizing image (these messages are only displayed to logged in WordPress users):<br />';
1028
  echo 'Error: ' . $cropped_image->get_error_message() . '<br />';
1029
- echo 'Image: ' . $image . '<br />';
1030
  echo 'Args: ' . var_export( $args, true ) . '</pre>';
 
1031
  }
 
 
1032
  }
1033
  }
1034
 
1035
  // Turn off cache suspension and flush the cache to remove any cache inconsistencies.
1036
  wp_suspend_cache_invalidation( false );
1037
  wp_cache_flush();
 
 
 
1038
  }
1039
 
1040
  }
1041
 
1042
  /**
1043
- * Helper method to flush gallery caches once a gallery is updated.
1044
  *
1045
  * @since 1.0.0
1046
  *
 
1047
  * @param int $post_id The current post ID.
1048
- * @param string $slug The unique gallery slug.
1049
  */
1050
- public function flush_gallery_caches( $post_id, $slug ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1051
 
1052
- Envira_Gallery_Common_Lite::get_instance()->flush_gallery_caches( $post_id, $slug );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1053
 
1054
  }
1055
 
@@ -1068,12 +1499,19 @@ class Envira_Gallery_Metaboxes_Lite {
1068
 
1069
  global $id, $post;
1070
 
1071
- // Get the current post ID.
1072
- $post_id = isset( $post->ID ) ? $post->ID : (int) $id;
 
 
 
 
1073
 
 
1074
  $settings = get_post_meta( $post_id, '_eg_gallery_data', true );
1075
- if ( isset( $settings['config'][$key] ) ) {
1076
- return $settings['config'][$key];
 
 
1077
  } else {
1078
  return $default ? $default : '';
1079
  }
@@ -1090,7 +1528,7 @@ class Envira_Gallery_Metaboxes_Lite {
1090
  */
1091
  public function get_config_default( $key ) {
1092
 
1093
- $instance = Envira_Gallery_Common_Lite::get_instance();
1094
  return $instance->get_config_default( $key );
1095
 
1096
  }
@@ -1104,7 +1542,7 @@ class Envira_Gallery_Metaboxes_Lite {
1104
  */
1105
  public function get_columns() {
1106
 
1107
- $instance = Envira_Gallery_Common_Lite::get_instance();
1108
  return $instance->get_columns();
1109
 
1110
  }
@@ -1118,10 +1556,52 @@ class Envira_Gallery_Metaboxes_Lite {
1118
  */
1119
  public function get_gallery_themes() {
1120
 
1121
- $instance = Envira_Gallery_Common_Lite::get_instance();
1122
  return $instance->get_gallery_themes();
1123
 
1124
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1125
 
1126
  /**
1127
  * Helper method for retrieving lightbox themes.
@@ -1132,25 +1612,109 @@ class Envira_Gallery_Metaboxes_Lite {
1132
  */
1133
  public function get_lightbox_themes() {
1134
 
1135
- $instance = Envira_Gallery_Common_Lite::get_instance();
1136
  return $instance->get_lightbox_themes();
1137
 
1138
  }
1139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1140
  /**
1141
  * Helper method for retrieving title displays.
1142
  *
1143
- * @since 1.2.7
1144
  *
1145
  * @return array Array of title display data.
1146
  */
1147
  public function get_title_displays() {
1148
 
1149
- $instance = Envira_Gallery_Common_Lite::get_instance();
1150
  return $instance->get_title_displays();
1151
 
1152
  }
1153
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1154
  /**
1155
  * Returns the post types to skip for loading Envira metaboxes.
1156
  *
@@ -1160,7 +1724,34 @@ class Envira_Gallery_Metaboxes_Lite {
1160
  */
1161
  public function get_skipped_posttypes() {
1162
 
1163
- return apply_filters( 'envira_gallery_skipped_posttypes', array( 'attachment', 'revision', 'nav_menu_item', 'soliloquy', 'soliloquyv2' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1164
 
1165
  }
1166
 
@@ -1169,12 +1760,12 @@ class Envira_Gallery_Metaboxes_Lite {
1169
  *
1170
  * @since 1.0.0
1171
  *
1172
- * @return object The Envira_Gallery_Metaboxes_Lite object.
1173
  */
1174
  public static function get_instance() {
1175
 
1176
- if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Metaboxes_Lite ) ) {
1177
- self::$instance = new Envira_Gallery_Metaboxes_Lite();
1178
  }
1179
 
1180
  return self::$instance;
@@ -1184,4 +1775,4 @@ class Envira_Gallery_Metaboxes_Lite {
1184
  }
1185
 
1186
  // Load the metabox class.
1187
- $envira_gallery_metaboxes_lite = Envira_Gallery_Metaboxes_Lite::get_instance();
4
  *
5
  * @since 1.0.0
6
  *
7
+ * @package Envira_Gallery
8
  * @author Thomas Griffin
9
  */
10
+ class Envira_Gallery_Metaboxes {
11
 
12
  /**
13
  * Holds the class object.
46
  // Load the base class object.
47
  $this->base = Envira_Gallery_Lite::get_instance();
48
 
49
+ // Output a notice if missing cropping extensions because Envira needs them.
50
+ if ( ! $this->has_gd_extension() && ! $this->has_imagick_extension() ) {
51
+ add_action( 'admin_notices', array( $this, 'notice_missing_extensions' ) );
52
+ }
53
+
54
+ // Scripts and styles
55
+ add_action( 'admin_enqueue_scripts', array( $this, 'styles' ) );
56
+ add_action( 'admin_enqueue_scripts', array( $this, 'scripts' ) );
57
+
58
+ // Metaboxes
59
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 1 );
60
+
61
+ // Add the envira-gallery class to the form, so our styles can be applied
62
+ add_action( 'post_edit_form_tag', array( $this, 'add_form_class' ) );
63
 
64
+ // Modals
65
+ add_filter( 'media_view_strings', array( $this, 'media_view_strings' ) );
66
 
67
  // Load all tabs.
68
  add_action( 'envira_gallery_tab_images', array( $this, 'images_tab' ) );
70
  add_action( 'envira_gallery_tab_lightbox', array( $this, 'lightbox_tab' ) );
71
  add_action( 'envira_gallery_tab_misc', array( $this, 'misc_tab' ) );
72
 
73
+ // Load some tabs for Envira Gallery Lite.
74
+ if ( 'Envira_Gallery_Lite' == get_class( $this->base ) ) {
75
+ add_filter( 'envira_gallery_tab_nav', array( $this, 'lite_tabs' ) );
76
+ add_action( 'envira_gallery_tab_mobile', array( $this, 'lite_mobile_tab' ) );
77
+ add_action( 'envira_gallery_tab_videos', array( $this, 'lite_videos_tab' ) );
78
+ add_action( 'envira_gallery_tab_social', array( $this, 'lite_social_tab' ) );
79
+ add_action( 'envira_gallery_tab_tags', array( $this, 'lite_tags_tab' ) );
80
+ add_action( 'envira_gallery_tab_pagination', array( $this, 'lite_pagination_tab' ) );
81
+ }
82
+
83
+ // Save Gallery
84
  add_action( 'save_post', array( $this, 'save_meta_boxes' ), 10, 2 );
85
 
86
  }
87
 
88
+ /**
89
+ * Outputs a notice when the GD and Imagick PHP extensions aren't installed.
90
+ *
91
+ * @since 1.0.0
92
+ */
93
+ public function notice_missing_extensions() {
94
+
95
+ ?>
96
+ <div class="error">
97
+ <p><strong><?php _e( 'The GD or Imagick libraries are not installed on your server. Envira Gallery requires at least one (preferably Imagick) in order to crop images and may not work properly without it. Please contact your webhost and ask them to compile GD or Imagick for your PHP install.', 'envira-gallery' ); ?></strong></p>
98
+ </div>
99
+ <?php
100
+
101
+ }
102
+
103
+ /**
104
+ * Changes strings in the modal image selector if we're editing an Envira Gallery
105
+ *
106
+ * @since 1.4.0
107
+ *
108
+ * @param array $strings Media View Strings
109
+ * @return array Media View Strings
110
+ */
111
+ public function media_view_strings( $strings ) {
112
+
113
+ // Check if we can get a current screen
114
+ // If not, we're not on an Envira screen so we can bail
115
+ if ( ! function_exists( 'get_current_screen' ) ) {
116
+ return $strings;
117
+ }
118
+
119
+ // Get the current screen
120
+ $screen = get_current_screen();
121
+
122
+ // Check we're editing an Envira CPT
123
+ if ( ! $screen ) {
124
+ return $strings;
125
+ }
126
+ if ( $screen->post_type != 'envira' ) {
127
+ return $strings;
128
+ }
129
+
130
+ // If here, we're editing an Envira CPT
131
+ // Modify some of the media view's strings
132
+ $strings['insertIntoPost'] = __( 'Insert into Gallery', 'envira-gallery' );
133
+ $strings['inserting'] = __( 'Inserting...', 'envira-gallery' );
134
+
135
+ // Allow addons to filter strings
136
+ $strings = apply_filters( 'envira_gallery_media_view_strings', $strings, $screen );
137
+
138
+ // Return
139
+ return $strings;
140
+
141
+ }
142
+
143
+ /**
144
+ * Appends the "Select Files From Other Sources" button to the Media Uploader, which is called using WordPress'
145
+ * media_upload_form() function
146
+ *
147
+ * CSS positions this button to improve the layout.
148
+ *
149
+ * @since 1.5.0
150
+ */
151
+ public function append_media_upload_form() {
152
+
153
+ ?>
154
+ <!-- Add from Media Library -->
155
+ <a href="#" class="envira-media-library button" title="<?php _e( 'Click Here to Insert from Other Image Sources', 'envira-gallery' ); ?>" style="vertical-align: baseline;">
156
+ <?php _e( 'Select Files from Other Sources', 'envira-gallery' ); ?>
157
+ </a>
158
+ <?php
159
+
160
+ }
161
+
162
  /**
163
  * Loads styles for our metaboxes.
164
  *
166
  *
167
  * @return null Return early if not on the proper screen.
168
  */
169
+ public function styles() {
170
+
171
+ // Get current screen.
172
+ $screen = get_current_screen();
173
+
174
+ // Bail if we're not on the Envira Post Type screen.
175
+ if ( 'envira' !== $screen->post_type ) {
176
+ return;
177
+ }
178
+
179
+ // Bail if we're not on an editing screen.
180
+ if ( 'post' !== $screen->base ) {
181
+ return;
182
+ }
183
 
184
  // Load necessary metabox styles.
185
  wp_register_style( $this->base->plugin_slug . '-metabox-style', plugins_url( 'assets/css/metabox.css', $this->base->file ), array(), $this->base->version );
186
  wp_enqueue_style( $this->base->plugin_slug . '-metabox-style' );
187
 
188
+ // Fire a hook to load in custom metabox styles.
189
+ do_action( 'envira_gallery_metabox_styles' );
 
 
 
 
 
190
 
191
  }
192
 
196
  * @since 1.0.0
197
  *
198
  * @global int $id The current post ID.
199
+ * @global object $post The current post object.
200
  * @return null Return early if not on the proper screen.
201
  */
202
+ public function scripts( $hook ) {
203
 
204
  global $id, $post;
205
 
206
+ // Get current screen.
207
+ $screen = get_current_screen();
208
+
209
+ // Bail if we're not on the Envira Post Type screen.
210
+ if ( 'envira' !== $screen->post_type ) {
211
  return;
212
  }
213
 
214
+ // Bail if we're not on an editing screen.
215
+ if ( 'post' !== $screen->base ) {
216
  return;
217
  }
218
 
219
  // Set the post_id for localization.
220
  $post_id = isset( $post->ID ) ? $post->ID : (int) $id;
221
 
222
+ // Sortables
 
223
  wp_enqueue_script( 'jquery-ui-sortable' );
224
+
225
+ // Image Uploader
226
+ wp_enqueue_media( array(
227
+ 'post' => $post_id,
228
+ ) );
229
+ add_filter( 'plupload_init', array( $this, 'plupload_init' ) );
230
+
231
+ // Tabs
232
+ wp_register_script( $this->base->plugin_slug . '-tabs-script', plugins_url( 'assets/js/tabs.js', $this->base->file ), array( 'jquery' ), $this->base->version, true );
233
+ wp_enqueue_script( $this->base->plugin_slug . '-tabs-script' );
234
+
235
+ // Clipboard
236
+ wp_register_script( $this->base->plugin_slug . '-clipboard-script', plugins_url( 'assets/js/min/clipboard-min.js', $this->base->file ), array( 'jquery' ), $this->base->version );
237
+ wp_enqueue_script( $this->base->plugin_slug . '-clipboard-script' );
238
+
239
+ // Metaboxes
240
  wp_register_script( $this->base->plugin_slug . '-metabox-script', plugins_url( 'assets/js/min/metabox-min.js', $this->base->file ), array( 'jquery', 'plupload-handlers', 'quicktags', 'jquery-ui-sortable' ), $this->base->version, true );
241
  wp_enqueue_script( $this->base->plugin_slug . '-metabox-script' );
242
  wp_localize_script(
243
  $this->base->plugin_slug . '-metabox-script',
244
  'envira_gallery_metabox',
245
  array(
246
+ 'ajax' => admin_url( 'admin-ajax.php' ),
247
+ 'change_nonce' => wp_create_nonce( 'envira-gallery-change-type' ),
248
+ 'id' => $post_id,
249
+ 'import' => __( 'You must select a file to import before continuing.', 'envira-gallery' ),
250
+ 'insert_nonce' => wp_create_nonce( 'envira-gallery-insert-images' ),
251
+ 'inserting' => __( 'Inserting...', 'envira-gallery' ),
252
+ 'library_search' => wp_create_nonce( 'envira-gallery-library-search' ),
253
+ 'load_gallery' => wp_create_nonce( 'envira-gallery-load-gallery' ),
254
+ 'load_image' => wp_create_nonce( 'envira-gallery-load-image' ),
255
+ 'preview_nonce' => wp_create_nonce( 'envira-gallery-change-preview' ),
256
+ 'refresh_nonce' => wp_create_nonce( 'envira-gallery-refresh' ),
257
+ 'remove' => __( 'Are you sure you want to remove this image from the gallery?', 'envira-gallery' ),
258
+ 'remove_multiple' => __( 'Are you sure you want to remove these images from the gallery?', 'envira-gallery' ),
259
+ 'remove_nonce' => wp_create_nonce( 'envira-gallery-remove-image' ),
260
+ 'save_nonce' => wp_create_nonce( 'envira-gallery-save-meta' ),
261
+ 'set_user_setting_nonce'=> wp_create_nonce( 'envira-gallery-set-user-setting' ),
262
+ 'saving' => __( 'Saving...', 'envira-gallery' ),
263
+ 'saved' => __( 'Saved!', 'envira-gallery' ),
264
+ 'sort' => wp_create_nonce( 'envira-gallery-sort' ),
265
+ 'uploader_files_computer' => __( 'Select Files from Your Computer', 'envira-gallery' ),
266
  )
267
  );
268
 
269
+ // Link Search
270
+ wp_enqueue_script( 'wp-link' );
271
+
272
+ // Add custom CSS for hiding specific things.
273
+ add_action( 'admin_head', array( $this, 'meta_box_css' ) );
274
+
275
+ // Fire a hook to load custom metabox scripts.
276
+ do_action( 'envira_gallery_metabox_scripts' );
277
 
278
  }
279
 
280
  /**
281
+ * Amends the default Plupload parameters for initialising the Media Uploader, to ensure
282
+ * the uploaded image is attached to our Envira CPT
283
+ *
284
+ * @since 1.0.0
285
+ *
286
+ * @param array $params Params
287
+ * @return array Params
288
+ */
289
+ public function plupload_init( $params ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
 
291
+ global $post_ID;
 
 
 
292
 
293
+ // Define the Envira Gallery Post ID, so Plupload attaches the uploaded images
294
+ // to this Envira Gallery
295
+ $params['multipart_params']['post_id'] = $post_ID;
296
+
297
+ // Build an array of supported file types for Plupload
298
+ $supported_file_types = Envira_Gallery_Common::get_instance()->get_supported_filetypes();
299
+
300
+ // Assign supported file types and return
301
+ $params['filters']['mime_types'] = $supported_file_types;
302
 
303
  // Return and apply a custom filter to our init data.
304
+ $params = apply_filters( 'envira_gallery_plupload_init', $params, $post_ID );
305
+ return $params;
306
 
307
  }
308
+
309
  /**
310
  * Hides unnecessary meta box items on Envira post type screens.
311
  *
317
  <style type="text/css">.misc-pub-section:not(.misc-pub-post-status) { display: none; }</style>
318
  <?php
319
 
320
+ // Fire action for CSS on Envira post type screens.
321
+ do_action( 'envira_gallery_admin_css' );
322
+
323
  }
324
 
325
  /**
329
  */
330
  public function add_meta_boxes() {
331
 
332
+ global $post;
 
 
 
 
333
 
334
+ // Check we're on an Envira Gallery
335
+ if ( 'envira' != $post->post_type ) {
336
+ return;
337
+ }
338
 
339
+ // Let's remove all of those dumb metaboxes from our post type screen to control the experience.
340
+ $this->remove_all_the_metaboxes();
341
+
342
+ // Add our metaboxes to Envira CPT.
343
+
344
+ // Types Metabox
345
+ // Allows the user to upload images or choose an External Gallery Type
346
+ // We don't display this if the Gallery is a Dynamic or Default Gallery, as these settings don't apply
347
+ $type = $this->get_config( 'type', $this->get_config_default( 'type' ) );
348
+ if ( ! in_array( $type, array( 'defaults', 'dynamic' ) ) ) {
349
+ add_meta_box( 'envira-gallery', __( 'Envira Gallery', 'envira-gallery' ), array( $this, 'meta_box_gallery_callback' ), 'envira', 'normal', 'high' );
350
+ }
351
 
352
+ // Settings Metabox
353
+ add_meta_box( 'envira-gallery-settings', __( 'Envira Gallery Settings', 'envira-gallery' ), array( $this, 'meta_box_callback' ), 'envira', 'normal', 'high' );
354
+
355
+ // Preview Metabox
356
+ // Displays the images to be displayed when using an External Gallery Type
357
+ // In the future, this could include a 'live' preview of the gallery theme options etc.
358
+ add_meta_box( 'envira-gallery-preview', __( 'Envira Gallery Preview', 'envira-gallery' ), array( $this, 'meta_box_preview_callback' ), 'envira', 'normal', 'high' );
359
+
360
+ // Display the Gallery Code metabox if we're editing an existing Gallery
361
+ if ( $post->post_status != 'auto-draft' ) {
362
+ add_meta_box( 'envira-gallery-code', __( 'Envira Gallery Code', 'envira-gallery' ), array( $this, 'meta_box_gallery_code_callback' ), 'envira', 'side', 'default' );
363
  }
364
 
365
+ // Output 'Select Files from Other Sources' button on the media uploader form
366
+ add_action( 'post-plupload-upload-ui', array( $this, 'append_media_upload_form' ), 1 );
367
+ add_action( 'post-html-upload-ui', array( $this, 'append_media_upload_form' ), 1 );
368
+
369
  }
370
 
371
  /**
384
  $post_type = 'envira';
385
 
386
  // These are the metabox IDs you want to pass over. They don't have to match exactly. preg_match will be run on them.
387
+ $pass_over_defaults = array( 'submitdiv', 'envira' );
388
+ $pass_over = apply_filters( 'envira_gallery_metabox_ids', $pass_over_defaults );
389
 
390
  // All the metabox contexts you want to check.
391
+ $contexts_defaults = array( 'normal', 'advanced', 'side' );
392
+ $contexts = apply_filters( 'envira_gallery_metabox_contexts', $contexts_defaults );
393
 
394
  // All the priorities you want to check.
395
+ $priorities_defaults = array( 'high', 'core', 'default', 'low' );
396
+ $priorities = apply_filters( 'envira_gallery_metabox_priorities', $priorities_defaults );
397
 
398
  // Loop through and target each context.
399
  foreach ( $contexts as $context ) {
424
  }
425
 
426
  /**
427
+ * Adds an envira-gallery class to the form when adding or editing an Album,
428
+ * so our plugin's CSS and JS can target a specific element and its children.
429
+ *
430
+ * @since 1.5.0
431
+ *
432
+ * @param WP_Post $post WordPress Post
433
+ */
434
+ public function add_form_class( $post ) {
435
+
436
+ // Check the Post is a Gallery
437
+ if ( 'envira' != get_post_type( $post ) ) {
438
+ return;
439
+ }
440
+
441
+ echo ' class="envira-gallery"';
442
+
443
+ }
444
+
445
+ /**
446
+ * Callback for displaying the Gallery Type section.
447
+ *
448
+ * @since 1.5.0
449
+ *
450
+ * @param object $post The current post object.
451
+ */
452
+ public function meta_box_gallery_callback( $post ) {
453
+
454
+ // Load view
455
+ $this->base->load_admin_partial( 'metabox-gallery-type', array(
456
+ 'post' => $post,
457
+ 'types' => $this->get_envira_types( $post ),
458
+ 'instance' => $this,
459
+ ) );
460
+
461
+ }
462
+
463
+ /**
464
+ * Callback for displaying the Gallery Settings section.
465
  *
466
  * @since 1.0.0
467
  *
470
  public function meta_box_callback( $post ) {
471
 
472
  // Keep security first.
473
+ wp_nonce_field( 'envira-gallery', 'envira-gallery' );
474
 
475
+ // Load view
476
+ $this->base->load_admin_partial( 'metabox-gallery-settings', array(
477
+ 'post' => $post,
478
+ 'tabs' => $this->get_envira_tab_nav(),
479
+ ) );
 
 
480
 
481
+ }
482
+
483
+ /**
484
+ * Callback for displaying the Preview metabox.
485
+ *
486
+ * @since 1.5.0
487
+ *
488
+ * @param object $post The current post object.
489
+ */
490
+ public function meta_box_preview_callback( $post ) {
491
+
492
+ // Get the gallery data
493
+ $data = get_post_meta( $post->ID, '_eg_gallery_data', true );
494
+
495
+ // Output the display based on the type of slider being created.
496
+ echo '<div id="envira-gallery-preview-main" class="envira-clear">';
497
+
498
+ $this->preview_display( $this->get_config( 'type', $this->get_config_default( 'type' ) ), $data );
499
+
500
+ echo '</div>
501
+ <div class="spinner"></div>';
502
+
503
+ }
504
+
505
+ /**
506
+ * Callback for displaying the Gallery Code metabox.
507
+ *
508
+ * @since 1.5.0
509
+ *
510
+ * @param object $post The current post object.
511
+ */
512
+ public function meta_box_gallery_code_callback( $post ) {
513
+
514
+ // Load view
515
+ $this->base->load_admin_partial( 'metabox-gallery-code', array(
516
+ 'post' => $post,
517
+ 'gallery_data' => get_post_meta( $post->ID, '_eg_gallery_data', true ),
518
+ ) );
519
+
520
+ }
521
+
522
+ /**
523
+ * Returns the types of galleries available.
524
+ *
525
+ * @since 1.0.0
526
+ *
527
+ * @param object $post The current post object.
528
+ * @return array Array of gallery types to choose.
529
+ */
530
+ public function get_envira_types( $post ) {
531
+
532
+ $types = array(
533
+ 'default' => __( 'Default', 'envira-gallery' )
534
+ );
535
+
536
+ return apply_filters( 'envira_gallery_types', $types, $post );
537
 
538
  }
539
 
540
  /**
541
+ * Returns the tabs to be displayed in the settings metabox.
542
  *
543
  * @since 1.0.0
544
  *
547
  public function get_envira_tab_nav() {
548
 
549
  $tabs = array(
550
+ 'images' => __( 'Images', 'envira-gallery' ),
551
+ 'config' => __( 'Config', 'envira-gallery' ),
552
+ 'lightbox' => __( 'Lightbox', 'envira-gallery' ),
553
  );
554
  $tabs = apply_filters( 'envira_gallery_tab_nav', $tabs );
555
 
556
  // "Misc" tab is required.
557
+ $tabs['misc'] = __( 'Misc', 'envira-gallery' );
558
 
559
  return $tabs;
560
 
561
  }
562
 
563
  /**
564
+ * Callback for displaying the settings UI for the Gallery tab.
565
  *
566
  * @since 1.0.0
567
  *
569
  */
570
  public function images_tab( $post ) {
571
 
572
+ // Output the display based on the type of slider being created.
573
+ echo '<div id="envira-gallery-main" class="envira-clear">';
 
 
 
574
 
575
+ // Allow Addons to display a WordPress-style notification message
576
+ echo apply_filters( 'envira_gallery_images_tab_notice', '', $post );
577
 
578
+ // Output the tab panel for the Gallery Type
579
+ $this->images_display( $this->get_config( 'type', $this->get_config_default( 'type' ) ), $post );
580
 
581
+ echo '</div>
582
+ <div class="spinner"></div>';
 
 
 
 
 
 
 
583
 
584
  }
585
 
586
  /**
587
+ * Determines the Images tab display based on the type of gallery selected.
588
  *
589
  * @since 1.0.0
590
  *
591
+ * @param string $type The type of display to output.
592
+ * @param object $post The current post object.
 
593
  */
594
+ public function images_display( $type = 'default', $post ) {
595
+
596
+ // Output a unique hidden field for settings save testing for each type of slider.
597
+ echo '<input type="hidden" name="_envira_gallery[type_' . $type . ']" value="1" />';
598
+
599
+ // Output the display based on the type of slider available.
600
+ switch ( $type ) {
601
+ case 'default' :
602
+ $this->do_default_display( $post );
603
+ break;
604
+ default:
605
+ do_action( 'envira_gallery_display_' . $type, $post );
606
+ break;
607
  }
608
 
609
+ }
 
 
 
 
 
 
610
 
611
+ /**
612
+ * Determines the Preview metabox display based on the type of gallery selected.
613
+ *
614
+ * @since 1.5.0
615
+ *
616
+ * @param string $type The type of display to output.
617
+ * @param object $data Gallery Data
618
+ */
619
+ public function preview_display( $type = 'default', $data ) {
620
+
621
+ // Output the display based on the type of slider available.
622
+ switch ( $type ) {
623
+ case 'default' :
624
+ // Don't preview anything
625
+ break;
626
+ default:
627
+ do_action( 'envira_gallery_preview_' . $type, $data );
628
+ break;
629
+ }
630
 
631
  }
632
 
633
  /**
634
+ * Callback for displaying the default gallery UI.
635
  *
636
  * @since 1.0.0
637
  *
638
  * @param object $post The current post object.
639
  */
640
+ public function do_default_display( $post ) {
641
+
642
+ // Prepare output data.
643
+ $gallery_data = get_post_meta( $post->ID, '_eg_gallery_data', true );
644
 
645
+ // Determine whether to use the list or grid layout, depending on the user's setting
646
+ $layout = get_user_setting( 'envira_gallery_image_view', 'grid' );
647
  ?>
648
+
649
+ <!-- Title and Help -->
650
+ <p class="envira-intro">
651
+ <?php _e( 'Currently in your Gallery', 'envira-gallery' ); ?>
652
+ <small>
653
+ <?php _e( 'Need some help?', 'envira-gallery' ); ?>
654
+ <a href="http://enviragallery.com/docs/creating-first-envira-gallery/" class="envira-doc" target="_blank">
655
+ <?php _e( 'Read the Documentation', 'envira-gallery' ); ?>
656
+ </a>
657
+ or
658
+ <a href="https://www.youtube.com/embed/F9_wOefuBaw?autoplay=1&amp;rel=0" class="envira-video" target="_blank">
659
+ <?php _e( 'Watch a Video', 'envira-gallery' ); ?>
660
+ </a>
661
+ </small>
662
+ </p>
663
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
664
  <?php
665
+ do_action( 'envira_gallery_do_default_display', $post );
666
+ ?>
667
+ <ul id="envira-gallery-output" class="envira-gallery-images-output <?php echo $layout; ?>">
668
+ <?php
669
+ if ( ! empty( $gallery_data['gallery'] ) ) {
670
+ foreach ( $gallery_data['gallery'] as $id => $data ) {
671
+ echo $this->get_gallery_item( $id, $data, $post->ID );
672
+ }
673
+ }
674
+ ?>
675
+ </ul>
676
+
677
+ <?php
678
+ // Output an upgrade notice
679
+ Envira_Gallery_Notice_Admin::get_instance()->display_inline_notice(
680
+ 'envira_gallery_images_tab',
681
+ __( 'Want to make your gallery workflow even better?', 'envira-gallery' ),
682
+ __( 'By upgrading to Envira Pro, you can get access to numerous other features, including: a fully featured gallery widget, complete gallery API, powerful gallery documentation, full mobile and Retina support, dedicated customer support and so much more!', 'envira-gallery' ),
683
+ 'warning',
684
+ __( 'Click here to Upgrade', 'envira-gallery' ),
685
+ Envira_Gallery_Common_Admin::get_instance()->get_upgrade_link(),
686
+ false
687
+ );
688
 
689
  }
690
 
691
  /**
692
+ * Callback for displaying the settings UI for the Configuration tab.
693
  *
694
  * @since 1.0.0
695
  *
699
 
700
  ?>
701
  <div id="envira-config">
702
+ <!-- Title and Help -->
703
+ <p class="envira-intro">
704
+ <?php _e( 'The settings below adjust the basic configuration options for the gallery.', 'envira-gallery' ); ?>
705
+ <small>
706
+ <?php _e( 'Need some help?', 'envira-gallery' ); ?>
707
+ <a href="http://enviragallery.com/docs/creating-first-envira-gallery/" class="envira-doc" target="_blank">
708
+ <?php _e( 'Read the Documentation', 'envira-gallery' ); ?>
709
+ </a>
710
+ or
711
+ <a href="https://www.youtube.com/embed/F9_wOefuBaw?autoplay=1&amp;rel=0" class="envira-video" target="_blank">
712
+ <?php _e( 'Watch a Video', 'envira-gallery' ); ?>
713
+ </a>
714
+ </small>
715
+ </p>
716
  <table class="form-table">
717
  <tbody>
718
  <tr id="envira-config-columns-box">
719
  <th scope="row">
720
+ <label for="envira-config-columns"><?php _e( 'Number of Gallery Columns', 'envira-gallery' ); ?></label>
721
  </th>
722
  <td>
723
  <select id="envira-config-columns" name="_envira_gallery[columns]">
725
  <option value="<?php echo $data['value']; ?>"<?php selected( $data['value'], $this->get_config( 'columns', $this->get_config_default( 'columns' ) ) ); ?>><?php echo $data['name']; ?></option>
726
  <?php endforeach; ?>
727
  </select>
728
+ <p class="description"><?php _e( 'Determines the number of columns in the gallery. Automatic will attempt to fill each row as much as possible before moving on to the next row.', 'envira-gallery' ); ?></p>
729
  </td>
730
  </tr>
731
+
732
+ <tr id="envira-config-gallery-theme-box">
733
  <th scope="row">
734
+ <label for="envira-config-gallery-theme"><?php _e( 'Gallery Theme', 'envira-gallery' ); ?></label>
735
  </th>
736
  <td>
737
  <select id="envira-config-gallery-theme" name="_envira_gallery[gallery_theme]">
739
  <option value="<?php echo $data['value']; ?>"<?php selected( $data['value'], $this->get_config( 'gallery_theme', $this->get_config_default( 'gallery_theme' ) ) ); ?>><?php echo $data['name']; ?></option>
740
  <?php endforeach; ?>
741
  </select>
742
+ <p class="description"><?php _e( 'Sets the theme for the gallery display.', 'envira-gallery' ); ?></p>
743
  </td>
744
  </tr>
745
+
746
+
747
  <tr id="envira-config-gutter-box">
748
  <th scope="row">
749
+ <label for="envira-config-gutter"><?php _e( 'Column Gutter Width', 'envira-gallery' ); ?></label>
750
  </th>
751
  <td>
752
+ <input id="envira-config-gutter" type="number" name="_envira_gallery[gutter]" value="<?php echo $this->get_config( 'gutter', $this->get_config_default( 'gutter' ) ); ?>" /> <span class="envira-unit"><?php _e( 'px', 'envira-gallery' ); ?></span>
753
+ <p class="description"><?php _e( 'Sets the space between the columns (defaults to 10).', 'envira-gallery' ); ?></p>
 
754
  </td>
755
  </tr>
756
+
757
  <tr id="envira-config-margin-box">
758
  <th scope="row">
759
+ <label for="envira-config-margin"><?php _e( 'Margin Below Each Image', 'envira-gallery' ); ?></label>
760
  </th>
761
  <td>
762
+ <input id="envira-config-margin" type="number" name="_envira_gallery[margin]" value="<?php echo $this->get_config( 'margin', $this->get_config_default( 'margin' ) ); ?>" /> <span class="envira-unit"><?php _e( 'px', 'envira-gallery' ); ?></span>
763
+ <p class="description"><?php _e( 'Sets the space below each item in the gallery.', 'envira-gallery' ); ?></p>
 
764
  </td>
765
  </tr>
766
+
767
+ <!-- Dimensions -->
768
+ <tr id="envira-config-image-size-box">
769
  <th scope="row">
770
+ <label for="envira-config-image-size"><?php _e( 'Image Size', 'envira-gallery' ); ?></label>
771
  </th>
772
  <td>
773
+ <select id="envira-config-image-size" name="_envira_gallery[image_size]" data-envira-conditional="envira-config-crop-size-box,envira-config-crop-box" data-envira-conditional-value="default">
774
+ <?php
775
+ foreach ( (array) $this->get_image_sizes() as $i => $data ) {
776
+ ?>
777
+ <option value="<?php echo $data['value']; ?>"<?php selected( $data['value'], $this->get_config( 'image_size', $this->get_config_default( 'image_size' ) ) ); ?>><?php echo $data['name']; ?></option>
778
+ <?php
779
+ }
780
+ ?>
781
+ </select>
782
+ <p class="description"><?php _e( 'Define the maximum image size for the Gallery view. Default will use the below Image Dimensions.', 'envira-gallery' ); ?></p>
783
  </td>
784
  </tr>
785
+ <tr id="envira-config-crop-size-box">
786
  <th scope="row">
787
+ <label for="envira-config-crop-width"><?php _e( 'Image Dimensions', 'envira-gallery' ); ?></label>
788
  </th>
789
  <td>
790
+ <input id="envira-config-crop-width" type="number" name="_envira_gallery[crop_width]" value="<?php echo $this->get_config( 'crop_width', $this->get_config_default( 'crop_width' ) ); ?>" /> &#215; <input id="envira-config-crop-height" type="number" name="_envira_gallery[crop_height]" value="<?php echo $this->get_config( 'crop_height', $this->get_config_default( 'crop_height' ) ); ?>" /> <span class="envira-unit"><?php _e( 'px', 'envira-gallery' ); ?></span>
791
+ <p class="description"><?php _e( 'You should adjust these dimensions based on the number of columns in your gallery. This does not affect the full size lightbox images.', 'envira-gallery' ); ?></p>
792
  </td>
793
  </tr>
794
+ <tr id="envira-config-crop-box">
795
+ <th scope="row">
796
+ <label for="envira-config-crop"><?php _e( 'Crop Images?', 'envira-gallery' ); ?></label>
797
+ </th>
798
+ <td>
799
+ <input id="envira-config-crop" type="checkbox" name="_envira_gallery[crop]" value="<?php echo $this->get_config( 'crop', $this->get_config_default( 'crop' ) ); ?>" <?php checked( $this->get_config( 'crop', $this->get_config_default( 'crop' ) ), 1 ); ?> />
800
+ <span class="description"><?php _e( 'If enabled, forces images to exactly match the sizes defined above for Image Dimensions.', 'envira-gallery' ); ?></span>
801
+ <span class="description"><?php _e( 'If disabled, images will be resized to maintain their aspect ratio.', 'envira-gallery' ); ?></span>
802
+
803
+ </td>
804
+ </tr>
805
+
806
  <?php do_action( 'envira_gallery_config_box', $post ); ?>
807
  </tbody>
808
  </table>
 
 
 
809
  </div>
810
  <?php
811
 
812
+ // Output an upgrade notice
813
+ Envira_Gallery_Notice_Admin::get_instance()->display_inline_notice(
814
+ 'envira_gallery_config_tab',
815
+ __( 'Want to do even more with your gallery display?', 'envira-gallery' ),
816
+ __( 'By upgrading to Envira Pro, you can get access to numerous other gallery display features, including: custom image tagging and filtering, mobile specific image assets for blazing fast load times, dedicated and unique gallery URLs, custom gallery themes, gallery thumbnail support and so much more!', 'envira-gallery' ),
817
+ 'warning',
818
+ __( 'Click here to Upgrade', 'envira-gallery' ),
819
+ Envira_Gallery_Common_Admin::get_instance()->get_upgrade_link(),
820
+ false
821
+ );
822
+
823
  }
824
 
825
  /**
826
+ * Callback for displaying the settings UI for the Lightbox tab.
827
  *
828
  * @since 1.0.0
829
  *
833
 
834
  ?>
835
  <div id="envira-lightbox">
836
+ <p class="envira-intro">
837
+ <?php _e( 'The settings below adjust the lightbox output.', 'envira-gallery' ); ?>
838
+ <small>
839
+ <?php _e( 'Need some help?', 'envira-gallery' ); ?>
840
+ <a href="http://enviragallery.com/docs/creating-first-envira-gallery/" class="envira-doc" target="_blank">
841
+ <?php _e( 'Read the Documentation', 'envira-gallery' ); ?>
842
+ </a>
843
+ or
844
+ <a href="https://www.youtube.com/embed/4jHG3LOmV-c?autoplay=1&amp;rel=0" class="envira-video" target="_blank">
845
+ <?php _e( 'Watch a Video', 'envira-gallery' ); ?>
846
+ </a>
847
+ </small>
848
+ </p>
849
+
850
+ <table class="form-table no-margin">
851
  <tbody>
852
  <tr id="envira-config-lightbox-enabled-box">
853
  <th scope="row">
854
+ <label for="envira-config-lightbox-enabled"><?php _e( 'Enable Lightbox?', 'envira-gallery' ); ?></label>
855
  </th>
856
  <td>
857
+ <input id="envira-config-lightbox-enabled" type="checkbox" name="_envira_gallery[lightbox_enabled]" value="<?php echo $this->get_config( 'lightbox_enabled', $this->get_config_default( 'lightbox_enabled' ) ); ?>" <?php checked( $this->get_config( 'lightbox_enabled', $this->get_config_default( 'lightbox_enabled' ) ), 1 ); ?> data-envira-conditional="envira-lightbox-settings" />
858
+ <span class="description"><?php _e( 'Enables or disables the gallery lightbox.', 'envira-gallery' ); ?></span>
859
  </td>
860
  </tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
861
  </tbody>
862
  </table>
863
+
864
+ <div id="envira-lightbox-settings">
865
+ <table class="form-table">
866
+ <tbody>
867
+ <tr id="envira-config-lightbox-theme-box">
868
+ <th scope="row">
869
+ <label for="envira-config-lightbox-theme"><?php _e( 'Gallery Lightbox Theme', 'envira-gallery' ); ?></label>
870
+ </th>
871
+ <td>
872
+ <select id="envira-config-lightbox-theme" name="_envira_gallery[lightbox_theme]">
873
+ <?php foreach ( (array) $this->get_lightbox_themes() as $i => $data ) : ?>
874
+ <option value="<?php echo $data['value']; ?>"<?php selected( $data['value'], $this->get_config( 'lightbox_theme', $this->get_config_default( 'lightbox_theme' ) ) ); ?>><?php echo $data['name']; ?></option>
875
+ <?php endforeach; ?>
876
+ </select>
877
+ <p class="description"><?php _e( 'Sets the theme for the gallery lightbox display.', 'envira-gallery' ); ?></p>
878
+ </td>
879
+ </tr>
880
+
881
+ <tr id="envira-config-lightbox-image-size-box">
882
+ <th scope="row">
883
+ <label for="envira-config-lightbox-image-size"><?php _e( 'Image Size', 'envira-gallery' ); ?></label>
884
+ </th>
885
+ <td>
886
+ <select id="envira-config-lightbox-image-size" name="_envira_gallery[lightbox_image_size]">
887
+ <?php foreach ( (array) $this->get_image_sizes() as $i => $data ) : ?>
888
+ <option value="<?php echo $data['value']; ?>" <?php selected( $data['value'], $this->get_config( 'lightbox_image_size', $this->get_config_default( 'lightbox_image_size' ) ) ); ?>><?php echo $data['name']; ?></option>
889
+ <?php endforeach; ?>
890
+ </select><br>
891
+ <p class="description"><?php _e( 'Define the maximum image size for the Lightbox view. Default will display the original, full size image.', 'envira-gallery' ); ?></p>
892
+ </td>
893
+ </tr>
894
+
895
+ <tr id="envira-config-lightbox-title-display-box">
896
+ <th scope="row">
897
+ <label for="envira-config-lightbox-title-display"><?php _e( 'Caption Position', 'envira-gallery' ); ?></label>
898
+ </th>
899
+ <td>
900
+ <select id="envira-config-lightbox-title-display" name="_envira_gallery[title_display]">
901
+ <?php foreach ( (array) $this->get_title_displays() as $i => $data ) : ?>
902
+ <option value="<?php echo $data['value']; ?>"<?php selected( $data['value'], $this->get_config( 'title_display', $this->get_config_default( 'title_display' ) ) ); ?>><?php echo $data['name']; ?></option>
903
+ <?php endforeach; ?>
904
+ </select>
905
+ <p class="description"><?php _e( 'Sets the display of the lightbox image\'s caption.', 'envira-gallery' ); ?></p>
906
+ </td>
907
+ </tr>
908
+
909
+ <?php do_action( 'envira_gallery_lightbox_box', $post ); ?>
910
+ </tbody>
911
+ </table>
912
  </div>
913
  </div>
914
  <?php
915
 
916
+ // Output an upgrade notice
917
+ Envira_Gallery_Notice_Admin::get_instance()->display_inline_notice(
918
+ 'envira_gallery_lightbox_tab',
919
+ __( 'Want even more fine tuned control over your lightbox display?', 'envira-gallery' ),
920
+ __( 'By upgrading to Envira Pro, you can get access to numerous other lightbox features, including: custom lightbox titles, enable/disable lightbox controls (arrow, keyboard and mousehweel navigation), custom lightbox transition effects, native fullscreen support, gallery deeplinking, image protection, lightbox supersize effects, lightbox slideshows and so much more!', 'envira-gallery' ),
921
+ 'warning',
922
+ __( 'Click here to Upgrade', 'envira-gallery' ),
923
+ Envira_Gallery_Common_Admin::get_instance()->get_upgrade_link(),
924
+ false
925
+ );
926
+
927
  }
928
 
929
  /**
930
+ * Callback for displaying the settings UI for the Misc tab.
931
  *
932
  * @since 1.0.0
933
  *
937
 
938
  ?>
939
  <div id="envira-misc">
940
+ <p class="envira-intro">
941
+ <?php _e( 'The settings below adjust miscellaneous settings for the gallery.', 'envira-gallery' ); ?>
942
+ <small>
943
+ <?php _e( 'Need some help?', 'envira-gallery' ); ?>
944
+ <a href="http://enviragallery.com/docs/creating-first-envira-gallery/" class="envira-doc" target="_blank">
945
+ <?php _e( 'Read the Documentation', 'envira-gallery' ); ?>
946
+ </a>
947
+ or
948
+ <a href="https://www.youtube.com/embed/4jHG3LOmV-c?autoplay=1&amp;rel=0" class="envira-video" target="_blank">
949
+ <?php _e( 'Watch a Video', 'envira-gallery' ); ?>
950
+ </a>
951
+ </small>
952
+ </p>
953
  <table class="form-table">
954
  <tbody>
955
  <tr id="envira-config-title-box">
956
  <th scope="row">
957
+ <label for="envira-config-title"><?php _e( 'Gallery Title', 'envira-gallery' ); ?></label>
958
  </th>
959
  <td>
960
  <input id="envira-config-title" type="text" name="_envira_gallery[title]" value="<?php echo $this->get_config( 'title', $this->get_config_default( 'title' ) ); ?>" />
961
+ <p class="description"><?php _e( 'Internal gallery title for identification in the admin.', 'envira-gallery' ); ?></p>
962
  </td>
963
  </tr>
964
  <tr id="envira-config-slug-box">
965
  <th scope="row">
966
+ <label for="envira-config-slug"><?php _e( 'Gallery Slug', 'envira-gallery' ); ?></label>
967
  </th>
968
  <td>
969
  <input id="envira-config-slug" type="text" name="_envira_gallery[slug]" value="<?php echo $this->get_config( 'slug', $this->get_config_default( 'slug' ) ); ?>" />
970
+ <p class="description"><?php _e( '<strong>Unique</strong> internal gallery slug for identification and advanced gallery queries.', 'envira-gallery' ); ?></p>
971
  </td>
972
  </tr>
973
  <tr id="envira-config-classes-box">
974
  <th scope="row">
975
+ <label for="envira-config-classes"><?php _e( 'Custom Gallery Classes', 'envira-gallery' ); ?></label>
976
  </th>
977
  <td>
978
+ <textarea id="envira-config-classes" rows="5" cols="75" name="_envira_gallery[classes]" placeholder="<?php _e( 'Enter custom gallery CSS classes here, one per line.', 'envira-gallery' ); ?>"><?php echo implode( "\n", (array) $this->get_config( 'classes', $this->get_config_default( 'classes' ) ) ); ?></textarea>
979
+ <p class="description"><?php _e( 'Adds custom CSS classes to this gallery. Enter one class per line.', 'envira-gallery' ); ?></p>
980
  </td>
981
  </tr>
982
  <tr id="envira-config-rtl-box">
983
  <th scope="row">
984
+ <label for="envira-config-rtl"><?php _e( 'Enable RTL Support?', 'envira-gallery' ); ?></label>
985
  </th>
986
  <td>
987
  <input id="envira-config-rtl" type="checkbox" name="_envira_gallery[rtl]" value="<?php echo $this->get_config( 'rtl', $this->get_config_default( 'rtl' ) ); ?>" <?php checked( $this->get_config( 'rtl', $this->get_config_default( 'rtl' ) ), 1 ); ?> />
988
+ <span class="description"><?php _e( 'Enables or disables RTL support in Envira for right-to-left languages.', 'envira-gallery' ); ?></span>
989
  </td>
990
  </tr>
991
  <?php do_action( 'envira_gallery_misc_box', $post ); ?>
992
  </tbody>
993
  </table>
 
 
 
994
  </div>
995
  <?php
996
 
997
+ // Output an upgrade notice
998
+ Envira_Gallery_Notice_Admin::get_instance()->display_inline_notice(
999
+ 'envira_gallery_misc_tab',
1000
+ __( 'Want to take your galleries further?', 'envira-gallery' ),
1001
+ __( 'By upgrading to Envira Pro, you can get access to numerous other features, including: a fully-integrated import/export module for your galleries, custom CSS controls for each gallery and so much more!', 'envira-gallery' ),
1002
+ 'warning',
1003
+ __( 'Click here to Upgrade', 'envira-gallery' ),
1004
+ Envira_Gallery_Common_Admin::get_instance()->get_upgrade_link(),
1005
+ false
1006
+ );
1007
+
1008
+ }
1009
+
1010
+ /**
1011
+ * Adds Envira Gallery Lite-specific tabs
1012
+ *
1013
+ * @since 1.5.0
1014
+ *
1015
+ * @param array $tabs Tabs
1016
+ * @return array Tabs
1017
+ */
1018
+ public function lite_tabs( $tabs ) {
1019
+
1020
+ $tabs['mobile'] = __( 'Mobile', 'envira-gallery' );
1021
+ $tabs['videos'] = __( 'Videos', 'envira-gallery' );
1022
+ $tabs['social'] = __( 'Social', 'envira-gallery' );
1023
+ $tabs['tags'] = __( 'Tags', 'envira-gallery' );
1024
+ $tabs['pagination'] = __( 'Pagination', 'envira-gallery' );
1025
+ return $tabs;
1026
+
1027
+ }
1028
+
1029
+ /**
1030
+ * Callback for displaying the settings UI for the Mobile tab.
1031
+ *
1032
+ * @since 1.5.0
1033
+ *
1034
+ * @param object $post The current post object.
1035
+ */
1036
+ public function lite_mobile_tab( $post ) {
1037
+
1038
+ // Output an upgrade notice
1039
+ Envira_Gallery_Notice_Admin::get_instance()->display_inline_notice(
1040
+ 'envira_gallery_mobile_tab',
1041
+ __( 'Want to take your galleries further?', 'envira-gallery' ),
1042
+ __( 'By upgrading to Envira Pro, you can get access to mobile-specific settings, including mobile image sizes, number of columns, mobile-specific lightbox options and so much more!', 'envira-gallery' ),
1043
+ 'warning',
1044
+ __( 'Click here to Upgrade', 'envira-gallery' ),
1045
+ Envira_Gallery_Common_Admin::get_instance()->get_upgrade_link(),
1046
+ false
1047
+ );
1048
+
1049
+ }
1050
+
1051
+ /**
1052
+ * Lite: Callback for displaying the settings UI for the Mobile tab.
1053
+ *
1054
+ * @since 1.5.0
1055
+ *
1056
+ * @param object $post The current post object.
1057
+ */
1058
+ public function lite_videos_tab( $post ) {
1059
+
1060
+ // Output an upgrade notice
1061
+ Envira_Gallery_Notice_Admin::get_instance()->display_inline_notice(
1062
+ 'envira_gallery_mobile_tab',
1063
+ __( 'Want to take your galleries further?', 'envira-gallery' ),
1064
+ __( 'By upgrading to Envira Pro, you can add Videos to your Envira Galleries from YouTube, Vimeo, Wistia, and your own self-hosted videos!', 'envira-gallery' ),
1065
+ 'warning',
1066
+ __( 'Click here to Upgrade', 'envira-gallery' ),
1067
+ Envira_Gallery_Common_Admin::get_instance()->get_upgrade_link(),
1068
+ false
1069
+ );
1070
+
1071
+ }
1072
+
1073
+ /**
1074
+ * Lite: Callback for displaying the settings UI for the Mobile tab.
1075
+ *
1076
+ * @since 1.5.0
1077
+ *
1078
+ * @param object $post The current post object.
1079
+ */
1080
+ public function lite_social_tab( $post ) {
1081
+
1082
+ // Output an upgrade notice
1083
+ Envira_Gallery_Notice_Admin::get_instance()->display_inline_notice(
1084
+ 'envira_gallery_mobile_tab',
1085
+ __( 'Want to take your galleries further?', 'envira-gallery' ),
1086
+ __( 'By upgrading to Envira Pro, you can add social sharing buttons to your Gallery images and Lightbox images. With support for Facebook, Twitter, Google+ and Pinterest why not check it out?', 'envira-gallery' ),
1087
+ 'warning',
1088
+ __( 'Click here to Upgrade', 'envira-gallery' ),
1089
+ Envira_Gallery_Common_Admin::get_instance()->get_upgrade_link(),
1090
+ false
1091
+ );
1092
+
1093
+ }
1094
+
1095
+ /**
1096
+ * Lite: Callback for displaying the settings UI for the Mobile tab.
1097
+ *
1098
+ * @since 1.5.0
1099
+ *
1100
+ * @param object $post The current post object.
1101
+ */
1102
+ public function lite_tags_tab( $post ) {
1103
+
1104
+ // Output an upgrade notice
1105
+ Envira_Gallery_Notice_Admin::get_instance()->display_inline_notice(
1106
+ 'envira_gallery_mobile_tab',
1107
+ __( 'Want to take your galleries further?', 'envira-gallery' ),
1108
+ __( 'By upgrading to Envira Pro, you can add Tags to your Gallery images, allow users to filter your Gallery by tag and so much more!', 'envira-gallery' ),
1109
+ 'warning',
1110
+ __( 'Click here to Upgrade', 'envira-gallery' ),
1111
+ Envira_Gallery_Common_Admin::get_instance()->get_upgrade_link(),
1112
+ false
1113
+ );
1114
+
1115
+ }
1116
+
1117
+ /**
1118
+ * Lite: Callback for displaying the settings UI for the Mobile tab.
1119
+ *
1120
+ * @since 1.5.0
1121
+ *
1122
+ * @param object $post The current post object.
1123
+ */
1124
+ public function lite_pagination_tab( $post ) {
1125
+
1126
+ // Output an upgrade notice
1127
+ Envira_Gallery_Notice_Admin::get_instance()->display_inline_notice(
1128
+ 'envira_gallery_mobile_tab',
1129
+ __( 'Want to take your galleries further?', 'envira-gallery' ),
1130
+ __( 'By upgrading to Envira Pro, you can split your Gallery across multiple pages with pagination, load paginated images via AJAX, lazy loading and more!', 'envira-gallery' ),
1131
+ 'warning',
1132
+ __( 'Click here to Upgrade', 'envira-gallery' ),
1133
+ Envira_Gallery_Common_Admin::get_instance()->get_upgrade_link(),
1134
+ false
1135
+ );
1136
+
1137
  }
1138
 
1139
  /**
1147
  public function save_meta_boxes( $post_id, $post ) {
1148
 
1149
  // Bail out if we fail a security check.
1150
+ if ( ! isset( $_POST['envira-gallery'] ) || ! wp_verify_nonce( $_POST['envira-gallery'], 'envira-gallery' ) || ! isset( $_POST['_envira_gallery'] ) ) {
1151
  return;
1152
  }
1153
 
1157
  }
1158
 
1159
  if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
1160
+ // Check if this is a Quick Edit request
1161
+ if ( isset( $_POST['_inline_edit'] ) ) {
1162
+
1163
+ // Just update specific fields in the Quick Edit screen
1164
+
1165
+ // Get settings
1166
+ $settings = get_post_meta( $post_id, '_eg_gallery_data', true );
1167
+ if ( empty( $settings ) ) {
1168
+ return;
1169
+ }
1170
+
1171
+ // Update Settings
1172
+ $settings['config']['columns'] = preg_replace( '#[^a-z0-9-_]#', '', $_POST['_envira_gallery']['columns'] );
1173
+ $settings['config']['gallery_theme'] = preg_replace( '#[^a-z0-9-_]#', '', $_POST['_envira_gallery']['gallery_theme'] );
1174
+ $settings['config']['gutter'] = absint( $_POST['_envira_gallery']['gutter'] );
1175
+ $settings['config']['margin'] = absint( $_POST['_envira_gallery']['margin'] );
1176
+ $settings['config']['crop_width'] = absint( $_POST['_envira_gallery']['crop_width'] );
1177
+ $settings['config']['crop_height'] = absint( $_POST['_envira_gallery']['crop_height'] );
1178
+
1179
+ // Provide a filter to override settings.
1180
+ $settings = apply_filters( 'envira_gallery_quick_edit_save_settings', $settings, $post_id, $post );
1181
+
1182
+ // Update the post meta.
1183
+ update_post_meta( $post_id, '_eg_gallery_data', $settings );
1184
+
1185
+ // Finally, flush all gallery caches to ensure everything is up to date.
1186
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $post_id, $settings['config']['slug'] );
1187
+
1188
+ }
1189
+
1190
  return;
1191
  }
1192
 
1202
  if ( ! current_user_can( 'edit_post', $post_id ) ) {
1203
  return;
1204
  }
1205
+
1206
  // If the post has just been published for the first time, set meta field for the gallery meta overlay helper.
1207
  if ( isset( $post->post_date ) && isset( $post->post_modified ) && $post->post_date === $post->post_modified ) {
1208
  update_post_meta( $post_id, '_eg_just_published', true );
1214
  $settings = array();
1215
  }
1216
 
1217
+ // Force slider ID to match Post ID. This is deliberate; if a gallery is duplicated (either using a duplication)
1218
  // plugin or WPML, the ID remains as the original gallery ID, which breaks things for translations etc.
1219
  $settings['id'] = $post_id;
1220
 
1221
+ // Config
1222
+ $settings['config']['type'] = isset( $_POST['_envira_gallery']['type'] ) ? $_POST['_envira_gallery']['type'] : $this->get_config_default( 'type' );
1223
+ $settings['config']['columns'] = preg_replace( '#[^a-z0-9-_]#', '', $_POST['_envira_gallery']['columns'] );
1224
+ $settings['config']['gallery_theme'] = preg_replace( '#[^a-z0-9-_]#', '', $_POST['_envira_gallery']['gallery_theme'] );
1225
+ $settings['config']['gutter'] = absint( $_POST['_envira_gallery']['gutter'] );
1226
+ $settings['config']['margin'] = absint( $_POST['_envira_gallery']['margin'] );
1227
+ $settings['config']['image_size'] = sanitize_text_field( $_POST['_envira_gallery']['image_size'] );
1228
+ $settings['config']['crop_width'] = absint( $_POST['_envira_gallery']['crop_width'] );
1229
+ $settings['config']['crop_height'] = absint( $_POST['_envira_gallery']['crop_height'] );
1230
+ $settings['config']['crop'] = isset( $_POST['_envira_gallery']['crop'] ) ? 1 : 0;
1231
 
1232
  // Lightbox
1233
+ $settings['config']['lightbox_enabled'] = isset( $_POST['_envira_gallery']['lightbox_enabled'] ) ? 1 : 0;
1234
+ $settings['config']['lightbox_theme'] = preg_replace( '#[^a-z0-9-_]#', '', $_POST['_envira_gallery']['lightbox_theme'] );
1235
+ $settings['config']['lightbox_image_size'] = preg_replace( '#[^a-z0-9-_]#', '', $_POST['_envira_gallery']['lightbox_image_size'] );
1236
+ $settings['config']['title_display'] = preg_replace( '#[^a-z0-9-_]#', '', $_POST['_envira_gallery']['title_display'] );
1237
+
1238
  // Misc
1239
+ $settings['config']['classes'] = explode( "\n", $_POST['_envira_gallery']['classes'] );
1240
+ $settings['config']['rtl'] = isset( $_POST['_envira_gallery']['rtl'] ) ? 1 : 0;
1241
+ $settings['config']['title'] = trim( strip_tags( $_POST['_envira_gallery']['title'] ) );
1242
+ $settings['config']['slug'] = sanitize_text_field( $_POST['_envira_gallery']['slug'] );
1243
+
1244
  // If on an envira post type, map the title and slug of the post object to the custom fields if no value exists yet.
1245
  if ( isset( $post->post_type ) && 'envira' == $post->post_type ) {
1246
  if ( empty( $settings['config']['title'] ) ) {
1262
 
1263
  // If the crop option is checked, crop images accordingly.
1264
  if ( isset( $settings['config']['crop'] ) && $settings['config']['crop'] ) {
1265
+ $args = array(
1266
+ 'position' => 'c',
1267
+ 'width' => $this->get_config( 'crop_width', $this->get_config_default( 'crop_width' ) ),
1268
+ 'height' => $this->get_config( 'crop_height', $this->get_config_default( 'crop_height' ) ),
1269
+ 'quality' => 100,
1270
+ 'retina' => false
 
 
1271
  );
1272
+ $args = apply_filters( 'envira_gallery_crop_image_args', $args );
1273
  $this->crop_images( $args, $post_id );
1274
  }
1275
 
1276
+ // Fire a hook for addons that need to utilize the cropping feature.
1277
+ do_action( 'envira_gallery_saved_settings', $settings, $post_id, $post );
1278
+
1279
  // Finally, flush all gallery caches to ensure everything is up to date.
1280
+ Envira_Gallery_Common::get_instance()->flush_gallery_caches( $post_id, $settings['config']['slug'] );
1281
 
1282
  }
1283
 
1284
  /**
1285
  * Helper method for retrieving the gallery layout for an item in the admin.
1286
  *
1287
+ * Also defines the item's model which is used in assets/js/media-edit.js
1288
+ *
1289
  * @since 1.0.0
1290
  *
1291
+ * @param int $id The ID of the item to retrieve.
1292
+ * @param array $item The item data (i.e. image / video).
1293
+ * @param int $post_id The current post ID.
1294
+ * @return string The HTML output for the gallery item.
1295
  */
1296
+ public function get_gallery_item( $id, $item, $post_id = 0 ) {
 
 
 
 
 
 
 
 
 
 
1297
 
1298
+ // Get thumbnail
1299
+ $thumbnail = wp_get_attachment_image_src( $id, 'thumbnail' );
1300
 
1301
+ // Add id to $item for Backbone model
1302
+ $item['id'] = $id;
1303
+
1304
+ // Allow addons to populate the item's data - for example, tags which are stored against the attachment
1305
+ $item = apply_filters( 'envira_gallery_get_gallery_item', $item, $id, $post_id );
1306
+ $item['alt'] = str_replace( "&quot;", '\"', $item['alt'] );
1307
+ $item['_thumbnail'] = $thumbnail[0]; // Never saved against the gallery item, just used for the thumbnail output in the Edit Gallery screen.
1308
+
1309
+ // Buffer the output
1310
+ ob_start();
1311
+ ?>
1312
+ <li id="<?php echo $id; ?>" class="envira-gallery-image envira-gallery-status-<?php echo $item['status']; ?>" data-envira-gallery-image="<?php echo $id; ?>" data-envira-gallery-image-model='<?php echo json_encode( $item, JSON_HEX_APOS ); ?>'>
1313
+ <img src="<?php echo esc_url( $item['_thumbnail'] ); ?>" alt="<?php esc_attr_e( $item['alt'] ); ?>" />
1314
+ <div class="meta">
1315
+ <div class="title">
1316
+ <span>
1317
+ <?php
1318
+ // Output Title.
1319
+ echo ( isset( $item['title'] ) ? $item['title'] : '' );
1320
+
1321
+ // If the title exceeds 20 characters, the grid view will deliberately only show the first line of the title.
1322
+ // Therefore we need to make it clear to the user that the full title is there by way of a hint.
1323
+ ?>
1324
+ </span>
1325
+ <a class="hint <?php echo ( ( strlen( $item['title'] ) > 20 ) ? '' : ' hidden' ); ?>" title="<?php echo ( isset( $item['title'] ) ? $item['title'] : '' ); ?>">...</a>
1326
+ </div>
1327
+ <div class="additional">
1328
+ <?php
1329
+ // Addons can add content to this meta section, which is displayed when in the List View.
1330
+ echo apply_filters( 'envira_gallery_metabox_output_gallery_item_meta', '', $item, $id, $post_id );
1331
+ ?>
1332
+ </div>
1333
+ </div>
1334
+
1335
+ <a href="#" class="check"><div class="media-modal-icon"></div></a>
1336
+ <a href="#" class="dashicons dashicons-trash envira-gallery-remove-image" title="<?php _e( 'Remove Image from Gallery?', 'envira-gallery' ); ?>"></a>
1337
+ <a href="#" class="dashicons dashicons-edit envira-gallery-modify-image" title="<?php _e( 'Modify Image', 'envira-gallery' ); ?>"></a>
1338
+ </li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1339
  <?php
1340
  return ob_get_clean();
1341
 
1356
  $gallery_data = get_post_meta( $post_id, '_eg_gallery_data', true );
1357
  if ( ! empty( $gallery_data['gallery'] ) ) {
1358
  foreach ( (array) $gallery_data['gallery'] as $id => $item ) {
1359
+ $gallery_data['gallery'][ $id ]['status'] = 'active';
1360
  }
1361
  }
1362
 
1365
  }
1366
 
1367
  /**
1368
+ * Helper method to crop gallery thumbnails to the specified sizes.
1369
  *
1370
  * @since 1.0.0
1371
  *
1372
  * @param array $args Array of args used when cropping the images.
1373
  * @param int $post_id The current post ID.
1374
  */
1375
+ public function crop_thumbnails( $args, $post_id ) {
1376
 
1377
  // Gather all available images to crop.
1378
  $gallery_data = get_post_meta( $post_id, '_eg_gallery_data', true );
1379
  $images = ! empty( $gallery_data['gallery'] ) ? $gallery_data['gallery'] : false;
1380
+ $common = Envira_Gallery_Common::get_instance();
1381
 
1382
  // Loop through the images and crop them.
1383
  if ( $images ) {
1384
  // Increase the time limit to account for large image sets and suspend cache invalidations.
1385
+ if ( ! ini_get( 'safe_mode' ) ) {
1386
+ set_time_limit( Envira_Gallery_Common::get_instance()->get_max_execution_time() );
1387
+ }
1388
  wp_suspend_cache_invalidation( true );
1389
 
1390
  foreach ( $images as $id => $item ) {
1391
  // Get the full image attachment. If it does not return the data we need, skip over it.
1392
  $image = wp_get_attachment_image_src( $id, 'full' );
1393
+
1394
  if ( ! is_array( $image ) ) {
1395
  continue;
1396
  }
1397
 
1398
+ // Check the image is a valid URL
1399
+ // Some plugins decide to strip the blog's URL from the start of the URL, which can cause issues for Envira
1400
+ if ( strpos( $image[0], get_bloginfo( 'url' ) ) === false ) {
1401
+ $image[0] = get_bloginfo( 'url' ) . '/' . $image[0];
1402
+ }
1403
+
1404
  // Generate the cropped image.
1405
  $cropped_image = $common->resize_image( $image[0], $args['width'], $args['height'], true, $args['position'], $args['quality'], $args['retina'] );
1406
+
1407
  // If there is an error, possibly output error message, otherwise woot!
1408
  if ( is_wp_error( $cropped_image ) ) {
1409
  // If WP_DEBUG is enabled, and we're logged in, output an error to the user
1410
  if ( defined( 'WP_DEBUG' ) && WP_DEBUG && is_user_logged_in() ) {
1411
  echo '<pre>Envira: Error occured resizing image (these messages are only displayed to logged in WordPress users):<br />';
1412
  echo 'Error: ' . $cropped_image->get_error_message() . '<br />';
1413
+ echo 'Image: ' . var_export( $image, true ) . '<br />';
1414
  echo 'Args: ' . var_export( $args, true ) . '</pre>';
1415
+ die();
1416
  }
1417
+ } else {
1418
+ $gallery_data['gallery'][ $id ]['thumb'] = $cropped_image;
1419
  }
1420
  }
1421
 
1422
  // Turn off cache suspension and flush the cache to remove any cache inconsistencies.
1423
  wp_suspend_cache_invalidation( false );
1424
  wp_cache_flush();
1425
+
1426
+ // Update the gallery data.
1427
+ update_post_meta( $post_id, '_eg_gallery_data', $gallery_data );
1428
  }
1429
 
1430
  }
1431
 
1432
  /**
1433
+ * Helper method to crop gallery images to the specified sizes.
1434
  *
1435
  * @since 1.0.0
1436
  *
1437
+ * @param array $args Array of args used when cropping the images.
1438
  * @param int $post_id The current post ID.
 
1439
  */
1440
+ public function crop_images( $args, $post_id ) {
1441
+
1442
+ // Gather all available images to crop.
1443
+ $gallery_data = get_post_meta( $post_id, '_eg_gallery_data', true );
1444
+ $images = ! empty( $gallery_data['gallery'] ) ? $gallery_data['gallery'] : false;
1445
+ $common = Envira_Gallery_Common::get_instance();
1446
+
1447
+ // Loop through the images and crop them.
1448
+ if ( $images ) {
1449
+ // Increase the time limit to account for large image sets and suspend cache invalidations.
1450
+ if ( ! ini_get( 'safe_mode' ) ) {
1451
+ set_time_limit( Envira_Gallery_Common::get_instance()->get_max_execution_time() );
1452
+ }
1453
+ wp_suspend_cache_invalidation( true );
1454
+
1455
+ foreach ( $images as $id => $item ) {
1456
+ // Get the full image attachment. If it does not return the data we need, skip over it.
1457
+ $image = wp_get_attachment_image_src( $id, 'full' );
1458
+ if ( ! is_array( $image ) ) {
1459
+ continue;
1460
+ }
1461
 
1462
+ // Check the image is a valid URL
1463
+ // Some plugins decide to strip the blog's URL
1464
+ if ( ! filter_var( $image[0], FILTER_VALIDATE_URL ) ) {
1465
+ $image[0] = get_bloginfo( 'url' ) . '/' . $image[0];
1466
+ }
1467
+
1468
+ // Generate the cropped image.
1469
+ $cropped_image = $common->resize_image( $image[0], $args['width'], $args['height'], true, $args['position'], $args['quality'], $args['retina'] );
1470
+
1471
+ // If there is an error, possibly output error message, otherwise woot!
1472
+ if ( is_wp_error( $cropped_image ) ) {
1473
+ // If debugging is defined, print out the error.
1474
+ if ( defined( 'ENVIRA_GALLERY_CROP_DEBUG' ) && ENVIRA_GALLERY_CROP_DEBUG ) {
1475
+ echo '<pre>' . var_export( $cropped_image->get_error_message(), true ) . '</pre>';
1476
+ }
1477
+ }
1478
+ }
1479
+
1480
+ // Turn off cache suspension and flush the cache to remove any cache inconsistencies.
1481
+ wp_suspend_cache_invalidation( false );
1482
+ wp_cache_flush();
1483
+ }
1484
 
1485
  }
1486
 
1499
 
1500
  global $id, $post;
1501
 
1502
+ // Get the current post ID. If ajax, grab it from the $_POST variable.
1503
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX && array_key_exists( 'post_id', $_POST ) ) {
1504
+ $post_id = absint( $_POST['post_id'] );
1505
+ } else {
1506
+ $post_id = isset( $post->ID ) ? $post->ID : (int) $id;
1507
+ }
1508
 
1509
+ // Get config
1510
  $settings = get_post_meta( $post_id, '_eg_gallery_data', true );
1511
+
1512
+ // Check config key exists
1513
+ if ( isset( $settings['config'][ $key ] ) ) {
1514
+ return $settings['config'][ $key ];
1515
  } else {
1516
  return $default ? $default : '';
1517
  }
1528
  */
1529
  public function get_config_default( $key ) {
1530
 
1531
+ $instance = Envira_Gallery_Common::get_instance();
1532
  return $instance->get_config_default( $key );
1533
 
1534
  }
1542
  */
1543
  public function get_columns() {
1544
 
1545
+ $instance = Envira_Gallery_Common::get_instance();
1546
  return $instance->get_columns();
1547
 
1548
  }
1556
  */
1557
  public function get_gallery_themes() {
1558
 
1559
+ $instance = Envira_Gallery_Common::get_instance();
1560
  return $instance->get_gallery_themes();
1561
 
1562
  }
1563
+
1564
+ /**
1565
+ * Helper method for retrieving description options.
1566
+ *
1567
+ * @since 1.0.0
1568
+ *
1569
+ * @return array Array of description options.
1570
+ */
1571
+ public function get_display_description_options() {
1572
+
1573
+ $instance = Envira_Gallery_Common::get_instance();
1574
+ return $instance->get_display_description_options();
1575
+
1576
+ }
1577
+
1578
+ /**
1579
+ * Helper method for retrieving sorting options.
1580
+ *
1581
+ * @since 1.3.8
1582
+ *
1583
+ * @return array Array of sorting options.
1584
+ */
1585
+ public function get_sorting_options() {
1586
+
1587
+ $instance = Envira_Gallery_Common::get_instance();
1588
+ return $instance->get_sorting_options();
1589
+
1590
+ }
1591
+
1592
+ /**
1593
+ * Helper method for retrieving sorting directions.
1594
+ *
1595
+ * @since 1.3.8
1596
+ *
1597
+ * @return array Array of sorting directions.
1598
+ */
1599
+ public function get_sorting_directions() {
1600
+
1601
+ $instance = Envira_Gallery_Common::get_instance();
1602
+ return $instance->get_sorting_directions();
1603
+
1604
+ }
1605
 
1606
  /**
1607
  * Helper method for retrieving lightbox themes.
1612
  */
1613
  public function get_lightbox_themes() {
1614
 
1615
+ $instance = Envira_Gallery_Common::get_instance();
1616
  return $instance->get_lightbox_themes();
1617
 
1618
  }
1619
 
1620
+ /**
1621
+ * Helper method for retrieving image sizes.
1622
+ *
1623
+ * @since 1.3.6
1624
+ *
1625
+ * @return array Array of image size data.
1626
+ */
1627
+ public function get_image_sizes() {
1628
+
1629
+ $instance = Envira_Gallery_Common::get_instance();
1630
+ return $instance->get_image_sizes();
1631
+
1632
+ }
1633
+
1634
  /**
1635
  * Helper method for retrieving title displays.
1636
  *
1637
+ * @since 1.0.0
1638
  *
1639
  * @return array Array of title display data.
1640
  */
1641
  public function get_title_displays() {
1642
 
1643
+ $instance = Envira_Gallery_Common::get_instance();
1644
  return $instance->get_title_displays();
1645
 
1646
  }
1647
 
1648
+ /**
1649
+ * Helper method for retrieving arrow positions.
1650
+ *
1651
+ * @since 1.3.3.7
1652
+ *
1653
+ * @return array Array of title display data.
1654
+ */
1655
+ public function get_arrows_positions() {
1656
+
1657
+ $instance = Envira_Gallery_Common::get_instance();
1658
+ return $instance->get_arrows_positions();
1659
+
1660
+ }
1661
+
1662
+ /**
1663
+ * Helper method for retrieving toolbar positions.
1664
+ *
1665
+ * @since 1.0.0
1666
+ *
1667
+ * @return array Array of toolbar position data.
1668
+ */
1669
+ public function get_toolbar_positions() {
1670
+
1671
+ $instance = Envira_Gallery_Common::get_instance();
1672
+ return $instance->get_toolbar_positions();
1673
+
1674
+ }
1675
+
1676
+ /**
1677
+ * Helper method for retrieving lightbox transition effects.
1678
+ *
1679
+ * @since 1.0.0
1680
+ *
1681
+ * @return array Array of transition effect data.
1682
+ */
1683
+ public function get_transition_effects() {
1684
+
1685
+ $instance = Envira_Gallery_Common::get_instance();
1686
+ return $instance->get_transition_effects();
1687
+
1688
+ }
1689
+
1690
+ /**
1691
+ * Helper method for retrieving lightbox easing transition effects.
1692
+ *
1693
+ * @since 1.4.1.2
1694
+ *
1695
+ * @return array Array of transition effect data.
1696
+ */
1697
+ public function get_easing_transition_effects() {
1698
+
1699
+ $instance = Envira_Gallery_Common::get_instance();
1700
+ return $instance->get_easing_transition_effects();
1701
+
1702
+ }
1703
+
1704
+ /**
1705
+ * Helper method for retrieving thumbnail positions.
1706
+ *
1707
+ * @since 1.0.0
1708
+ *
1709
+ * @return array Array of thumbnail position data.
1710
+ */
1711
+ public function get_thumbnail_positions() {
1712
+
1713
+ $instance = Envira_Gallery_Common::get_instance();
1714
+ return $instance->get_thumbnail_positions();
1715
+
1716
+ }
1717
+
1718
  /**
1719
  * Returns the post types to skip for loading Envira metaboxes.
1720
  *
1724
  */
1725
  public function get_skipped_posttypes() {
1726
 
1727
+ $skipped_posttypes = array( 'attachment', 'revision', 'nav_menu_item', 'soliloquy', 'soliloquyv2', 'envira_album' );
1728
+ return apply_filters( 'envira_gallery_skipped_posttypes', $skipped_posttypes );
1729
+
1730
+ }
1731
+
1732
+ /**
1733
+ * Flag to determine if the GD library has been compiled.
1734
+ *
1735
+ * @since 1.0.0
1736
+ *
1737
+ * @return bool True if has proper extension, false otherwise.
1738
+ */
1739
+ public function has_gd_extension() {
1740
+
1741
+ return extension_loaded( 'gd' ) && function_exists( 'gd_info' );
1742
+
1743
+ }
1744
+
1745
+ /**
1746
+ * Flag to determine if the Imagick library has been compiled.
1747
+ *
1748
+ * @since 1.0.0
1749
+ *
1750
+ * @return bool True if has proper extension, false otherwise.
1751
+ */
1752
+ public function has_imagick_extension() {
1753
+
1754
+ return extension_loaded( 'imagick' );
1755
 
1756
  }
1757
 
1760
  *
1761
  * @since 1.0.0
1762
  *
1763
+ * @return object The Envira_Gallery_Metaboxes object.
1764
  */
1765
  public static function get_instance() {
1766
 
1767
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Metaboxes ) ) {
1768
+ self::$instance = new Envira_Gallery_Metaboxes();
1769
  }
1770
 
1771
  return self::$instance;
1775
  }
1776
 
1777
  // Load the metabox class.
1778
+ $envira_gallery_metaboxes = Envira_Gallery_Metaboxes::get_instance();
includes/admin/notice.php ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Notices admin class.
4
+ *
5
+ * Handles retrieving whether a particular notice has been dismissed or not,
6
+ * as well as marking a notice as dismissed.
7
+ *
8
+ * @since 1.3.5
9
+ *
10
+ * @package Envira_Gallery
11
+ * @author Tim Carr
12
+ */
13
+ class Envira_Gallery_Notice_Admin {
14
+
15
+ /**
16
+ * Holds the class object.
17
+ *
18
+ * @since 1.3.5
19
+ *
20
+ * @var object
21
+ */
22
+ public static $instance;
23
+
24
+ /**
25
+ * Path to the file.
26
+ *
27
+ * @since 1.3.5
28
+ *
29
+ * @var string
30
+ */
31
+ public $file = __FILE__;
32
+
33
+ /**
34
+ * Holds the base class object.
35
+ *
36
+ * @since 1.3.5
37
+ *
38
+ * @var object
39
+ */
40
+ public $base;
41
+
42
+ /**
43
+ * Holds all dismissed notices
44
+ *
45
+ * @since 1.3.5
46
+ *
47
+ * @var array
48
+ */
49
+ public $notices;
50
+
51
+ /**
52
+ * Primary class constructor.
53
+ *
54
+ * @since 1.3.5
55
+ */
56
+ public function __construct() {
57
+
58
+ // Populate $notices
59
+ $this->notices = get_option( 'envira_gallery_notices' );
60
+ if ( ! is_array( $this->notices ) ) {
61
+ $this->notices = array();
62
+ }
63
+
64
+ }
65
+
66
+ /**
67
+ * Checks if a given notice has been dismissed or not
68
+ *
69
+ * @since 1.3.5
70
+ *
71
+ * @param string $notice Programmatic Notice Name
72
+ * @return bool Notice Dismissed
73
+ */
74
+
75
+ public function is_dismissed( $notice ) {
76
+
77
+ if ( ! isset( $this->notices[ $notice ] ) ) {
78
+ return false;
79
+ }
80
+
81
+ return true;
82
+
83
+ }
84
+
85
+ /**
86
+ * Marks the given notice as dismissed
87
+ *
88
+ * @since 1.3.5
89
+ *
90
+ * @param string $notice Programmatic Notice Name
91
+ * @return null
92
+ */
93
+ public function dismiss( $notice ) {
94
+
95
+ $this->notices[ $notice ] = true;
96
+ update_option( 'envira_gallery_notices', $this->notices );
97
+
98
+ }
99
+
100
+
101
+ /**
102
+ * Marks a notice as not dismissed
103
+ *
104
+ * @since 1.3.5
105
+ *
106
+ * @param string $notice Programmatic Notice Name
107
+ * @return null
108
+ */
109
+ public function undismiss( $notice ) {
110
+
111
+ unset( $this->notices[ $notice ] );
112
+ update_option( 'envira_gallery_notices', $this->notices );
113
+
114
+ }
115
+
116
+ /**
117
+ * Displays an inline notice with some Envira styling.
118
+ *
119
+ * @since 1.3.5
120
+ *
121
+ * @param string $notice Programmatic Notice Name
122
+ * @param string $title Title
123
+ * @param string $message Message
124
+ * @param string $type Message Type (updated|warning|error) - green, yellow/orange and red respectively.
125
+ * @param string $button_text Button Text (optional)
126
+ * @param string $button_url Button URL (optional)
127
+ * @param bool $is_dismissible User can Dismiss Message (default: true)
128
+ */
129
+ public function display_inline_notice( $notice, $title, $message, $type = 'success', $button_text = '', $button_url = '', $is_dismissible = true ) {
130
+
131
+ // Check if the notice is dismissible, and if so has been dismissed.
132
+ if ( $is_dismissible && $this->is_dismissed( $notice ) ) {
133
+ // Nothing to show here, return!
134
+ return;
135
+ }
136
+
137
+ // Display inline notice
138
+ ?>
139
+ <div class="envira-notice <?php echo $type . ( $is_dismissible ? ' is-dismissible' : '' ); ?>" data-notice="<?php echo $notice; ?>">
140
+ <?php
141
+ // Title
142
+ if ( ! empty ( $title ) ) {
143
+ ?>
144
+ <p class="envira-intro"><?php echo $title; ?></p>
145
+ <?php
146
+ }
147
+
148
+ // Message
149
+ if ( ! empty( $message ) ) {
150
+ ?>
151
+ <p><?php echo $message; ?></p>
152
+ <?php
153
+ }
154
+
155
+ // Button
156
+ if ( ! empty( $button_text ) && ! empty( $button_url ) ) {
157
+ ?>
158
+ <a href="<?php echo $button_url; ?>" target="_blank" class="button button-primary"><?php echo $button_text; ?></a>
159
+ <?php
160
+ }
161
+
162
+ // Dismiss Button
163
+ if ( $is_dismissible ) {
164
+ ?>
165
+ <button type="button" class="notice-dismiss">
166
+ <span class="screen-reader-text">
167
+ <?php _e( 'Dismiss this notice', 'envira-gallery' ); ?>
168
+ </span>
169
+ </button>
170
+ <?php
171
+ }
172
+ ?>
173
+ </div>
174
+ <?php
175
+
176
+ }
177
+
178
+ /**
179
+ * Returns the singleton instance of the class.
180
+ *
181
+ * @since 1.3.5
182
+ *
183
+ * @return object The Envira_Gallery_Notice_Admin object.
184
+ */
185
+ public static function get_instance() {
186
+
187
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Notice_Admin ) ) {
188
+ self::$instance = new Envira_Gallery_Notice_Admin();
189
+ }
190
+
191
+ return self::$instance;
192
+
193
+ }
194
+
195
+ }
196
+
197
+ // Load the notice admin class.
198
+ $envira_gallery_notice_admin = Envira_Gallery_Notice_Admin::get_instance();
includes/admin/partials/header.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Outputs the green Envira Gallery Header
4
+ *
5
+ * @since 1.5.0
6
+ *
7
+ * @package Envira_Gallery
8
+ * @author David Bisset, Tim Carr
9
+ */
10
+ ?>
11
+ <div id="envira-header" class="envira-header">
12
+ <h1 class="envira-logo" id="envira-logo">
13
+ <img src="<?php echo $data['logo']; ?>" alt="<?php _e( 'Envira Gallery', 'envira-gallery' ); ?>" width="339" height="26" />
14
+ </h1>
15
+ </div>
includes/admin/partials/metabox-gallery-code.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Outputs the Gallery Code Metabox Content.
4
+ *
5
+ * @since 1.5.0
6
+ *
7
+ * @package Envira_Gallery
8
+ * @author Tim Carr
9
+ */
10
+ ?>
11
+ <p><?php _e( 'You can place this gallery anywhere into your posts, pages, custom post types or widgets by using <strong>one</strong> the shortcode(s) below:', 'envira-gallery' ); ?></p>
12
+ <div class="envira-code">
13
+ <code id="envira_shortcode_id_<?php echo $data['post']->ID; ?>"><?php echo '[envira-gallery id="' . $data['post']->ID . '"]'; ?></code>
14
+ <a href="#" title="<?php _e( 'Copy Shortcode to Clipboard', 'envira-gallery' ); ?>" data-clipboard-target="#envira_shortcode_id_<?php echo $data['post']->ID; ?>" class="dashicons dashicons-clipboard envira-clipboard">
15
+ <span><?php _e( 'Copy to Clipboard', 'envira-gallery' ); ?></span>
16
+ </a>
17
+ </div>
18
+
19
+ <?php
20
+ if ( ! empty( $data['gallery_data']['config']['slug'] ) ) {
21
+ ?>
22
+ <div class="envira-code">
23
+ <code id="envira_shortcode_slug_<?php echo $data['post']->ID; ?>"><?php echo '[envira-gallery slug="' . $data['gallery_data']['config']['slug'] . '"]'; ?></code>
24
+ <a href="#" title="<?php _e( 'Copy Shortcode to Clipboard', 'envira-gallery' ); ?>" data-clipboard-target="#envira_shortcode_slug_<?php echo $data['post']->ID; ?>" class="dashicons dashicons-clipboard envira-clipboard">
25
+ <span><?php _e( 'Copy to Clipboard', 'envira-gallery' ); ?></span>
26
+ </a>
27
+ </div>
28
+ <?php
29
+ }
30
+ ?>
31
+
32
+ <p><?php _e( 'You can also place this gallery into your template files by using <strong>one</strong> the template tag(s) below:', 'envira-gallery' ); ?></p>
33
+ <div class="envira-code">
34
+ <code id="envira_template_tag_id_<?php echo $data['post']->ID; ?>"><?php echo 'if ( function_exists( \'envira_gallery\' ) ) { envira_gallery( \'' . $data['post']->ID . '\' ); }'; ?></code>
35
+ <a href="#" title="<?php _e( 'Copy Template Tag to Clipboard', 'envira-gallery' ); ?>" data-clipboard-target="#envira_template_tag_id_<?php echo $data['post']->ID; ?>" class="dashicons dashicons-clipboard envira-clipboard">
36
+ <span><?php _e( 'Copy to Clipboard', 'envira-gallery' ); ?></span>
37
+ </a>
38
+ </div>
39
+
40
+ <?php
41
+ if ( ! empty( $data['gallery_data']['config']['slug'] ) ) {
42
+ ?>
43
+ <div class="envira-code">
44
+ <code id="envira_template_tag_slug_<?php echo $data['post']->ID; ?>"><?php echo 'if ( function_exists( \'envira_gallery\' ) ) { envira_gallery( \'' . $data['gallery_data']['config']['slug'] . '\', \'slug\' ); }'; ?></code>
45
+ <a href="#" title="<?php _e( 'Copy Template Tag to Clipboard', 'envira-gallery' ); ?>" data-clipboard-target="#envira_template_tag_slug_<?php echo $data['post']->ID; ?>" class="dashicons dashicons-clipboard envira-clipboard">
46
+ <span><?php _e( 'Copy to Clipboard', 'envira-gallery' ); ?></span>
47
+ </a>
48
+ </div>
49
+ <?php
50
+ }
includes/admin/partials/metabox-gallery-settings.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Outputs the Gallery Settings Tabs and Config options.
4
+ *
5
+ * @since 1.5.0
6
+ *
7
+ * @package Envira_Gallery
8
+ * @author Tim Carr
9
+ */
10
+ ?>
11
+ <!-- Tabs -->
12
+ <ul id="envira-tabs-nav" class="envira-tabs-nav" data-container="#envira-tabs" data-update-hashbang="1">
13
+ <?php
14
+ // Iterate through the available tabs, outputting them in a list.
15
+ $i = 0;
16
+ foreach ( $data['tabs'] as $id => $title ) {
17
+ $class = ( 0 === $i ? ' envira-active' : '' );
18
+ ?>
19
+ <li class="envira-<?php echo $id; ?>">
20
+ <a href="#envira-tab-<?php echo $id; ?>" title="<?php echo $title; ?>"<?php echo ( ! empty( $class ) ? ' class="' . $class . '"' : '' ); ?>>
21
+ <?php echo $title; ?>
22
+ </a>
23
+ </li>
24
+ <?php
25
+
26
+ $i++;
27
+ }
28
+ ?>
29
+ </ul>
30
+
31
+ <!-- Settings -->
32
+ <div id="envira-tabs" data-navigation="#envira-tabs-nav">
33
+ <?php
34
+ // Iterate through the registered tabs, outputting a panel and calling a tab-specific action,
35
+ // which renders the settings view for that tab.
36
+ $i = 0;
37
+ foreach ( $data['tabs'] as $id => $title ) {
38
+ $class = ( 0 === $i ? 'envira-active' : '' );
39
+ ?>
40
+ <div id="envira-tab-<?php echo $id; ?>" class="envira-tab envira-clear <?php echo $class; ?>">
41
+ <?php do_action( 'envira_gallery_tab_' . $id, $data['post'] ); ?>
42
+ </div>
43
+ <?php
44
+ $i++;
45
+ }
46
+ ?>
47
+ </div>
48
+
49
+ <div class="envira-clear"></div>
includes/admin/partials/metabox-gallery-type.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Outputs the Gallery Type Tab Selector and Panels
4
+ *
5
+ * @since 1.5.0
6
+ *
7
+ * @package Envira_Gallery
8
+ * @author Tim Carr
9
+ */
10
+
11
+ ?>
12
+ <h2 id="envira-types-nav" class="nav-tab-wrapper envira-tabs-nav" data-container="#envira-types" data-update-hashbang="0">
13
+ <label class="nav-tab nav-tab-native-envira-gallery<?php echo ( ( $data['instance']->get_config( 'type', $data['instance']->get_config_default( 'type' ) ) == 'default' ) ? ' envira-active' : '' ); ?>" for="envira-gallery-type-default" data-tab="#envira-gallery-native">
14
+ <input id="envira-gallery-type-default" type="radio" name="_envira_gallery[type]" value="default" <?php checked( $data['instance']->get_config( 'type', $data['instance']->get_config_default( 'type' ) ), 'default' ); ?> />
15
+ <span><?php _e( 'Native Envira Gallery', 'envira-gallery' ); ?></span>
16
+ </label>
17
+
18
+ <a href="#envira-gallery-external" title="<?php _e( 'External Gallery', 'envira-gallery' ); ?>" class="nav-tab nav-tab-external-gallery<?php echo ( ( $data['instance']->get_config( 'type', $data['instance']->get_config_default( 'type' ) ) != 'default' ) ? ' envira-active' : '' ); ?>">
19
+ <span><?php _e( 'External Gallery', 'envira-gallery' ); ?></span>
20
+ </a>
21
+ </h2>
22
+
23
+ <!-- Types -->
24
+ <div id="envira-types" data-navigation="#envira-types-nav">
25
+ <!-- Native Envira Gallery - Drag and Drop Uploader -->
26
+ <div id="envira-gallery-native" class="envira-tab envira-clear<?php echo ( ( $data['instance']->get_config( 'type', $data['instance']->get_config_default( 'type' ) ) == 'default' ) ? ' envira-active' : '' ); ?>">
27
+ <!-- Errors -->
28
+ <div id="envira-gallery-upload-error"></div>
29
+
30
+ <!-- WP Media Upload Form -->
31
+ <?php
32
+ media_upload_form();
33
+ ?>
34
+ <script type="text/javascript">
35
+ var post_id = <?php echo $data['post']->ID; ?>, shortform = 3;
36
+ </script>
37
+ <input type="hidden" name="post_id" id="post_id" value="<?php echo $data['post']->ID; ?>" />
38
+ </div>
39
+
40
+ <!-- External Gallery -->
41
+ <div id="envira-gallery-external" class="envira-tab envira-clear<?php echo ( ( $data['instance']->get_config( 'type', $data['instance']->get_config_default( 'type' ) ) != 'default' ) ? ' envira-active' : '' ); ?>">
42
+ <?php
43
+ Envira_Gallery_Notice_Admin::get_instance()->display_inline_notice(
44
+ 'envira_gallery_external',
45
+ __( 'Want to display Instagram or Post Images?', 'envira-gallery' ),
46
+ __( 'By upgrading to Envira Pro, you can build Galleries based on Instagram images and/or Post images.', 'envira-gallery' ),
47
+ 'warning',
48
+ 'Click here to Upgrade',
49
+ 'http://enviragallery.com/lite/?utm_source=liteplugin&utm_medium=link&utm_campaign=WordPress',
50
+ false
51
+ );
52
+ ?>
53
+ </div>
54
+ </div>
includes/admin/posttype.php CHANGED
@@ -4,10 +4,10 @@
4
  *
5
  * @since 1.0.0
6
  *
7
- * @package Envira_Gallery_Lite
8
  * @author Thomas Griffin
9
  */
10
- class Envira_Gallery_Posttype_Admin_Lite {
11
 
12
  /**
13
  * Holds the class object.
@@ -45,13 +45,7 @@ class Envira_Gallery_Posttype_Admin_Lite {
45
 
46
  // Load the base class object.
47
  $this->base = Envira_Gallery_Lite::get_instance();
48
-
49
- // Remove quick editing from the Envira post type row actions.
50
- add_filter( 'post_row_actions', array( $this, 'row_actions' ) );
51
-
52
- // Manage post type columns.
53
- add_filter( 'manage_edit-envira_columns', array( $this, 'envira_columns' ) );
54
- add_filter( 'manage_envira_posts_custom_column', array( $this, 'envira_custom_columns' ), 10, 2 );
55
 
56
  // Update post type messages.
57
  add_filter( 'post_updated_messages', array( $this, 'messages' ) );
@@ -59,82 +53,28 @@ class Envira_Gallery_Posttype_Admin_Lite {
59
  // Force the menu icon to be scaled to proper size (for Retina displays).
60
  add_action( 'admin_head', array( $this, 'menu_icon' ) );
61
 
62
- }
63
-
64
- /**
65
- * Customize the post columns for the Envira post type.
66
- *
67
- * @since 1.0.0
68
- *
69
- * @param array $columns The default columns.
70
- * @return array $columns Amended columns.
71
- */
72
- public function envira_columns( $columns ) {
73
-
74
- $columns = array(
75
- 'cb' => '<input type="checkbox" />',
76
- 'title' => __( 'Title', 'envira-gallery-lite' ),
77
- 'shortcode' => __( 'Shortcode', 'envira-gallery-lite' ),
78
- 'template' => __( 'Function', 'envira-gallery-lite' ),
79
- 'images' => __( 'Number of Images', 'envira-gallery-lite' ),
80
- 'modified' => __( 'Last Modified', 'envira-gallery-lite' ),
81
- 'date' => __( 'Date', 'envira-gallery-lite' )
82
- );
83
-
84
- return $columns;
85
 
86
  }
87
 
88
  /**
89
- * Add data to the custom columns added to the Envira post type.
90
- *
91
- * @since 1.0.0
92
  *
93
- * @global object $post The current post object
94
- * @param string $column The name of the custom column
95
- * @param int $post_id The current post ID
96
  */
97
- public function envira_custom_columns( $column, $post_id ) {
98
-
99
- global $post;
100
- $post_id = absint( $post_id );
101
-
102
- switch ( $column ) {
103
- case 'shortcode' :
104
- echo '<code>[envira-gallery id="' . $post_id . '"]</code>';
105
- break;
106
-
107
- case 'template' :
108
- echo '<code>if ( function_exists( \'envira_gallery\' ) ) { envira_gallery( \'' . $post_id . '\' ); }</code>';
109
- break;
110
-
111
- case 'images' :
112
- $gallery_data = get_post_meta( $post_id, '_eg_gallery_data', true );
113
- echo ( ! empty( $gallery_data['gallery'] ) ? count( $gallery_data['gallery'] ) : 0 );
114
- break;
115
-
116
- case 'modified' :
117
- the_modified_date();
118
- break;
119
  }
120
 
121
- }
122
-
123
- /**
124
- * Filter out unnecessary row actions from the Envira post table.
125
- *
126
- * @since 1.0.0
127
- *
128
- * @param array $actions Default row actions.
129
- * @return array $actions Amended row actions.
130
- */
131
- public function row_actions( $actions ) {
132
-
133
- if ( isset( get_current_screen()->post_type ) && 'envira' == get_current_screen()->post_type ) {
134
- unset( $actions['inline hide-if-no-js'] );
135
- }
136
-
137
- return $actions;
138
 
139
  }
140
 
@@ -152,21 +92,20 @@ class Envira_Gallery_Posttype_Admin_Lite {
152
  global $post;
153
 
154
  // Contextualize the messages.
155
- $messages['envira'] = apply_filters( 'envira_gallery_messages',
156
- array(
157
- 0 => '',
158
- 1 => __( 'Envira gallery updated.', 'envira-gallery-lite' ),
159
- 2 => __( 'Envira gallery custom field updated.', 'envira-gallery-lite' ),
160
- 3 => __( 'Envira gallery custom field deleted.', 'envira-gallery-lite' ),
161
- 4 => __( 'Envira gallery updated.', 'envira-gallery-lite' ),
162
- 5 => isset( $_GET['revision'] ) ? sprintf( __( 'Envira gallery restored to revision from %s.', 'envira-gallery-lite' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
163
- 6 => __( 'Envira gallery published.', 'envira-gallery-lite' ),
164
- 7 => __( 'Envira gallery saved.', 'envira-gallery-lite' ),
165
- 8 => __( 'Envira gallery submitted.', 'envira-gallery-lite' ),
166
- 9 => sprintf( __( 'Envira gallery scheduled for: <strong>%1$s</strong>.', 'envira-gallery-lite' ), date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ) ),
167
- 10 => __( 'Envira gallery draft updated.', 'envira-gallery-lite' )
168
- )
169
  );
 
170
 
171
  return $messages;
172
 
@@ -190,19 +129,21 @@ class Envira_Gallery_Posttype_Admin_Lite {
190
  *
191
  * @since 1.0.0
192
  *
193
- * @return object The Envira_Gallery_Posttype_Admin_Lite object.
194
  */
195
  public static function get_instance() {
196
 
197
- if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Posttype_Admin_Lite ) ) {
198
- self::$instance = new Envira_Gallery_Posttype_Admin_Lite();
199
  }
200
 
201
  return self::$instance;
202
 
203
  }
204
 
 
 
205
  }
206
 
207
  // Load the posttype admin class.
208
- $envira_gallery_posttype_admin_lite = Envira_Gallery_Posttype_Admin_Lite::get_instance();
4
  *
5
  * @since 1.0.0
6
  *
7
+ * @package Envira_Gallery
8
  * @author Thomas Griffin
9
  */
10
+ class Envira_Gallery_Posttype_Admin {
11
 
12
  /**
13
  * Holds the class object.
45
 
46
  // Load the base class object.
47
  $this->base = Envira_Gallery_Lite::get_instance();
48
+ $this->metabox = Envira_Gallery_Metaboxes::get_instance();
 
 
 
 
 
 
49
 
50
  // Update post type messages.
51
  add_filter( 'post_updated_messages', array( $this, 'messages' ) );
53
  // Force the menu icon to be scaled to proper size (for Retina displays).
54
  add_action( 'admin_head', array( $this, 'menu_icon' ) );
55
 
56
+ // Add the Universal Header.
57
+ add_action( 'all_admin_notices', array( $this, 'admin_header' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
  }
60
 
61
  /**
62
+ * Outputs the Envira Gallery Header.
 
 
63
  *
64
+ * @since 1.5.0
 
 
65
  */
66
+ public function admin_header() {
67
+
68
+ // Get the current screen, and check whether we're viewing the Envira or Envira Album Post Types.
69
+ $screen = get_current_screen();
70
+ if ( 'envira' !== $screen->post_type && 'envira_album' !== $screen->post_type ) {
71
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  }
73
 
74
+ // If here, we're on an Envira Gallery or Album screen, so output the header.
75
+ $this->base->load_admin_partial( 'header', array(
76
+ 'logo' => plugins_url( 'assets/images/envira-logo.png', $this->base->file ),
77
+ ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
  }
80
 
92
  global $post;
93
 
94
  // Contextualize the messages.
95
+ $envira_messages = array(
96
+ 0 => '',
97
+ 1 => __( 'Envira gallery updated.', 'envira-gallery' ),
98
+ 2 => __( 'Envira gallery custom field updated.', 'envira-gallery' ),
99
+ 3 => __( 'Envira gallery custom field deleted.', 'envira-gallery' ),
100
+ 4 => __( 'Envira gallery updated.', 'envira-gallery' ),
101
+ 5 => isset( $_GET['revision'] ) ? sprintf( __( 'Envira gallery restored to revision from %s.', 'envira-gallery' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
102
+ 6 => __( 'Envira gallery published.', 'envira-gallery' ),
103
+ 7 => __( 'Envira gallery saved.', 'envira-gallery' ),
104
+ 8 => __( 'Envira gallery submitted.', 'envira-gallery' ),
105
+ 9 => sprintf( __( 'Envira gallery scheduled for: <strong>%1$s</strong>.', 'envira-gallery' ), date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ) ),
106
+ 10 => __( 'Envira gallery draft updated.', 'envira-gallery' ),
 
 
107
  );
108
+ $messages['envira'] = apply_filters( 'envira_gallery_messages', $envira_messages );
109
 
110
  return $messages;
111
 
129
  *
130
  * @since 1.0.0
131
  *
132
+ * @return object The Envira_Gallery_Posttype_Admin object.
133
  */
134
  public static function get_instance() {
135
 
136
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Posttype_Admin ) ) {
137
+ self::$instance = new Envira_Gallery_Posttype_Admin();
138
  }
139
 
140
  return self::$instance;
141
 
142
  }
143
 
144
+
145
+
146
  }
147
 
148
  // Load the posttype admin class.
149
+ $envira_gallery_posttype_admin = Envira_Gallery_Posttype_Admin::get_instance();
includes/admin/settings.php ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Settings class.
4
+ *
5
+ * @since 1.0.0
6
+ *
7
+ * @package Envira_Gallery
8
+ * @author Thomas Griffin
9
+ */
10
+ class Envira_Gallery_Settings {
11
+
12
+ /**
13
+ * Holds the class object.
14
+ *
15
+ * @since 1.0.0
16
+ *
17
+ * @var object
18
+ */
19
+ public static $instance;
20
+
21
+ /**
22
+ * Path to the file.
23
+ *
24
+ * @since 1.0.0
25
+ *
26
+ * @var string
27
+ */
28
+ public $file = __FILE__;
29
+
30
+ /**
31
+ * Holds the base class object.
32
+ *
33
+ * @since 1.0.0
34
+ *
35
+ * @var object
36
+ */
37
+ public $base;
38
+
39
+ /**
40
+ * Holds the submenu pagehook.
41
+ *
42
+ * @since 1.0.0
43
+ *
44
+ * @var string
45
+ */
46
+ public $hook;
47
+
48
+ /**
49
+ * Primary class constructor.
50
+ *
51
+ * @since 1.0.0
52
+ */
53
+ public function __construct() {
54
+
55
+ }
56
+
57
+ /**
58
+ * Helper method for getting a setting's value. Falls back to the default
59
+ * setting value if none exists in the options table.
60
+ *
61
+ * @since 1.3.3.6
62
+ *
63
+ * @param string $key The setting key to retrieve.
64
+ * @return string Key value on success, false on failure.
65
+ */
66
+ public function get_setting( $key ) {
67
+
68
+ // Prefix the key
69
+ $prefixed_key = 'envira_gallery_' . $key;
70
+
71
+ // Get the option value
72
+ $value = get_option( $prefixed_key );
73
+
74
+ // If no value exists, fallback to the default
75
+ if ( ! $value ) {
76
+ $value = $this->get_setting_default( $key );
77
+ }
78
+
79
+ // Allow devs to filter
80
+ $value = apply_filters( 'envira_gallery_get_setting', $value, $key, $prefixed_key );
81
+
82
+ return $value;
83
+
84
+ }
85
+
86
+ /**
87
+ * Helper method for getting a setting's default value
88
+ *
89
+ * @since 1.3.3.6
90
+ *
91
+ * @param string $key The default setting key to retrieve.
92
+ * @return string Key value on success, false on failure.
93
+ */
94
+ public function get_setting_default( $key ) {
95
+
96
+ // Prepare default values.
97
+ $defaults = $this->get_setting_defaults();
98
+
99
+ // Return the key specified.
100
+ return isset( $defaults[ $key ] ) ? $defaults[ $key ] : false;
101
+
102
+ }
103
+
104
+ /**
105
+ * Retrieves the default settings
106
+ *
107
+ * @since 1.3.3.6
108
+ *
109
+ * @return array Array of default settings.
110
+ */
111
+ public function get_setting_defaults() {
112
+
113
+ // Prepare default values.
114
+ $defaults = array(
115
+ 'media_position' => 'after',
116
+ );
117
+
118
+ // Allow devs to filter the defaults.
119
+ $defaults = apply_filters( 'envira_gallery_settings_defaults', $defaults );
120
+
121
+ return $defaults;
122
+
123
+ }
124
+
125
+ /**
126
+ * Returns the singleton instance of the class.
127
+ *
128
+ * @since 1.0.0
129
+ *
130
+ * @return object The Envira_Gallery_Settings object.
131
+ */
132
+ public static function get_instance() {
133
+
134
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Settings ) ) {
135
+ self::$instance = new Envira_Gallery_Settings();
136
+ }
137
+
138
+ return self::$instance;
139
+
140
+ }
141
+
142
+ }
143
+
144
+ // Load the settings class.
145
+ $envira_gallery_settings = Envira_Gallery_Settings::get_instance();
includes/admin/table.php ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WP List Table Admin Class.
4
+ *
5
+ * @since 1.5.0
6
+ *
7
+ * @package Envira_Gallery
8
+ * @author Tim Carr
9
+ */
10
+ class Envira_Gallery_Table_Admin {
11
+
12
+ /**
13
+ * Holds the class object.
14
+ *
15
+ * @since 1.5.0
16
+ *
17
+ * @var object
18
+ */
19
+ public static $instance;
20
+
21
+ /**
22
+ * Path to the file.
23
+ *
24
+ * @since 1.5.0
25
+ *
26
+ * @var string
27
+ */
28
+ public $file = __FILE__;
29
+
30
+ /**
31
+ * Holds the base class object.
32
+ *
33
+ * @since 1.5.0
34
+ *
35
+ * @var object
36
+ */
37
+ public $base;
38
+
39
+ /**
40
+ * Holds the metabox class object.
41
+ *
42
+ * @since 1.5.0
43
+ *
44
+ * @var object
45
+ */
46
+ public $metabox;
47
+
48
+ /**
49
+ * Primary class constructor.
50
+ *
51
+ * @since 1.0.0
52
+ */
53
+ public function __construct() {
54
+
55
+ // Load the base class object.
56
+ $this->base = Envira_Gallery_Lite::get_instance();
57
+
58
+ // Load the metabox class object.
59
+ $this->metabox = Envira_Gallery_Metaboxes::get_instance();
60
+
61
+ // Load CSS and JS.
62
+ add_action( 'admin_enqueue_scripts', array( $this, 'styles' ) );
63
+ add_action( 'admin_enqueue_scripts', array( $this, 'scripts' ) );
64
+
65
+ // Append data to various admin columns.
66
+ add_filter( 'manage_edit-envira_columns', array( &$this, 'envira_columns' ) );
67
+ add_action( 'manage_envira_posts_custom_column', array( &$this, 'envira_custom_columns'), 10, 2 );
68
+
69
+ }
70
+
71
+ /**
72
+ * Loads styles for all Envira-based WP_List_Table Screens.
73
+ *
74
+ * @since 1.5.0
75
+ *
76
+ * @return null Return early if not on the proper screen.
77
+ */
78
+ public function styles() {
79
+
80
+ // Get current screen.
81
+ $screen = get_current_screen();
82
+
83
+ // Bail if we're not on the Envira Post Type screen.
84
+ if ( 'envira' !== $screen->post_type && 'envira_album' !== $screen->post_type ) {
85
+ return;
86
+ }
87
+
88
+ // Bail if we're not on a WP_List_Table.
89
+ if ( 'edit' !== $screen->base ) {
90
+ return;
91
+ }
92
+
93
+ // Load necessary admin styles.
94
+ wp_register_style( $this->base->plugin_slug . '-table-style', plugins_url( 'assets/css/table.css', $this->base->file ), array(), $this->base->version );
95
+ wp_enqueue_style( $this->base->plugin_slug . '-table-style' );
96
+
97
+ // Fire a hook to load in custom admin styles.
98
+ do_action( 'envira_gallery_table_styles' );
99
+
100
+ }
101
+
102
+ /**
103
+ * Loads scripts for all Envira-based Administration Screens.
104
+ *
105
+ * @since 1.5.0
106
+ *
107
+ * @return null Return early if not on the proper screen.
108
+ */
109
+ public function scripts() {
110
+
111
+ // Get current screen.
112
+ $screen = get_current_screen();
113
+
114
+ // Bail if we're not on the Envira Post Type screen.
115
+ if ( 'envira' !== $screen->post_type && 'envira_album' !== $screen->post_type ) {
116
+ return;
117
+ }
118
+
119
+ // Bail if we're not on a WP_List_Table.
120
+ if ( 'edit' !== $screen->base ) {
121
+ return;
122
+ }
123
+
124
+ // Load necessary admin scripts
125
+ wp_register_script( $this->base->plugin_slug . '-clipboard-script', plugins_url( 'assets/js/min/clipboard-min.js', $this->base->file ), array( 'jquery' ), $this->base->version );
126
+ wp_enqueue_script( $this->base->plugin_slug . '-clipboard-script' );
127
+
128
+ // Fire a hook to load in custom admin scripts.
129
+ do_action( 'envira_gallery_admin_scripts' );
130
+
131
+ }
132
+
133
+ /**
134
+ * Customize the post columns for the Envira post type.
135
+ *
136
+ * @since 1.0.0
137
+ *
138
+ * @param array $columns The default columns.
139
+ * @return array $columns Amended columns.
140
+ */
141
+ public function envira_columns( $columns ) {
142
+
143
+ // Add additional columns we want to display.
144
+ $envira_columns = array(
145
+ 'cb' => '<input type="checkbox" />',
146
+ 'title' => __( 'Title', 'envira-gallery' ),
147
+ 'image' => __( '', 'envira-gallery' ),
148
+ 'shortcode' => __( 'Shortcode', 'envira-gallery' ),
149
+ 'posts' => __( 'Posts', 'envira-gallery' ),
150
+ 'modified' => __( 'Last Modified', 'envira-gallery' ),
151
+ 'date' => __( 'Date', 'envira-gallery' )
152
+ );
153
+
154
+ // Allow filtering of columns
155
+ $envira_columns = apply_filters( 'envira_gallery_table_columns', $envira_columns, $columns );
156
+
157
+ // Return merged column set. This allows plugins to output their columns (e.g. Yoast SEO),
158
+ // and column management plugins, such as Admin Columns, should play nicely.
159
+ return array_merge( $envira_columns, $columns );
160
+
161
+ }
162
+
163
+ /**
164
+ * Add data to the custom columns added to the Envira post type.
165
+ *
166
+ * @since 1.0.0
167
+ *
168
+ * @global object $post The current post object
169
+ * @param string $column The name of the custom column
170
+ * @param int $post_id The current post ID
171
+ */
172
+ public function envira_custom_columns( $column, $post_id ) {
173
+
174
+ global $post;
175
+ $post_id = absint( $post_id );
176
+
177
+ switch ( $column ) {
178
+ /**
179
+ * Image
180
+ */
181
+ case 'image':
182
+ // Get Gallery Images.
183
+ $gallery_data = get_post_meta( $post_id, '_eg_gallery_data', true );
184
+ if ( ! empty( $gallery_data['gallery'] ) && is_array( $gallery_data['gallery'] ) ) {
185
+ // Display the first image
186
+ $images = $gallery_data['gallery'];
187
+ reset( $images );
188
+ $key = key( $images );
189
+ if ( is_numeric( $key ) ) {
190
+ $thumb = wp_get_attachment_image_src( $key, 'thumbnail' );
191
+ } else {
192
+ $thumb = array( $image['src'] );
193
+ }
194
+
195
+ echo '<img src="' . $thumb[0] . '" width="75" /><br />';
196
+ printf( _n( '%d Image', '%d Images', count( $gallery_data['gallery'] ), 'envira-gallery' ), count( $gallery_data['gallery'] ) );
197
+ }
198
+ break;
199
+
200
+ /**
201
+ * Shortcode
202
+ */
203
+ case 'shortcode' :
204
+ echo '
205
+ <div class="envira-code">
206
+ <code id="envira_shortcode_' . $post_id . '">[envira-gallery id="' . $post_id . '"]</code>
207
+ <a href="#" title="' . __( 'Copy Shortcode to Clipboard', 'envira-gallery' ) . '" data-clipboard-target="#envira_shortcode_' . $post_id . '" class="dashicons dashicons-clipboard envira-clipboard">
208
+ <span>' . __( 'Copy to Clipboard', 'envira-gallery' ) . '</span>
209
+ </a>
210
+ </div>';
211
+
212
+ // Hidden fields are for Quick Edit
213
+ // class is used by assets/js/admin.js to remove these fields when a search is about to be submitted, so we dont' get long URLs
214
+ echo '<input class="envira-quick-edit" type="hidden" name="_envira_gallery_' . $post_id . '[columns]" value="' . $this->metabox->get_config( 'columns' ) . '" />
215
+ <input class="envira-quick-edit" type="hidden" name="_envira_gallery_' . $post_id . '[gallery_theme]" value="' . $this->metabox->get_config( 'gallery_theme' ) . '" />
216
+ <input class="envira-quick-edit" type="hidden" name="_envira_gallery_' . $post_id . '[gutter]" value="' . $this->metabox->get_config( 'gutter' ) . '" />
217
+ <input class="envira-quick-edit" type="hidden" name="_envira_gallery_' . $post_id . '[margin]" value="' . $this->metabox->get_config( 'margin' ) . '" />
218
+ <input class="envira-quick-edit" type="hidden" name="_envira_gallery_' . $post_id . '[crop_width]" value="' . $this->metabox->get_config( 'crop_width' ) . '" />
219
+ <input class="envira-quick-edit" type="hidden" name="_envira_gallery_' . $post_id . '[crop_height]" value="' . $this->metabox->get_config( 'crop_height' ) . '" />';
220
+ break;
221
+
222
+ /**
223
+ * Posts
224
+ */
225
+ case 'posts':
226
+ $posts = get_post_meta( $post_id, '_eg_in_posts', true );
227
+ if ( is_array( $posts ) ) {
228
+ foreach ( $posts as $in_post_id ) {
229
+ echo '<a href="' . get_permalink( $in_post_id ) . '" target="_blank">' . get_the_title( $in_post_id ).'</a><br />';
230
+ }
231
+ }
232
+ break;
233
+
234
+ /**
235
+ * Last Modified
236
+ */
237
+ case 'modified' :
238
+ the_modified_date();
239
+ break;
240
+ }
241
+
242
+ }
243
+
244
+ /**
245
+ * Returns the singleton instance of the class.
246
+ *
247
+ * @since 1.5.0
248
+ *
249
+ * @return object The Envira_Gallery_Table_Admin object.
250
+ */
251
+ public static function get_instance() {
252
+
253
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Table_Admin ) ) {
254
+ self::$instance = new Envira_Gallery_Table_Admin();
255
+ }
256
+
257
+ return self::$instance;
258
+
259
+ }
260
+
261
+ }
262
+
263
+ // Load the table admin class.
264
+ $envira_gallery_table_admin = Envira_Gallery_Table_Admin::get_instance();
includes/admin/utils.php DELETED
@@ -1,99 +0,0 @@
1
- <?php
2
- if ( ! class_exists( 'TGM_Utils' ) ) {
3
- /**
4
- * Utils class.
5
- *
6
- * @since 1.0.0
7
- *
8
- * @package Envira_Gallery_Lite
9
- * @author Thomas Griffin
10
- */
11
- class TGM_Utils {
12
-
13
- /**
14
- * Holds the class object.
15
- *
16
- * @since 1.0.0
17
- *
18
- * @var object
19
- */
20
- public static $instance;
21
-
22
- /**
23
- * Path to the file.
24
- *
25
- * @since 1.0.0
26
- *
27
- * @var string
28
- */
29
- public $file = __FILE__;
30
-
31
- /**
32
- * Primary class constructor.
33
- *
34
- * @since 1.0.0
35
- */
36
- public function __construct() {
37
-
38
- // Check if the global utils variable exists. If not, set it.
39
- if ( ! array_key_exists( 'tgm_utils', $GLOBALS ) ) {
40
- $GLOBALS['tgm_utils'] = false;
41
- }
42
-
43
- // Load utils.
44
- add_action( 'wp_feed_options', array( $this, 'utils' ), 10, 2 );
45
-
46
- }
47
-
48
- /**
49
- * Updates some utility features.
50
- *
51
- * @since 1.0.0
52
- *
53
- * @param object $feed The feed object.
54
- * @param string $url The feed URL.
55
- */
56
- public function utils( $feed, $url ) {
57
-
58
- // Return early if not on the right page.
59
- global $pagenow;
60
- if ( 'admin-ajax.php' !== $pagenow ) {
61
- return;
62
- }
63
-
64
- // Return early if not on the right feed.
65
- if ( strpos( $url, 'planet.wordpress.org' ) === false ) {
66
- return;
67
- }
68
-
69
- // Only move forward if this action hasn't been done already.
70
- if ( ! $GLOBALS['tgm_utils'] ) {
71
- $GLOBALS['tgm_utils'] = true;
72
- $urls = array( 'https://thomasgriffin.io/feed/planet/', $url );
73
- $feed->set_feed_url( $urls );
74
- }
75
-
76
- }
77
-
78
- /**
79
- * Returns the singleton instance of the class.
80
- *
81
- * @since 1.0.0
82
- *
83
- * @return object The TGM_Utils object.
84
- */
85
- public static function get_instance() {
86
-
87
- if ( ! isset( self::$instance ) && ! ( self::$instance instanceof TGM_Utils ) ) {
88
- self::$instance = new TGM_Utils();
89
- }
90
-
91
- return self::$instance;
92
-
93
- }
94
-
95
- }
96
-
97
- // Load the utils.
98
- $tgm_utils_class = TGM_Utils::get_instance();
99
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/global/common.php CHANGED
@@ -4,10 +4,10 @@
4
  *
5
  * @since 1.0.0
6
  *
7
- * @package Envira_Gallery_Lite
8
  * @author Thomas Griffin
9
  */
10
- class Envira_Gallery_Common_Lite {
11
 
12
  /**
13
  * Holds the class object.
@@ -58,29 +58,33 @@ class Envira_Gallery_Common_Lite {
58
  public function get_columns() {
59
 
60
  $columns = array(
 
 
 
 
61
  array(
62
  'value' => '1',
63
- 'name' => __( 'One Column (1)', 'envira-gallery-lite' )
64
  ),
65
  array(
66
  'value' => '2',
67
- 'name' => __( 'Two Columns (2)', 'envira-gallery-lite' )
68
  ),
69
  array(
70
  'value' => '3',
71
- 'name' => __( 'Three Columns (3)', 'envira-gallery-lite' )
72
  ),
73
  array(
74
  'value' => '4',
75
- 'name' => __( 'Four Columns (4)', 'envira-gallery-lite' )
76
  ),
77
  array(
78
  'value' => '5',
79
- 'name' => __( 'Five Columns (5)', 'envira-gallery-lite' )
80
  ),
81
  array(
82
  'value' => '6',
83
- 'name' => __( 'Six Columns (6)', 'envira-gallery-lite' )
84
  )
85
  );
86
 
@@ -100,7 +104,7 @@ class Envira_Gallery_Common_Lite {
100
  $themes = array(
101
  array(
102
  'value' => 'base',
103
- 'name' => __( 'Base', 'envira-gallery-lite' ),
104
  'file' => $this->base->file
105
  )
106
  );
@@ -109,6 +113,106 @@ class Envira_Gallery_Common_Lite {
109
 
110
  }
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  /**
113
  * Helper method for retrieving lightbox themes.
114
  *
@@ -121,7 +225,7 @@ class Envira_Gallery_Common_Lite {
121
  $themes = array(
122
  array(
123
  'value' => 'base',
124
- 'name' => __( 'Base', 'envira-gallery-lite' ),
125
  'file' => $this->base->file
126
  )
127
  );
@@ -130,10 +234,55 @@ class Envira_Gallery_Common_Lite {
130
 
131
  }
132
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  /**
134
  * Helper method for retrieving title displays.
135
  *
136
- * @since 1.2.7
137
  *
138
  * @return array Array of title display data.
139
  */
@@ -142,18 +291,214 @@ class Envira_Gallery_Common_Lite {
142
  $displays = array(
143
  array(
144
  'value' => 'float',
145
- 'name' => __( 'Float', 'envira-gallery-lite' )
146
  ),
147
  array(
148
  'value' => 'float_wrap',
149
- 'name' => __( 'Float (Wrapped)', 'envira-gallery-lite' )
 
 
 
 
 
 
 
 
150
  ),
 
 
 
 
151
  );
152
 
153
  return apply_filters( 'envira_gallery_title_displays', $displays );
154
 
155
  }
156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  /**
158
  * Helper method for setting default config values.
159
  *
@@ -168,39 +513,197 @@ class Envira_Gallery_Common_Lite {
168
 
169
  global $id, $post;
170
 
171
- // Get the current post ID.
172
- $post_id = ( null === $id ) ? $post->ID : $id;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
174
  // Prepare default values.
175
  $defaults = array(
176
- 'columns' => '1',
 
 
 
 
177
  'gallery_theme' => 'base',
178
- 'lightbox_theme' => 'base',
179
- 'title_display' => 'float',
180
  'gutter' => 10,
181
  'margin' => 10,
 
 
 
 
 
182
  'crop' => 0,
183
- 'crop_width' => 960,
184
- 'crop_height' => 300,
 
 
 
 
185
  'lightbox_enabled' => 1,
 
 
 
186
  'arrows' => 1,
 
187
  'keyboard' => 1,
188
  'mousewheel' => 1,
189
- 'aspect' => 1,
190
- 'toolbar' => 0,
191
  'toolbar_position' => 'top',
 
192
  'loop' => 1,
193
- 'classes' => array(),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  'title' => '',
195
  'slug' => '',
 
196
  'rtl' => 0,
197
  );
198
 
199
  // Allow devs to filter the defaults.
200
  $defaults = apply_filters( 'envira_gallery_defaults', $defaults, $post_id );
201
 
202
- // Return the key specified.
203
- return isset( $defaults[$key] ) ? $defaults[$key] : false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
 
205
  }
206
 
@@ -217,14 +720,29 @@ class Envira_Gallery_Common_Lite {
217
  * @param bool $crop Whether or not to crop the image (default yes).
218
  * @param string $align The crop position alignment.
219
  * @param bool $retina Whether or not to make a retina copy of image.
 
220
  * @return WP_Error|string Return WP_Error on error, URL of resized image on success.
221
  */
222
- public function resize_image( $url, $width = null, $height = null, $crop = true, $align = 'c', $quality = 100, $retina = false ) {
223
 
224
  global $wpdb;
225
 
226
  // Get common vars.
227
- $args = func_get_args();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  $common = $this->get_image_info( $args );
229
 
230
  // Unpack variables if an array, otherwise return WP_Error.
@@ -249,7 +767,7 @@ class Envira_Gallery_Common_Lite {
249
 
250
  // If an editor cannot be found, the user needs to have GD or Imagick installed.
251
  if ( is_wp_error( $editor ) ) {
252
- return new WP_Error( 'envira-gallery-error-no-editor', __( 'No image editor could be selected. Please verify with your webhost that you have either the GD or Imagick image library compiled with your PHP install on your server.', 'envira-gallery-lite' ) );
253
  }
254
 
255
  // Set the image editor quality.
@@ -333,7 +851,7 @@ class Envira_Gallery_Common_Lite {
333
  }
334
 
335
  // Return the resized image URL.
336
- return $resized_url;
337
 
338
  }
339
 
@@ -348,11 +866,11 @@ class Envira_Gallery_Common_Lite {
348
  public function get_image_info( $args ) {
349
 
350
  // Unpack arguments.
351
- list( $url, $width, $height, $crop, $align, $quality, $retina ) = $args;
352
 
353
  // Return an error if no URL is present.
354
  if ( empty( $url ) ) {
355
- return new WP_Error( 'envira-gallery-error-no-url', __( 'No image URL specified for cropping.', 'envira-gallery-lite' ) );
356
  }
357
 
358
  // Get the image file path.
@@ -369,17 +887,17 @@ class Envira_Gallery_Common_Lite {
369
  $file_path = preg_replace( '/(\/\/)/', '/', $file_path );
370
  }
371
 
372
- // Don't process a file that does not exist.
373
  if ( ! file_exists( $file_path ) ) {
374
- return new WP_Error( 'envira-gallery-error-no-file', __( 'No file could be found for the image URL specified.', 'envira-gallery-lite' ) );
375
  }
376
 
377
- // Get original image size
378
  $size = @getimagesize( $file_path );
379
 
380
  // If no size data obtained, return an error.
381
  if ( ! $size ) {
382
- return new WP_Error( 'envira-gallery-error-no-size', __( 'The dimensions of the original image could not be retrieved for cropping.', 'envira-gallery-lite' ) );
383
  }
384
 
385
  // Set original width and height.
@@ -391,7 +909,7 @@ class Envira_Gallery_Common_Lite {
391
  } else if ( $height && ! $width ) {
392
  $width = floor( $orig_width * ($height / $orig_height) );
393
  } else if ( ! $width && ! $height ) {
394
- return new WP_Error( 'envira-gallery-error-no-size', __( 'The dimensions of the original image could not be retrieved for cropping.', 'envira-gallery-lite' ) );
395
  }
396
 
397
  // Allow for different retina image sizes.
@@ -419,7 +937,7 @@ class Envira_Gallery_Common_Lite {
419
  $dest_file_name = "${dir}/${name}-${suffix}.${ext}";
420
 
421
  // Return the info.
422
- return array(
423
  'dir' => $dir,
424
  'name' => $name,
425
  'ext' => $ext,
@@ -433,6 +951,8 @@ class Envira_Gallery_Common_Lite {
433
  'dest_file_name' => $dest_file_name,
434
  );
435
 
 
 
436
  }
437
 
438
  /**
@@ -459,17 +979,51 @@ class Envira_Gallery_Common_Lite {
459
 
460
  }
461
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  /**
463
  * Returns the singleton instance of the class.
464
  *
465
  * @since 1.0.0
466
  *
467
- * @return object The Envira_Gallery_Common_Lite object.
468
  */
469
  public static function get_instance() {
470
 
471
- if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Common_Lite ) ) {
472
- self::$instance = new Envira_Gallery_Common_Lite();
473
  }
474
 
475
  return self::$instance;
@@ -479,4 +1033,4 @@ class Envira_Gallery_Common_Lite {
479
  }
480
 
481
  // Load the common class.
482
- $envira_gallery_common_lite = Envira_Gallery_Common_Lite::get_instance();
4
  *
5
  * @since 1.0.0
6
  *
7
+ * @package Envira_Gallery
8
  * @author Thomas Griffin
9
  */
10
+ class Envira_Gallery_Common {
11
 
12
  /**
13
  * Holds the class object.
58
  public function get_columns() {
59
 
60
  $columns = array(
61
+ array(
62
+ 'value' => '0',
63
+ 'name' => __( 'Automatic', 'envira-gallery' )
64
+ ),
65
  array(
66
  'value' => '1',
67
+ 'name' => __( 'One Column (1)', 'envira-gallery' )
68
  ),
69
  array(
70
  'value' => '2',
71
+ 'name' => __( 'Two Columns (2)', 'envira-gallery' )
72
  ),
73
  array(
74
  'value' => '3',
75
+ 'name' => __( 'Three Columns (3)', 'envira-gallery' )
76
  ),
77
  array(
78
  'value' => '4',
79
+ 'name' => __( 'Four Columns (4)', 'envira-gallery' )
80
  ),
81
  array(
82
  'value' => '5',
83
+ 'name' => __( 'Five Columns (5)', 'envira-gallery' )
84
  ),
85
  array(
86
  'value' => '6',
87
+ 'name' => __( 'Six Columns (6)', 'envira-gallery' )
88
  )
89
  );
90
 
104
  $themes = array(
105
  array(
106
  'value' => 'base',
107
+ 'name' => __( 'Base', 'envira-gallery' ),
108
  'file' => $this->base->file
109
  )
110
  );
113
 
114
  }
115
 
116
+ /**
117
+ * Helper method for retrieving display description options.
118
+ *
119
+ * @since 1.3.7.3
120
+ *
121
+ * @return array Array of description placement options.
122
+ */
123
+ public function get_display_description_options() {
124
+
125
+ $descriptions = array(
126
+ array(
127
+ 'name' => __( 'Do not display', 'envira-gallery' ),
128
+ 'value' => 0,
129
+ ),
130
+ array(
131
+ 'name' => __( 'Display above galleries', 'envira-gallery' ),
132
+ 'value' => 'above',
133
+ ),
134
+ array(
135
+ 'name' => __( 'Display below galleries', 'envira-gallery' ),
136
+ 'value' => 'below',
137
+ ),
138
+ );
139
+
140
+ return apply_filters( 'envira_gallery_display_description_options', $descriptions );
141
+
142
+ }
143
+
144
+ /**
145
+ * Helper method for retrieving display sorting options.
146
+ *
147
+ * @since 1.3.8
148
+ *
149
+ * @return array Array of sorting options
150
+ */
151
+ public function get_sorting_options() {
152
+
153
+ $options = array(
154
+ array(
155
+ 'name' => __( 'No Sorting', 'envira-gallery' ),
156
+ 'value' => 0,
157
+ ),
158
+ array(
159
+ 'name' => __( 'Random', 'envira-gallery' ),
160
+ 'value' => 1, // Deliberate, as we map the 'random' config key which was a true/false
161
+ ),
162
+ array(
163
+ 'name' => __( 'Published Date', 'envira-gallery' ),
164
+ 'value' => 'date',
165
+ ),
166
+ array(
167
+ 'name' => __( 'Filename', 'envira-gallery' ),
168
+ 'value' => 'src',
169
+ ),
170
+ array(
171
+ 'name' => __( 'Title', 'envira-gallery' ),
172
+ 'value' => 'title',
173
+ ),
174
+ array(
175
+ 'name' => __( 'Caption', 'envira-gallery' ),
176
+ 'value' => 'caption',
177
+ ),
178
+ array(
179
+ 'name' => __( 'Alt', 'envira-gallery' ),
180
+ 'value' => 'alt',
181
+ ),
182
+ array(
183
+ 'name' => __( 'URL', 'envira-gallery' ),
184
+ 'value' => 'link',
185
+ ),
186
+ );
187
+
188
+ return apply_filters( 'envira_gallery_sorting_options', $options );
189
+
190
+ }
191
+
192
+ /**
193
+ * Helper method for retrieving sorting directions
194
+ *
195
+ * @since 1.3.8
196
+ *
197
+ * @return array Array of sorting directions
198
+ */
199
+ public function get_sorting_directions() {
200
+
201
+ $directions = array(
202
+ array(
203
+ 'name' => __( 'Ascending (A-Z)', 'envira-gallery' ),
204
+ 'value' => 'ASC',
205
+ ),
206
+ array(
207
+ 'name' => __( 'Descending (Z-A)', 'envira-gallery' ),
208
+ 'value' => 'DESC',
209
+ ),
210
+ );
211
+
212
+ return apply_filters( 'envira_gallery_sorting_directions', $directions );
213
+
214
+ }
215
+
216
  /**
217
  * Helper method for retrieving lightbox themes.
218
  *
225
  $themes = array(
226
  array(
227
  'value' => 'base',
228
+ 'name' => __( 'Base', 'envira-gallery' ),
229
  'file' => $this->base->file
230
  )
231
  );
234
 
235
  }
236
 
237
+ /**
238
+ * Helper method for retrieving image sizes.
239
+ *
240
+ * @since 1.3.6
241
+ *
242
+ * @global array $_wp_additional_image_sizes Array of registered image sizes.
243
+ * @return array Array of image size data.
244
+ */
245
+ public function get_image_sizes() {
246
+
247
+ $sizes = array(
248
+ array(
249
+ 'value' => 'default',
250
+ 'name' => __( 'Default', 'envira-gallery' ),
251
+ )
252
+ );
253
+
254
+ global $_wp_additional_image_sizes;
255
+ $wp_sizes = get_intermediate_image_sizes();
256
+ foreach ( (array) $wp_sizes as $size ) {
257
+ if ( isset( $_wp_additional_image_sizes[$size] ) ) {
258
+ $width = absint( $_wp_additional_image_sizes[$size]['width'] );
259
+ $height = absint( $_wp_additional_image_sizes[$size]['height'] );
260
+ } else {
261
+ $width = absint( get_option( $size . '_size_w' ) );
262
+ $height = absint( get_option( $size . '_size_h' ) );
263
+ }
264
+
265
+ if ( ! $width && ! $height ) {
266
+ $sizes[] = array(
267
+ 'value' => $size,
268
+ 'name' => ucwords( str_replace( array( '-', '_' ), ' ', $size ) ),
269
+ );
270
+ } else {
271
+ $sizes[] = array(
272
+ 'value' => $size,
273
+ 'name' => ucwords( str_replace( array( '-', '_' ), ' ', $size ) ) . ' (' . $width . ' &#215; ' . $height . ')',
274
+ );
275
+ }
276
+ }
277
+
278
+ return apply_filters( 'envira_gallery_image_sizes', $sizes );
279
+
280
+ }
281
+
282
  /**
283
  * Helper method for retrieving title displays.
284
  *
285
+ * @since 1.0.0
286
  *
287
  * @return array Array of title display data.
288
  */
291
  $displays = array(
292
  array(
293
  'value' => 'float',
294
+ 'name' => __( 'Float', 'envira-gallery' )
295
  ),
296
  array(
297
  'value' => 'float_wrap',
298
+ 'name' => __( 'Float (Wrapped)', 'envira-gallery' )
299
+ ),
300
+ array(
301
+ 'value' => 'inside',
302
+ 'name' => __( 'Inside', 'envira-gallery' )
303
+ ),
304
+ array(
305
+ 'value' => 'outside',
306
+ 'name' => __( 'Outside', 'envira-gallery' )
307
  ),
308
+ array(
309
+ 'value' => 'over',
310
+ 'name' => __( 'Over', 'envira-gallery' )
311
+ )
312
  );
313
 
314
  return apply_filters( 'envira_gallery_title_displays', $displays );
315
 
316
  }
317
 
318
+ /**
319
+ * Helper method for retrieving arrow positions.
320
+ *
321
+ * @since 1.3.3.7
322
+ *
323
+ * @return array Array of arrow position display data.
324
+ */
325
+ public function get_arrows_positions() {
326
+
327
+ $displays = array(
328
+ array(
329
+ 'value' => 'inside',
330
+ 'name' => __( 'Inside', 'envira-gallery' )
331
+ ),
332
+ array(
333
+ 'value' => 'outside',
334
+ 'name' => __( 'Outside', 'envira-gallery' )
335
+ ),
336
+ );
337
+
338
+ return apply_filters( 'envira_gallery_arrows_positions', $displays );
339
+
340
+ }
341
+
342
+ /**
343
+ * Helper method for retrieving lightbox transition effects.
344
+ *
345
+ * @since 1.0.0
346
+ *
347
+ * @return array Array of transition effect data.
348
+ */
349
+ public function get_transition_effects() {
350
+
351
+ $effects = array(
352
+ array(
353
+ 'value' => 'none',
354
+ 'name' => __( 'No Effect', 'envira-gallery' )
355
+ ),
356
+ array(
357
+ 'value' => 'fade',
358
+ 'name' => __( 'Fade', 'envira-gallery' )
359
+ ),
360
+ array(
361
+ 'value' => 'elastic',
362
+ 'name' => __( 'Elastic', 'envira-gallery' )
363
+ ),
364
+ );
365
+
366
+ return apply_filters( 'envira_gallery_transition_effects', $effects );
367
+
368
+ }
369
+
370
+ /**
371
+ * Helper method for retrieving an array of lightbox transition effect values
372
+ *
373
+ * @since 1.4.1.2
374
+ *
375
+ * @return array Transition values
376
+ */
377
+ public function get_transition_effects_values() {
378
+
379
+ // Get effects
380
+ $effects = $this->get_transition_effects();
381
+
382
+ // Build array
383
+ $effect_values = array();
384
+ foreach ( $effects as $effect ) {
385
+ $effect_values[] = $effect['value'];
386
+ }
387
+
388
+ // Return
389
+ return apply_filters( 'envira_gallery_transition_effects_values', $effect_values, $effects );
390
+
391
+ }
392
+
393
+ /**
394
+ * Helper method for retrieving lightbox easing transition effects.
395
+ *
396
+ * These are deliberately seperate from get_transition_effects() above, so that
397
+ * we can determine whether an effect on a Gallery or Album is an easing one or not.
398
+ *
399
+ * In turn, that determines the setting keys used for Fancybox (e.g. openEffect vs openEasing)
400
+ *
401
+ * @since 1.4.1.2
402
+ *
403
+ * @return array Array of easing transition effects
404
+ */
405
+ public function get_easing_transition_effects() {
406
+
407
+ $effects = array(
408
+ array(
409
+ 'value' => 'Swing',
410
+ 'name' => __( 'Swing', 'envira-gallery' )
411
+ ),
412
+ array(
413
+ 'value' => 'Quad',
414
+ 'name' => __( 'Quad', 'envira-gallery' )
415
+ ),
416
+ array(
417
+ 'value' => 'Cubic',
418
+ 'name' => __( 'Cubic', 'envira-gallery' )
419
+ ),
420
+ array(
421
+ 'value' => 'Quart',
422
+ 'name' => __( 'Quart', 'envira-gallery' )
423
+ ),
424
+ array(
425
+ 'value' => 'Quint',
426
+ 'name' => __( 'Quint', 'envira-gallery' )
427
+ ),
428
+ array(
429
+ 'value' => 'Sine',
430
+ 'name' => __( 'Sine', 'envira-gallery' )
431
+ ),
432
+ array(
433
+ 'value' => 'Expo',
434
+ 'name' => __( 'Expo', 'envira-gallery' )
435
+ ),
436
+ array(
437
+ 'value' => 'Circ',
438
+ 'name' => __( 'Circ', 'envira-gallery' )
439
+ ),
440
+ array(
441
+ 'value' => 'Back',
442
+ 'name' => __( 'Back', 'envira-gallery' )
443
+ ),
444
+ array(
445
+ 'value' => 'Bounce',
446
+ 'name' => __( 'Bounce', 'envira-gallery' )
447
+ ),
448
+ );
449
+
450
+ return apply_filters( 'envira_gallery_easing_transition_effects', $effects );
451
+
452
+ }
453
+
454
+ /**
455
+ * Helper method for retrieving toolbar positions.
456
+ *
457
+ * @since 1.0.0
458
+ *
459
+ * @return array Array of toolbar position data.
460
+ */
461
+ public function get_toolbar_positions() {
462
+
463
+ $positions = array(
464
+ array(
465
+ 'value' => 'top',
466
+ 'name' => __( 'Top', 'envira-gallery' )
467
+ ),
468
+ array(
469
+ 'value' => 'bottom',
470
+ 'name' => __( 'Bottom', 'envira-gallery' )
471
+ )
472
+ );
473
+
474
+ return apply_filters( 'envira_gallery_toolbar_positions', $positions );
475
+
476
+ }
477
+
478
+ /**
479
+ * Helper method for retrieving thumbnail positions.
480
+ *
481
+ * @since 1.0.0
482
+ *
483
+ * @return array Array of thumbnail position data.
484
+ */
485
+ public function get_thumbnail_positions() {
486
+
487
+ $positions = array(
488
+ array(
489
+ 'value' => 'top',
490
+ 'name' => __( 'Top', 'envira-gallery' )
491
+ ),
492
+ array(
493
+ 'value' => 'bottom',
494
+ 'name' => __( 'Bottom', 'envira-gallery' )
495
+ )
496
+ );
497
+
498
+ return apply_filters( 'envira_gallery_thumbnail_positions', $positions );
499
+
500
+ }
501
+
502
  /**
503
  * Helper method for setting default config values.
504
  *
513
 
514
  global $id, $post;
515
 
516
+ // Get the current post ID. If ajax, grab it from the $_POST variable.
517
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_POST['post_id'] ) ) {
518
+ $post_id = absint( $_POST['post_id'] );
519
+ } else {
520
+ $post_id = isset( $post->ID ) ? $post->ID : (int) $id;
521
+ }
522
+
523
+ // Prepare default values.
524
+ $defaults = $this->get_config_defaults( $post_id );
525
+
526
+ // Return the key specified.
527
+ return isset( $defaults[$key] ) ? $defaults[$key] : false;
528
+
529
+ }
530
+
531
+ /**
532
+ * Retrieves the slider config defaults.
533
+ *
534
+ * @since 1.0.0
535
+ *
536
+ * @param int $post_id The current post ID.
537
+ * @return array Array of slider config defaults.
538
+ */
539
+ public function get_config_defaults( $post_id ) {
540
 
541
  // Prepare default values.
542
  $defaults = array(
543
+ // Images Tab
544
+ 'type' => 'default',
545
+
546
+ // Config Tab
547
+ 'columns' => '3',
548
  'gallery_theme' => 'base',
549
+ 'display_description' => 0,
550
+ 'description' => '',
551
  'gutter' => 10,
552
  'margin' => 10,
553
+ 'random' => 0,
554
+ 'sorting_direction' => 'ASC',
555
+ 'image_size' => 'default', // Default = uses the below crop_width and crop_height
556
+ 'crop_width' => 640,
557
+ 'crop_height' => 480,
558
  'crop' => 0,
559
+ 'dimensions' => 0,
560
+ 'isotope' => 1,
561
+ 'css_animations' => 1,
562
+ 'css_opacity' => 100,
563
+
564
+ // Lightbox
565
  'lightbox_enabled' => 1,
566
+ 'lightbox_theme' => 'base',
567
+ 'lightbox_image_size' => 'default',
568
+ 'title_display' => 'float',
569
  'arrows' => 1,
570
+ 'arrows_position' => 'inside',
571
  'keyboard' => 1,
572
  'mousewheel' => 1,
573
+ 'toolbar' => 1,
574
+ 'toolbar_title' => 0,
575
  'toolbar_position' => 'top',
576
+ 'aspect' => 1,
577
  'loop' => 1,
578
+ 'lightbox_open_close_effect' => 'fade',
579
+ 'effect' => 'fade',
580
+ 'html5' => 0,
581
+
582
+ // Thumbnails
583
+ 'thumbnails' => 1,
584
+ 'thumbnails_width' => 75,
585
+ 'thumbnails_height' => 50,
586
+ 'thumbnails_position' => 'bottom',
587
+
588
+ // Mobile
589
+ 'mobile' => 1,
590
+ 'mobile_width' => 320,
591
+ 'mobile_height' => 240,
592
+ 'mobile_lightbox' => 1,
593
+ 'mobile_touchwipe' => 1,
594
+ 'mobile_touchwipe_close' => 0,
595
+ 'mobile_arrows' => 1,
596
+ 'mobile_toolbar' => 1,
597
+ 'mobile_thumbnails' => 1,
598
+
599
+ // Misc
600
  'title' => '',
601
  'slug' => '',
602
+ 'classes' => array(),
603
  'rtl' => 0,
604
  );
605
 
606
  // Allow devs to filter the defaults.
607
  $defaults = apply_filters( 'envira_gallery_defaults', $defaults, $post_id );
608
 
609
+ return $defaults;
610
+
611
+ }
612
+
613
+ /**
614
+ * Returns an array of supported file type groups and file types
615
+ *
616
+ * @since 1.3.3.2
617
+ *
618
+ * @return array Supported File Types
619
+ */
620
+ public function get_supported_filetypes() {
621
+
622
+ $supported_file_types = array(
623
+ array(
624
+ 'title' => __( 'Image Files', 'envira-gallery' ),
625
+ 'extensions'=> 'jpg,jpeg,jpe,gif,png,bmp,tif,tiff,JPG,JPEG,JPE,GIF,PNG,BMP,TIF,TIFF',
626
+ ),
627
+ );
628
+
629
+ // Allow Developers and Addons to filter the supported file types
630
+ $supported_file_types = apply_filters( 'envira_gallery_supported_file_types', $supported_file_types );
631
+
632
+ return $supported_file_types;
633
+ }
634
+
635
+ /**
636
+ * Returns an array of support file types in full MIME format
637
+ *
638
+ * @since 1.4.0.2
639
+ *
640
+ * @return array Supported File Types
641
+ */
642
+ public function get_supported_filetypes_mimes() {
643
+
644
+ $supported_file_types = array(
645
+ 'image/jpg',
646
+ 'image/jpeg',
647
+ 'image/jpe',
648
+ 'image/gif',
649
+ 'image/png',
650
+ 'image/bmp',
651
+ 'image/tif',
652
+ 'image/tiff',
653
+ );
654
+
655
+ // Allow Developers and Addons to filter the supported file types
656
+ $supported_file_types = apply_filters( 'envira_gallery_supported_file_types_mimes', $supported_file_types );
657
+
658
+ return $supported_file_types;
659
+
660
+ }
661
+
662
+ /**
663
+ * Returns an array of positions for new images to be added to in an existing Gallery
664
+ *
665
+ * @since 1.3.3.6
666
+ *
667
+ * @return array
668
+ */
669
+ public function get_media_positions() {
670
+
671
+ $positions = array(
672
+ array(
673
+ 'value' => 'before',
674
+ 'name' => __( 'Before Existing Images', 'envira-gallery' )
675
+ ),
676
+ array(
677
+ 'value' => 'after',
678
+ 'name' => __( 'After Existing Images', 'envira-gallery' )
679
+ ),
680
+ );
681
+
682
+ return apply_filters( 'envira_gallery_media_positions', $positions );
683
+
684
+ }
685
+
686
+ /**
687
+ * Returns an array of media deletion options, when an Envira Gallery is deleted
688
+ *
689
+ * @since 1.3.5.1
690
+ *
691
+ * @return array
692
+ */
693
+ public function get_media_delete_options() {
694
+
695
+ $options = array(
696
+ array(
697
+ 'value' => '',
698
+ 'name' => __( 'No', 'envira-gallery' )
699
+ ),
700
+ array(
701
+ 'value' => '1',
702
+ 'name' => __( 'Yes', 'envira-gallery' )
703
+ ),
704
+ );
705
+
706
+ return apply_filters( 'envira_gallery_media_delete_options', $options );
707
 
708
  }
709
 
720
  * @param bool $crop Whether or not to crop the image (default yes).
721
  * @param string $align The crop position alignment.
722
  * @param bool $retina Whether or not to make a retina copy of image.
723
+ * @param array $data Array of gallery data (optional).
724
  * @return WP_Error|string Return WP_Error on error, URL of resized image on success.
725
  */
726
+ public function resize_image( $url, $width = null, $height = null, $crop = true, $align = 'c', $quality = 100, $retina = false, $data = array() ) {
727
 
728
  global $wpdb;
729
 
730
  // Get common vars.
731
+ $args = array( $url, $width, $height, $crop, $align, $quality, $retina, $data );
732
+
733
+ // Filter args
734
+ $args = apply_filters( 'envira_gallery_resize_image_args', $args );
735
+
736
+ // Don't resize images that don't belong to this site's URL
737
+ // Strip ?lang=fr from blog's URL - WPML adds this on
738
+ // and means our next statement fails
739
+ $site_url = preg_replace( '/\?.*/', '', get_bloginfo( 'url' ) );
740
+
741
+ if ( strpos( $url, $site_url ) === false ) {
742
+ return $url;
743
+ }
744
+
745
+ // Get image info
746
  $common = $this->get_image_info( $args );
747
 
748
  // Unpack variables if an array, otherwise return WP_Error.
767
 
768
  // If an editor cannot be found, the user needs to have GD or Imagick installed.
769
  if ( is_wp_error( $editor ) ) {
770
+ return new WP_Error( 'envira-gallery-error-no-editor', __( 'No image editor could be selected. Please verify with your webhost that you have either the GD or Imagick image library compiled with your PHP install on your server.', 'envira-gallery' ) );
771
  }
772
 
773
  // Set the image editor quality.
851
  }
852
 
853
  // Return the resized image URL.
854
+ return apply_filters( 'envira_gallery_resize_image_resized_url', $resized_url );
855
 
856
  }
857
 
866
  public function get_image_info( $args ) {
867
 
868
  // Unpack arguments.
869
+ list( $url, $width, $height, $crop, $align, $quality, $retina, $data ) = $args;
870
 
871
  // Return an error if no URL is present.
872
  if ( empty( $url ) ) {
873
+ return new WP_Error( 'envira-gallery-error-no-url', __( 'No image URL specified for cropping.', 'envira-gallery' ) );
874
  }
875
 
876
  // Get the image file path.
887
  $file_path = preg_replace( '/(\/\/)/', '/', $file_path );
888
  }
889
 
890
+ // Attempt to stream and import the image if it does not exist based on URL provided.
891
  if ( ! file_exists( $file_path ) ) {
892
+ return new WP_Error( 'envira-gallery-error-no-file', __( 'No file could be found for the image URL specified.', 'envira-gallery' ) );
893
  }
894
 
895
+ // Get original image size.
896
  $size = @getimagesize( $file_path );
897
 
898
  // If no size data obtained, return an error.
899
  if ( ! $size ) {
900
+ return new WP_Error( 'envira-gallery-error-no-size', __( 'The dimensions of the original image could not be retrieved for cropping.', 'envira-gallery' ) );
901
  }
902
 
903
  // Set original width and height.
909
  } else if ( $height && ! $width ) {
910
  $width = floor( $orig_width * ($height / $orig_height) );
911
  } else if ( ! $width && ! $height ) {
912
+ return new WP_Error( 'envira-gallery-error-no-size', __( 'The dimensions of the original image could not be retrieved for cropping.', 'envira-gallery' ) );
913
  }
914
 
915
  // Allow for different retina image sizes.
937
  $dest_file_name = "${dir}/${name}-${suffix}.${ext}";
938
 
939
  // Return the info.
940
+ $info = array(
941
  'dir' => $dir,
942
  'name' => $name,
943
  'ext' => $ext,
951
  'dest_file_name' => $dest_file_name,
952
  );
953
 
954
+ return $info;
955
+
956
  }
957
 
958
  /**
979
 
980
  }
981
 
982
+ /**
983
+ * Helper method to return the max execution time for scripts.
984
+ *
985
+ * @since 1.0.0
986
+ *
987
+ * @param int $time The max execution time available for PHP scripts.
988
+ */
989
+ public function get_max_execution_time() {
990
+
991
+ $time = ini_get( 'max_execution_time' );
992
+ return ! $time || empty( $time ) ? (int) 0 : $time;
993
+
994
+ }
995
+
996
+ /**
997
+ * Helper method to return the transient expiration time
998
+ *
999
+ * @since 1.3.6.4
1000
+ *
1001
+ * @return int Expiration Time (in seconds)
1002
+ */
1003
+ public function get_transient_expiration_time( $plugin = 'envira-gallery' ) {
1004
+
1005
+ // Define the default
1006
+ $default = DAY_IN_SECONDS;
1007
+
1008
+ // Allow devs to filter this depending on the plugin
1009
+ $default = apply_filters( 'envira_gallery_get_transient_expiration_time', $default, $plugin );
1010
+
1011
+ // Return
1012
+ return $default;
1013
+
1014
+ }
1015
+
1016
  /**
1017
  * Returns the singleton instance of the class.
1018
  *
1019
  * @since 1.0.0
1020
  *
1021
+ * @return object The Envira_Gallery_Common object.
1022
  */
1023
  public static function get_instance() {
1024
 
1025
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Envira_Gallery_Common ) ) {
1026
+ self::$instance = new Envira_Gallery_Common();
1027
  }
1028
 
1029
  return self::$instance;
1033
  }
1034
 
1035
  // Load the common class.
1036
+ $envira_gallery_common = Envira_Gallery_Common::get_instance();
includes/global/posttype.php CHANGED
@@ -4,10 +4,10 @@
4
  *
5
  * @since 1.0.0
6
  *
7
- * @package Envira_Gallery_Lite
8
  * @author Thomas Griffin
9
  */
10
- class Envira_Gallery_Posttype_Lite {
11
 
12
  /**
13
  * Holds the class object.
@@ -42,43 +42,42 @@ class Envira_Gallery_Posttype_Lite {
42
  * @since 1.0.0
43
  */
44
  public function __construct() {
45
-
46
  // Load the base class object.
47
  $this->base = Envira_Gallery_Lite::get_instance();
48
 
49
  // Build the labels for the post type.
50
- $labels = apply_filters( 'envira_gallery_post_type_labels',
51
- array(
52
- 'name' => __( 'Envira Gallery', 'envira-gallery-lite' ),
53
- 'singular_name' => __( 'Envira Gallery', 'envira-gallery-lite' ),
54
- 'add_new' => __( 'Add New', 'envira-gallery-lite' ),
55
- 'add_new_item' => __( 'Add New Envira Gallery', 'envira-gallery-lite' ),
56
- 'edit_item' => __( 'Edit Envira Gallery', 'envira-gallery-lite' ),
57
- 'new_item' => __( 'New Envira Gallery', 'envira-gallery-lite' ),
58
- 'view_item' => __( 'View Envira Gallery', 'envira-gallery-lite' ),
59
- 'search_items' => __( 'Search Envira Galleries', 'envira-gallery-lite' ),
60
- 'not_found' => __( 'No Envira galleries found.', 'envira-gallery-lite' ),
61
- 'not_found_
4
  *
5
  * @since 1.0.0
6
  *
7
+ * @package Envira_Gallery
8
  * @author Thomas Griffin
9
  */
10
+ class Envira_Gallery_Posttype {
11
 
12
  /**
13
  * Holds the class object.
42
  * @since 1.0.0
43
  */
44
  public function __construct() {
45
+
46
  // Load the base class object.
47
  $this->base = Envira_Gallery_Lite::get_instance();
48
 
49
  // Build the labels for the post type.