ThemeGrill Demo Importer - Version 1.5.0

Version Description

  • 21-08-2018 =
  • Feature - Fetches the demo config from GitHub repo.
  • Feature - Category and pagebuilder routes for views.
  • Fetaure - Install and activate plugins on a single click.
  • Fix - Slashes to be stripped from imported comments.
  • Fix - Importing export files with multiline term meta data.
  • Fix - Deprecation notices including wp_get_http() and screen_icon().
  • Tweak - Demo preview is supported via iframe.
  • Tweak - Different device preview is possible for a demo.
  • Tweak - Only store single demo package files in upload directory.
  • Dev - Improve PHP7 compatibility.
  • Deprecated - Upload process for the demo packages.
  • Deprecated - Filter hooks themegrill_demo_importer_config and themegrill_demo_importer_packages.

See changelog for all versions.

Download this release

Release Info

Developer ThemeGrill
Plugin Icon 128x128 ThemeGrill Demo Importer
Version 1.5.0
Comparing to
See all releases

Code changes from version 1.4.3 to 1.5.0

Files changed (38) hide show
  1. .stylelintrc +58 -0
  2. CHANGELOG.txt +73 -0
  3. CODE_OF_CONDUCT.md +46 -0
  4. assets/css/_animation.scss +9 -0
  5. assets/css/demo-importer-rtl.css +1 -1
  6. assets/css/demo-importer.css +1 -1
  7. assets/css/demo-importer.scss +154 -150
  8. assets/js/admin/demo-importer.js +654 -615
  9. assets/js/admin/demo-importer.min.js +1 -1
  10. assets/js/admin/demo-updates.js +21 -129
  11. assets/js/admin/demo-updates.min.js +1 -1
  12. assets/js/jquery-tiptip/jquery.tipTip.min.js +1 -1
  13. composer.lock +425 -0
  14. includes/admin/class-demo-installer-skin.php +0 -64
  15. includes/admin/class-demo-pack-upgrader.php +123 -0
  16. includes/admin/class-demo-upgrader.php +0 -351
  17. includes/admin/views/html-admin-page-importer.php +144 -172
  18. includes/admin/views/html-admin-page-installer-preview.php +0 -60
  19. includes/admin/views/html-admin-page-installer-uploads.php +0 -64
  20. includes/admin/views/html-admin-page-installer.php +0 -338
  21. includes/admin/views/html-notice-reset-wizard-success.php +3 -3
  22. includes/admin/views/html-notice-reset-wizard.php +3 -3
  23. includes/class-demo-importer.php +189 -232
  24. includes/class-themegrill-demo-importer.php +258 -0
  25. includes/functions-demo-importer.php +115 -194
  26. includes/functions-demo-template.php +0 -67
  27. includes/functions-demo-update.php +4 -61
  28. includes/importers/class-customizer-importer.php +9 -15
  29. includes/importers/class-widget-importer.php +3 -8
  30. includes/importers/customize/class-oc-customize-demo-importer-setting.php +2 -4
  31. includes/importers/wordpress-importer/class-wxr-importer.php +50 -72
  32. includes/importers/wordpress-importer/class-wxr-parsers.php +34 -27
  33. languages/themegrill-demo-importer.pot +279 -471
  34. package-lock.json +5900 -0
  35. phpcs.xml +45 -0
  36. readme.txt +25 -16
  37. themegrill-demo-importer.php +15 -280
  38. uninstall.php +5 -7
.stylelintrc ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "rules": {
3
+ "indentation": "tab",
4
+ "color-hex-case": "lower",
5
+ "color-no-invalid-hex": true,
6
+
7
+ "function-calc-no-unspaced-operator": true,
8
+ "function-comma-space-after": "always-single-line",
9
+ "function-comma-space-before": "never",
10
+ "function-name-case": "lower",
11
+ "function-url-quotes": "always",
12
+ "function-whitespace-after": "always",
13
+
14
+ "number-leading-zero": "always",
15
+ "number-no-trailing-zeros": true,
16
+ "length-zero-no-unit": true,
17
+
18
+ "string-no-newline": true,
19
+ "string-quotes": "single",
20
+
21
+ "unit-case": "lower",
22
+ "unit-no-unknown": true,
23
+ "unit-whitelist": ["px", "%", "deg", "ms", "em", "vh", "vw", "rem", "s", "ex", "pt", "cm"],
24
+
25
+ "value-list-comma-space-after": "always-single-line",
26
+ "value-list-comma-space-before": "never",
27
+
28
+ "shorthand-property-no-redundant-values": true,
29
+
30
+ "property-case": "lower",
31
+
32
+ "declaration-block-no-duplicate-properties": [true, { "severity": "warning" } ],
33
+ "declaration-block-trailing-semicolon": "always",
34
+ "declaration-block-single-line-max-declarations": 0,
35
+ "declaration-block-semicolon-space-before": "never",
36
+ "declaration-block-semicolon-space-after": "always-single-line",
37
+ "declaration-block-semicolon-newline-before": "never-multi-line",
38
+ "declaration-block-semicolon-newline-after": "always-multi-line",
39
+
40
+ "block-closing-brace-newline-after": "always",
41
+ "block-closing-brace-newline-before": "always-multi-line",
42
+ "block-no-empty": true,
43
+ "block-opening-brace-newline-after": "always-multi-line",
44
+ "block-opening-brace-space-before": "always",
45
+
46
+ "selector-attribute-brackets-space-inside": "never",
47
+ "selector-attribute-operator-space-after": "never",
48
+ "selector-attribute-operator-space-before": "never",
49
+ "selector-combinator-space-after": "always",
50
+ "selector-combinator-space-before": "always",
51
+ "selector-pseudo-class-case": "lower",
52
+ "selector-pseudo-class-parentheses-space-inside": "always",
53
+ "selector-pseudo-element-case": "lower",
54
+ "selector-pseudo-element-colon-notation": "double",
55
+ "selector-pseudo-element-no-unknown": true,
56
+ "selector-type-case": "lower"
57
+ }
58
+ }
CHANGELOG.txt ADDED
@@ -0,0 +1,73 @@
1
+ == Changelog ==
2
+
3
+ = 1.5.0 - 21-08-2018 =
4
+ * Feature - Fetches the demo config from GitHub repo.
5
+ * Feature - Category and pagebuilder routes for views.
6
+ * Fetaure - Install and activate plugins on a single click.
7
+ * Fix - Slashes to be stripped from imported comments.
8
+ * Fix - Importing export files with multiline term meta data.
9
+ * Fix - Deprecation notices including `wp_get_http()` and `screen_icon()`.
10
+ * Tweak - Demo preview is supported via iframe.
11
+ * Tweak - Different device preview is possible for a demo.
12
+ * Tweak - Only store single demo package files in upload directory.
13
+ * Dev - Improve PHP7 compatibility.
14
+ * Deprecated - Upload process for the demo packages.
15
+ * Deprecated - Filter hooks `themegrill_demo_importer_config` and `themegrill_demo_importer_packages`.
16
+
17
+ = 1.4.3 - 23-04-2018 =
18
+ * Support - Cenote theme.
19
+
20
+ = 1.4.2 - 25-12-2017 =
21
+ * Fix - Disable WooCommerce setup wizard for demo import.
22
+ * Fix - Styling issue caused by missing `theme-id-container` container.
23
+
24
+ = 1.4.1 - 08-12-2017 =
25
+ * Feature - Compatiable with Elementor page builder.
26
+ * Fix - Styling issue caused by missing `theme-id-container` container.
27
+
28
+ = 1.4.0 - 20-07-2017 =
29
+ * Feature - Plugin installer and activator mechinism.
30
+ * Fix - Call to undefined function `preg_filter()`.
31
+ * Dev - Improved file structure.
32
+ * Dev - Introduced `tg_demo_installer_enabled()`.
33
+ * Dev - Introduced `tg_demo_installer_preview()`.
34
+ * Dev - Introduced `tg_demo_preview_screenshot_url()`.
35
+
36
+ = 1.3.4 - 03-07-2017 =
37
+ * Feature - Support RTL for Importer.
38
+ * Feature - Reset wizard for clean up.
39
+ * Fixed - Undefined queue job update action.
40
+ * Fixed - Use of `wp-heading-inline` core class.
41
+ * Tweak - Use of defined constant for demo packs.
42
+ * Tweak - Uninstall data with a defined constant.
43
+ * Tweak - Fallback screenshot for flash demo preview.
44
+
45
+ = 1.3.3 =
46
+ * Tweak - Support demo import for suffice theme.
47
+
48
+ = 1.3.2 =
49
+ * Tweak - Load screenshots for pro theme demos.
50
+
51
+ = 1.3.1 =
52
+ * Tweak - Load screenshot from theme instead of plugin for themes with single demo.
53
+
54
+ = 1.3.0 =
55
+ * Tweak - Support data update for nested siteorigin layoutbuilder.
56
+ * Fix - Import button not working on firefox.
57
+
58
+ = 1.2.0 =
59
+ * Tweak - Load scripts perfecly on demo importer appearance page.
60
+ * Tweak - Set transient for redirecting to demo importer page after install or update.
61
+ * Tweak - Introduced filter hook `themegrill_demo_importer_installer` to control demo view.
62
+
63
+ = 1.1.0 =
64
+ * Feature - Backbone views interface for demos and previews
65
+ * Feature - Added download button for the preview not installed
66
+ * Feature - Robust quick search view to change in demo interface
67
+ * Feature - Detailed information in popup to showcase plugins, events, etc
68
+ * Refactor - Replace old way to import demo with new `wp.updates` methods
69
+ * Fix - Menu classes to hide admin menu if no JS using css class `hide-if-no-js`
70
+ * Fix - Remove the old demo pack if found and to update the new demo packs
71
+
72
+ = 1.0.0 =
73
+ * Initial Public Release
CODE_OF_CONDUCT.md ADDED
@@ -0,0 +1,46 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ Examples of behavior that contributes to creating a positive environment include:
10
+
11
+ * Using welcoming and inclusive language
12
+ * Being respectful of differing viewpoints and experiences
13
+ * Gracefully accepting constructive criticism
14
+ * Focusing on what is best for the community
15
+ * Showing empathy towards other community members
16
+
17
+ Examples of unacceptable behavior by participants include:
18
+
19
+ * The use of sexualized language or imagery and unwelcome sexual attention or advances
20
+ * Trolling, insulting/derogatory comments, and personal or political attacks
21
+ * Public or private harassment
22
+ * Publishing others' private information, such as a physical or electronic address, without explicit permission
23
+ * Other conduct which could reasonably be considered inappropriate in a professional setting
24
+
25
+ ## Our Responsibilities
26
+
27
+ Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28
+
29
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30
+
31
+ ## Scope
32
+
33
+ This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project email address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34
+
35
+ ## Enforcement
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at support@themegrill.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38
+
39
+ Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40
+
41
+ ## Attribution
42
+
43
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44
+
45
+ [homepage]: http://contributor-covenant.org
46
+ [version]: http://contributor-covenant.org/version/1/4/
assets/css/_animation.scss ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * _animation.scss
3
+ * Custom ThemeGrill Demo Importer Animations.
4
+ */
5
+ @keyframes spin {
6
+ 100% {
7
+ transform: rotate( 360deg );
8
+ }
9
+ }
assets/css/demo-importer-rtl.css CHANGED
@@ -1 +1 @@
1
- .appearance_page_demo-importer .demo-importer h1{margin-bottom:15px}.appearance_page_demo-importer .demo-importer .search-form{display:inline}.appearance_page_demo-importer .demo-importer .wp-filter-search{position:relative;top:-2px;right:20px;margin:0;width:280px;font-size:16px;font-weight:300;line-height:1.5}.appearance_page_demo-importer .demo-installer .wp-filter{padding:0 20px}.appearance_page_demo-importer .demo-installer .wp-filter .filter-links li>a:focus{box-shadow:none}.appearance_page_demo-importer .demo-installer .welcome-panel{margin:0;background:#e9eff3;border:10px solid #fff;box-shadow:none}.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-content{width:45%;float:right}.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-content .welcome-panel-column{width:100%}.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-content .welcome-panel-column ul{padding-right:10px}.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-iframe-video{float:left;width:50%}.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-iframe-video .welcome-panel-iframe-video-inner{position:relative;height:0;margin:0 10px 23px;padding-bottom:56.25%;border:5px solid #dadada}.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-iframe-video .welcome-panel-iframe-video-inner iframe{position:absolute;top:0;right:0;width:100%;height:100%}.appearance_page_demo-importer .demo-installer .premium-ribbon{position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden}.appearance_page_demo-importer .demo-installer .premium-ribbon span{color:#fff;display:block;text-transform:uppercase;border:1px solid #069c64;background-color:#24b37e;box-shadow:0 0 4px rgba(255,255,255,.5) inset,0 1px 3px rgba(0,0,0,.3);font-size:15px;font-weight:700;text-align:center;padding:5px 30px;-webkit-transform:rotate(-45deg);-ms-transform:rotate(-45deg);transform:rotate(-45deg);position:absolute;top:6px;left:-30px}table.plugins-list-table{margin-bottom:1em}table.plugins-list-table .plugin-status{text-align:center}table.plugins-list-table .plugin-status span{width:20px;height:20px;visibility:hidden;vertical-align:top;display:inline-block}table.plugins-list-table .plugin-status span::before{visibility:visible;display:inline-block;font:normal 20px/1 dashicons;-webkit-transition:color .1s ease-in 0;transition:color .1s ease-in 0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}table.plugins-list-table .plugin-status .active::before{color:#7ad03a;content:'\f147'}table.plugins-list-table .plugin-status .activate-now::before,table.plugins-list-table .plugin-status .install-now::before{color:#a00;content:'\f153'}table.plugins-list-table .plugin-status .activate-now::before{content:'\f534'}table.plugins-list-table .plugin-status .updating-message::before{color:#f56e28;content:'\f463';-webkit-animation:rotation 2s infinite linear;animation:rotation 2s infinite linear}table.plugins-list-table .plugin-actions .plugins-activate,table.plugins-list-table .plugin-actions .plugins-install{float:left;-webkit-transform:none;-ms-transform:none;transform:none}table.plugins-list-table .plugin-actions .plugins-install{margin-right:8px}.tips{cursor:help;text-decoration:none}img.tips{padding:5px 0 0}#tiptip_holder{display:none;z-index:8675309;position:absolute;top:0;left:0}#tiptip_holder.tip_top{padding-bottom:5px}#tiptip_holder.tip_top #tiptip_arrow_inner{margin-top:-7px;margin-right:-6px;border-top-color:#333}#tiptip_holder.tip_bottom{padding-top:5px}#tiptip_holder.tip_bottom #tiptip_arrow_inner{margin-top:-5px;margin-right:-6px;border-bottom-color:#333}#tiptip_holder.tip_right{padding-right:5px}#tiptip_holder.tip_right #tiptip_arrow_inner{margin-top:-6px;margin-right:-5px;border-left-color:#333}#tiptip_holder.tip_left{padding-left:5px}#tiptip_holder.tip_left #tiptip_arrow_inner{margin-top:-6px;margin-right:-7px;border-right-color:#333}#tiptip_content{color:#fff;font-size:.8em;max-width:150px;background:#333;text-align:center;border-radius:3px;padding:.618em 1em;box-shadow:0 1px 3px rgba(0,0,0,.2)}#tiptip_content code{padding:1px;background:#888}#tiptip_arrow,#tiptip_arrow_inner{position:absolute;border-color:transparent;border-style:solid;border-width:6px;height:0;width:0}#tiptip_arrow{right:50%;margin-right:-6px}@media screen and (max-width:500px){.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-content,.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-iframe-video{float:none;width:100%}}
1
+ @-webkit-keyframes spin{100%{-webkit-transform:rotate(-360deg);transform:rotate(-360deg)}}@keyframes spin{100%{-webkit-transform:rotate(-360deg);transform:rotate(-360deg)}}.appearance_page_demo-importer .demo-importer .wp-filter{padding:0 20px}.appearance_page_demo-importer .demo-importer .wp-filter .search-form{margin-right:1em}.appearance_page_demo-importer .demo-importer .wp-filter .filter-section{float:right}.appearance_page_demo-importer .demo-importer .wp-filter .filter-section.right{float:left}.appearance_page_demo-importer .demo-importer .wp-filter .filter-links li>a:focus{box-shadow:none}.appearance_page_demo-importer .demo-importer .theme-browser .theme .premium-demo-banner{position:absolute;top:15px;left:-16px;color:#fff;padding:0 20px;font-weight:600;min-height:30px;line-height:28px;background:#5fbd0a;text-transform:uppercase}.appearance_page_demo-importer .demo-importer .theme-browser .theme .premium-demo-banner::after,.appearance_page_demo-importer .demo-importer .theme-browser .theme .premium-demo-banner::before{content:'';position:absolute}.appearance_page_demo-importer .demo-importer .theme-browser .theme .premium-demo-banner::before{right:-15px;color:#fff;border:15px solid #5fbd0a;border-right-color:transparent}.appearance_page_demo-importer .demo-importer .theme-browser .theme .premium-demo-banner::after{top:30px;left:0;border:8px solid #478d07;border-left-color:transparent;border-bottom-color:transparent}.appearance_page_demo-importer .demo-importer .theme-browser .theme .theme-screenshot img{-o-object-fit:cover;object-fit:cover}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-header{background-color:#eee}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content{z-index:1;bottom:132px}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info .theme-version{margin-top:0}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info .theme-screenshot{width:100%;box-sizing:border-box}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info .premium-demo-tag{color:#fff;font-size:13px;font-weight:400;margin-right:5px;padding:0 10px;line-height:22px;border-radius:3px;background:#67c016;display:inline-block}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info table.plugins-list-table{margin-bottom:1em}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info table.plugins-list-table .plugin-status{float:left}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info table.plugins-list-table .plugin-status span{width:20px;height:20px;overflow:hidden;border-radius:50%;position:relative;vertical-align:top;white-space:nowrap;text-indent:-9999px;display:inline-block;border:2px solid #bfbfbf}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info table.plugins-list-table .plugin-status span.active{border-color:#5cb85c}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info table.plugins-list-table .plugin-status span.active::after{position:absolute;right:50%;top:50%;opacity:1;width:25%;height:50%;content:'';-webkit-transform-origin:right top;-ms-transform-origin:right top;transform-origin:right top;border-top:2px solid #5cb85c;border-left:2px solid #5cb85c;-webkit-transform:scaleX(-1) rotate(-135deg) translate(58%,-40%);-ms-transform:scaleX(-1) rotate(-135deg) translate(58%,-40%);transform:scaleX(-1) rotate(-135deg) translate(58%,-40%)}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info table.plugins-list-table .plugin-status span.updating-message{border-right-color:#5cb85c;-webkit-animation:spin .75s linear infinite;animation:spin .75s linear infinite}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer{height:132px}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .devices button:focus,.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .devices button:hover{background-color:transparent}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .demo-import-actions{padding:20px;background:#fff;border-bottom:1px solid #ddd}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .demo-import-actions .button{width:100%;text-align:center}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .demo-import-actions .button.installed::before,.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .demo-import-actions .button.installing::before,.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .demo-import-actions .button.updated-message::before,.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .demo-import-actions .button.updating-message::before{margin-left:6px;vertical-align:text-bottom}.appearance_page_demo-importer .demo-importer .theme-install-overlay.expanded .wp-full-overlay-footer{right:initial}.tips{cursor:help;text-decoration:none}img.tips{padding:5px 0 0}#tiptip_holder{display:none;z-index:8675309;position:absolute;top:0;left:0}#tiptip_holder.tip_top{padding-bottom:5px}#tiptip_holder.tip_top #tiptip_arrow_inner{margin-top:-7px;margin-right:-6px;border-top-color:#333}#tiptip_holder.tip_bottom{padding-top:5px}#tiptip_holder.tip_bottom #tiptip_arrow_inner{margin-top:-5px;margin-right:-6px;border-bottom-color:#333}#tiptip_holder.tip_right{padding-right:5px}#tiptip_holder.tip_right #tiptip_arrow_inner{margin-top:-6px;margin-right:-5px;border-left-color:#333}#tiptip_holder.tip_left{padding-left:5px}#tiptip_holder.tip_left #tiptip_arrow_inner{margin-top:-6px;margin-right:-7px;border-right-color:#333}#tiptip_content{color:#fff;font-size:.8em;max-width:150px;background:#333;text-align:center;border-radius:3px;padding:.618em 1em;box-shadow:0 1px 3px rgba(0,0,0,.2)}#tiptip_content code{padding:1px;background:#888}#tiptip_arrow,#tiptip_arrow_inner{position:absolute;border-color:transparent;border-style:solid;border-width:6px;height:0;width:0}#tiptip_arrow{right:50%;margin-right:-6px}
assets/css/demo-importer.css CHANGED
@@ -1 +1 @@
1
- .appearance_page_demo-importer .demo-importer h1{margin-bottom:15px}.appearance_page_demo-importer .demo-importer .search-form{display:inline}.appearance_page_demo-importer .demo-importer .wp-filter-search{position:relative;top:-2px;left:20px;margin:0;width:280px;font-size:16px;font-weight:300;line-height:1.5}.appearance_page_demo-importer .demo-installer .wp-filter{padding:0 20px}.appearance_page_demo-importer .demo-installer .wp-filter .filter-links li>a:focus{box-shadow:none}.appearance_page_demo-importer .demo-installer .welcome-panel{margin:0;background:#e9eff3;border:10px solid #fff;box-shadow:none}.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-content{width:45%;float:left}.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-content .welcome-panel-column{width:100%}.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-content .welcome-panel-column ul{padding-left:10px}.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-iframe-video{float:right;width:50%}.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-iframe-video .welcome-panel-iframe-video-inner{position:relative;height:0;margin:0 10px 23px;padding-bottom:56.25%;border:5px solid #dadada}.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-iframe-video .welcome-panel-iframe-video-inner iframe{position:absolute;top:0;left:0;width:100%;height:100%}.appearance_page_demo-importer .demo-installer .premium-ribbon{position:absolute;right:0;top:0;width:100%;height:100%;overflow:hidden}.appearance_page_demo-importer .demo-installer .premium-ribbon span{color:#fff;display:block;text-transform:uppercase;border:1px solid #069c64;background-color:#24b37e;box-shadow:0 0 4px rgba(255,255,255,.5) inset,0 1px 3px rgba(0,0,0,.3);font-size:15px;font-weight:700;text-align:center;padding:5px 30px;-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg);position:absolute;top:6px;right:-30px}table.plugins-list-table{margin-bottom:1em}table.plugins-list-table .plugin-status{text-align:center}table.plugins-list-table .plugin-status span{width:20px;height:20px;visibility:hidden;vertical-align:top;display:inline-block}table.plugins-list-table .plugin-status span::before{visibility:visible;display:inline-block;font:normal 20px/1 dashicons;-webkit-transition:color .1s ease-in 0;transition:color .1s ease-in 0;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}table.plugins-list-table .plugin-status .active::before{color:#7ad03a;content:'\f147'}table.plugins-list-table .plugin-status .activate-now::before,table.plugins-list-table .plugin-status .install-now::before{color:#a00;content:'\f153'}table.plugins-list-table .plugin-status .activate-now::before{content:'\f534'}table.plugins-list-table .plugin-status .updating-message::before{color:#f56e28;content:'\f463';-webkit-animation:rotation 2s infinite linear;animation:rotation 2s infinite linear}table.plugins-list-table .plugin-actions .plugins-activate,table.plugins-list-table .plugin-actions .plugins-install{float:right;-webkit-transform:none;-ms-transform:none;transform:none}table.plugins-list-table .plugin-actions .plugins-install{margin-left:8px}.tips{cursor:help;text-decoration:none}img.tips{padding:5px 0 0}#tiptip_holder{display:none;z-index:8675309;position:absolute;top:0;left:0}#tiptip_holder.tip_top{padding-bottom:5px}#tiptip_holder.tip_top #tiptip_arrow_inner{margin-top:-7px;margin-left:-6px;border-top-color:#333}#tiptip_holder.tip_bottom{padding-top:5px}#tiptip_holder.tip_bottom #tiptip_arrow_inner{margin-top:-5px;margin-left:-6px;border-bottom-color:#333}#tiptip_holder.tip_right{padding-left:5px}#tiptip_holder.tip_right #tiptip_arrow_inner{margin-top:-6px;margin-left:-5px;border-right-color:#333}#tiptip_holder.tip_left{padding-right:5px}#tiptip_holder.tip_left #tiptip_arrow_inner{margin-top:-6px;margin-left:-7px;border-left-color:#333}#tiptip_content{color:#fff;font-size:.8em;max-width:150px;background:#333;text-align:center;border-radius:3px;padding:.618em 1em;box-shadow:0 1px 3px rgba(0,0,0,.2)}#tiptip_content code{padding:1px;background:#888}#tiptip_arrow,#tiptip_arrow_inner{position:absolute;border-color:transparent;border-style:solid;border-width:6px;height:0;width:0}@media screen and (max-width:500px){.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-content,.appearance_page_demo-importer .demo-installer .welcome-panel .welcome-panel-iframe-video{float:none;width:100%}}
1
+ @-webkit-keyframes spin{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes spin{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.appearance_page_demo-importer .demo-importer .wp-filter{padding:0 20px}.appearance_page_demo-importer .demo-importer .wp-filter .search-form{margin-left:1em}.appearance_page_demo-importer .demo-importer .wp-filter .filter-section{float:left}.appearance_page_demo-importer .demo-importer .wp-filter .filter-section.right{float:right}.appearance_page_demo-importer .demo-importer .wp-filter .filter-links li>a:focus{box-shadow:none}.appearance_page_demo-importer .demo-importer .theme-browser .theme .premium-demo-banner{position:absolute;top:15px;right:-16px;color:#fff;padding:0 20px;font-weight:600;min-height:30px;line-height:28px;background:#5fbd0a;text-transform:uppercase}.appearance_page_demo-importer .demo-importer .theme-browser .theme .premium-demo-banner::after,.appearance_page_demo-importer .demo-importer .theme-browser .theme .premium-demo-banner::before{content:'';position:absolute}.appearance_page_demo-importer .demo-importer .theme-browser .theme .premium-demo-banner::before{left:-15px;color:#fff;border:15px solid #5fbd0a;border-left-color:transparent}.appearance_page_demo-importer .demo-importer .theme-browser .theme .premium-demo-banner::after{top:30px;right:0;border:8px solid #478d07;border-right-color:transparent;border-bottom-color:transparent}.appearance_page_demo-importer .demo-importer .theme-browser .theme .theme-screenshot img{-o-object-fit:cover;object-fit:cover}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-header{background-color:#eee}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content{z-index:1;bottom:132px}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info .theme-version{margin-top:0}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info .theme-screenshot{width:100%;box-sizing:border-box}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info .premium-demo-tag{color:#fff;font-size:13px;font-weight:400;margin-left:5px;padding:0 10px;line-height:22px;border-radius:3px;background:#67c016;display:inline-block}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info table.plugins-list-table{margin-bottom:1em}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info table.plugins-list-table .plugin-status{float:right}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info table.plugins-list-table .plugin-status span{width:20px;height:20px;overflow:hidden;border-radius:50%;position:relative;vertical-align:top;white-space:nowrap;text-indent:-9999px;display:inline-block;border:2px solid #bfbfbf}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info table.plugins-list-table .plugin-status span.active{border-color:#5cb85c}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info table.plugins-list-table .plugin-status span.active::after{position:absolute;left:50%;top:50%;opacity:1;width:25%;height:50%;content:'';-webkit-transform-origin:left top;-ms-transform-origin:left top;transform-origin:left top;border-top:2px solid #5cb85c;border-right:2px solid #5cb85c;-webkit-transform:scaleX(-1) rotate(135deg) translate(-58%,-40%);-ms-transform:scaleX(-1) rotate(135deg) translate(-58%,-40%);transform:scaleX(-1) rotate(135deg) translate(-58%,-40%)}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-sidebar-content .install-theme-info table.plugins-list-table .plugin-status span.updating-message{border-left-color:#5cb85c;-webkit-animation:spin .75s linear infinite;animation:spin .75s linear infinite}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer{height:132px}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .devices button:focus,.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .devices button:hover{background-color:transparent}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .demo-import-actions{padding:20px;background:#fff;border-bottom:1px solid #ddd}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .demo-import-actions .button{width:100%;text-align:center}.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .demo-import-actions .button.installed::before,.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .demo-import-actions .button.installing::before,.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .demo-import-actions .button.updated-message::before,.appearance_page_demo-importer .demo-importer .theme-install-overlay .wp-full-overlay-footer .demo-import-actions .button.updating-message::before{margin-right:6px;vertical-align:text-bottom}.appearance_page_demo-importer .demo-importer .theme-install-overlay.expanded .wp-full-overlay-footer{left:initial}.tips{cursor:help;text-decoration:none}img.tips{padding:5px 0 0}#tiptip_holder{display:none;z-index:8675309;position:absolute;top:0;left:0}#tiptip_holder.tip_top{padding-bottom:5px}#tiptip_holder.tip_top #tiptip_arrow_inner{margin-top:-7px;margin-left:-6px;border-top-color:#333}#tiptip_holder.tip_bottom{padding-top:5px}#tiptip_holder.tip_bottom #tiptip_arrow_inner{margin-top:-5px;margin-left:-6px;border-bottom-color:#333}#tiptip_holder.tip_right{padding-left:5px}#tiptip_holder.tip_right #tiptip_arrow_inner{margin-top:-6px;margin-left:-5px;border-right-color:#333}#tiptip_holder.tip_left{padding-right:5px}#tiptip_holder.tip_left #tiptip_arrow_inner{margin-top:-6px;margin-left:-7px;border-left-color:#333}#tiptip_content{color:#fff;font-size:.8em;max-width:150px;background:#333;text-align:center;border-radius:3px;padding:.618em 1em;box-shadow:0 1px 3px rgba(0,0,0,.2)}#tiptip_content code{padding:1px;background:#888}#tiptip_arrow,#tiptip_arrow_inner{position:absolute;border-color:transparent;border-style:solid;border-width:6px;height:0;width:0}
assets/css/demo-importer.scss CHANGED
@@ -4,170 +4,191 @@
4
*/
5
6
/**
7
- * Styling begins
8
*/
9
.appearance_page_demo-importer {
10
.demo-importer {
11
- h1 {
12
- margin-bottom: 15px;
13
- }
14
15
- .search-form {
16
- display: inline;
17
- }
18
19
- .wp-filter-search {
20
- position: relative;
21
- top: -2px;
22
- left: 20px;
23
- margin: 0;
24
- width: 280px;
25
- font-size: 16px;
26
- font-weight: 300;
27
- line-height: 1.5;
28
- }
29
- }
30
31
- .demo-installer {
32
- .wp-filter {
33
- padding: 0 20px;
34
35
.filter-links li > a:focus {
36
box-shadow: none;
37
}
38
}
39
40
- .welcome-panel {
41
- margin: 0;
42
- background: #e9eff3;
43
- border: 10px solid #fff;
44
- box-shadow: none;
45
-
46
- .welcome-panel-content {
47
- width: 45%;
48
- float: left;
49
50
- .welcome-panel-column {
51
- width: 100%;
52
53
- ul {
54
- padding-left: 10px;
55
}
56
}
57
}
58
59
- .welcome-panel-iframe-video {
60
- float: right;
61
- width: 50%;
62
63
- .welcome-panel-iframe-video-inner {
64
- position: relative;
65
- height: 0;
66
- margin: 0 10px 23px;
67
- padding-bottom: 56.25%; /* 16:9 */
68
- border: 5px solid #dadada;
69
70
- iframe {
71
- position: absolute;
72
- top: 0;
73
- left: 0;
74
width: 100%;
75
- height: 100%;
76
}
77
- }
78
- }
79
- }
80
81
- .premium-ribbon {
82
- position: absolute;
83
- right: 0;
84
- top: 0;
85
- width: 100%;
86
- height: 100%;
87
- overflow: hidden;
88
-
89
- span {
90
- color: #fff;
91
- display: block;
92
- text-transform: uppercase;
93
- border: 1px solid #069c64;
94
- background-color: #24b37e;
95
- box-shadow: 0 0 4px rgba( 255, 255, 255, 0.5 ) inset, 0 1px 3px rgba( 0, 0, 0, 0.3 );
96
- font-size: 15px;
97
- font-weight: 700;
98
- text-align: center;
99
- padding: 5px 30px;
100
- transform: rotate(45deg);
101
- position: absolute;
102
- top: 6px;
103
- right: -30px;
104
- }
105
- }
106
- }
107
- }
108
109
- table.plugins-list-table {
110
- margin-bottom: 1em;
111
-
112
- .plugin-status {
113
- text-align: center;
114
-
115
- span {
116
- width: 20px;
117
- height: 20px;
118
- visibility: hidden;
119
- vertical-align: top;
120
- display: inline-block;
121
-
122
- &::before {
123
- visibility: visible;
124
- display: inline-block;
125
- font: normal 20px/1 'dashicons';
126
- transition: color 0.1s ease-in 0;
127
- -webkit-font-smoothing: antialiased;
128
- -moz-osx-font-smoothing: grayscale;
129
}
130
- }
131
132
- .active {
133
- &::before {
134
- color: #7ad03a;
135
- content: '\f147';
136
- }
137
- }
138
139
- .install-now,
140
- .activate-now {
141
- &::before {
142
- color: #a00;
143
- content: '\f153';
144
- }
145
- }
146
147
- .activate-now {
148
- &::before {
149
- content: '\f534';
150
- }
151
- }
152
153
- .updating-message {
154
- &::before {
155
- color: #f56e28;
156
- content: '\f463';
157
- animation: rotation 2s infinite linear;
158
}
159
- }
160
- }
161
-
162
- .plugin-actions {
163
- .plugins-install,
164
- .plugins-activate {
165
- float: right;
166
- transform: none;
167
- }
168
169
- .plugins-install {
170
- margin-left: 8px;
171
}
172
}
173
}
@@ -265,20 +286,3 @@ img.tips {
265
margin-right: -6px;
266
}
267
*/
268
-
269
- /**
270
- * Optimisation for screens 500px and smaller
271
- */
272
- @media screen and (max-width: 500px) {
273
- .appearance_page_demo-importer {
274
- .demo-installer {
275
- .welcome-panel {
276
- .welcome-panel-content,
277
- .welcome-panel-iframe-video {
278
- float: none;
279
- width: 100%;
280
- }
281
- }
282
- }
283
- }
284
- }
4
*/
5
6
/**
7
+ * Import.
8
+ */
9
+ @import 'animation';
10
+
11
+ /**
12
+ * Styling begins.
13
*/
14
.appearance_page_demo-importer {
15
.demo-importer {
16
+ .wp-filter {
17
+ padding: 0 20px;
18
19
+ .search-form {
20
+ margin-left: 1em;
21
+ }
22
23
+ .filter-section {
24
+ float: left;
25
26
+ &.right {
27
+ float: right;
28
+ }
29
+ }
30
31
.filter-links li > a:focus {
32
box-shadow: none;
33
}
34
}
35
36
+ .theme-browser {
37
+ .theme {
38
+ .premium-demo-banner {
39
+ position: absolute;
40
+ top: 15px;
41
+ right: -16px;
42
+ color: #fff;
43
+ padding: 0 20px;
44
+ font-weight: 600;
45
+ min-height: 30px;
46
+ line-height: 28px;
47
+ background: #5fbd0a;
48
+ text-transform: uppercase;
49
+
50
+ &::before,
51
+ &::after {
52
+ content: '';
53
+ position: absolute;
54
+ }
55
56
+ &::before {
57
+ left: -15px;
58
+ color: #fff;
59
+ border: 15px solid #5fbd0a;
60
+ border-left-color: transparent;
61
+ }
62
63
+ &::after {
64
+ top: 30px;
65
+ right: 0;
66
+ border: 8px solid #478d07;
67
+ border-right-color: transparent;
68
+ border-bottom-color: transparent;
69
}
70
}
71
+
72
+ .theme-screenshot img {
73
+ object-fit: cover;
74
+ }
75
+ }
76
+ }
77
+
78
+ .theme-install-overlay {
79
+ .wp-full-overlay-header {
80
+ background-color: #eee;
81
}
82
83
+ .wp-full-overlay-sidebar-content {
84
+ z-index: 1;
85
+ bottom: 132px;
86
87
+ .install-theme-info {
88
+ .theme-version {
89
+ margin-top: 0;
90
+ }
91
92
+ .theme-screenshot {
93
width: 100%;
94
+ box-sizing: border-box;
95
}
96
97
+ .premium-demo-tag {
98
+ color: #fff;
99
+ font-size: 13px;
100
+ font-weight: 400;
101
+ margin-left: 5px;
102
+ padding: 0px 10px;
103
+ line-height: 22px;
104
+ border-radius: 3px;
105
+ background: #67c016;
106
+ display: inline-block;
107
+ }
108
109
+ table.plugins-list-table {
110
+ margin-bottom: 1em;
111
+
112
+ .plugin-status {
113
+ float: right;
114
+
115
+ span {
116
+ width: 20px;
117
+ height: 20px;
118
+ overflow: hidden;
119
+ border-radius: 50%;
120
+ position: relative;
121
+ vertical-align: top;
122
+ white-space: nowrap;
123
+ text-indent: -9999px;
124
+ display: inline-block;
125
+ border: 2px solid #bfbfbf;
126
+
127
+ &.active {
128
+ border-color: #5cb85c;
129
+
130
+ &::after {
131
+ position: absolute;
132
+ left: 50%;
133
+ top: 50%;
134
+ opacity: 1;
135
+ width: 25%;
136
+ height: 50%;
137
+ content: '';
138
+ transform-origin: left top;
139
+ border-top: 2px solid #5cb85c;
140
+ border-right: 2px solid #5cb85c;
141
+ transform: scaleX(-1) rotate(135deg) translate(-58%, -40%);
142
+ }
143
+ }
144
+
145
+ &.updating-message {
146
+ border-left-color: #5cb85c;
147
+ animation: spin .75s linear infinite;
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
153
}
154
155
+ .wp-full-overlay-footer {
156
+ height: 132px;
157
158
+ .devices button {
159
+ &:hover,
160
+ &:focus {
161
+ background-color: transparent;
162
+ }
163
+ }
164
165
+ .demo-import-actions {
166
+ padding: 20px;
167
+ background: #fff;
168
+ border-bottom: 1px solid #ddd;
169
170
+ .button {
171
+ width: 100%;
172
+ text-align: center;
173
+
174
+ &.installed,
175
+ &.installing,
176
+ &.updated-message,
177
+ &.updating-message {
178
+ &::before {
179
+ margin-right: 6px;
180
+ vertical-align: text-bottom;
181
+ }
182
+ }
183
+ }
184
+ }
185
}
186
187
+ &.expanded {
188
+ .wp-full-overlay-footer {
189
+ left: initial;
190
+ }
191
+ }
192
}
193
}
194
}
286
margin-right: -6px;
287
}
288
*/
assets/js/admin/demo-importer.js CHANGED
@@ -1,4 +1,4 @@
1
- /* global demoImporterLocalizeScript */
2
window.wp = window.wp || {};
3
4
( function( $ ) {
@@ -9,29 +9,21 @@ demos = wp.demos = wp.demos || {};
9
10
// Store the demo data and settings for organized and quick access
11
// demos.data.settings, demos.data.demos, demos.data.l10n
12
- demos.data = demoImporterLocalizeScript;
13
l10n = demos.data.l10n;
14
15
- // Shortcut for isPreview check
16
- demos.isPreview = !! demos.data.settings.isPreview;
17
-
18
- // Shortcut for isInstall check
19
- demos.isInstall = !! demos.data.settings.isInstall;
20
21
// Setup app structure
22
_.extend( demos, { model: {}, view: {}, routes: {}, router: {}, template: wp.template });
23
24
demos.Model = Backbone.Model.extend({
25
- // Adds attributes to the default data coming through the .org demos api
26
// Map `id` to `slug` for shared code
27
initialize: function() {
28
var description;
29
30
- // If demo is already installed, set an attribute.
31
- if ( _.indexOf( demos.data.installedDemos, this.get( 'slug' ) ) !== -1 ) {
32
- this.set({ installed: true });
33
- }
34
-
35
// Set the attributes
36
this.set({
37
// slug is for installation, id is for existing.
@@ -80,6 +72,8 @@ demos.view.Appearance = wp.Backbone.View.extend({
80
// Render search form.
81
this.search();
82
83
// Render and append
84
this.view.render();
85
this.$el.empty().append( this.view.el ).addClass( 'rendered' );
@@ -103,16 +97,20 @@ demos.view.Appearance = wp.Backbone.View.extend({
103
collection: self.collection,
104
parent: this
105
});
106
107
// Render and append after screen title
108
view.render();
109
this.searchContainer
110
.append( $.parseHTML( '<label class="screen-reader-text" for="wp-filter-search-input">' + l10n.search + '</label>' ) )
111
- .append( view.el );
112
},
113
114
// Checks when the user gets close to the bottom
115
- // of the mage and triggers a demo:scroll event
116
scroller: function() {
117
var self = this,
118
bottom, threshold;
@@ -122,15 +120,8 @@ demos.view.Appearance = wp.Backbone.View.extend({
122
threshold = Math.round( threshold * 0.9 );
123
124
if ( bottom > threshold ) {
125
- this.trigger( 'demo:scroll' );
126
}
127
- },
128
-
129
- // Remove any lingering tooltips and initialize TipTip
130
- initTipTip: function() {
131
- $( '#tiptip_holder' ).removeAttr( 'style' );
132
- $( '#tiptip_arrow' ).removeAttr( 'style' );
133
- $( '.tips' ).tipTip({ 'attribute': 'data-tip', 'fadeIn': 50, 'fadeOut': 50, 'delay': 50 });
134
}
135
});
136
@@ -224,7 +215,135 @@ demos.Collection = Backbone.Collection.extend({
224
collection = _( collection.first( 20 ) );
225
226
return collection;
227
- }
228
});
229
230
// This is the view that controls each demo item
@@ -239,12 +358,12 @@ demos.view.Demo = wp.Backbone.View.extend({
239
state: 'grid',
240
241
// The HTML template for each element to be rendered
242
- html: demos.template( demos.isPreview ? 'demo-preview' : 'demo' ),
243
244
events: {
245
- 'click': 'expand',
246
- 'keydown': 'expand',
247
- 'touchend': 'expand',
248
'keyup': 'addFocus',
249
'touchmove': 'preventExpand',
250
'click .demo-import': 'importDemo'
@@ -290,47 +409,150 @@ demos.view.Demo = wp.Backbone.View.extend({
290
$demoToFocus.addClass('focus');
291
},
292
293
- // Single theme overlay screen
294
- // It's shown when clicking a theme
295
- expand: function( event ) {
296
- var self = this;
297
298
- // Prevent the modal.
299
- if ( demos.isPreview ) {
300
- return;
301
- }
302
303
event = event || window.event;
304
305
- // 'enter' and 'space' keys expand the details view when a theme is :focused
306
- if ( event.type === 'keydown' && ( event.which !== 13 && event.which !== 32 ) ) {
307
- return;
308
- }
309
-
310
// Bail if the user scrolled on a touch device
311
if ( this.touchDrag === true ) {
312
return this.touchDrag = false;
313
}
314
315
- // Prevent the modal from showing when the user clicks
316
- // one of the direct action buttons
317
- if ( $( event.target ).is( '.theme-actions a' ) ) {
318
return;
319
}
320
321
- // Prevent the modal from showing when the user clicks one of the direct action buttons.
322
- if ( $( event.target ).is( '.theme-actions a, .update-message, .button-link, .notice-dismiss' ) ) {
323
return;
324
}
325
326
- // Set focused demo to current element
327
demos.focusedDemo = this.$el;
328
329
- this.trigger( 'demo:expand', self.model.cid );
330
},
331
332
- preventExpand: function() {
333
- this.touchDrag = true;
334
},
335
336
importDemo: function( event ) {
@@ -342,11 +564,12 @@ demos.view.Demo = wp.Backbone.View.extend({
342
return;
343
}
344
345
- // Confirmation dialog for importing a demo.
346
if ( ! window.confirm( wp.demos.data.settings.confirmImport ) ) {
347
return;
348
}
349
350
$( document ).on( 'wp-demo-import-success', function( event, response ) {
351
if ( _this.model.get( 'id' ) === response.slug ) {
352
_this.model.set( { 'imported': true } );
@@ -359,139 +582,142 @@ demos.view.Demo = wp.Backbone.View.extend({
359
}
360
});
361
362
- // Demo Details view
363
// Set ups a modal overlay with the expanded demo data
364
- demos.view.Details = wp.Backbone.View.extend({
365
366
- // Wrap theme data on a div.theme element
367
- className: 'theme-overlay',
368
369
events: {
370
- 'click': 'collapse',
371
- 'click .delete-demo': 'deleteDemo',
372
- 'click .left': 'previousDemo',
373
- 'click .right': 'nextDemo',
374
'click .demo-import': 'importDemo',
375
- 'click .plugins-install': 'installPlugin'
376
},
377
378
- // The HTML template for the theme overlay
379
- html: demos.template( 'demo-single' ),
380
381
render: function() {
382
- var data = this.model.toJSON();
383
- this.$el.html( this.html( data ) );
384
- // Renders active theme styles
385
- this.activeDemo();
386
- // Set up navigation events
387
- this.navigation();
388
- // Checks screenshot size
389
- this.screenshotCheck( this.$el );
390
- // Contain "tabbing" inside the overlay
391
- this.containFocus( this.$el );
392
},
393
394
- // Adds a class to the currently active theme
395
- // and to the overlay in detailed view mode
396
- activeDemo: function() {
397
- // Check the model has the active property
398
- this.$el.toggleClass( 'active', this.model.get( 'active' ) );
399
},
400
401
- // Set initial focus and constrain tabbing within the theme browser modal.
402
- containFocus: function( $el ) {
403
-
404
- // Set initial focus on the primary action control.
405
- _.delay( function() {
406
- $( '.theme-wrap a.button-primary:visible' ).focus();
407
- }, 100 );
408
-
409
- // Constrain tabbing within the modal.
410
- $el.on( 'keydown.wp-themes', function( event ) {
411
- var $firstFocusable = $el.find( '.theme-header button:not(.disabled)' ).first(),
412
- $lastFocusable = $el.find( '.theme-actions a:visible' ).last();
413
-
414
- // Check for the Tab key.
415
- if ( 9 === event.which ) {
416
- if ( $firstFocusable[0] === event.target && event.shiftKey ) {
417
- $lastFocusable.focus();
418
- event.preventDefault();
419
- } else if ( $lastFocusable[0] === event.target && ! event.shiftKey ) {
420
- $firstFocusable.focus();
421
- event.preventDefault();
422
- }
423
}
424
- });
425
},
426
427
- // Single demo overlay screen
428
- // It's shown when clicking a demo
429
collapse: function( event ) {
430
- var self = this,
431
- scroll;
432
-
433
- event = event || window.event;
434
-
435
- // Prevent collapsing detailed view when there is only one demo available
436
- if ( demos.data.demos.length === 1 ) {
437
- return;
438
}
439
440
- // Detect if the click is inside the overlay
441
- // and don't close it unless the target was
442
- // the div.back button
443
- if ( $( event.target ).is( '.theme-backdrop' ) || $( event.target ).is( '.close' ) || event.keyCode === 27 ) {
444
445
- // Add a temporary closing class while overlay fades out
446
- $( 'body' ).addClass( 'closing-overlay' );
447
448
- // With a quick fade out animation
449
- this.$el.fadeOut( 130, function() {
450
- // Clicking outside the modal box closes the overlay
451
- $( 'body' ).removeClass( 'closing-overlay' );
452
- // Handle event cleanup
453
- self.closeOverlay();
454
455
- // Get scroll position to avoid jumping to the top
456
- scroll = document.body.scrollTop;
457
458
- // Clean the url structure
459
- demos.router.navigate( demos.router.baseUrl( '' ) );
460
461
- // Restore scroll position
462
- document.body.scrollTop = scroll;
463
464
- // Return focus to the demo div
465
- if ( demos.focusedDemo ) {
466
- demos.focusedDemo.focus();
467
- }
468
- });
469
- }
470
},
471
472
- // Handles .disabled classes for next/previous buttons
473
- navigation: function() {
474
-
475
- // Disable Left/Right when at the start or end of the collection
476
- if ( this.model.cid === this.model.collection.at(0).cid ) {
477
- this.$el.find( '.left' )
478
- .addClass( 'disabled' )
479
- .prop( 'disabled', true );
480
}
481
- if ( this.model.cid === this.model.collection.at( this.model.collection.length - 1 ).cid ) {
482
- this.$el.find( '.right' )
483
- .addClass( 'disabled' )
484
- .prop( 'disabled', true );
485
}
486
},
487
488
- // Performs the actions to effectively close
489
- // the demo details overlay
490
- closeOverlay: function() {
491
- $( 'body' ).removeClass( 'modal-open' );
492
- this.remove();
493
- this.unbind();
494
- this.trigger( 'demo:collapse' );
495
},
496
497
importDemo: function( event ) {
@@ -499,36 +725,34 @@ demos.view.Details = wp.Backbone.View.extend({
499
$target = $( event.target );
500
event.preventDefault();
501
502
- if ( $target.hasClass( 'disabled' ) ) {
503
return;
504
}
505
506
- // Confirmation dialog for importing a demo.
507
if ( ! window.confirm( wp.demos.data.settings.confirmImport ) ) {
508
return;
509
}
510
511
$( document ).on( 'wp-demo-import-success', function( event, response ) {
512
if ( _this.model.get( 'id' ) === response.slug ) {
513
_this.model.set( { 'imported': true } );
514
}
515
} );
516
517
- // Handle a demo queue job.
518
- $( document ).on( 'wp-updates-queue-job', function( event, job ) {
519
- if ( 'import-demo' === job.action ) {
520
- wp.updates.importDemo( job.data );
521
- }
522
- } );
523
-
524
wp.updates.importDemo( {
525
slug: $target.data( 'slug' )
526
} );
527
},
528
529
- installPlugin: function( event ) {
530
- var itemsSelected = $( document ).find( 'input[name="required[]"], input[name="checked[]"]:checked' ),
531
- $target = $( event.target ),
532
success = 0,
533
error = 0,
534
errorMessages = [];
@@ -539,55 +763,41 @@ demos.view.Details = wp.Backbone.View.extend({
539
return;
540
}
541
542
- // Remove previous error messages, if any.
543
- $( '.theme-info .update-message' ).remove();
544
-
545
- // Bail if there were no items selected.
546
- if ( ! itemsSelected.length ) {
547
- event.preventDefault();
548
- $( '.theme-about' ).animate( { scrollTop: 0 } );
549
- $( '.theme-info .plugins-info' ).after( wp.updates.adminNotice( {
550
- id: 'no-items-selected',
551
- className: 'update-message notice-error notice-alt',
552
- message: wp.updates.l10n.noItemsSelected
553
- } ) );
554
- }
555
556
- wp.updates.maybeRequestFilesystemCredentials( event );
557
558
- // Confirmation dialog for installing bulk plugins.
559
- if ( ! window.confirm( wp.demos.data.settings.confirmInstall ) ) {
560
- return;
561
- }
562
563
- // Un-check the bulk checkboxes.
564
- $( document ).find( '.manage-column [type="checkbox"]' ).prop( 'checked', false );
565
566
- $( document ).trigger( 'wp-plugin-bulk-install', itemsSelected );
567
568
- // Find all the checkboxes which have been checked.
569
- itemsSelected.each( function( index, element ) {
570
- var $checkbox = $( element ),
571
- $itemRow = $checkbox.parents( 'tr' );
572
573
- // Only add install-able items to the update queue.
574
- if ( ! $itemRow.hasClass( 'install' ) || $itemRow.find( 'notice-error' ).length ) {
575
576
- // Un-check the box.
577
- $checkbox.filter( ':not(:disabled)' ).prop( 'checked', false );
578
return;
579
- } else {
580
- $target
581
- .addClass( 'updating-message' )
582
- .text( wp.updates.l10n.installing );
583
-
584
- wp.a11y.speak( wp.updates.l10n.installingMsg, 'polite' );
585
}
586
587
// Add it to the queue.
588
wp.updates.queue.push( {
589
action: 'install-plugin',
590
data: {
591
slug: $itemRow.data( 'slug' )
592
}
593
} );
@@ -607,14 +817,12 @@ demos.view.Details = wp.Backbone.View.extend({
607
errorMessages.push( itemName + ': ' + response.errorMessage );
608
}
609
610
- $itemRow.find( 'input[name="checked[]"]:checked' ).filter( ':not(:disabled)' ).prop( 'checked', false );
611
-
612
wp.updates.adminNotice = wp.template( 'wp-bulk-installs-admin-notice' );
613
614
// Remove previous error messages, if any.
615
- $( '.theme-info .bulk-action-notice' ).remove();
616
617
- $( '.theme-info .plugins-info' ).after( wp.updates.adminNotice( {
618
id: 'bulk-action-notice',
619
className: 'bulk-action-notice notice-alt',
620
successes: success,
@@ -635,20 +843,14 @@ demos.view.Details = wp.Backbone.View.extend({
635
if ( ! wp.updates.queue.length ) {
636
if ( error > 0 ) {
637
$target
638
- .removeClass( 'updating-message' ).addClass( 'disabled' )
639
- .text( wp.updates.l10n.installFailedShort );
640
-
641
- wp.a11y.speak( wp.updates.l10n.installedMsg, 'polite' );
642
-
643
- $( '.theme-about' ).animate( { scrollTop: 0 } );
644
} else {
645
- $target
646
- .removeClass( 'updating-message' ).addClass( 'disabled' )
647
- .text( wp.updates.l10n.pluginInstalled );
648
-
649
- wp.a11y.speak( wp.updates.l10n.installedMsg, 'polite' );
650
651
- $( '.plugins-activate' ).removeAttr( 'disabled' );
652
}
653
}
654
} );
@@ -660,64 +862,6 @@ demos.view.Details = wp.Backbone.View.extend({
660
661
// Check the queue, now that the event handlers have been added.
662
wp.updates.queueChecker();
663
- },
664
-
665
- deleteDemo: function( event ) {
666
- var _this = this,
667
- _collection = this.model.collection,
668
- _demos = demos;
669
- event.preventDefault();
670
-
671
- // Confirmation dialog for deleting a demo.
672
- if ( ! window.confirm( wp.demos.data.settings.confirmDelete ) ) {
673
- return;
674
- }
675
-
676
- wp.updates.maybeRequestFilesystemCredentials( event );
677
-
678
- $( document ).one( 'wp-demo-delete-success', function( event, response ) {
679
- _this.$el.find( '.close' ).trigger( 'click' );
680
- $( '[data-slug="' + response.slug + '"' ).css( { backgroundColor:'#faafaa' } ).fadeOut( 350, function() {
681
- $( this ).remove();
682
- _demos.data.demos = _.without( _demos.data.demos, _.findWhere( _demos.data.demos, { id: response.slug } ) );
683
-
684
- $( '.wp-filter-search' ).val( '' );
685
- _collection.doSearch( '' );
686
- _collection.remove( _this.model );
687
- _collection.trigger( 'demos:update' );
688
- } );
689
- } );
690
-
691
- wp.updates.deleteDemo( {
692
- slug: this.model.get( 'id' )
693
- } );
694
- },
695
-
696
- nextDemo: function() {
697
- var self = this;
698
- self.trigger( 'demo:next', self.model.cid );
699
- return false;
700
- },
701
-
702
- previousDemo: function() {
703
- var self = this;
704
- self.trigger( 'demo:previous', self.model.cid );
705
- return false;
706
- },
707
-
708
- // Checks if the theme screenshot is the old 300px width version
709
- // and adds a corresponding class if it's true
710
- screenshotCheck: function( el ) {
711
- var screenshot, image;
712
-
713
- screenshot = el.find( '.screenshot img' );
714
- image = new Image();
715
- image.src = screenshot.attr( 'src' );
716
-
717
- // Width check
718
- if ( image.width && image.width <= 300 ) {
719
- el.addClass( 'small-screenshot' );
720
- }
721
}
722
});
723
@@ -744,18 +888,17 @@ demos.view.Demos = wp.Backbone.View.extend({
744
// Set up parent
745
this.parent = options.parent;
746
747
- // Move the imported demo to the beginning of the collection
748
- self.importedDemo();
749
-
750
// Set current view to [grid]
751
this.setView( 'grid' );
752
753
// When the collection is updated by user input...
754
this.listenTo( self.collection, 'demos:update', function() {
755
self.parent.page = 0;
756
self.importedDemo();
757
self.render( this );
758
- self.parent.initTipTip();
759
} );
760
761
// Update demo count to full result set when available.
@@ -776,39 +919,6 @@ demos.view.Demos = wp.Backbone.View.extend({
776
this.listenTo( this.parent, 'demo:scroll', function() {
777
self.renderDemos( self.parent.page );
778
});
779
-
780
- this.listenTo( this.parent, 'demo:close', function() {
781
- if ( self.overlay ) {
782
- self.overlay.closeOverlay();
783
- }
784
- } );
785
-
786
- // Bind keyboard events.
787
- $( 'body' ).on( 'keyup', function( event ) {
788
- if ( ! self.overlay ) {
789
- return;
790
- }
791
-
792
- // Bail if the filesystem credentials dialog is shown.
793
- if ( $( '#request-filesystem-credentials-dialog' ).is( ':visible' ) ) {
794
- return;
795
- }
796
-
797
- // Pressing the right arrow key fires a demo:next event
798
- if ( event.keyCode === 39 ) {
799
- self.overlay.nextDemo();
800
- }
801
-
802
- // Pressing the left arrow key fires a demo:previous event
803
- if ( event.keyCode === 37 ) {
804
- self.overlay.previousDemo();
805
- }
806
-
807
- // Pressing the escape key fires a demo:collapse event
808
- if ( event.keyCode === 27 ) {
809
- self.overlay.collapse( event );
810
- }
811
- });
812
},
813
814
// Manages rendering of demo pages
@@ -817,22 +927,6 @@ demos.view.Demos = wp.Backbone.View.extend({
817
// Clear the DOM, please
818
this.$el.empty();
819
820
- // If the user doesn't have switch capabilities
821
- // or there is only one demo in the collection
822
- // render the detailed view of the active demo
823
- if ( ! demos.isPreview && demos.data.demos.length === 1 ) {
824
-
825
- // Constructs the view
826
- this.singleDemo = new demos.view.Details({
827
- model: this.collection.models[0]
828
- });
829
-
830
- // Render and apply a 'single-theme' class to our container
831
- this.singleDemo.render();
832
- this.$el.addClass( 'single-theme' );
833
- this.$el.append( this.singleDemo.el );
834
- }
835
-
836
// Generate the demos
837
// Using page instance
838
// While checking the collection has items
@@ -846,7 +940,7 @@ demos.view.Demos = wp.Backbone.View.extend({
846
},
847
848
// Iterates through each instance of the collection
849
- // and renders each theme module
850
renderDemos: function( page ) {
851
var self = this;
852
@@ -859,6 +953,11 @@ demos.view.Demos = wp.Backbone.View.extend({
859
return;
860
}
861
862
// Loop through the demos and setup each demo view
863
self.instance.each( function( demo ) {
864
self.demo = new demos.view.Demo({
@@ -870,15 +969,11 @@ demos.view.Demos = wp.Backbone.View.extend({
870
self.demo.render();
871
// and append them to div.themes
872
self.$el.append( self.demo.el );
873
-
874
- // Binds to demo:expand to show the modal box
875
- // with the demo details
876
- self.listenTo( self.demo, 'demo:expand', self.expand, self );
877
});
878
879
- // 'Add new demo' element shown at the end of the grid
880
- if ( ! demos.isPreview && demos.isInstall && demos.data.settings.canInstall ) {
881
- this.$el.append( '<div class="theme add-new-theme"><a href="' + demos.data.settings.installURI + '"><div class="theme-screenshot"><span></span></div><h2 class="theme-name">' + l10n.addNew + '</h2></a></div>' );
882
}
883
884
this.parent.page++;
@@ -903,108 +998,6 @@ demos.view.Demos = wp.Backbone.View.extend({
903
return view;
904
},
905
906
- // Renders the overlay with the DemoDetails view
907
- // Uses the current model data
908
- expand: function( id ) {
909
- var self = this, $card, $modal;
910
-
911
- // Set the current demo model
912
- this.model = self.collection.get( id );
913
-
914
- // Trigger a route update for the current model
915
- demos.router.navigate( demos.router.baseUrl( demos.router.demoPath + this.model.id ) );
916
-
917
- // Sets this.view to 'detail'
918
- this.setView( 'detail' );
919
- $( 'body' ).addClass( 'modal-open' );
920
-
921
- // Set up the demo details view
922
- this.overlay = new demos.view.Details({
923
- model: self.model
924
- });
925
-
926
- this.overlay.render();
927
-
928
- if ( this.model.get( 'hasUpdate' ) ) {
929
- $card = $( '[data-slug="' + this.model.id + '"]' );
930
- $modal = $( this.overlay.el );
931
-
932
- if ( $card.find( '.updating-message' ).length ) {
933
- $modal.find( '.notice-warning h3' ).remove();
934
- $modal.find( '.notice-warning' )
935
- .removeClass( 'notice-large' )
936
- .addClass( 'updating-message' )
937
- .find( 'p' ).text( wp.updates.l10n.updating );
938
- } else if ( $card.find( '.notice-error' ).length ) {
939
- $modal.find( '.notice-warning' ).remove();
940
- }
941
- }
942
-
943
- this.$overlay.html( this.overlay.el );
944
-
945
- // Bind to demo:next and demo:previous
946
- // triggered by the arrow keys
947
- //
948
- // Keep track of the current model so we
949
- // can infer an index position
950
- this.listenTo( this.overlay, 'demo:next', function() {
951
- // Renders the next demo on the overlay
952
- self.next( [ self.model.cid ] );
953
-
954
- })
955
- .listenTo( this.overlay, 'demo:previous', function() {
956
- // Renders the previous demo on the overlay
957
- self.previous( [ self.model.cid ] );
958
- });
959
- },
960
-
961
- // This method renders the next demo on the overlay modal
962
- // based on the current position in the collection
963
- // @params [model cid]
964
- next: function( args ) {
965
- var self = this,
966
- model, nextModel;
967
-
968
- // Get the current demo
969
- model = self.collection.get( args[0] );
970
- // Find the next model within the collection
971
- nextModel = self.collection.at( self.collection.indexOf( model ) + 1 );
972
-
973
- // Sanity check which also serves as a boundary test
974
- if ( nextModel !== undefined ) {
975
-
976
- // We have a new demo...
977
- // Close the overlay
978
- this.overlay.closeOverlay();
979
-
980
- // Trigger a route update for the current model
981
- self.demo.trigger( 'demo:expand', nextModel.cid );
982
- }
983
- },
984
-
985
- // This method renders the previous demo on the overlay modal
986
- // based on the current position in the collection
987
- // @params [model cid]
988
- previous: function( args ) {
989
- var self = this,
990
- model, previousModel;
991
-
992
- // Get the current demo
993
- model = self.collection.get( args[0] );
994
- // Find the previous model within the collection
995
- previousModel = self.collection.at( self.collection.indexOf( model ) - 1 );
996
-
997
- if ( previousModel !== undefined ) {
998
-
999
- // We have a new demo...
1000
- // Close the overlay
1001
- this.overlay.closeOverlay();
1002
-
1003
- // Trigger a route update for the current model
1004
- self.demo.trigger( 'demo:expand', previousModel.cid );
1005
- }
1006
- },
1007
-
1008
// Dispatch audible search results feedback message
1009
announceSearchResults: function( count ) {
1010
if ( 0 === count ) {
@@ -1050,17 +1043,15 @@ demos.view.Search = wp.Backbone.View.extend({
1050
event.target.value = '';
1051
}
1052
1053
- /**
1054
- * Since doSearch is debounced, it will only run when user input comes to a rest
1055
- */
1056
this.doSearch( event );
1057
},
1058
1059
// Runs a search on the demo collection.
1060
- doSearch: _.debounce( function( event ) {
1061
var options = {};
1062
1063
- this.collection.doSearch( event.target.value );
1064
1065
// if search is initiated and key is not return
1066
if ( this.searching && event.which !== 13 ) {
@@ -1075,13 +1066,13 @@ demos.view.Search = wp.Backbone.View.extend({
1075
} else {
1076
demos.router.navigate( demos.router.baseUrl( '' ) );
1077
}
1078
- }, 500 ),
1079
1080
pushState: function( event ) {
1081
var url = demos.router.baseUrl( '' );
1082
1083
if ( event.target.value ) {
1084
- url = demos.router.baseUrl( demos.router.searchPath + event.target.value );
1085
}
1086
1087
this.searching = false;
@@ -1089,16 +1080,31 @@ demos.view.Search = wp.Backbone.View.extend({
1089
}
1090
});
1091
1092
// Sets up the routes events for relevant url queries
1093
// Listens to [demo] and [search] params
1094
demos.Router = Backbone.Router.extend({
1095
1096
routes: {
1097
- 'themes.php?page=demo-importer&demo=:slug': 'demo',
1098
'themes.php?page=demo-importer&search=:query': 'search',
1099
- 'themes.php?page=demo-importer&s=:query': 'search',
1100
- 'themes.php?page=demo-importer': 'demos',
1101
- '': 'demos'
1102
},
1103
1104
baseUrl: function( url ) {
@@ -1106,182 +1112,222 @@ demos.Router = Backbone.Router.extend({
1106
},
1107
1108
demoPath: '&demo=',
1109
searchPath: '&search=',
1110
1111
search: function( query ) {
1112
- $( '.wp-filter-search' ).val( query );
1113
- },
1114
-
1115
- demos: function() {
1116
- $( '.wp-filter-search' ).val( '' );
1117
},
1118
1119
- navigate: function() {
1120
- if ( Backbone.history._hasPushState ) {
1121
- Backbone.Router.prototype.navigate.apply( this, arguments );
1122
- }
1123
- }
1124
});
1125
1126
- // Execute and setup the application
1127
- demos.Run = {
1128
- init: function() {
1129
- // Initializes the blog's demo library view
1130
- // Create a new collection with data
1131
- this.demos = new demos.Collection( demos.data.demos );
1132
-
1133
- // Set up the view
1134
- this.view = new demos.view.Appearance({
1135
- collection: this.demos
1136
- });
1137
1138
- this.render();
1139
},
1140
1141
- render: function() {
1142
1143
- // Render results
1144
- this.view.render();
1145
- this.view.initTipTip();
1146
- this.routes();
1147
1148
- Backbone.history.start({
1149
- root: demos.data.settings.adminUrl,
1150
- pushState: true,
1151
- hashChange: false
1152
- });
1153
},
1154
1155
- routes: function() {
1156
- var self = this;
1157
- // Bind to our global thx object
1158
- // so that the object is available to sub-views
1159
- demos.router = new demos.Router();
1160
1161
- // Handles demo details route event
1162
- demos.router.on( 'route:demo', function( slug ) {
1163
- self.view.view.expand( slug );
1164
- });
1165
1166
- demos.router.on( 'route:demos', function() {
1167
- self.demos.doSearch( '' );
1168
- self.view.trigger( 'demo:close' );
1169
- });
1170
1171
- // Handles search route event
1172
- demos.router.on( 'route:search', function() {
1173
- $( '.wp-filter-search' ).trigger( 'keyup' );
1174
- });
1175
1176
- this.extraRoutes();
1177
- },
1178
1179
- extraRoutes: function() {
1180
- return false;
1181
}
1182
- };
1183
1184
demos.view.Installer = demos.view.Appearance.extend({
1185
1186
el: '#wpbody-content .wrap',
1187
1188
// Initial render method
1189
render: function() {
1190
this.search();
1191
- this.uploader();
1192
1193
- // Setup the main demo view
1194
- // with the current demo collection
1195
this.view = new demos.view.Demos({
1196
collection: this.collection,
1197
parent: this
1198
});
1199
1200
// Render and append
1201
this.$el.find( '.themes' ).remove();
1202
this.view.render();
1203
this.$el.find( '.theme-browser' ).append( this.view.el ).addClass( 'rendered' );
1204
},
1205
1206
- /*
1207
- * When users press the "Upload Theme" button, show the upload form in place.
1208
- */
1209
- uploader: function() {
1210
- var uploadViewToggle = $( '.upload-view-toggle' ),
1211
- $body = $( document.body );
1212
-
1213
- uploadViewToggle.on( 'click', function() {
1214
- // Toggle the upload view.
1215
- $body.toggleClass( 'show-upload-view' );
1216
- // Toggle the `aria-expanded` button attribute.
1217
- uploadViewToggle.attr( 'aria-expanded', $body.hasClass( 'show-upload-view' ) );
1218
- });
1219
},
1220
1221
- clearSearch: function() {
1222
- $( '#wp-filter-search-input').val( '' );
1223
- }
1224
- });
1225
1226
- demos.InstallerRouter = Backbone.Router.extend({
1227
1228
- routes: {
1229
- 'themes.php?page=demo-importer&browse=uploads&demo=:slug': 'demo',
1230
- 'themes.php?page=demo-importer&browse=:sort&search=:query': 'search',
1231
- 'themes.php?page=demo-importer&browse=:sort&s=:query': 'search',
1232
- 'themes.php?page=demo-importer&browse=welcome': 'sort',
1233
- 'themes.php?page=demo-importer&browse=:sort': 'demos',
1234
- 'themes.php?page=demo-importer': 'sort'
1235
- },
1236
1237
- browse: function() {
1238
- return demos.isPreview ? 'preview' : 'uploads';
1239
- },
1240
1241
- baseUrl: function( url ) {
1242
- return 'themes.php?page=demo-importer&browse=' + this.browse() + url;
1243
},
1244
1245
- demoPath: '&demo=',
1246
- searchPath: '&search=',
1247
1248
- search: function( sort, query ) {
1249
- $( '.wp-filter-search' ).val( query );
1250
- },
1251
1252
- demos: function() {
1253
- $( '.wp-filter-search' ).val( '' );
1254
},
1255
1256
- navigate: function() {
1257
- if ( Backbone.history._hasPushState ) {
1258
- Backbone.Router.prototype.navigate.apply( this, arguments );
1259
- }
1260
}
1261
});
1262
1263
demos.RunInstaller = {
1264
1265
init: function() {
1266
- // Initializes the blog's demo library view
1267
- // Create a new collection with data
1268
- this.demos = new demos.Collection( demos.data.demos );
1269
-
1270
// Set up the view
1271
this.view = new demos.view.Installer({
1272
- collection: this.demos
1273
});
1274
1275
this.render();
1276
},
1277
1278
render: function() {
1279
1280
// Render results
1281
this.view.render();
1282
- this.view.initTipTip();
1283
this.routes();
1284
1285
Backbone.history.start({
1286
root: demos.data.settings.adminUrl,
1287
pushState: true,
@@ -1290,27 +1336,57 @@ demos.RunInstaller = {
1290
},
1291
1292
routes: function() {
1293
- var self = this;
1294
- // Bind to our global thx object
1295
// so that the object is available to sub-views
1296
- demos.router = new demos.InstallerRouter();
1297
1298
- // Handles demo details route event
1299
- demos.router.on( 'route:demo', function( slug ) {
1300
- self.view.view.expand( slug );
1301
- });
1302
1303
- demos.router.on( 'route:demos', function() {
1304
- self.demos.doSearch( '' );
1305
- self.view.trigger( 'demo:close' );
1306
});
1307
1308
// Handles sorting / browsing routes
1309
// Also handles the root URL triggering a sort request
1310
- // for `welcome`, the default view
1311
demos.router.on( 'route:sort', function( sort ) {
1312
- if ( ! sort || 'welcome' === sort ) {
1313
- $( '.wp-filter-search' ).hide();
1314
}
1315
});
1316
@@ -1329,29 +1405,21 @@ demos.RunInstaller = {
1329
1330
// Ready...
1331
$( document ).ready( function() {
1332
- if ( demos.isInstall ) {
1333
- demos.RunInstaller.init();
1334
- } else {
1335
- demos.Run.init();
1336
- }
1337
1338
- // Load videos when help button is clicked or welcome page is viewed.
1339
- $( document.body ).on( 'themegrill_demo_importer_guided_tour_embed', function() {
1340
- $( '.themegrill-demo-importer-guided-tour-embed' ).each( function() {
1341
- var video_id = $( this ).data( 'video_id' );
1342
- $( this ).replaceWith( '<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/' + video_id + '" frameborder="0" allowfullscreen></iframe>' );
1343
- } );
1344
- } );
1345
1346
- if ( demos.isInstall ) {
1347
- $( document.body ).trigger( 'themegrill_demo_importer_guided_tour_embed' );
1348
- } else {
1349
- $( '#contextual-help-link' ).on( 'click', function() {
1350
- $( document.body ).trigger( 'themegrill_demo_importer_guided_tour_embed' );
1351
- } );
1352
- }
1353
1354
- // Rating footer.
1355
$( '.themegrill-demo-importer-rating-link' ).on( 'click', function() {
1356
var $this_el = $( this );
1357
@@ -1361,35 +1429,6 @@ $( document ).ready( function() {
1361
1362
$this_el.parent().text( $this_el.data( 'rated' ) );
1363
} );
1364
-
1365
- // Confirm WordPress reset wizard.
1366
- $( '.themegrill-reset-wordpress' ).on( 'click', function() {
1367
- return window.confirm( demos.data.settings.confirmReset );
1368
- });
1369
-
1370
- // Make disabled checkbox always checked through data-checked.
1371
- $( document.body ).on( 'click', 'thead .check-column :checkbox', function( event ) {
1372
- var $this = $( this ),
1373
- $table = $this.closest( 'table' ),
1374
- controlChecked = $this.prop( 'checked' ),
1375
- toggle = event.shiftKey || $this.data( 'wp-toggle' );
1376
-
1377
- $table.children( 'tbody' ).filter( ':visible' )
1378
- .children().children( '.check-column' ).find( ':checkbox' )
1379
- .prop( 'checked', function() {
1380
- if ( $( this ).is( ':hidden,:disabled' ) ) {
1381
- return $( this ).data( 'checked' ) ? true : false;
1382
- }
1383
-
1384
- if ( toggle ) {
1385
- return ! $( this ).prop( 'checked' );
1386
- } else if ( controlChecked ) {
1387
- return true;
1388
- }
1389
-
1390
- return false;
1391
- });
1392
- });
1393
});
1394
1395
})( jQuery );
1
+ /* global _demoImporterSettings */
2
window.wp = window.wp || {};
3
4
( function( $ ) {
9
10
// Store the demo data and settings for organized and quick access
11
// demos.data.settings, demos.data.demos, demos.data.l10n
12
+ demos.data = _demoImporterSettings;
13
l10n = demos.data.l10n;
14
15
+ // Shortcut for isNew check
16
+ demos.isNew = !! demos.data.settings.isNew;
17
18
// Setup app structure
19
_.extend( demos, { model: {}, view: {}, routes: {}, router: {}, template: wp.template });
20
21
demos.Model = Backbone.Model.extend({
22
+ // Adds attributes to the default data coming through the demos api
23
// Map `id` to `slug` for shared code
24
initialize: function() {
25
var description;
26
27
// Set the attributes
28
this.set({
29
// slug is for installation, id is for existing.
72
// Render search form.
73
this.search();
74
75
+ this.$el.removeClass( 'search-loading' );
76
+
77
// Render and append
78
this.view.render();
79
this.$el.empty().append( this.view.el ).addClass( 'rendered' );
97
collection: self.collection,
98
parent: this
99
});
100
+ self.SearchView = view;
101
102
// Render and append after screen title
103
view.render();
104
this.searchContainer
105
.append( $.parseHTML( '<label class="screen-reader-text" for="wp-filter-search-input">' + l10n.search + '</label>' ) )
106
+ .append( view.el )
107
+ .on( 'submit', function( event ) {
108
+ event.preventDefault();
109
+ });
110
},
111
112
// Checks when the user gets close to the bottom
113
+ // of the page and triggers a demo:scroll event
114
scroller: function() {
115
var self = this,
116
bottom, threshold;
120
threshold = Math.round( threshold * 0.9 );
121
122
if ( bottom > threshold ) {
123
+ // this.trigger( 'demo:scroll' );
124
}
125
}
126
});
127
215
collection = _( collection.first( 20 ) );
216
217
return collection;
218
+ },
219
+
220
+ count: false,
221
+
222
+ // Handles requests for more demos
223
+ // and caches results
224
+ //
225
+ // When we are missing a cache object we fire an apiCall()
226
+ // which triggers events of `query:success` or `query:fail`
227
+ query: function( request ) {
228
+ /**
229
+ * @static
230
+ * @type Array
231
+ */
232
+ var queries = this.queries,
233
+ self = this,
234
+ query, isPaginated, count;
235
+
236
+ // Store current query request args
237
+ // for later use with the event `demo:end`
238
+ this.currentQuery.request = request;
239
+
240
+ // Search the query cache for matches.
241
+ query = _.find( queries, function( query ) {
242
+ return _.isEqual( query.request, request );
243
+ });
244
+
245
+ // If the request matches the stored currentQuery.request
246
+ // it means we have a paginated request.
247
+ isPaginated = _.has( request, 'page' );
248
+
249
+ // Reset the internal api page counter for non paginated queries.
250
+ if ( ! isPaginated ) {
251
+ this.currentQuery.page = 1;
252
+ }
253
+
254
+ // Otherwise, send a new API call and add it to the cache.
255
+ if ( ! query && ! isPaginated ) {
256
+ query = this.apiCall( request ).done( function( data ) {
257
+
258
+ // Update the collection with the queried data.
259
+ if ( data.demos ) {
260
+ self.reset( data.demos );
261
+ count = data.info.results;
262
+ // Store the results and the query request
263
+ queries.push( { demos: data.demos, request: request, total: count } );
264
+ }
265
+
266
+ // Trigger a collection refresh event
267
+ // and a `query:success` event with a `count` argument.
268
+ self.trigger( 'demos:update' );
269
+ self.trigger( 'query:success', count );
270
+
271
+ if ( data.demos && data.demos.length === 0 ) {
272
+ self.trigger( 'query:empty' );
273
+ }
274
+
275
+ }).fail( function() {
276
+ self.trigger( 'query:fail' );
277
+ });
278
+ } else {
279
+ // If it's a paginated request we need to fetch more demos...
280
+ if ( isPaginated ) {
281
+ return this.apiCall( request, isPaginated ).done( function( data ) {
282
+ // Add the new demos to the current collection
283
+ // @todo update counter
284
+ self.add( data.demos );
285
+ self.trigger( 'query:success' );
286
+
287
+ // We are done loading demos for now.
288
+ self.loadingDemos = false;
289
+
290
+ }).fail( function() {
291
+ self.trigger( 'query:fail' );
292
+ });
293
+ }
294
+
295
+ if ( query.demos.length === 0 ) {
296
+ self.trigger( 'query:empty' );
297
+ } else {
298
+ $( 'body' ).removeClass( 'no-results' );
299
+ }
300
+
301
+ // Only trigger an update event since we already have the demos
302
+ // on our cached object
303
+ if ( _.isNumber( query.total ) ) {
304
+ this.count = query.total;
305
+ }
306
+
307
+ this.reset( query.demos );
308
+ if ( ! query.total ) {
309
+ this.count = this.length;
310
+ }
311
+
312
+ this.trigger( 'demos:update' );
313
+ this.trigger( 'query:success', this.count );
314
+ }
315
+ },
316
+
317
+ // Local cache array for API queries
318
+ queries: [],
319
+
320
+ // Keep track of current query so we can handle pagination
321
+ currentQuery: {
322
+ page: 1,
323
+ request: {}
324
+ },
325
+
326
+ // Send request to api.github.com/repos/themegrill-demo-pack
327
+ apiCall: function( request, paginated ) {
328
+ return wp.ajax.send( 'query-demos', {
329
+ data: {
330
+ // Request data
331
+ request: _.extend({
332
+ per_page: 100
333
+ }, request )
334
+ },
335
+
336
+ beforeSend: function() {
337
+ if ( ! paginated ) {
338
+ // Spin it
339
+ $( 'body' ).addClass( 'loading-content' ).removeClass( 'no-results' );
340
+ }
341
+ }
342
+ });
343
+ },
344
+
345
+ // Static status controller for when we are loading demos.
346
+ loadingDemos: false
347
});
348
349
// This is the view that controls each demo item
358
state: 'grid',
359
360
// The HTML template for each element to be rendered
361
+ html: demos.template( 'demo' ),
362
363
events: {
364
+ 'click': 'preview',
365
+ 'keydown': 'preview',
366
+ 'touchend': 'preview',
367
'keyup': 'addFocus',
368
'touchmove': 'preventExpand',
369
'click .demo-import': 'importDemo'
409
$demoToFocus.addClass('focus');
410
},
411
412
+ preventExpand: function() {
413
+ this.touchDrag = true;
414
+ },
415
416
+ preview: function( event ) {
417
+ var self = this,
418
+ current, preview;
419
420
event = event || window.event;
421
422
// Bail if the user scrolled on a touch device
423
if ( this.touchDrag === true ) {
424
return this.touchDrag = false;
425
}
426
427
+ // Allow direct link path to installing a demo.
428
+ if ( $( event.target ).not( '.install-demo-preview' ).parents( '.theme-actions' ).length ) {
429
+ return;
430
+ }
431
+
432
+ // 'enter' and 'space' keys expand the details view when a demo is :focused
433
+ if ( event.type === 'keydown' && ( event.which !== 13 && event.which !== 32 ) ) {
434
return;
435
}
436
437
+ // pressing enter while focused on the buttons shouldn't open the preview
438
+ if ( event.type === 'keydown' && event.which !== 13 && $( ':focus' ).hasClass( 'button' ) ) {
439
return;
440
}
441
442
+ event.preventDefault();
443
+
444
+ event = event || window.event;
445
+
446
+ // Set focus to current demo.
447
demos.focusedDemo = this.$el;
448
449
+ // Construct a new Preview view.
450
+ demos.preview = preview = new demos.view.Preview({
451
+ model: this.model
452
+ });
453
+
454
+ // Render the view and append it.
455
+ preview.render();
456
+ this.setNavButtonsState();
457
+
458
+ // Hide previous/next navigation if there is only one demo
459
+ if ( this.model.collection.length === 1 ) {
460
+ preview.$el.addClass( 'no-navigation' );
461
+ } else {
462
+ preview.$el.removeClass( 'no-navigation' );
463
+ }
464
+
465
+ // Append preview
466
+ $( 'div.wrap' ).append( preview.el );
467
+
468
+ // Listen to our preview object
469
+ // for `demo:next` and `demo:previous` events.
470
+ this.listenTo( preview, 'demo:next', function() {
471
+
472
+ // Keep local track of current demo model.
473
+ current = self.model;
474
+
475
+ // If we have ventured away from current model update the current model position.
476
+ if ( ! _.isUndefined( self.current ) ) {
477
+ current = self.current;
478
+ }
479
+
480
+ // Get next demo model.
481
+ self.current = self.model.collection.at( self.model.collection.indexOf( current ) + 1 );
482
+
483
+ // If we have no more themes, bail.
484
+ if ( _.isUndefined( self.current ) ) {
485
+ self.options.parent.parent.trigger( 'demo:end' );
486
+ return self.current = current;
487
+ }
488
+
489
+ preview.model = self.current;
490
+
491
+ // Render and append.
492
+ preview.render();
493
+ this.setNavButtonsState();
494
+ $( '.next-theme' ).focus();
495
+ })
496
+ .listenTo( preview, 'demo:previous', function() {
497
+
498
+ // Keep track of current demo model.
499
+ current = self.model;
500
+
501
+ // Bail early if we are at the beginning of the collection
502
+ if ( self.model.collection.indexOf( self.current ) === 0 ) {
503
+ return;
504
+ }
505
+
506
+ // If we have ventured away from current model update the current model position.
507
+ if ( ! _.isUndefined( self.current ) ) {
508
+ current = self.current;
509
+ }
510
+
511
+ // Get previous theme model.
512
+ self.current = self.model.collection.at( self.model.collection.indexOf( current ) - 1 );
513
+
514
+ // If we have no more themes, bail.
515
+ if ( _.isUndefined( self.current ) ) {
516
+ return;
517
+ }
518
+
519
+ preview.model = self.current;
520
+
521
+ // Render and append.
522
+ preview.render();
523
+ this.setNavButtonsState();
524
+ $( '.previous-theme' ).focus();
525
+ });
526
+
527
+ this.listenTo( preview, 'preview:close', function() {
528
+ self.current = self.model;
529
+ });
530
},
531
532
+ // Handles .disabled classes for previous/next buttons in demo installer preview
533
+ setNavButtonsState: function() {
534
+ var $demoInstaller = $( '.theme-install-overlay' ),
535
+ current = _.isUndefined( this.current ) ? this.model : this.current,
536
+ previousDemoButton = $demoInstaller.find( '.previous-theme' ),
537
+ nextDemoButton = $demoInstaller.find( '.next-theme' );
538
+
539
+ // Disable previous at the zero position
540
+ if ( 0 === this.model.collection.indexOf( current ) ) {
541
+ previousDemoButton
542
+ .addClass( 'disabled' )
543
+ .prop( 'disabled', true );
544
+
545
+ nextDemoButton.focus();
546
+ }
547
+
548
+ // Disable next if the next model is undefined
549
+ if ( _.isUndefined( this.model.collection.at( this.model.collection.indexOf( current ) + 1 ) ) ) {
550
+ nextDemoButton
551
+ .addClass( 'disabled' )
552
+ .prop( 'disabled', true );
553
+
554
+ previousDemoButton.focus();
555
+ }
556
},
557
558
importDemo: function( event ) {
564
return;
565
}
566
567
if ( ! window.confirm( wp.demos.data.settings.confirmImport ) ) {
568
return;
569
}
570
571
+ wp.updates.maybeRequestFilesystemCredentials( event );
572
+
573
$( document ).on( 'wp-demo-import-success', function( event, response ) {
574
if ( _this.model.get( 'id' ) === response.slug ) {
575
_this.model.set( { 'imported': true } );
582
}
583
});
584
585
+ // Theme Preview view
586
// Set ups a modal overlay with the expanded demo data
587
+ demos.view.Preview = wp.Backbone.View.extend({
588
589
+ className: 'wp-full-overlay expanded',
590
+ el: '.theme-install-overlay',
591
592
events: {
593
+ 'click .close-full-overlay': 'close',
594
+ 'click .collapse-sidebar': 'collapse',
595
+ 'click .devices button': 'previewDevice',
596
+ 'click .previous-theme': 'previousDemo',
597
+ 'click .next-theme': 'nextDemo',
598
+ 'keyup': 'keyEvent',
599
'click .demo-import': 'importDemo',
600
+ 'click .plugins-install': 'installPlugins'
601
},
602
603
+ // The HTML template for the demo preview
604
+ html: demos.template( 'demo-preview' ),
605
606
render: function() {
607
+ var self = this,
608
+ currentPreviewDevice,
609
+ data = this.model.toJSON(),
610
+ $body = $( document.body );
611
+
612
+ $body.attr( 'aria-busy', 'true' );
613
+
614
+ this.$el.removeClass( 'iframe-ready' ).html( this.html( data ) );
615
+
616
+ currentPreviewDevice = this.$el.data( 'current-preview-device' );
617
+ if ( currentPreviewDevice ) {
618
+ self.tooglePreviewDeviceButtons( currentPreviewDevice );
619
+ }
620
+
621
+ demos.router.navigate( demos.router.baseUrl( demos.router.demoPath + this.model.get( 'id' ) ), { replace: false } );
622
+
623
+ this.$el.fadeIn( 200, function() {
624
+ $body.addClass( 'demo-importer-active full-overlay-active' );
625
+ });
626
+
627
+ this.$el.find( 'iframe' ).one( 'load', function() {
628
+ self.iframeLoaded();
629
+ });
630
},
631
632
+ iframeLoaded: function() {
633
+ this.$el.addClass( 'iframe-ready' );
634
+ $( document.body ).attr( 'aria-busy', 'false' );
635
},
636
637
+ close: function() {
638
+ this.$el.fadeOut( 200, function() {
639
+ $( 'body' ).removeClass( 'demo-importer-active full-overlay-active' );
640
+
641
+ // Return focus to the demo div
642
+ if ( demos.focusedDemo ) {
643
+ demos.focusedDemo.focus();
644
}
645
+ }).removeClass( 'iframe-ready' );
646
+
647
+ // Restore the previous browse tab if available.
648
+ if ( demos.router.selectedTab ) {
649
+ demos.router.navigate( demos.router.baseUrl( '&browse=' + demos.router.selectedTab ) );
650
+ } else {
651
+ demos.router.navigate( demos.router.baseUrl( '' ) );
652
+ }
653
+ this.trigger( 'preview:close' );
654
+ this.undelegateEvents();
655
+ this.unbind();
656
+ return false;
657
},
658
659
collapse: function( event ) {
660
+ var $button = $( event.currentTarget );
661
+ if ( 'true' === $button.attr( 'aria-expanded' ) ) {
662
+ $button.attr({ 'aria-expanded': 'false', 'aria-label': l10n.expandSidebar });
663
+ } else {
664
+ $button.attr({ 'aria-expanded': 'true', 'aria-label': l10n.collapseSidebar });
665
}
666
667
+ this.$el.toggleClass( 'collapsed' ).toggleClass( 'expanded' );
668
+ return false;
669
+ },
670
671
+ previewDevice: function( event ) {
672
+ var device = $( event.currentTarget ).data( 'device' );
673
674
+ this.$el
675
+ .removeClass( 'preview-desktop preview-tablet preview-mobile' )
676
+ .addClass( 'preview-' + device )
677
+ .data( 'current-preview-device', device );
678
679
+ this.tooglePreviewDeviceButtons( device );
680
+ },
681
682
+ tooglePreviewDeviceButtons: function( newDevice ) {
683
+ var $devices = $( '.wp-full-overlay-footer .devices' );
684
685
+ $devices.find( 'button' )
686
+ .removeClass( 'active' )
687
+ .attr( 'aria-pressed', false );
688
689
+ $devices.find( 'button.preview-' + newDevice )
690
+ .addClass( 'active' )
691
+ .attr( 'aria-pressed', true );
692
},
693
694
+ keyEvent: function( event ) {
695
+ // The escape key closes the preview
696
+ if ( event.keyCode === 27 ) {
697
+ this.undelegateEvents();
698
+ this.close();
699
}
700
+ // The right arrow key, next demo
701
+ if ( event.keyCode === 39 ) {
702
+ _.once( this.nextDemo() );
703
+ }
704
+
705
+ // The left arrow key, previous demo
706
+ if ( event.keyCode === 37 ) {
707
+ this.previousDemo();
708
}
709
},
710
711
+ nextDemo: function() {
712
+ var self = this;
713
+ self.trigger( 'demo:next', self.model.cid );
714
+ return false;
715
+ },
716
+
717
+ previousDemo: function() {
718
+ var self = this;
719
+ self.trigger( 'demo:previous', self.model.cid );
720
+ return false;
721
},
722
723
importDemo: function( event ) {
725
$target = $( event.target );
726
event.preventDefault();
727
728
+ if ( $target.hasClass( 'disabled' ) || $target.hasClass( 'updating-message' ) ) {
729
return;
730
}
731
732
if ( ! window.confirm( wp.demos.data.settings.confirmImport ) ) {
733
return;
734
}
735
736
+ wp.updates.maybeRequestFilesystemCredentials( event );
737
+
738
+ // Disable the next and previous demo.
739
+ $( '.theme-install-overlay' ).find( '.next-theme, .previous-theme' ).addClass( 'disabled' );
740
+
741
$( document ).on( 'wp-demo-import-success', function( event, response ) {
742
if ( _this.model.get( 'id' ) === response.slug ) {
743
_this.model.set( { 'imported': true } );
744
}
745
} );
746
747
wp.updates.importDemo( {
748
slug: $target.data( 'slug' )
749
} );
750
},
751
752
+ installPlugins: function( event ) {
753
+ var _this = this,
754
+ pluginsList = $( '.plugins-list-table' ).find( '#the-list tr' ),
755
+ $target = $( '.plugins-install' ),
756
success = 0,
757
error = 0,
758
errorMessages = [];
763
return;
764
}
765
766
+ // Bail if there were required plugins.
767
+ if ( pluginsList.length ) {
768
+ $( '.wp-full-overlay-sidebar-content' ).animate( { scrollTop: $( document ).height() } );
769
770
+ if ( $target.html() !== wp.updates.l10n.installing ) {
771
+ $target.data( 'originaltext', $target.html() );
772
+ }
773
774
+ $target
775
+ .addClass( 'updating-message' )
776
+ .text( wp.updates.l10n.installing );
777
+ wp.a11y.speak( wp.updates.l10n.installingMsg, 'polite' );
778
779
+ // Disable the next and previous demo.
780
+ $( '.theme-install-overlay' ).find( '.next-theme, .previous-theme' ).addClass( 'disabled' );
781
+ }
782
783
+ wp.updates.maybeRequestFilesystemCredentials( event );
784
785
+ $( document ).trigger( 'wp-plugin-bulk-install', pluginsList );
786
787
+ // Find all the plugins which are required.
788
+ pluginsList.each( function( index, element ) {
789
+ var $itemRow = $( element );
790
791
+ // Only add inactive items to the update queue.
792
+ if ( ! $itemRow.hasClass( 'inactive' ) || $itemRow.find( 'notice-error' ).length ) {
793
return;
794
}
795
796
// Add it to the queue.
797
wp.updates.queue.push( {
798
action: 'install-plugin',
799
data: {
800
+ plugin: $itemRow.data( 'plugin' ),
801
slug: $itemRow.data( 'slug' )
802
}
803
} );
817
errorMessages.push( itemName + ': ' + response.errorMessage );
818
}
819
820
wp.updates.adminNotice = wp.template( 'wp-bulk-installs-admin-notice' );
821
822
// Remove previous error messages, if any.
823
+ $( '.plugins-details .bulk-action-notice' ).remove();
824
825
+ $( '.plugins-details .plugins-info' ).after( wp.updates.adminNotice( {
826
id: 'bulk-action-notice',
827
className: 'bulk-action-notice notice-alt',
828
successes: success,
843
if ( ! wp.updates.queue.length ) {
844
if ( error > 0 ) {
845
$target
846
+ .removeClass( 'updating-message' )
847
+ .text( $target.data( 'originaltext' ) );
848
} else {
849
+ _this.model.set( { requiredPlugins: false } );
850
+ _this.render();
851
852
+ // Disable the next and previous demo.
853
+ $( '.theme-install-overlay' ).find( '.next-theme, .previous-theme' ).addClass( 'disabled' );
854
}
855
}
856
} );
862
863
// Check the queue, now that the event handlers have been added.
864
wp.updates.queueChecker();
865
}
866
});
867
888
// Set up parent
889
this.parent = options.parent;
890
891
// Set current view to [grid]
892
this.setView( 'grid' );
893
894
+ // Move the imported demo to the beginning of the collection
895
+ self.importedDemo();
896
+
897
// When the collection is updated by user input...
898
this.listenTo( self.collection, 'demos:update', function() {
899
self.parent.page = 0;
900
self.importedDemo();
901
self.render( this );
902
} );
903
904
// Update demo count to full result set when available.
919
this.listenTo( this.parent, 'demo:scroll', function() {
920
self.renderDemos( self.parent.page );
921
});
922
},
923
924
// Manages rendering of demo pages
927
// Clear the DOM, please
928
this.$el.empty();
929
930
// Generate the demos
931
// Using page instance
932
// While checking the collection has items
940
},
941
942
// Iterates through each instance of the collection
943
+ // and renders each demo module
944
renderDemos: function( page ) {
945
var self = this;
946
953
return;
954
}
955
956
+ // Make sure the add-new stays at the end
957
+ if ( demos.isNew && page >= 1 ) {
958
+ $( '.add-new-theme' ).remove();
959
+ }
960
+
961
// Loop through the demos and setup each demo view
962
self.instance.each( function( demo ) {
963
self.demo = new demos.view.Demo({
969
self.demo.render();
970
// and append them to div.themes
971
self.$el.append( self.demo.el );
972
});
973
974
+ // 'Suggest us!' element shown at the end of the grid
975
+ if ( demos.isNew && demos.data.settings.suggestURI ) {
976
+ this.$el.append( '<div class="theme add-new-theme"><a href="' + demos.data.settings.suggestURI + '" target="blank"><div class="theme-screenshot"><span></span></div><h2 class="theme-name">' + l10n.suggestNew + '</h2></a></div>' );
977
}
978
979
this.parent.page++;
998
return view;
999
},
1000
1001
// Dispatch audible search results feedback message
1002
announceSearchResults: function( count ) {
1003
if ( 0 === count ) {
1043
event.target.value = '';
1044
}
1045
1046
+ // Since doSearch is debounced, it will only run when user input comes to a rest.
1047
this.doSearch( event );
1048
},
1049
1050
// Runs a search on the demo collection.
1051
+ doSearch: function( event ) {
1052
var options = {};
1053
1054
+ this.collection.doSearch( event.target.value.replace( /\+/g, ' ' ) );
1055
1056
// if search is initiated and key is not return
1057
if ( this.searching && event.which !== 13 ) {
1066
} else {
1067
demos.router.navigate( demos.router.baseUrl( '' ) );
1068
}
1069
+ },
1070
1071
pushState: function( event ) {
1072
var url = demos.router.baseUrl( '' );
1073
1074
if ( event.target.value ) {
1075
+ url = demos.router.baseUrl( demos.router.searchPath + encodeURIComponent( event.target.value ) );
1076
}
1077
1078
this.searching = false;
1080
}
1081
});
1082
1083
+ /**
1084
+ * Navigate router.
1085
+ *
1086
+ * @since 1.5.0
1087
+ *
1088
+ * @param {string} url - URL to navigate to.
1089
+ * @param {object} state - State.
1090
+ * @returns {void}
1091
+ */
1092
+ function navigateRouter( url, state ) {
1093
+ var router = this;
1094
+ if ( Backbone.history._hasPushState ) {
1095
+ Backbone.Router.prototype.navigate.call( router, url, state );
1096
+ }
1097
+ }
1098
+
1099
// Sets up the routes events for relevant url queries
1100
// Listens to [demo] and [search] params
1101
demos.Router = Backbone.Router.extend({
1102
1103
routes: {
1104
+ 'themes.php?page=demo-importer&demo=:slug': 'preview',
1105
+ 'themes.php?page=demo-importer&browse=:sort': 'sort',
1106
'themes.php?page=demo-importer&search=:query': 'search',