├── docs ├── .nojekyll ├── favicon.ico ├── images │ ├── profile_icon.png │ ├── icons │ │ ├── icon-72x72.png │ │ ├── icon-96x96.png │ │ ├── icon-128x128.png │ │ ├── icon-144x144.png │ │ ├── icon-152x152.png │ │ ├── icon-192x192.png │ │ ├── icon-384x384.png │ │ ├── icon-512x512.png │ │ └── desktop │ │ │ ├── favicon.ico │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── apple-touch-icon.png │ │ │ ├── mstile-150x150.png │ │ │ ├── android-chrome-192x192.png │ │ │ └── android-chrome-512x512.png │ ├── lighthouse-report.png │ ├── image_place_holder_576x324.svg │ └── image_place_holder_640x480.svg ├── robots.txt ├── humans.txt ├── browserconfig.xml ├── 404.html ├── offline.html ├── manifest.json ├── index.js ├── index.html ├── sw.js └── js │ └── zuix.min.js ├── source ├── .nojekyll ├── favicon.ico ├── images │ ├── profile_icon.png │ ├── icons │ │ ├── icon-128x128.png │ │ ├── icon-144x144.png │ │ ├── icon-152x152.png │ │ ├── icon-192x192.png │ │ ├── icon-384x384.png │ │ ├── icon-512x512.png │ │ ├── icon-72x72.png │ │ ├── icon-96x96.png │ │ └── desktop │ │ │ ├── favicon.ico │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── mstile-150x150.png │ │ │ ├── apple-touch-icon.png │ │ │ ├── android-chrome-192x192.png │ │ │ └── android-chrome-512x512.png │ └── lighthouse-report.png ├── robots.txt ├── pages │ ├── home │ │ ├── items_list.html │ │ ├── items_list │ │ │ ├── item_mini.css │ │ │ ├── item.css │ │ │ ├── item.js │ │ │ ├── item.html │ │ │ ├── item_mini.html │ │ │ └── item_mini.js │ │ ├── items_list.css │ │ └── items_list.js │ ├── search.html │ ├── notifications.html │ ├── home.css │ ├── search.css │ ├── notifications.css │ ├── about.css │ ├── about.html │ └── home.html ├── shared │ ├── input_box.html │ ├── input_box.js │ ├── main_menu.html │ ├── main_menu.css │ └── input_box.css ├── humans.txt ├── service-worker.js ├── browserconfig.xml ├── layout │ ├── footer.html │ ├── header.html │ ├── footer.css │ └── header.css ├── index.css ├── 404.html ├── offline.html ├── manifest.json ├── index.js ├── index.html ├── sw.js └── js │ ├── zuix-bundler.min.js │ ├── zuix-bundler.min.js.map │ ├── zuix-bundler.js │ └── zuix.min.js ├── .gitignore ├── package.json ├── LICENSE └── README.md /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | /node_modules 3 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/favicon.ico -------------------------------------------------------------------------------- /source/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/favicon.ico -------------------------------------------------------------------------------- /docs/images/profile_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/profile_icon.png -------------------------------------------------------------------------------- /docs/robots.txt: -------------------------------------------------------------------------------- 1 | # www.robotstxt.org/ 2 | 3 | # Allow crawling of all content 4 | User-agent: * 5 | Disallow: 6 | -------------------------------------------------------------------------------- /source/images/profile_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/profile_icon.png -------------------------------------------------------------------------------- /source/robots.txt: -------------------------------------------------------------------------------- 1 | # www.robotstxt.org/ 2 | 3 | # Allow crawling of all content 4 | User-agent: * 5 | Disallow: 6 | -------------------------------------------------------------------------------- /docs/images/icons/icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/icon-72x72.png -------------------------------------------------------------------------------- /docs/images/icons/icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/icon-96x96.png -------------------------------------------------------------------------------- /docs/images/lighthouse-report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/lighthouse-report.png -------------------------------------------------------------------------------- /docs/images/icons/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/icon-128x128.png -------------------------------------------------------------------------------- /docs/images/icons/icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/icon-144x144.png -------------------------------------------------------------------------------- /docs/images/icons/icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/icon-152x152.png -------------------------------------------------------------------------------- /docs/images/icons/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/icon-192x192.png -------------------------------------------------------------------------------- /docs/images/icons/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/icon-384x384.png -------------------------------------------------------------------------------- /docs/images/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/icon-512x512.png -------------------------------------------------------------------------------- /source/images/icons/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/icon-128x128.png -------------------------------------------------------------------------------- /source/images/icons/icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/icon-144x144.png -------------------------------------------------------------------------------- /source/images/icons/icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/icon-152x152.png -------------------------------------------------------------------------------- /source/images/icons/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/icon-192x192.png -------------------------------------------------------------------------------- /source/images/icons/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/icon-384x384.png -------------------------------------------------------------------------------- /source/images/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/icon-512x512.png -------------------------------------------------------------------------------- /source/images/icons/icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/icon-72x72.png -------------------------------------------------------------------------------- /source/images/icons/icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/icon-96x96.png -------------------------------------------------------------------------------- /source/images/lighthouse-report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/lighthouse-report.png -------------------------------------------------------------------------------- /docs/images/icons/desktop/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/desktop/favicon.ico -------------------------------------------------------------------------------- /source/images/icons/desktop/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/desktop/favicon.ico -------------------------------------------------------------------------------- /docs/images/icons/desktop/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/desktop/favicon-16x16.png -------------------------------------------------------------------------------- /docs/images/icons/desktop/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/desktop/favicon-32x32.png -------------------------------------------------------------------------------- /source/pages/home/items_list.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /docs/images/icons/desktop/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/desktop/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/images/icons/desktop/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/desktop/mstile-150x150.png -------------------------------------------------------------------------------- /source/images/icons/desktop/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/desktop/favicon-16x16.png -------------------------------------------------------------------------------- /source/images/icons/desktop/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/desktop/favicon-32x32.png -------------------------------------------------------------------------------- /source/images/icons/desktop/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/desktop/mstile-150x150.png -------------------------------------------------------------------------------- /source/shared/input_box.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /source/images/icons/desktop/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/desktop/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/images/icons/desktop/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/desktop/android-chrome-192x192.png -------------------------------------------------------------------------------- /docs/images/icons/desktop/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/docs/images/icons/desktop/android-chrome-512x512.png -------------------------------------------------------------------------------- /source/images/icons/desktop/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/desktop/android-chrome-192x192.png -------------------------------------------------------------------------------- /source/images/icons/desktop/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zuixjs/zuix-html-pwa/HEAD/source/images/icons/desktop/android-chrome-512x512.png -------------------------------------------------------------------------------- /source/pages/search.html: -------------------------------------------------------------------------------- 1 |
2 |
Search
search 3 |
4 | -------------------------------------------------------------------------------- /source/shared/input_box.js: -------------------------------------------------------------------------------- 1 | /* global zuix */ 2 | 'use strict'; 3 | zuix.controller(function(cp){ 4 | cp.create = function() { 5 | // TODO: handle input 6 | }; 7 | }); 8 | -------------------------------------------------------------------------------- /source/pages/notifications.html: -------------------------------------------------------------------------------- 1 |
2 |
Notifications
notifications 3 |
4 | -------------------------------------------------------------------------------- /docs/humans.txt: -------------------------------------------------------------------------------- 1 | # humanstxt.org/ 2 | # The humans responsible & technology colophon 3 | 4 | # TEAM 5 | 6 | -- -- 7 | 8 | # THANKS 9 | 10 | 11 | 12 | # TECHNOLOGY COLOPHON 13 | 14 | HTML5, CSS3 15 | -------------------------------------------------------------------------------- /source/humans.txt: -------------------------------------------------------------------------------- 1 | # humanstxt.org/ 2 | # The humans responsible & technology colophon 3 | 4 | # TEAM 5 | 6 | -- -- 7 | 8 | # THANKS 9 | 10 | 11 | 12 | # TECHNOLOGY COLOPHON 13 | 14 | HTML5, CSS3 15 | -------------------------------------------------------------------------------- /source/pages/home.css: -------------------------------------------------------------------------------- 1 | .content { 2 | font-family: serif; 3 | font-size: 110%; 4 | width: 100vw; 5 | height: 100vh; 6 | overflow-y: scroll; 7 | } 8 | 9 | .feed-pager { 10 | height: 100vh; 11 | z-index: 0; 12 | } 13 | -------------------------------------------------------------------------------- /source/pages/search.css: -------------------------------------------------------------------------------- 1 | .message { 2 | color: darkgrey; 3 | min-height: 100vh; 4 | width: 100vw; 5 | font-size: 200%; 6 | } 7 | .message i { 8 | margin-left: 16px; 9 | color: darkgrey; 10 | font-size: 150%; 11 | } 12 | -------------------------------------------------------------------------------- /source/pages/notifications.css: -------------------------------------------------------------------------------- 1 | .message { 2 | color: darkgrey; 3 | min-height: 100vh; 4 | width: 100vw; 5 | font-size: 200%; 6 | } 7 | .message i { 8 | margin-left: 16px; 9 | color: darkgrey; 10 | font-size: 150%; 11 | } 12 | -------------------------------------------------------------------------------- /source/pages/home/items_list/item_mini.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 120%; 3 | font-weight: 500; 4 | margin: 0; 5 | } 6 | 7 | .cover-wrapper { 8 | margin: 4px; 9 | padding-top: 56.25%; 10 | } 11 | 12 | .summary { 13 | cursor: pointer; 14 | margin-top: 16px; 15 | } 16 | -------------------------------------------------------------------------------- /source/service-worker.js: -------------------------------------------------------------------------------- 1 | if ('serviceWorker' in navigator) { 2 | const p = navigator.serviceWorker 3 | .register('./sw.js') 4 | .then(reg => console.log('PWA service-worker ready.', reg)) 5 | .catch(err => console.error('Could not load service-worker.', err)); 6 | } 7 | -------------------------------------------------------------------------------- /docs/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #ffc40d 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /source/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #ffc40d 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/images/image_place_holder_576x324.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/images/image_place_holder_640x480.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /source/layout/footer.html: -------------------------------------------------------------------------------- 1 | 4 | 7 | 10 | 13 | -------------------------------------------------------------------------------- /source/pages/home/items_list/item.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 140%; 3 | font-weight: 500; 4 | margin: 0 4px; 5 | } 6 | 7 | .summary { 8 | position: absolute; 9 | padding: 4px; 10 | left:0; bottom:8px; right: 0; 11 | } 12 | .summary { 13 | color: white; 14 | background-color: rgba(0,0,0,0.6); 15 | } 16 | [self*="size-1of3"] h1 { 17 | font-size: 120% !important; 18 | } 19 | -------------------------------------------------------------------------------- /source/pages/about.css: -------------------------------------------------------------------------------- 1 | . { 2 | color: black; 3 | padding: 24px; 4 | margin-top: 64px; 5 | margin-bottom: 64px; 6 | } 7 | 8 | h1,h2,h3 { 9 | color: grey; 10 | } 11 | 12 | h2 { 13 | font-size: 130%; 14 | } 15 | 16 | a, a:visited, a:hover { 17 | font-weight: 700; 18 | color: darkorange; 19 | text-decoration: none; 20 | } 21 | 22 | .small { 23 | font-size: 90%; 24 | } 25 | -------------------------------------------------------------------------------- /source/index.css: -------------------------------------------------------------------------------- 1 | /* CSS files add styling rules to your content */ 2 | 3 | body { 4 | font-family: "Benton Sans", "Helvetica Neue", helvetica, arial, sans-serif; 5 | font-size: 16px; 6 | margin: 0; padding: 0; 7 | background: white; 8 | -webkit-user-select:none; 9 | -moz-user-select:none; 10 | -ms-user-select:none; 11 | user-select:none; 12 | overscroll-behavior-y: contain; 13 | } 14 | 15 | .drawer { 16 | background: white; 17 | } 18 | -------------------------------------------------------------------------------- /source/pages/home/items_list/item.js: -------------------------------------------------------------------------------- 1 | /* global zuix */ 2 | 'use strict'; 3 | zuix.controller(function(cp){ 4 | 5 | cp.create = function() { 6 | cp.field('container') 7 | .css('background-image', 'url('+cp.model().cover+')') 8 | .on('click', function() { 9 | window.open(cp.model().link); 10 | }); 11 | cp.field('more').on('click', function() { 12 | // show context menu 13 | zuix.context('news-options-menu').show(); 14 | }); 15 | }; 16 | 17 | }); 18 | -------------------------------------------------------------------------------- /source/pages/home/items_list/item.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 |

The quick brown fox jumped?

6 |
7 |
8 |
9 | Date N/A 10 | 13 |
14 | 15 |
16 | -------------------------------------------------------------------------------- /source/pages/home/items_list/item_mini.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 |

The little brown fox jumped?

7 |
8 |
9 | Date N/A 10 | 13 |
14 | 15 |
16 | -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Offline 5 | 20 | 21 | 22 | 23 |
24 |

Not found =/

25 |
26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /source/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Offline 5 | 20 | 21 | 22 | 23 |
24 |

Not found =/

25 |
26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /docs/offline.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Offline 5 | 20 | 21 | 22 | 23 |
24 |

Offline =/

25 |
26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /source/offline.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Offline 5 | 20 | 21 | 22 | 23 |
24 |

Offline =/

25 |
26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /source/pages/home/items_list/item_mini.js: -------------------------------------------------------------------------------- 1 | /* global zuix */ 2 | 'use strict'; 3 | zuix.controller(function(cp){ 4 | 5 | cp.create = function() { 6 | cp.field('container') 7 | .css('background-image', 'url('+cp.model().cover+')') 8 | .on('click', function() { 9 | window.open(cp.model().link); 10 | }); 11 | cp.view('.summary') 12 | .on('click', function() { 13 | window.open(cp.model().link); 14 | }); 15 | cp.field('more').on('click', function() { 16 | // show context menu 17 | zuix.context('news-options-menu').show(); 18 | }); 19 | }; 20 | 21 | }); 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zuix-html-pwa", 3 | "version": "1.0.1", 4 | "description": "Progressive Web App template with zero build steps.", 5 | "private": true, 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "http-server --cors ./source" 9 | }, 10 | "keywords": [ 11 | "zuix", 12 | "html", 13 | "pwa", 14 | "simple", 15 | "webapp" 16 | ], 17 | "author": "G-Labs", 18 | "contributors": [], 19 | "license": "MIT", 20 | "homepage": "https://github.com/zuixjs", 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/zuixjs/zuix-html-pwa" 24 | }, 25 | "devDependencies": { 26 | "http-server": "^14.1.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /source/layout/header.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | Profile Icon 4 |
5 |
6 |
7 | Home 8 |
9 |
10 |
11 | Notifications 12 |
13 |
14 | Messages 15 |
16 |
17 |
18 |
19 |
20 |
21 | Top Stories 22 |
23 |
24 | World 25 |
26 |
27 | Europe 28 |
29 |
30 | Travel 31 |
32 |
33 |
34 | -------------------------------------------------------------------------------- /source/shared/main_menu.html: -------------------------------------------------------------------------------- 1 |
2 | Profile Icon 3 |
4 |
5 |
DevUser
6 |
@devrocks
7 |
8 | 123 Following 9 | 456 Followers 10 |
11 |
12 | 13 |
14 | 15 |
16 | 17 | 21 | 22 | 26 | 27 | 31 | 32 | 36 | 37 |
38 | 39 |
40 | 41 |
42 | 43 | 46 | 47 |
48 | -------------------------------------------------------------------------------- /source/layout/footer.css: -------------------------------------------------------------------------------- 1 | . { 2 | position: fixed; 3 | left:0; bottom:0; right: 0; 4 | height: 56px; 5 | background: rgba(240,240,240,0.97); 6 | border-top: solid 1px rgba(0,0,0,0.25); 7 | box-shadow: 0 -6px 2px -2px rgba(100,100,100,0.25); 8 | text-align: center; 9 | z-index: 100; 10 | overflow: hidden; 11 | } 12 | 13 | button { 14 | padding: 12px; 15 | max-height: 56px; 16 | margin-left: 8px; 17 | margin-right: 8px; 18 | background: transparent; 19 | border: none; 20 | border-radius: 8px; 21 | color: rgba(0,0,0,0.5); 22 | -webkit-transition: all .3s; /* Safari */ 23 | transition: all .3s; 24 | } 25 | button:hover { 26 | background: rgba(255,255,255,0.25); 27 | } 28 | button:focus {outline:0;} 29 | button i {font-size: 32px !important;} 30 | 31 | .active { 32 | transform: scale(1.2); 33 | color: #0085b6; 34 | text-shadow: 35 | 1px 1px 0 #e1e8ed, 36 | -1px -1px 0 #e1e8ed, 37 | 1px -1px 0 #e1e8ed, 38 | -1px 1px 0 #e1e8ed, 39 | 1px 1px 0 #e1e8ed; 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 g-labs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /source/pages/about.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |

About

4 | 5 |

6 | This web application template is built with zuix.js. 7 |
8 | Source code and documentation available from HTML-PWA repository. 9 |

10 | 11 |

Other resources

12 |
    13 |
  • 14 | zKit
    15 | a collection of components for modern web. 16 |
  • 17 |
  • 18 | WebFlix
    19 | a netflix mobile app clone implemented as a progressive web app. 20 |
  • 21 |
  • 22 | zuix.js Web Starter
    23 | a web starter based on zuix.js, a library for component-based web development, and Eleventy, static site generator. 24 |
  • 25 |
26 | 27 |

Disclaimer

28 |

This product contains sample static data from CNN.com RSS feed but is not endorsed or certified by CNN.com.

29 | 30 |
31 | -------------------------------------------------------------------------------- /source/pages/home/items_list.css: -------------------------------------------------------------------------------- 1 | .list { 2 | margin-top: 96px; 3 | margin-bottom: 206px; 4 | } 5 | 6 | .card-wrapper { 7 | margin: 0; 8 | padding:8px; 9 | max-width: 100%; 10 | /* min-height: 100px; this is causing strange behavior on mobile, like delayed loading?!? */ 11 | overflow: hidden; 12 | font-family: Helvetica, sans-serif !important; 13 | } 14 | 15 | .info { 16 | margin-left:4px; 17 | margin-right:4px; 18 | } 19 | 20 | .card { 21 | width: 100%; 22 | position: relative; 23 | max-width: 640px; 24 | min-height: 200px; 25 | padding: 12px; 26 | padding-bottom: 24px; 27 | } 28 | .card i { 29 | color: gray; 30 | font-size: 200%; 31 | } 32 | .cover-wrapper { 33 | cursor: pointer; 34 | width: 100%; 35 | border-radius: 12px; 36 | padding-top: 75%; 37 | position: relative; 38 | overflow: hidden; 39 | background-size: cover; 40 | background: #f2f2f2 no-repeat center center; 41 | } 42 | .summary { 43 | width: 100%; 44 | } 45 | .options { 46 | color: dimgrey; 47 | } 48 | .options span { 49 | font-size: 80%; 50 | } 51 | .options button { 52 | width: 48px; 53 | height: 48px; 54 | padding-top: 4px; 55 | background: rgba(50,50,50,0.01); 56 | border: none; 57 | border-radius: 24px; 58 | } 59 | .options button:hover { 60 | background: rgba(0,0,0,0.1); 61 | } 62 | -------------------------------------------------------------------------------- /docs/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "HTML Progressive Web App", 3 | "short_name": "HTML PWA", 4 | "description": "A very cool web app powered by zUIx.js", 5 | "theme_color": "#f5f8fa", 6 | "background_color": "white", 7 | "display": "standalone", 8 | "Scope": "./", 9 | "start_url": "index.html", 10 | "icons": [ 11 | { 12 | "src": "images/icons/icon-72x72.png", 13 | "sizes": "72x72", 14 | "type": "image/png" 15 | }, 16 | { 17 | "src": "images/icons/icon-96x96.png", 18 | "sizes": "96x96", 19 | "type": "image/png" 20 | }, 21 | { 22 | "src": "images/icons/icon-128x128.png", 23 | "sizes": "128x128", 24 | "type": "image/png" 25 | }, 26 | { 27 | "src": "images/icons/icon-144x144.png", 28 | "sizes": "144x144", 29 | "type": "image/png" 30 | }, 31 | { 32 | "src": "images/icons/icon-152x152.png", 33 | "sizes": "152x152", 34 | "type": "image/png" 35 | }, 36 | { 37 | "src": "images/icons/icon-192x192.png", 38 | "sizes": "192x192", 39 | "type": "image/png" 40 | }, 41 | { 42 | "src": "images/icons/icon-384x384.png", 43 | "sizes": "384x384", 44 | "type": "image/png" 45 | }, 46 | { 47 | "src": "images/icons/icon-512x512.png", 48 | "sizes": "512x512", 49 | "type": "image/png" 50 | } 51 | ], 52 | "splash_pages": null 53 | } 54 | -------------------------------------------------------------------------------- /source/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "HTML Progressive Web App", 3 | "short_name": "HTML PWA", 4 | "description": "A very cool web app powered by zUIx.js", 5 | "theme_color": "#f5f8fa", 6 | "background_color": "white", 7 | "display": "standalone", 8 | "Scope": "./", 9 | "start_url": "index.html", 10 | "icons": [ 11 | { 12 | "src": "images/icons/icon-72x72.png", 13 | "sizes": "72x72", 14 | "type": "image/png" 15 | }, 16 | { 17 | "src": "images/icons/icon-96x96.png", 18 | "sizes": "96x96", 19 | "type": "image/png" 20 | }, 21 | { 22 | "src": "images/icons/icon-128x128.png", 23 | "sizes": "128x128", 24 | "type": "image/png" 25 | }, 26 | { 27 | "src": "images/icons/icon-144x144.png", 28 | "sizes": "144x144", 29 | "type": "image/png" 30 | }, 31 | { 32 | "src": "images/icons/icon-152x152.png", 33 | "sizes": "152x152", 34 | "type": "image/png" 35 | }, 36 | { 37 | "src": "images/icons/icon-192x192.png", 38 | "sizes": "192x192", 39 | "type": "image/png" 40 | }, 41 | { 42 | "src": "images/icons/icon-384x384.png", 43 | "sizes": "384x384", 44 | "type": "image/png" 45 | }, 46 | { 47 | "src": "images/icons/icon-512x512.png", 48 | "sizes": "512x512", 49 | "type": "image/png" 50 | } 51 | ], 52 | "splash_pages": null 53 | } 54 | -------------------------------------------------------------------------------- /source/shared/main_menu.css: -------------------------------------------------------------------------------- 1 | . { 2 | font-family: "Trebuchet MS", sans-serif; 3 | overflow-x: hidden; 4 | } 5 | 6 | a { 7 | text-decoration: none; 8 | color: black; 9 | } 10 | 11 | hr { 12 | margin-top: 12px; 13 | margin-bottom: 12px; 14 | opacity: 0.2; 15 | } 16 | 17 | .profile { 18 | margin-top: 16px; 19 | margin-left: 16px; 20 | width: 64px; 21 | height: 64px; 22 | background: #f5f8fa; 23 | border-radius: 50%; 24 | border: solid 1px #00aced; 25 | overflow: hidden; 26 | cursor: pointer; 27 | } 28 | 29 | .profile img { 30 | margin-left: -4px; 31 | width: 68px; 32 | height: 68px; 33 | } 34 | 35 | .info { 36 | margin-top: 8px; 37 | margin-left: 16px; 38 | font-size: 120%; 39 | } 40 | 41 | .nick { 42 | font-weight: bold; 43 | } 44 | .name { 45 | font-size: 90%; 46 | color: gray; 47 | } 48 | .summary { 49 | color: darkgray; 50 | font-size: 80%; 51 | margin-top: 8px; 52 | } 53 | .summary strong { 54 | color: gray; 55 | } 56 | 57 | .options button { 58 | font-family: "Trebuchet MS", sans-serif; 59 | font-size: 110%; 60 | width: 100%; 61 | height:56px; 62 | border: 0; 63 | margin: 0; 64 | padding: 0 0 0 16px; 65 | background: transparent; 66 | color: black; 67 | vertical-align: middle; 68 | align-items: center; 69 | display: -webkit-box; 70 | display: -webkit-flex; 71 | display: -ms-flexbox; 72 | display: flex; 73 | } 74 | .options button i { 75 | font-size: 200%; 76 | color: darkgray; 77 | } 78 | .options button span { 79 | margin-left: 8px; 80 | } 81 | -------------------------------------------------------------------------------- /source/shared/input_box.css: -------------------------------------------------------------------------------- 1 | 2 | . { 3 | width: 100%; 4 | max-width: 640px; 5 | height: 100%; 6 | text-align: center; 7 | display: flex; 8 | align-items: center; 9 | justify-content: center; 10 | } 11 | 12 | input { 13 | width: 100%; 14 | font-size: 130%; 15 | font-family: inherit; 16 | line-height: inherit; 17 | color: #2e3750; 18 | min-width: 12em; 19 | } 20 | 21 | .input { 22 | width: 100%; 23 | position: relative; 24 | background: linear-gradient(21deg, #10abff, #1beabd); 25 | padding: 2px; 26 | display: inline-block; 27 | border-radius: 9999em; 28 | margin: 8px; 29 | } 30 | .input *:not(span) { 31 | position: relative; 32 | display: inherit; 33 | border-radius: inherit; 34 | margin: 0; 35 | border: none; 36 | outline: none; 37 | padding: 3px 8px; 38 | z-index: 1; 39 | } 40 | .input *:not(span):focus + span { 41 | opacity: 1; 42 | -webkit-transform: scale(1); 43 | transform: scale(1); 44 | } 45 | .input span { 46 | -webkit-transform: scale(1); 47 | transform: scale(1); 48 | transition: opacity .25s, -webkit-transform .5s; 49 | transition: transform .5s, opacity .25s; 50 | transition: transform .5s, opacity .25s, -webkit-transform .5s; 51 | opacity: 0; 52 | position: absolute; 53 | z-index: 0; 54 | margin: 4px; 55 | left: 0; 56 | top: 0; 57 | right: 0; 58 | bottom: 0; 59 | border-radius: inherit; 60 | pointer-events: none; 61 | box-shadow: inset 0 0 0 2px #fff, 0 0 0 2px #fff, 2px -2px 22px #1beabd, -2px 2px 22px #10abff; 62 | } 63 | 64 | ::-webkit-input-placeholder { 65 | color: #cbd0d5; 66 | } 67 | 68 | :-ms-input-placeholder { 69 | color: #cbd0d5; 70 | } 71 | 72 | ::-ms-input-placeholder { 73 | color: #cbd0d5; 74 | } 75 | 76 | ::placeholder { 77 | color: #cbd0d5; 78 | } 79 | -------------------------------------------------------------------------------- /source/layout/header.css: -------------------------------------------------------------------------------- 1 | . { 2 | position: fixed; 3 | top:0; 4 | left:0; 5 | right:0; 6 | height:auto; 7 | background: rgba(240,240,240,0.97); 8 | border-bottom: solid 1px rgba(0,0,0,0.25); 9 | box-shadow: 0 6px 2px -2px rgba(100,100,100,0.25); 10 | z-index: 100; 11 | } 12 | 13 | .header { 14 | height: 56px; 15 | max-height: 56px; 16 | } 17 | 18 | .title { 19 | position: absolute; 20 | top: 12px; 21 | left: 80px; 22 | font-size: 180%; 23 | } 24 | 25 | .profile { 26 | position: absolute; 27 | left: 20px; top: 8px; 28 | width: 42px; 29 | height: 42px; 30 | background: #f5f8fa; 31 | border-radius: 50%; 32 | border: solid 1px #00aced; 33 | overflow: hidden; 34 | cursor: pointer; 35 | } 36 | .profile img { 37 | margin-left: -2px; 38 | height: 44px; 39 | } 40 | 41 | .topics { 42 | width: 100%; 43 | height:40px; 44 | } 45 | .topics div { 46 | font-size: 16px; 47 | height:36px; 48 | min-width: 96px; 49 | text-align: center; 50 | vertical-align: middle; 51 | line-height: 36px; 52 | border-bottom: solid 4px transparent; 53 | cursor: pointer; 54 | } 55 | 56 | .active { 57 | color: initial; 58 | font-weight: bold; 59 | border-bottom: solid 4px #00aced !important; 60 | } 61 | 62 | [data-ui-field="header-box"] { 63 | padding-left: 72px; 64 | padding-right: 16px; 65 | height: 100%; 66 | } 67 | 68 | /* Pulse Animation from https://codepen.io/olam/pen/zcqea */ 69 | 70 | .pulse { 71 | box-shadow: 0 0 0 rgba(204,169,44, 0.4); 72 | animation: pulse 2s infinite; 73 | } 74 | .pulse:hover { 75 | animation: none; 76 | } 77 | 78 | @-webkit-keyframes pulse { 79 | 0% { 80 | -webkit-box-shadow: 0 0 0 0 rgba(204,169,44, 0.4); 81 | } 82 | 70% { 83 | -webkit-box-shadow: 0 0 0 10px rgba(204,169,44, 0); 84 | } 85 | 100% { 86 | -webkit-box-shadow: 0 0 0 0 rgba(204,169,44, 0); 87 | } 88 | } 89 | @keyframes pulse { 90 | 0% { 91 | -moz-box-shadow: 0 0 0 0 rgba(204,169,44, 0.4); 92 | box-shadow: 0 0 0 0 rgba(204,169,44, 0.4); 93 | } 94 | 70% { 95 | -moz-box-shadow: 0 0 0 10px rgba(204,169,44, 0); 96 | box-shadow: 0 0 0 10px rgba(204,169,44, 0); 97 | } 98 | 100% { 99 | -moz-box-shadow: 0 0 0 0 rgba(204,169,44, 0); 100 | box-shadow: 0 0 0 0 rgba(204,169,44, 0); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /source/pages/home.html: -------------------------------------------------------------------------------- 1 |
5 | 6 | 7 |
8 | 9 |
11 | 12 |
13 | 14 | 15 |
16 | 17 |
19 | 20 |
21 | 22 | 23 |
24 | 25 |
27 | 28 |
29 | 30 | 31 |
32 | 33 |
35 | 36 |
37 | 38 |
39 |
41 |
42 | 46 | 50 | 54 | 58 | 62 | 66 |
67 |
68 | -------------------------------------------------------------------------------- /docs/index.js: -------------------------------------------------------------------------------- 1 | /* global zuix */ 2 | 3 | let drawerLayout; 4 | let viewPager; 5 | let topicIndicator; 6 | let topicButtons; 7 | 8 | zuix.using('script', './service-worker.js'); 9 | zuix.using('style', '//zuixjs.github.io/zkit/css/flex-layout-attribute.min.css'); 10 | zuix.using('style', './index.css'); 11 | 12 | zuix.$.find('.profile').on('click', function() { 13 | if (drawerLayout) drawerLayout.open(); 14 | }); 15 | 16 | window.options = { 17 | drawerLayout: { 18 | autoHideWidth: -1, 19 | drawerWidth: 280, 20 | ready: function() { drawerLayout = this; this.close(); } 21 | }, 22 | headerBar: { 23 | ready: function() { 24 | const view = zuix.$(this.view()); 25 | // handle 'topic' buttons click (goto clicked topic page) 26 | topicButtons = view.find('.topics').children().each(function(i, el){ 27 | this.on('click', function(e) { 28 | if (viewPager) viewPager.page(i); 29 | }); 30 | }); 31 | // open drawer when the profile icon is clicked 32 | view.find('.profile').on('click', function() { 33 | if (drawerLayout) drawerLayout.open(); 34 | }); 35 | showPage(0); 36 | } 37 | }, 38 | footerBar: { 39 | ready: function(){ 40 | const view = zuix.$(this.view()); 41 | const buttons = view.find('button'); 42 | buttons.each(function(i, el) { 43 | // TODO: 44 | this.on('click', function() { 45 | buttons.removeClass('active'); 46 | this.addClass('active'); 47 | showPage(i); 48 | }); 49 | }); 50 | } 51 | }, 52 | viewPager: { 53 | enablePaging: true, 54 | startGap: 36, 55 | on: { 56 | 'page:change': function(e, page) { 57 | syncPageIndicator(page); 58 | // show header/footer 59 | if (viewPager) { 60 | const p = viewPager.get(page.in); 61 | zuix.context(p).show(); 62 | } 63 | } 64 | }, 65 | ready: function() { 66 | viewPager = this; 67 | } 68 | }, 69 | topicIndicator: { 70 | enablePaging: true, 71 | startGap: 36, 72 | ready: function() { 73 | topicIndicator = this; 74 | } 75 | }, 76 | autoHidingBars: { 77 | header: 'header-bar', 78 | footer: 'footer-bar', 79 | height: 56, 80 | on: { 81 | 'page:scroll': function(e, data) { 82 | zuix.componentize(); 83 | } 84 | } 85 | }, 86 | content: { 87 | css: false 88 | } 89 | }; 90 | 91 | function syncPageIndicator(page) { 92 | if (topicButtons) { 93 | topicButtons.eq(page.out).removeClass('active'); 94 | topicButtons.eq(page.in).addClass('active'); 95 | } 96 | if (topicIndicator) topicIndicator.page(page.in); 97 | } 98 | 99 | function showPage(i) { 100 | // show header top-box 101 | zuix.field('header-box') 102 | .children().hide() 103 | .eq(i).show(); 104 | // show header bottom-box 105 | zuix.field('header-tools') 106 | .children().hide() 107 | .eq(i).show(); 108 | // show page 109 | zuix.field('pages') 110 | .children().hide() 111 | .eq(i).show(); 112 | if (viewPager) viewPager.refresh(); 113 | } 114 | 115 | // Turn off debug output 116 | window.zuixNoConsoleOutput = true; 117 | -------------------------------------------------------------------------------- /source/index.js: -------------------------------------------------------------------------------- 1 | /* global zuix */ 2 | 3 | let drawerLayout; 4 | let viewPager; 5 | let topicIndicator; 6 | let topicButtons; 7 | 8 | zuix.using('script', './service-worker.js'); 9 | zuix.using('style', 'https://cdnjs.cloudflare.com/ajax/libs/flex-layout-attribute/1.0.3/css/flex-layout-attribute.min.css'); 10 | zuix.using('style', './index.css'); 11 | 12 | zuix.$.find('.profile').on('click', function() { 13 | if (drawerLayout) drawerLayout.open(); 14 | }); 15 | 16 | window.options = { 17 | drawerLayout: { 18 | autoHideWidth: -1, 19 | drawerWidth: 280, 20 | ready: function() { drawerLayout = this; this.close(); } 21 | }, 22 | headerBar: { 23 | ready: function() { 24 | const view = zuix.$(this.view()); 25 | // handle 'topic' buttons click (goto clicked topic page) 26 | topicButtons = view.find('.topics').children().each(function(i, el){ 27 | this.on('click', function(e) { 28 | if (viewPager) viewPager.page(i); 29 | }); 30 | }); 31 | // open drawer when the profile icon is clicked 32 | view.find('.profile').on('click', function() { 33 | if (drawerLayout) drawerLayout.open(); 34 | }); 35 | showPage(0); 36 | } 37 | }, 38 | footerBar: { 39 | ready: function(){ 40 | const view = zuix.$(this.view()); 41 | const buttons = view.find('button'); 42 | buttons.each(function(i, el) { 43 | // TODO: 44 | this.on('click', function() { 45 | buttons.removeClass('active'); 46 | this.addClass('active'); 47 | showPage(i); 48 | }); 49 | }); 50 | } 51 | }, 52 | viewPager: { 53 | enablePaging: true, 54 | startGap: 36, 55 | on: { 56 | 'page:change': function(e, page) { 57 | syncPageIndicator(page); 58 | // show header/footer 59 | if (viewPager) { 60 | const p = viewPager.get(page.in); 61 | zuix.context(p).show(); 62 | } 63 | } 64 | }, 65 | ready: function() { 66 | viewPager = this; 67 | } 68 | }, 69 | topicIndicator: { 70 | enablePaging: true, 71 | startGap: 36, 72 | ready: function() { 73 | topicIndicator = this; 74 | } 75 | }, 76 | autoHidingBars: { 77 | header: 'header-bar', 78 | footer: 'footer-bar', 79 | height: 56, 80 | on: { 81 | 'page:scroll': function(e, data) { 82 | zuix.componentize(); 83 | } 84 | } 85 | }, 86 | content: { 87 | css: false 88 | } 89 | }; 90 | 91 | function syncPageIndicator(page) { 92 | if (topicButtons) { 93 | topicButtons.eq(page.out).removeClass('active'); 94 | topicButtons.eq(page.in).addClass('active'); 95 | } 96 | if (topicIndicator) topicIndicator.page(page.in); 97 | } 98 | 99 | function showPage(i) { 100 | // show header top-box 101 | zuix.field('header-box') 102 | .children().hide() 103 | .eq(i).show(); 104 | // show header bottom-box 105 | zuix.field('header-tools') 106 | .children().hide() 107 | .eq(i).show(); 108 | // show page 109 | zuix.field('pages') 110 | .children().hide() 111 | .eq(i).show(); 112 | if (viewPager) viewPager.refresh(); 113 | } 114 | 115 | // Turn off debug output 116 | window.zuixNoConsoleOutput = true; 117 | -------------------------------------------------------------------------------- /source/pages/home/items_list.js: -------------------------------------------------------------------------------- 1 | /* global zuix */ 2 | 'use strict'; 3 | zuix.controller(function(cp) { 4 | const zx = zuix; // shorthand 5 | let itemsList; 6 | 7 | cp.create = function() { 8 | let url = cp.view().attr('data-o-rss'); 9 | // Use a proxy to prevent CORS policy restrictions errors 10 | fetchList(url); 11 | }; 12 | 13 | function refresh() { 14 | const list = cp.field('list'); 15 | if (itemsList != null) { 16 | zx.$.each(itemsList, function(i, item) { 17 | const options = { 18 | lazyLoad: true, 19 | model: item 20 | }; 21 | let el; 22 | if (i < 5) { 23 | // different layout for first 4 items (bigger) 24 | el = zx.createComponent('pages/home/items_list/item', options).container(); 25 | // 2 columns layout 26 | if (i < 2) { 27 | el.setAttribute('self', 'size-1of2 lg-full md-full sm-full'); 28 | } else { 29 | el.setAttribute('self', 'size-1of3 lg-half md-half sm-full'); 30 | } 31 | el.setAttribute('class', 'card-wrapper'); // <-- will this work? 32 | } else { 33 | // "mini" layout for subsequent items 34 | el = zx.createComponent('pages/home/items_list/item_mini', options).container(); 35 | // 4 columns layout 36 | el.setAttribute('self', 'size-1of4 lg-half md-half sm-full'); 37 | el.setAttribute('class', 'card-wrapper mini'); // <-- will this work? 38 | } 39 | // center the list on wide screens 40 | el.setAttribute('layout', 'column stretch-center'); 41 | list.append(el); 42 | }); 43 | zuix.componentize(); 44 | } 45 | } 46 | 47 | // Download RSS feed 48 | function fetchList(rssUrl) { 49 | zx.$.ajax({ 50 | url: rssUrl, 51 | success: function(res) { 52 | itemsList = parseRss(res); 53 | refresh(); 54 | }, 55 | error: function(err) { 56 | // TODO: handle error 57 | } 58 | }); 59 | } 60 | 61 | // Parse RSS feed and create a JSON object out of it 62 | function parseRss(rssText) { 63 | const items = []; 64 | const parser = new DOMParser(); 65 | const doc = parser.parseFromString(rssText, "text/xml"); 66 | let d = zx.$(doc); 67 | d.find('channel > item').each(function(i, el){ 68 | const title = getText(this.find('title')); 69 | const description = getText(this.find('description')); 70 | const pubDate = getText(this.find('pubDate')); 71 | const link = getText(this.find('link')); 72 | const imageList = this.find('[medium="image"]'); 73 | if (title !== '') { 74 | const images = []; 75 | // parse images to a json list 76 | imageList.each(function(i, el) { 77 | images.push({ 78 | url: this.attr('url'), 79 | width: this.attr('width'), 80 | height: this.attr('height') 81 | }); 82 | }); 83 | let cover; 84 | if (i < 5 && images[3] != null) cover = images[3].url; 85 | else if (i > 3 && images[4] != null) cover = images[4].url; 86 | const date = pubDate; // TODO: format date 87 | items.push({ 88 | title, 89 | link, 90 | cover, 91 | date, 92 | images 93 | }); 94 | } 95 | }); 96 | return items; 97 | } 98 | 99 | function getText(node) { 100 | let text; 101 | // if node is ZxQuery, then get underlying HTMLElement 102 | if (node.length() > 0) node = node.get(); 103 | if (node != null && node.firstChild != null) { 104 | // get rid of CDATA wrapper eventually 105 | text = node.firstChild.wholeText; 106 | } else if (node != null) { 107 | // get value as is 108 | text = node.innerHTML; 109 | } 110 | return text; 111 | } 112 | }); 113 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | HTML PWA 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
70 | 71 |
72 | 73 | 74 |
75 | 76 | 77 |
78 | 79 | 80 |
81 | 82 | 83 |
84 | 85 |
86 | 87 | 88 |
91 | 92 | 93 |
97 | 98 |
99 |
100 | 101 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /source/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | HTML PWA 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 |
68 | 69 |
70 | 71 | 72 |
73 | 74 | 75 |
76 | 77 | 78 |
79 | 80 | 81 |
82 | 83 |
84 | 85 | 86 |
89 | 90 | 91 |
95 | 96 |
97 |
98 | 99 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /docs/sw.js: -------------------------------------------------------------------------------- 1 | // TODO: increase `version` number to force cache update when publishing a new release 2 | const version = 'v1'; 3 | 4 | const config = { 5 | cacheRemote: true, 6 | version: version+'::', 7 | preCachingItems: [ 8 | 'app.bundle.js', 9 | 'index.html', 10 | 'index.js', 11 | 'offline.html', 12 | '404.html', 13 | 'sw.js' 14 | ], 15 | blacklistCacheItems: [ 16 | 'index.html', 17 | 'service-worker.js' 18 | ], 19 | offlineImage: '' + 'Offline' + '' + '' + 'offline', 20 | offlinePage: 'offline.html', 21 | notFoundPage: '404.html' 22 | }; 23 | 24 | function cacheName(key, opts) { 25 | return `${opts.version}${key}`; 26 | } 27 | 28 | function addToCache(cacheKey, request, response) { 29 | if (response.ok) { 30 | const copy = response.clone(); 31 | caches.open(cacheKey).then(cache => { 32 | cache.put(request, copy); 33 | }); 34 | } 35 | return response; 36 | } 37 | 38 | function fetchFromCache(event) { 39 | return caches.match(event.request).then(response => { 40 | if (!response) { 41 | throw Error(`${event.request.url} not found in cache`); 42 | } else if (response.status === 404) { 43 | return caches.match(config.notFoundPage); 44 | } 45 | return response; 46 | }); 47 | } 48 | 49 | function offlineResponse(resourceType, opts) { 50 | if (resourceType === 'content') { 51 | return caches.match(opts.offlinePage); 52 | } 53 | if (resourceType === 'image') { 54 | return new Response(opts.offlineImage, { 55 | headers: { 'Content-Type': 'image/svg+xml' } 56 | }); 57 | } 58 | return undefined; 59 | } 60 | 61 | self.addEventListener('install', event => { 62 | event.waitUntil(caches.open( 63 | cacheName('static', config) 64 | ) 65 | .then(cache => cache.addAll(config.preCachingItems)) 66 | .then(() => self.skipWaiting()) 67 | ); 68 | }); 69 | self.addEventListener('activate', event => { 70 | function clearCacheIfDifferent(event, opts) { 71 | return caches.keys().then(cacheKeys => { 72 | const oldCacheKeys = cacheKeys.filter(key => key.indexOf(opts.version) !== 0); 73 | const deletePromises = oldCacheKeys.map(oldKey => caches.delete(oldKey)); 74 | return Promise.all(deletePromises); 75 | }); 76 | } 77 | event.waitUntil( 78 | clearCacheIfDifferent(event, config) 79 | .then(() => self.clients.claim()) 80 | ); 81 | }); 82 | self.addEventListener('fetch', event => { 83 | const request = event.request; 84 | const url = new URL(request.url); 85 | if (request.method !== 'GET' 86 | || (config.cacheRemote !== true && url.origin !== self.location.origin) 87 | || (config.blacklistCacheItems.length > 0 && config.blacklistCacheItems.indexOf(url.pathname) !== -1)) { 88 | // default browser behavior 89 | return; 90 | } 91 | let cacheKey; 92 | let resourceType = 'content'; 93 | if (/(.jpg|.jpeg|.webp|.png|.svg|.gif)$/.test(url.pathname)) { 94 | resourceType = 'image'; 95 | } else if (/.\/fonts.(?:googleapis|gstatic).com/.test(url.origin)) { 96 | resourceType = 'font'; 97 | } 98 | cacheKey = cacheName(resourceType, config); 99 | if (resourceType === 'content') { 100 | // Network First Strategy 101 | event.respondWith( 102 | fetch(request) 103 | .then(response => addToCache(cacheKey, request, response)) 104 | .catch(() => fetchFromCache(event)) 105 | .catch(() => offlineResponse(resourceType, config)) 106 | ); 107 | } else { 108 | // Cache First Strategy 109 | event.respondWith( 110 | fetchFromCache(event) 111 | .catch(() => fetch(request)) 112 | .then(response => addToCache(cacheKey, request, response)) 113 | .catch(() => offlineResponse(resourceType, config)) 114 | ); 115 | } 116 | }); 117 | -------------------------------------------------------------------------------- /source/sw.js: -------------------------------------------------------------------------------- 1 | // TODO: increase `version` number to force cache update when publishing a new release 2 | const version = 'v1'; 3 | 4 | const config = { 5 | cacheRemote: true, 6 | version: version+'::', 7 | preCachingItems: [ 8 | 'app.bundle.js', 9 | 'index.html', 10 | 'index.js', 11 | 'offline.html', 12 | '404.html', 13 | 'sw.js' 14 | ], 15 | blacklistCacheItems: [ 16 | 'index.html', 17 | 'service-worker.js' 18 | ], 19 | offlineImage: '' + 'Offline' + '' + '' + 'offline', 20 | offlinePage: 'offline.html', 21 | notFoundPage: '404.html' 22 | }; 23 | 24 | function cacheName(key, opts) { 25 | return `${opts.version}${key}`; 26 | } 27 | 28 | function addToCache(cacheKey, request, response) { 29 | if (response.ok) { 30 | const copy = response.clone(); 31 | caches.open(cacheKey).then(cache => { 32 | cache.put(request, copy); 33 | }); 34 | } 35 | return response; 36 | } 37 | 38 | function fetchFromCache(event) { 39 | return caches.match(event.request).then(response => { 40 | if (!response) { 41 | throw Error(`${event.request.url} not found in cache`); 42 | } else if (response.status === 404) { 43 | return caches.match(config.notFoundPage); 44 | } 45 | return response; 46 | }); 47 | } 48 | 49 | function offlineResponse(resourceType, opts) { 50 | if (resourceType === 'content') { 51 | return caches.match(opts.offlinePage); 52 | } 53 | if (resourceType === 'image') { 54 | return new Response(opts.offlineImage, { 55 | headers: { 'Content-Type': 'image/svg+xml' } 56 | }); 57 | } 58 | return undefined; 59 | } 60 | 61 | self.addEventListener('install', event => { 62 | event.waitUntil(caches.open( 63 | cacheName('static', config) 64 | ) 65 | .then(cache => cache.addAll(config.preCachingItems)) 66 | .then(() => self.skipWaiting()) 67 | ); 68 | }); 69 | self.addEventListener('activate', event => { 70 | function clearCacheIfDifferent(event, opts) { 71 | return caches.keys().then(cacheKeys => { 72 | const oldCacheKeys = cacheKeys.filter(key => key.indexOf(opts.version) !== 0); 73 | const deletePromises = oldCacheKeys.map(oldKey => caches.delete(oldKey)); 74 | return Promise.all(deletePromises); 75 | }); 76 | } 77 | event.waitUntil( 78 | clearCacheIfDifferent(event, config) 79 | .then(() => self.clients.claim()) 80 | ); 81 | }); 82 | self.addEventListener('fetch', event => { 83 | const request = event.request; 84 | const url = new URL(request.url); 85 | if (request.method !== 'GET' 86 | || (config.cacheRemote !== true && url.origin !== self.location.origin) 87 | || (config.blacklistCacheItems.length > 0 && config.blacklistCacheItems.indexOf(url.pathname) !== -1)) { 88 | // default browser behavior 89 | return; 90 | } 91 | let cacheKey; 92 | let resourceType = 'content'; 93 | if (/(.jpg|.jpeg|.webp|.png|.svg|.gif)$/.test(url.pathname)) { 94 | resourceType = 'image'; 95 | } else if (/.\/fonts.(?:googleapis|gstatic).com/.test(url.origin)) { 96 | resourceType = 'font'; 97 | } 98 | cacheKey = cacheName(resourceType, config); 99 | if (resourceType === 'content') { 100 | // Network First Strategy 101 | event.respondWith( 102 | fetch(request) 103 | .then(response => addToCache(cacheKey, request, response)) 104 | .catch(() => fetchFromCache(event)) 105 | .catch(() => offlineResponse(resourceType, config)) 106 | ); 107 | } else { 108 | // Cache First Strategy 109 | event.respondWith( 110 | fetchFromCache(event) 111 | .catch(() => fetch(request)) 112 | .then(response => addToCache(cacheKey, request, response)) 113 | .catch(() => offlineResponse(resourceType, config)) 114 | ); 115 | } 116 | }); 117 | -------------------------------------------------------------------------------- /source/js/zuix-bundler.min.js: -------------------------------------------------------------------------------- 1 | /* zUIx v1.0.1 18.08.30 21:48:09 */ 2 | 3 | /* 4 | @license 5 | Copyright 2015-2018 G-Labs. All Rights Reserved. 6 | https://zuixjs.github.io/zuix 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 20 | 'use strict';(function(a){"object"===typeof exports&&"undefined"!==typeof module?module.exports=a():"function"===typeof define&&define.amd?define([],a):("undefined"!==typeof window?window:"undefined"!==typeof global?global:"undefined"!==typeof self?self:this).zuixBundler=a()})(function(){return function(){function a(e,f,g){function c(k,b){if(!f[k]){if(!e[k]){var q="function"==typeof require&&require;if(!b&&q)return q(k,!0);if(n)return n(k,!0);b=Error("Cannot find module '"+k+"'");throw b.code="MODULE_NOT_FOUND", 21 | b;}b=f[k]={exports:{}};e[k][0].call(b.exports,function(b){return c(e[k][1][b]||b)},b,b.exports,a,e,f,g)}return f[k].exports}for(var n="function"==typeof require&&require,l=0;l\/\u2028\u2029]/g,b={"<":"\\u003C",">":"\\u003E","/":"\\u002F","\u2028":"\\u2028","\u2029":"\\u2029"};e.exports=function(b,a){function e(b,a){if(!a)return a;b=typeof a;return"object"===b?"[object RegExp]"===Object.prototype.toString.call(a)?"@__R-"+c+"-"+(h.push(a)-1)+"__@":a:"function"===b?"@__F-"+c+"-"+(f.push(a)-1)+"__@":a}a||(a={});if("number"===typeof a||"string"===typeof a)a={space:a};const f=[],h=[];b=a.isJSON&& 27 | !a.space?JSON.stringify(b):JSON.stringify(b,a.isJSON?null:e,a.space);if("string"!==typeof b)return String(b);b=b.replace(k,g);return 0===f.length&&0===h.length?b:b.replace(n,function(a,b,c){if("R"===b)return h[c].toString();a=f[c];b=a.toString();if(l.test(b))throw new TypeError("Serializing native function: "+a.name);return b})}},{}],4:[function(a,e,f){function g(){var a=zuix.bundle();var b="\n/*\n * zUIx Application Bundle\n * \n * app.bundle.js generated by *zuix-bundler*\n * on "+(new Date).toISOString(); 28 | b=b+"\n * "+("\n * Resource list ("+a.length+"):");b+="\n * ";for(let c=0;c 95 |
97 | 98 |
99 | 100 | 101 |
102 | 103 | 104 |
105 | 106 | 107 |
108 | 109 | 110 |
111 | 112 |
113 | 114 | 115 |
117 | 118 | 119 |
121 | 122 |
123 |
124 | ``` 125 | 126 | For a deeper insight on using these special attributes for component-based developemnt with **zUIx.js** see related link 127 | at the bottom of this page. 128 | 129 | ### The news list 130 | 131 | In order to display the list of news articles, the `pages/home` is using the `pages/home/items_list` component. 132 | 133 | **pages/home.html** (snippet) 134 | ```html 135 | ... 136 | 137 | 138 |
140 | 141 | 142 |
144 | 145 | ... 146 | ``` 147 | 148 | Once the `items_list` component is loaded it will read the attribute `data-o-rss` of the element and download the RSS 149 | feed specified by it. Then it will parse the RSS feed and render it to the wrapping element. 150 | This component is just an example and you can modify and adapt it to work with any data source or it can be replace with 151 | a server-side rendering approach. 152 | 153 | ### About the @lib prefix 154 | 155 | The special *@lib* prefix is used with the `data-ui-include` and `data-ui-load` attribute to load components from a 156 | shared location that by default will point to the [zKit](https://zuixjs.github.io/zkit/) components library. 157 | This path is resolved to `https://zuixjs.github.io/zkit/lib/` but can also be customized to point to a different location: 158 | 159 | ```javascript 160 | zuix.store('config', { 161 | libraryPath: 'https://my.shared.components.io/lib/' 162 | }); 163 | ``` 164 | 165 | You can so create your own shared component library to use across all of your websites. 166 | 167 | ### Further implementation details 168 | 169 | If you have more questions about how to use this template, do not hesitate to [file an issue](https://github.com/zuixjs/zuix-html-pwa/issues). 170 | 171 | 172 | ## Service Worker and Offline mode 173 | 174 | A service worker is also included with this template. This is a script (`sw.js`) that runs in the background as a separate 175 | thread from the main page and takes care of providing caching of most resources with a fallback mechanism in presence of 176 | network errors. 177 | This makes the application to launch even if there's no network connection, like with a real mobile app. It also provides 178 | a configurable `404.html` *"not found"* page and `offline.html` page. 179 | When publishing a new version of the application the *version number* found at the top of the `sw.js` file **must be increased** 180 | in order to clean the cache and correctly update the application files. 181 | 182 | 183 | ## Debugging 184 | 185 | To enable verbose debugging information in the browser console, comment out the last line in the `index.js` file as 186 | shown below: 187 | 188 | ``` javascript 189 | // Turn off debug output 190 | //window.zuixNoConsoleOutput = true; 191 | ``` 192 | 193 | 194 | ## Bundling 195 | 196 | Bundling is the process of collecting all resources used in a page and then compiling them into a single and optimized file. 197 | 198 | This will drastically narrow down the number of network requests the browser will make to complete the page loading, 199 | thus resulting in a faster startup. 200 | 201 | There are actually two way of doing this: 202 | 203 | - **In-Browser** bundler: 204 | this method does not require any build tool nor plugins, it just works in the browser as-is. 205 | 206 | - **Web-Starter** bundler: 207 | is the [zuix-web-starter](https://github.com/zuixjs/zuix-web-starter) bare template, with a bunch of extra features and 208 | enhancements. It requires *Node.js* to be installed. 209 | 210 | This template is already configured for **in-browser** bundling. 211 | 212 | ### In-Browser bundling 213 | 214 | When the website is ready for production you can decide to bundle it in order to gain better performances. All of its 215 | components and resources will be crunched into a single file and loaded from memory rather than from network/localhost. 216 | 217 | #### Step by step guide 218 | 219 | Open the development website and generate the application bundle by typing in the **browser console** the command 220 | 221 | ```javascript 222 | zuix.saveBundle() 223 | ``` 224 | 225 | This will create and save the **app.bundle.js** file to the *Downloads* folder. 226 | 227 | Copy all files from the *source* folder to the **production** folder (*./docs*) with the exception of *./components*, 228 | *./controllers*, *./pages*, *./layout* and *./index.css*. 229 | 230 | These folders contain *zuix* components and pages that are already packed in the *app.bundle.js* file. 231 | 232 | Copy *app.bundle.js* to the *production* folder. Edit the `index.html` file in the *production* folder and in the `head` 233 | section replace the `js/zuix-bundler.min.js` script import with `app.bundle.js`. 234 | 235 | ```html 236 | 237 | 238 | ``` 239 | 240 | You can also remove all `js/zuix*.*` files from the *production* folder but keep the `zuix.min.js` one. 241 | 242 | #### Remarks 243 | 244 | When using *lazy-loading* only components loaded so far will be included in the bundle (incremental bundling). 245 | 246 | To force inclusion of all components/resources used in the page, issue the following commands in the console: 247 | 248 | ```javascript 249 | // disable lazy-loading 250 | zuix.lazyLoad(false) 251 | // force loading of all components 252 | zuix.componentize() 253 | // create the bundle 254 | zuix.saveBundle() 255 | ``` 256 | 257 | Also external JavaScript libraries and CSS files can be included in the page bundle. In order to achieve this, remove 258 | the `` or `` and instead use the method `zuix.using(...)` to load the script/css. 259 | 260 | ```javascript 261 | // Loading a .css style 262 | const flaCss = 'https://cdnjs.cloudflare.com/ajax/libs/flex-layout-attribute/1.0.3/css/flex-layout-attribute.min.css'; 263 | zuix.using('style', flaCss, function(res, styleObject) { 264 | console.log("Added Flex Layout Attributes CSS.", res, styleObject); 265 | }); 266 | // Loading a .js script 267 | const momentJs = 'https://momentjs.com/downloads/moment.js'; 268 | zuix.using('script', momentJs, function(res, scriptObject){ 269 | console.log("Added Moment.js.", res, scriptObject); 270 | }); 271 | ``` 272 | 273 | Place the *using* commands preferably at the top of `index.js`. You can remove from the *production* folder all files 274 | imported with the *using* command. 275 | 276 | # Further reading 277 | 278 | - [zUIx.js](https://zuixjs.org) 279 | - [zKit](https://zuixjs.github.io/zkit/) 280 | - [PWA Builder](https://www.pwabuilder.com/) 281 | - [Progressive Web App](https://developers.google.com/web/progressive-web-apps) 282 | - [Service Workers](https://developers.google.com/web/fundamentals/primers/service-workers) 283 | -------------------------------------------------------------------------------- /source/js/zuix-bundler.min.js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version":3, 3 | "file":"/home/gene/WebstormProjects/zuix/dist/js/zuix-bundler.min.js", 4 | "lineCount":28, 5 | "mappings":"A;;;;;;;;;;;;;;;;;aACC,SAAQ,CAACA,CAAD,CAAG,CAAqB,QAApB,GAAG,MAAOC,QAAV,EAA8C,WAA9C,GAA8B,MAAOC,OAArC,CAA2DA,MAAAD,QAA3D,CAA0ED,CAAA,EAA1E,CAAsG,UAAnB,GAAG,MAAOG,OAAV,EAA+BA,MAAAC,IAA/B,CAA2CD,MAAA,CAAO,EAAP,CAAUH,CAAV,CAA3C,CAAgNK,CAA1H,WAAnBC,GAAG,MAAOC,OAAVD,CAAkCC,MAAlCD,CAAiE,WAAnB,GAAG,MAAOE,OAAV,CAAkCA,MAAlC,CAA+D,WAAjB,GAAG,MAAOC,KAAV,CAAgCA,IAAhC,CAA4C,IAAKJ,aAAhN,CAAgOL,CAAA,EAApT,CAAX,CAAD,CAAuU,QAAQ,EAAE,CAA2B,MAAQ,SAAQ,EAAE,CAACU,QAASA,EAAC,CAACC,CAAD,CAAGC,CAAH,CAAKC,CAAL,CAAO,CAACC,QAASA,EAAC,CAACC,CAAD,CAAGf,CAAH,CAAK,CAAC,GAAG,CAACY,CAAA,CAAEG,CAAF,CAAJ,CAAS,CAAC,GAAG,CAACJ,CAAA,CAAEI,CAAF,CAAJ,CAAS,CAAC,IAAIC,EAAE,UAAFA,EAAc,MAAOC,QAArBD,EAA8BC,OAAQ,IAAG,CAACjB,CAAJ,EAAOgB,CAAP,CAAS,MAAOA,EAAA,CAAED,CAAF,CAAI,CAAA,CAAJ,CAAQ,IAAGG,CAAH,CAAK,MAAOA,EAAA,CAAEH,CAAF,CAAI,CAAA,CAAJ,CAAYI,EAAAA,CAAMC,KAAJ,CAAU,sBAAV,CAAiCL,CAAjC,CAAmC,GAAnC,CAAwC,MAAMI,EAAAE,KAAA,CAAO,kBAAP;AAA0BF,CAAhC,CAArI,CAA2KG,CAAAA,CAAEV,CAAA,CAAEG,CAAF,CAAFO,CAAO,CAACrB,QAAQ,EAAT,CAAaU,EAAA,CAAEI,CAAF,CAAA,CAAK,CAAL,CAAAQ,KAAA,CAAaD,CAAArB,QAAb,CAAuB,QAAQ,CAACS,CAAD,CAAG,CAAkB,MAAOI,EAAA,CAAlBH,CAAA,CAAEI,CAAF,CAAA,CAAK,CAAL,CAAAH,CAAQF,CAARE,CAAkB,EAAKF,CAAL,CAAzB,CAAlC,CAAoEY,CAApE,CAAsEA,CAAArB,QAAtE,CAAgFS,CAAhF,CAAkFC,CAAlF,CAAoFC,CAApF,CAAsFC,CAAtF,CAAzM,CAAkS,MAAOD,EAAA,CAAEG,CAAF,CAAAd,QAAnT,CAAgU,IAAhV,IAAwViB,EAAE,UAAFA,EAAc,MAAOD,QAArBC,EAA8BD,OAAtX,CAA8XF,EAAE,CAAhD,CAAkDA,CAAlD,CAAoDF,CAAAW,OAApD,CAA6DT,CAAA,EAA7D,CAAiED,CAAA,CAAED,CAAA,CAAEE,CAAF,CAAF,CAAQ,OAAOD,EAAha,CAAka,MAAOJ,EAA3b,CAAX,EAAA,CAA4c,CAAC,EAAE,CAAC,QAAQ,CAACe,CAAD,CAASvB,CAAT,CAAgBD,CAAhB,CAAwB,CA8C31B,CAAA,CAAAwB,CAAA,CAAQ,+BAAR,CAPyB,SAAtB,GAAI,MAAOvB,EAAX,EAAkCA,CAAAD,QAAlC,CAEHC,CAAAD,QAFG,CAEeyB,CAADH,KAAA,CAKvBI,IALuB,CAFd,CAOTA,IAFMC,KALG,CAKUF,CAADH,KAAA,CAElBI,IAFkB,CA5C+0B,CAAjC,CAgDh0B,CAAC,gCAAgC,CAAjC,CAhDg0B,CAAH,CAgDxxB,EAAE,CAAC,QAAQ,CAACF,CAAD,CAASvB,CAAT,CAAgBD,CAAhB,CAAwB,CAkB1E,IAAI4B,EAASA,CAATA,EAAoB,QAAQ,CAACC,CAAD,CAAO,CAGtC,GAAI,EAAgB,WAAhB,GAAA,MAAOA,EAAP,EAAoD,WAApD,GAA+B,MAAOC,UAAtC,EAAmE,cAAAC,KAAA,CAAoBD,SAAAE,UAApB,CAAnE,CAAJ,CAAA,CAHsC,IAYnCC;AALMJ,CAAAK,SAKMC,gBAAA,CAAoB,8BAApB,CAAoD,GAApD,CAZuB,CAanCC,EAAoB,UAApBA,EAAkCH,EAbC,CAkBnCI,EAAY,cAAAN,KAAA,CAAoBF,CAAAS,YAApB,CAAZD,EAAqDR,CAAAU,OAlBlB,CAmBnCC,EAAe,cAAAT,KAAA,CAAoBD,SAAAE,UAApB,CAnBoB,CAoBnCS,EAAgBA,QAAQ,CAACC,CAAD,CAAK,CAC9B,CAACb,CAAAc,aAAD,EAAsBd,CAAAe,WAAtB,EAAuC,QAAQ,EAAG,CACjD,KAAMF,EAAN,CADiD,CAAlD,CAEG,CAFH,CAD8B,CApBM,CA4BnCG,EAASA,QAAQ,CAACC,CAAD,CAAO,CAQzBF,UAAA,CAPcG,QAAQ,EAAG,CACJ,QAApB,GAAI,MAAOD,EAAX,CACCE,CArBKnB,CAAAoB,IAqBLD,EArBiBnB,CAAAqB,UAqBjBF,EArBmCnB,CAqBnCmB,iBAAA,CAA0BF,CAA1B,CADD,CAGCA,CAAAK,OAAA,EAJuB,CAOzB,CAT4BC,GAS5B,CARyB,CA5BW,CAoDnCC,EAAWA,QAAQ,CAACC,CAAD,CAAO,CAG3B,MAAI,4EAAAvB,KAAA,CAAkFuB,CAAAC,KAAlF,CAAJ,CACQ,IAAIC,IAAJ,CAAS,CAACC,MAAAC,aAAA,CAAoB,KAApB,CAAD;AAA8BJ,CAA9B,CAAT,CAA8C,CAACC,KAAMD,CAAAC,KAAP,CAA9C,CADR,CAGOD,CANoB,CApDS,CA4DnCK,EAAYA,QAAQ,CAACL,CAAD,CAAOM,CAAP,CAAaC,CAAb,CAA0B,CAC1CA,CAAL,GACCP,CADD,CACQD,CAAA,CAASC,CAAT,CADR,CAD+C,KAM5CQ,EAAY,IANgC,CAQ5CC,EA3CoBC,0BA2CpBD,GADOT,CAAAC,KAPqC,CAU5CU,EAAeA,QAAQ,EAAG,CACP,IAAA,EAAA,CAAA,YAAA,CAAA,UAAA,CAAA,OAAA,CAAA,UAAA,CAhCtBC,EAAA,CAAc,EAAAC,OAAA,CAAUD,CAAV,CAEd,KADA,IAAIpD,EAAIoD,CAAA3C,OACR,CAAOT,CAAA,EAAP,CAAA,CAAY,CACX,IAAIsD,EA6BMN,CA7BK,CAAU,IAAV,CAAiBI,CAAA,CAAYpD,CAAZ,CAAjB,CACf,IAAwB,UAAxB,GAAI,MAAOsD,EAAX,CACC,GAAI,CACHA,CAAA9C,KAAA,CA0BQwC,CA1BR,CA0BQA,CA1BR,CADG,CAEF,MAAOpB,CAAP,CAAW,CACZD,CAAA,CAAcC,CAAd,CADY,CALH,CA6BiB,CAsC7BoB,EAAAO,WAAA,CAAuBP,CAAAQ,KAEvB,IAAIlC,CAAJ,CAAuB,CACtB,IAAAmC,EAAaC,CArGP3C,CAAAoB,IAqGOuB,EArGK3C,CAAAqB,UAqGLsB,EArGuB3C,CAqGvB2C,iBAAA,CAA0BlB,CAA1B,CACbV,WAAA,CAAW,QAAQ,EAAG,CACrBX,CAAAwC,KAAA,CAAiBF,CACjBtC,EAAAyC,SAAA,CAAqBd,CAnGvB,KAAIe,EAAQ,IAAIC,UAAJ,CAAe,OAAf,CAoGJ3C,EAnGR4C,cAAA,CAAmBF,CAAnB,CAoGEV,EAAA,EACApB,EAAA,CAAO0B,CAAP,CACAT,EAAAO,WAAA,CAAuBP,CAAAgB,KANF,CAAtB,CAFsB,CAAvB,IApCcC,SAAQ,EAAG,CACvB,IAAKvC,CAAL;AAAuBuB,CAAvB,EAAgC1B,CAAhC,GAA+CR,CAAAmD,WAA/C,CAAgE,CAE/D,IAAIC,EAAS,IAAID,UACjBC,EAAAC,UAAA,CAAmBC,QAAQ,EAAG,CAC7B,IAAIC,EAAM5C,CAAA,CAAgByC,CAAAI,OAAhB,CAAgCJ,CAAAI,OAAAC,QAAA,CAAsB,cAAtB,CAAsC,uBAAtC,CAC9BzD,EAAA0D,KAAAC,CAAUJ,CAAVI,CAAe,QAAfA,CACZ,GAAW3D,CAAA4D,SAAAhB,KAAX,CAAgCW,CAAhC,CAEAtB,EAAAO,WAAA,CAAuBP,CAAAgB,KACvBb,EAAA,EAN6B,CAQ9BgB,EAAAS,cAAA,CAAqBpC,CAArB,CACAQ,EAAAO,WAAA,CAAuBP,CAAAQ,KAZwC,CAAhE,IAgBKC,EAcL,GAbCA,CAaD,CAbcC,CAlFT3C,CAAAoB,IAkFSuB,EAlFG3C,CAAAqB,UAkFHsB,EAlFqB3C,CAkFrB2C,iBAAA,CAA0BlB,CAA1B,CAad,EAXIS,CAAJ,CACClC,CAAA4D,SAAAhB,KADD,CACsBF,CADtB,CAGc1C,CAAA0D,KAAAI,CAAUpB,CAAVoB,CAAsB,QAAtBA,CAHd,GAME9D,CAAA4D,SAAAhB,KANF,CAMuBF,CANvB,CAWA,CAFAT,CAAAO,WAEA,CAFuBP,CAAAgB,KAEvB,CADAb,CAAA,EACA,CAAApB,CAAA,CAAO0B,CAAP,CA/BuB,CAAXQ,CAiDd,EA/D+C,CA5DX,CA6HnCa,EAAWjC,CAAAkC,UAMd,IAAyB,WAAzB,GAAI,MAAO/D,UAAX,EAAwCA,SAAAgE,iBAAxC,CACC,MAAO,SAAQ,CAACxC,CAAD,CAAOM,CAAP,CAAaC,CAAb,CAA0B,CACxCD,CAAA,CAAOA,CAAP,EAAeN,CAAAM,KAAf;AAA4B,UAEvBC,EAAL,GACCP,CADD,CACQD,CAAA,CAASC,CAAT,CADR,CAGA,OAAOxB,UAAAgE,iBAAA,CAA2BxC,CAA3B,CAAiCM,CAAjC,CANiC,CAU1CgC,EAAAG,MAAA,CAAiBC,QAAQ,EAAE,EAC3BJ,EAAAvB,WAAA,CAAsBuB,CAAAtB,KAAtB,CAAsC,CACtCsB,EAAAK,QAAA,CAAmB,CACnBL,EAAAd,KAAA,CAAgB,CAEhBc,EAAAM,MAAA,CACAN,CAAAO,aADA,CAEAP,CAAAQ,WAFA,CAGAR,CAAAS,QAHA,CAIAT,CAAAU,QAJA,CAKAV,CAAAW,QALA,CAMAX,CAAAY,WANA,CAOC,IAED,OA9BY5E,SAAQ,CAAC0B,CAAD,CAAOM,CAAP,CAAaC,CAAb,CAA0B,CAC5C,MAAO,KAAIF,CAAJ,CAAcL,CAAd,CAAoBM,CAApB,EAA4BN,CAAAM,KAA5B,EAAyC,UAAzC,CAAqDC,CAArD,CADqC,CA3H9C,CAHsC,CAAf,CA8JJ,WA9JI,GA8JpB,MAAOrD,KA9Ja,EA8JWA,IA9JX,EA+JF,WA/JE,GA+JpB,MAAOF,OA/Ja,EA+JaA,MA/Jb,EAgKpB,IAAAmG,QAhKoB,CAsKF,YAAtB,GAAI,MAAOxG,EAAX,EAAqCA,CAAAD,QAArC,GACEC,CAAAD,QAAA4B,OADF,CAC0BA,CAD1B,CAxL0E,CAAjC,CAgMvC,EAhMuC,CAhDsxB,CAgPzzB,EAAE,CAAC,QAAQ,CAACJ,CAAD,CAASvB,CAAT,CAAgBD,CAAhB,CAAwB,CA8BzC0G,QAASA,EAAiB,CAACC,CAAD,CAAa,CACnC,MAAOC,EAAA,CAAcD,CAAd,CAD4B,CAhBvC,MAAME,EAAMC,IAAAC,MAAA,CAA2B,aAA3B,CAAWD,IAAAE,OAAA,EAAX,CAAAC,SAAA,CAAmD,EAAnD,CAAZ;AACMC,EAAsB,IAAIC,MAAJ,CAAW,YAAX,CAA0BN,CAA1B,CAAgC,aAAhC,CAA+C,GAA/C,CAD5B,CAGMO,EAAwB,4BAH9B,CAIMC,EAAsB,qBAJ5B,CAQMT,EAAgB,CAClB,IAAK,SADa,CAElB,IAAK,SAFa,CAGlB,IAAK,SAHa,CAIlB,SAAU,SAJQ,CAKlB,SAAU,SALQ,CAYtB3G,EAAAD,QAAA,CAAiBsH,QAAkB,CAACC,CAAD,CAAMC,CAAN,CAAe,CAe9CC,QAASA,EAAQ,CAACC,CAAD,CAAMC,CAAN,CAAa,CAC1B,GAAI,CAACA,CAAL,CACI,MAAOA,EAGLpE,EAAAA,CAAO,MAAOoE,EAEpB,OAAa,QAAb,GAAIpE,CAAJ,CA7C0C,iBA8CtC,GA9CDqE,MAAA/B,UAAAoB,SAAA3F,KAAA,CA8CcqG,CA9Cd,CA8CC,CACW,OADX,CACqBd,CADrB,CAC2B,GAD3B,EACkCgB,CAAAC,KAAA,CAAaH,CAAb,CADlC,CACwD,CADxD,EAC6D,KAD7D,CAIOA,CALX,CAQa,UAAb,GAAIpE,CAAJ,CACW,OADX,CACqBsD,CADrB,CAC2B,GAD3B,EACkCkB,CAAAD,KAAA,CAAeH,CAAf,CADlC,CAC0D,CAD1D,EAC+D,KAD/D,CAIOA,CAnBmB,CAd9BH,CAAA,GAAYA,CAAZ,CAAsB,EAAtB,CAKA,IAAuB,QAAvB,GAAI,MAAOA,EAAX,EAAsD,QAAtD,GAAmC,MAAOA,EAA1C,CACIA,CAAA,CAAU,CAACQ,MAAOR,CAAR,CAGd,OAAMO,EAAY,EAAlB,CACMF,EAAU,EA+BZI,EAAA,CADAT,CAAAU,OAAJ;AAAsB,CAACV,CAAAQ,MAAvB,CACUG,IAAAC,UAAA,CAAeb,CAAf,CADV,CAGUY,IAAAC,UAAA,CAAeb,CAAf,CAAoBC,CAAAU,OAAA,CAAiB,IAAjB,CAAwBT,CAA5C,CAAsDD,CAAAQ,MAAtD,CAKV,IAAmB,QAAnB,GAAI,MAAOC,EAAX,CACI,MAAOxE,OAAA,CAAOwE,CAAP,CAMXA,EAAA,CAAMA,CAAA3C,QAAA,CAAY+B,CAAZ,CAAiCX,CAAjC,CAEN,OAAyB,EAAzB,GAAIqB,CAAAxG,OAAJ,EAAiD,CAAjD,GAA8BsG,CAAAtG,OAA9B,CACW0G,CADX,CAOOA,CAAA3C,QAAA,CAAY4B,CAAZ,CAAiC,QAAQ,CAACmB,CAAD,CAAQ9E,CAAR,CAAc+E,CAAd,CAA0B,CACtE,GAAa,GAAb,GAAI/E,CAAJ,CACI,MAAOsE,EAAA,CAAQS,CAAR,CAAArB,SAAA,EAGLsB,EAAAA,CAAKR,CAAA,CAAUO,CAAV,CACLE,EAAAA,CAAeD,CAAAtB,SAAA,EAErB,IAAIG,CAAArF,KAAA,CAA2ByG,CAA3B,CAAJ,CACI,KAAM,KAAIC,SAAJ,CAAc,+BAAd,CAAgDF,CAAA3E,KAAhD,CAAN,CAGJ,MAAO4E,EAZ+D,CAAnE,CAjEuC,CAlCT,CAAjC,CAmHN,EAnHM,CAhPuzB,CAmWzzB,EAAE,CAAC,QAAQ,CAAChH,CAAD,CAASvB,CAAT,CAAgBD,CAAhB,CAAwB,CAiDzC0I,QAASA,EAAU,EAAG,CAElB,IAAMC,EAAYhH,IAAAiH,OAAA,EAKlB,KAAAC,EADAA,+FACAA,CAA8BC,CAAA,IAAIC,IAAJD,aAAA,EAE9BD;CAAA,CADAA,CACA,CADiB,OACjB,EAAiB,sBAAjB,CAAwCF,CAAApH,OAAxC,CAAyD,IAAzD,CACAsH,EAAA,EAAiB,OACjB,KAAK,IAAI/H,EAAI,CAAb,CAAgBA,CAAhB,CAAoB6H,CAAApH,OAApB,CAAsCT,CAAA,EAAtC,CAA2C,CACvC,MAAMkI,EAAIL,CAAA,CAAU7H,CAAV,CACV,KAAImI,EAAQ,EACE,KAAd,EAAID,CAAAnH,KAAJ,GACIoH,CADJ,EACa,SADb,CAGa,KAAb,EAAID,CAAAE,IAAJ,GACID,CADJ,EACa,QADb,CAGoB,KAApB,EAAID,CAAAG,WAAJ,GACIF,CADJ,EACa,OADb,CAGA,KAAIG,EAAQJ,CAAAK,YACG,KAAf,EAAIL,CAAAM,MAAJ,GACIF,CADJ,CACYJ,CAAAM,MADZ,CACoB,IADpB,CACyBF,CADzB,CAC+B,GAD/B,CAGAP,EAAA,EAAiB,SAAjB,CAA2BI,CAC3BJ,EAAA,EAAiB,SAAjB,CAA2BO,CAC3BP,EAAA,EAAiB,OAlBsB,CAuBvCD,CAAAA,CAHJC,CAGID,CADa,eACbA,CAAyBW,CAAA,CAAU5H,IAAAiH,OAAA,EAAV,CAE7BA,EAAA,CAASA,CAAAtD,QAAA,CAAe,IAAI6B,MAAJ,CAAWqC,CAAAC,aAAX,CAA0C,SAA1C,CAAqD,GAArD,CAAf,CACLD,CAAAC,aADK,CAC0B,UAD1B,CAETb,EAAA,CAASA,CAAAtD,QAAA,CAAe,IAAI6B,MAAJ,CAAWqC,CAAAE,WAAX,CAAwC,SAAxC,CAAmD,GAAnD,CAAf,CACLF,CAAAE,WADK,CACwB,UADxB,CAGHpG,EAAAA,CAAO,IAAIE,IAAJ,CAAS,CAAC,cAAD;AAAkBoF,CAAlB,CAA2B,IAA3B,CAAT,CAA2C,CAACrF,KAAM,0BAAP,CAA3C,CACboG,EAAA/H,OAAA,CAAiB0B,CAAjB,CAzCuBsG,eAyCvB,CACA,OAAOhB,EA3CW,CApBtB,MAAMe,EAAYnI,CAAA,CAAQ,aAAR,CAAlB,CACM+H,EAAY/H,CAAA,CAAQ,cAAR,CADlB,CAEMgI,EAAoBhI,CAAA,CAAQ,0BAAR,CAAA,EAgE1BvB,EAAAD,QAAA,CAAiBsH,QAAQ,CAAC5F,CAAD,CAAO,CAC5B,GAAY,IAAZ,EAAIC,IAAJ,CACIkI,KAAA,CAAM,wDAAN,CADJ,KAKA,OADAlI,KAAA+G,WACO/G,CADW+G,CACX/G,CAAAA,IANqB,CA/FS,CAAjC,CAwGN,CAAC,2BAA2B,CAA5B,CAA8B,cAAc,CAA5C,CAA8C,eAAe,CAA7D,CAxGM,CAnWuzB,CA2c5vB,EAAE,CAAC,QAAQ,CAACH,CAAD,CAASvB,CAAT,CAAgBD,CAAhB,CAAwB,CA2BtG,MAAM8J,EAAmBlC,MAAAmC,OAAA,CAAc,CACnCC,cACI,iBAF+B,CAGnCC,WACI,cAJ+B,CAKnCC,gBACI,mBAN+B,CAOnCC,cACI,iBAR+B;AASnCC,YACI,eAV+B,CAWnCC,cACI,iBAZ+B,CAanCC,eACI,kBAd+B,CAenCC,WACI,cAhB+B,CAiBnCd,aACI,gBAlB+B,CAmBnCe,cACI,iBApB+B,CAqBnCC,eACI,kBAtB+B,CAuBnCC,WACI,cAxB+B,CAyBnChB,WACI,aA1B+B,CAAd,CAiCzBzJ,EAAAD,QAAA,CAAiBsH,QAAQ,CAAC5F,CAAD,CAAO,CAC5B,MAAOoI,EADqB,CA5DsE,CAAjC,CAgEnE,EAhEmE,CA3c0vB,CAA5c,CA2gB5W,EA3gB4W,CA2gBzW,CAAC,CAAD,CA3gByW,CAAA,CA2gBpW,CA3gBoW,CAAlC,CAAjV;", 6 | "sources":["/home/gene/WebstormProjects/zuix/dist/js/zuix-bundler.js"], 7 | "names":["f","exports","module","define","amd","zuixBundler","g","window","global","self","r","e","n","t","o","i","c","require","u","a","Error","code","p","call","length","_dereq_","factory","root","zuix","saveAs","view","navigator","test","userAgent","save_link","document","createElementNS","can_use_save_link","is_safari","HTMLElement","safari","is_chrome_ios","throw_outside","ex","setImmediate","setTimeout","revoke","file","revoker","revokeObjectURL","URL","webkitURL","remove","arbitrary_revoke_timeout","auto_bom","blob","type","Blob","String","fromCharCode","FileSaver","name","no_auto_bom","filesaver","force","force_saveable_type","dispatch_all","event_types","concat","listener","readyState","INIT","object_url","createObjectURL","href","download","event","MouseEvent","dispatchEvent","DONE","fs_error","FileReader","reader","onloadend","reader.onloadend","url","result","replace","open","popup","location","readAsDataURL","opened","FS_proto","prototype","msSaveOrOpenBlob","abort","FS_proto.abort","WRITING","error","onwritestart","onprogress","onwrite","onabort","onerror","onwriteend","content","escapeUnsafeChars","unsafeChar","ESCAPED_CHARS","UID","Math","floor","random","toString","PLACE_HOLDER_REGEXP","RegExp","IS_NATIVE_CODE_REGEXP","UNSAFE_CHARS_REGEXP","module.exports","obj","options","replacer","key","value","Object","regexps","push","functions","space","str","isJSON","JSON","stringify","match","valueIndex","fn","serializedFn","TypeError","saveBundle","bundleObj","bundle","headerSummary","toISOString","Date","b","ctype","css","controller","cpath","componentId","using","serialize","_optionAttributes","dataUiLoaded","zuixLoaded","fileSaver","bundleFileName","alert","OptionAttributes","freeze","dataBindModel","dataBindTo","dataUiComponent","dataUiContext","dataUiField","dataUiInclude","dataUiLazyload","dataUiLoad","dataUiOptions","dataUiPriority","dataUiView"] 8 | } 9 | -------------------------------------------------------------------------------- /source/js/zuix-bundler.js: -------------------------------------------------------------------------------- 1 | /* zUIx v1.0.1 18.08.30 21:48:09 */ 2 | 3 | /** @typedef {Zuix} window.zuix */ 4 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.zuixBundler = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 30 | */ 31 | 32 | /* global define */ 33 | 34 | 'use strict'; 35 | 36 | // TODO: detect whether running in a browser environment or not 37 | (function(root, factory) { 38 | if (typeof define === 'function' && define.amd) { 39 | // AMD. Register as an anonymous module. 40 | define('zuix', function() { 41 | return (root.zuix = (factory).call(root)); 42 | }); 43 | } else if (typeof module === 'object' && module.exports) { 44 | // Node 45 | module.exports = (factory).call(root); 46 | } else { 47 | // Browser globals 48 | root.zuix = (factory).call(root); 49 | } 50 | }(this, _dereq_('./zuix-bundler/ZuixBundler.js'))); 51 | 52 | },{"./zuix-bundler/ZuixBundler.js":4}],2:[function(_dereq_,module,exports){ 53 | /* FileSaver.js 54 | * A saveAs() FileSaver implementation. 55 | * 1.3.2 56 | * 2016-06-16 18:25:19 57 | * 58 | * By Eli Grey, http://eligrey.com 59 | * License: MIT 60 | * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md 61 | */ 62 | 63 | /* eslint-disable */ 64 | 65 | /* global self */ 66 | /* jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ 67 | 68 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 69 | 70 | var saveAs = saveAs || (function(view) { 71 | "use strict"; 72 | // IE <10 is explicitly unsupported 73 | if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { 74 | return; 75 | } 76 | var 77 | doc = view.document 78 | // only get URL when necessary in case Blob.js hasn't overridden it yet 79 | , get_URL = function() { 80 | return view.URL || view.webkitURL || view; 81 | } 82 | , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") 83 | , can_use_save_link = "download" in save_link 84 | , click = function(node) { 85 | var event = new MouseEvent("click"); 86 | node.dispatchEvent(event); 87 | } 88 | , is_safari = /constructor/i.test(view.HTMLElement) || view.safari 89 | , is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent) 90 | , throw_outside = function(ex) { 91 | (view.setImmediate || view.setTimeout)(function() { 92 | throw ex; 93 | }, 0); 94 | } 95 | , force_saveable_type = "application/octet-stream" 96 | // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to 97 | , arbitrary_revoke_timeout = 1000 * 40 // in ms 98 | , revoke = function(file) { 99 | var revoker = function() { 100 | if (typeof file === "string") { // file is an object URL 101 | get_URL().revokeObjectURL(file); 102 | } else { // file is a File 103 | file.remove(); 104 | } 105 | }; 106 | setTimeout(revoker, arbitrary_revoke_timeout); 107 | } 108 | , dispatch = function(filesaver, event_types, event) { 109 | event_types = [].concat(event_types); 110 | var i = event_types.length; 111 | while (i--) { 112 | var listener = filesaver["on" + event_types[i]]; 113 | if (typeof listener === "function") { 114 | try { 115 | listener.call(filesaver, event || filesaver); 116 | } catch (ex) { 117 | throw_outside(ex); 118 | } 119 | } 120 | } 121 | } 122 | , auto_bom = function(blob) { 123 | // prepend BOM for UTF-8 XML and text/* types (including HTML) 124 | // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF 125 | if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { 126 | return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type}); 127 | } 128 | return blob; 129 | } 130 | , FileSaver = function(blob, name, no_auto_bom) { 131 | if (!no_auto_bom) { 132 | blob = auto_bom(blob); 133 | } 134 | // First try a.download, then web filesystem, then object URLs 135 | var 136 | filesaver = this 137 | , type = blob.type 138 | , force = type === force_saveable_type 139 | , object_url 140 | , dispatch_all = function() { 141 | dispatch(filesaver, "writestart progress write writeend".split(" ")); 142 | } 143 | // on any filesys errors revert to saving with object URLs 144 | , fs_error = function() { 145 | if ((is_chrome_ios || (force && is_safari)) && view.FileReader) { 146 | // Safari doesn't allow downloading of blob urls 147 | var reader = new FileReader(); 148 | reader.onloadend = function() { 149 | var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;'); 150 | var popup = view.open(url, '_blank'); 151 | if(!popup) view.location.href = url; 152 | url=undefined; // release reference before dispatching 153 | filesaver.readyState = filesaver.DONE; 154 | dispatch_all(); 155 | }; 156 | reader.readAsDataURL(blob); 157 | filesaver.readyState = filesaver.INIT; 158 | return; 159 | } 160 | // don't create more object URLs than needed 161 | if (!object_url) { 162 | object_url = get_URL().createObjectURL(blob); 163 | } 164 | if (force) { 165 | view.location.href = object_url; 166 | } else { 167 | var opened = view.open(object_url, "_blank"); 168 | if (!opened) { 169 | // Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html 170 | view.location.href = object_url; 171 | } 172 | } 173 | filesaver.readyState = filesaver.DONE; 174 | dispatch_all(); 175 | revoke(object_url); 176 | } 177 | ; 178 | filesaver.readyState = filesaver.INIT; 179 | 180 | if (can_use_save_link) { 181 | object_url = get_URL().createObjectURL(blob); 182 | setTimeout(function() { 183 | save_link.href = object_url; 184 | save_link.download = name; 185 | click(save_link); 186 | dispatch_all(); 187 | revoke(object_url); 188 | filesaver.readyState = filesaver.DONE; 189 | }); 190 | return; 191 | } 192 | 193 | fs_error(); 194 | } 195 | , FS_proto = FileSaver.prototype 196 | , saveAs = function(blob, name, no_auto_bom) { 197 | return new FileSaver(blob, name || blob.name || "download", no_auto_bom); 198 | } 199 | ; 200 | // IE 10+ (native saveAs) 201 | if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { 202 | return function(blob, name, no_auto_bom) { 203 | name = name || blob.name || "download"; 204 | 205 | if (!no_auto_bom) { 206 | blob = auto_bom(blob); 207 | } 208 | return navigator.msSaveOrOpenBlob(blob, name); 209 | }; 210 | } 211 | 212 | FS_proto.abort = function(){}; 213 | FS_proto.readyState = FS_proto.INIT = 0; 214 | FS_proto.WRITING = 1; 215 | FS_proto.DONE = 2; 216 | 217 | FS_proto.error = 218 | FS_proto.onwritestart = 219 | FS_proto.onprogress = 220 | FS_proto.onwrite = 221 | FS_proto.onabort = 222 | FS_proto.onerror = 223 | FS_proto.onwriteend = 224 | null; 225 | 226 | return saveAs; 227 | }( 228 | typeof self !== "undefined" && self 229 | || typeof window !== "undefined" && window 230 | || this.content 231 | )); 232 | // `self` is undefined in Firefox for Android content script context 233 | // while `this` is nsIContentFrameMessageManager 234 | // with an attribute `content` that corresponds to the window 235 | 236 | if (typeof module !== "undefined" && module.exports) { 237 | module.exports.saveAs = saveAs; 238 | } else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) { 239 | define("FileSaver.js", function() { 240 | return saveAs; 241 | }); 242 | } 243 | 244 | },{}],3:[function(_dereq_,module,exports){ 245 | /* 246 | Copyright (c) 2014, Yahoo! Inc. All rights reserved. 247 | Copyrights licensed under the New BSD License. 248 | See the accompanying LICENSE file for terms. 249 | 250 | https://github.com/yahoo/serialize-javascript 251 | 252 | */ 253 | 254 | const isRegExp = function(re) { 255 | return Object.prototype.toString.call(re) === '[object RegExp]'; 256 | }; 257 | 258 | const UID = Math.floor(Math.random() * 0x10000000000).toString(16); 259 | const PLACE_HOLDER_REGEXP = new RegExp('"@__(F|R)-' + UID + '-(\\d+)__@"', 'g'); 260 | 261 | const IS_NATIVE_CODE_REGEXP = /\{\s*\[native code\]\s*\}/g; 262 | const UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g; 263 | 264 | // Mapping of unsafe HTML and invalid JavaScript line terminator chars to their 265 | // Unicode char counterparts which are safe to use in JavaScript strings. 266 | const ESCAPED_CHARS = { 267 | '<': '\\u003C', 268 | '>': '\\u003E', 269 | '/': '\\u002F', 270 | '\u2028': '\\u2028', 271 | '\u2029': '\\u2029' 272 | }; 273 | 274 | function escapeUnsafeChars(unsafeChar) { 275 | return ESCAPED_CHARS[unsafeChar]; 276 | } 277 | 278 | module.exports = function serialize(obj, options) { 279 | options || (options = {}); 280 | 281 | // component item serialization 282 | 283 | // Backwards-compatability for `space` as the second argument. 284 | if (typeof options === 'number' || typeof options === 'string') { 285 | options = {space: options}; 286 | } 287 | 288 | const functions = []; 289 | const regexps = []; 290 | 291 | // Returns placeholders for functions and regexps (identified by index) 292 | // which are later replaced by their string representation. 293 | function replacer(key, value) { 294 | if (!value) { 295 | return value; 296 | } 297 | 298 | const type = typeof value; 299 | 300 | if (type === 'object') { 301 | if (isRegExp(value)) { 302 | return '@__R-' + UID + '-' + (regexps.push(value) - 1) + '__@'; 303 | } 304 | 305 | return value; 306 | } 307 | 308 | if (type === 'function') { 309 | return '@__F-' + UID + '-' + (functions.push(value) - 1) + '__@'; 310 | } 311 | 312 | return value; 313 | } 314 | 315 | let str; 316 | 317 | // Creates a JSON string representation of the value. 318 | // NOTE: Node 0.12 goes into slow mode with extra JSON.stringify() args. 319 | if (options.isJSON && !options.space) { 320 | str = JSON.stringify(obj); 321 | } else { 322 | str = JSON.stringify(obj, options.isJSON ? null : replacer, options.space); 323 | } 324 | 325 | // Protects against `JSON.stringify()` returning `undefined`, by serializing 326 | // to the literal string: "undefined". 327 | if (typeof str !== 'string') { 328 | return String(str); 329 | } 330 | 331 | // Replace unsafe HTML and invalid JavaScript line terminator chars with 332 | // their safe Unicode char counterpart. This _must_ happen before the 333 | // regexps and functions are serialized and added back to the string. 334 | str = str.replace(UNSAFE_CHARS_REGEXP, escapeUnsafeChars); 335 | 336 | if (functions.length === 0 && regexps.length === 0) { 337 | return str; 338 | } 339 | 340 | // Replaces all occurrences of function and regexp placeholders in the JSON 341 | // string with their string representations. If the original value can not 342 | // be found, then `undefined` is used. 343 | return str.replace(PLACE_HOLDER_REGEXP, function(match, type, valueIndex) { 344 | if (type === 'R') { 345 | return regexps[valueIndex].toString(); 346 | } 347 | 348 | const fn = functions[valueIndex]; 349 | const serializedFn = fn.toString(); 350 | 351 | if (IS_NATIVE_CODE_REGEXP.test(serializedFn)) { 352 | throw new TypeError('Serializing native function: ' + fn.name); 353 | } 354 | 355 | return serializedFn; 356 | }); 357 | }; 358 | 359 | },{}],4:[function(_dereq_,module,exports){ 360 | /* 361 | * Copyright 2015-2018 G-Labs. All Rights Reserved. 362 | * https://zuixjs.github.io/zuix 363 | * 364 | * Licensed under the Apache License, Version 2.0 (the "License"); 365 | * you may not use this file except in compliance with the License. 366 | * You may obtain a copy of the License at 367 | * 368 | * http://www.apache.org/licenses/LICENSE-2.0 369 | * 370 | * Unless required by applicable law or agreed to in writing, software 371 | * distributed under the License is distributed on an "AS IS" BASIS, 372 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 373 | * See the License for the specific language governing permissions and 374 | * limitations under the License. 375 | */ 376 | 377 | /* 378 | * 379 | * This file is part of 380 | * zUIx, Javascript library for component-based development. 381 | * https://zuixjs.github.io/zuix 382 | * 383 | * @author Generoso Martello 384 | */ 385 | 386 | 'use strict'; 387 | 388 | const fileSaver = _dereq_('./FileSaver'); 389 | const serialize = _dereq_('./Serializer'); 390 | const _optionAttributes = _dereq_('../zuix/OptionAttributes')(); 391 | 392 | /** 393 | * Create application bundle containing all components 394 | * and resources used in the app. This method can be called 395 | * from the browser developer console. When using lazy-loading 396 | * only components loaded so far will be bundled (incremental bundle). 397 | * To force inclusion of all components/resources 398 | * disable lazy-loading first by calling 399 | * `zuix.lazyLoad(false)` and then `zuix.saveBundle()`. 400 | * After the bundle is created it will be downloaded 401 | * by the browser as 'app.bundle.js' file that you can 402 | * then compress, copy and include in your app. 403 | * This will speed-up resource loading and improve 404 | * user experience. 405 | * 406 | * @return {string} bundle 407 | */ 408 | function saveBundle() { 409 | const bundleFileName = 'app.bundle.js'; 410 | const bundleObj = zuix.bundle(); 411 | let headerSummary = '\n/*'; 412 | headerSummary += '\n * zUIx Application Bundle'; 413 | headerSummary += '\n * '; 414 | headerSummary += '\n * '+bundleFileName+' generated by *zuix-bundler*'; 415 | headerSummary += '\n * on '+new Date().toISOString(); 416 | headerSummary += '\n * '; 417 | headerSummary += '\n * Resource list ('+bundleObj.length+'):'; 418 | headerSummary += '\n * '; 419 | for (let i = 0; i < bundleObj.length; i++) { 420 | const b = bundleObj[i]; 421 | let ctype = ''; 422 | if (b.view != null) { 423 | ctype += '[html] '; 424 | } 425 | if (b.css != null) { 426 | ctype += '[css] '; 427 | } 428 | if (b.controller != null) { 429 | ctype += '[js] '; 430 | } 431 | let cpath = b.componentId; 432 | if (b.using != null) { 433 | cpath = b.using+' ('+cpath+')'; 434 | } 435 | headerSummary += '\n * - '+ctype; 436 | headerSummary += '\n * '+cpath; 437 | headerSummary += '\n * '; 438 | } 439 | headerSummary += '\n * '; 440 | headerSummary += '\n*/'; 441 | headerSummary += '\n\n'; 442 | let bundle = headerSummary + serialize(zuix.bundle()); 443 | // revert loaded status before exporting 444 | bundle = bundle.replace(new RegExp(_optionAttributes.dataUiLoaded+'="true"', 'g'), 445 | _optionAttributes.dataUiLoaded+'="false"'); 446 | bundle = bundle.replace(new RegExp(_optionAttributes.zuixLoaded+'="true"', 'g'), 447 | _optionAttributes.zuixLoaded+'="false"'); 448 | // save bundle 449 | const blob = new Blob(['zuix.bundle(' + bundle + ');'], {type: 'text/plain;charset=utf-8'}); 450 | fileSaver.saveAs(blob, bundleFileName); 451 | return bundle; 452 | } 453 | 454 | module.exports = function(root) { 455 | if (zuix == null) { 456 | alert('Error: ZuixBundler requires Zuix to be included first.'); 457 | return; 458 | } 459 | zuix.saveBundle = saveBundle; 460 | return zuix; 461 | }; 462 | 463 | },{"../zuix/OptionAttributes":5,"./FileSaver":2,"./Serializer":3}],5:[function(_dereq_,module,exports){ 464 | /* 465 | * Copyright 2015-2018 G-Labs. All Rights Reserved. 466 | * https://zuixjs.github.io/zuix 467 | * 468 | * Licensed under the Apache License, Version 2.0 (the "License"); 469 | * you may not use this file except in compliance with the License. 470 | * You may obtain a copy of the License at 471 | * 472 | * http://www.apache.org/licenses/LICENSE-2.0 473 | * 474 | * Unless required by applicable law or agreed to in writing, software 475 | * distributed under the License is distributed on an "AS IS" BASIS, 476 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 477 | * See the License for the specific language governing permissions and 478 | * limitations under the License. 479 | */ 480 | 481 | /* 482 | * 483 | * This file is part of 484 | * zUIx, Javascript library for component-based development. 485 | * https://zuixjs.github.io/zuix 486 | * 487 | * @author Generoso Martello 488 | */ 489 | 490 | const OptionAttributes = Object.freeze({ 491 | dataBindModel: 492 | 'data-bind-model', 493 | dataBindTo: 494 | 'data-bind-to', 495 | dataUiComponent: 496 | 'data-ui-component', 497 | dataUiContext: 498 | 'data-ui-context', 499 | dataUiField: 500 | 'data-ui-field', 501 | dataUiInclude: 502 | 'data-ui-include', 503 | dataUiLazyload: 504 | 'data-ui-lazyload', 505 | dataUiLoad: 506 | 'data-ui-load', 507 | dataUiLoaded: 508 | 'data-ui-loaded', 509 | dataUiOptions: 510 | 'data-ui-options', 511 | dataUiPriority: 512 | 'data-ui-priority', 513 | dataUiView: 514 | 'data-ui-view', 515 | zuixLoaded: 516 | 'zuix-loaded' 517 | }); 518 | 519 | /** 520 | * @param root 521 | * @return {Zuix} 522 | */ 523 | module.exports = function(root) { 524 | return OptionAttributes; 525 | }; 526 | 527 | },{}]},{},[1])(1) 528 | }); 529 | -------------------------------------------------------------------------------- /docs/js/zuix.min.js: -------------------------------------------------------------------------------- 1 | /* zUIx v1.0.1 18.08.30 21:48:09 */ 2 | 3 | /* 4 | @license 5 | Copyright 2015-2018 G-Labs. All Rights Reserved. 6 | https://zuixjs.github.io/zuix 7 | 8 | Licensed under the Apache License, Version 2.0 (the "License"); 9 | you may not use this file except in compliance with the License. 10 | You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software 15 | distributed under the License is distributed on an "AS IS" BASIS, 16 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | See the License for the specific language governing permissions and 18 | limitations under the License. 19 | */ 20 | 'use strict';(function(m){"object"===typeof exports&&"undefined"!==typeof module?module.exports=m():"function"===typeof define&&define.amd?define([],m):("undefined"!==typeof window?window:"undefined"!==typeof global?global:"undefined"!==typeof self?self:this).zuix=m()})(function(){return function(){function m(r,x,a){function l(e,h){if(!x[e]){if(!r[e]){var b="function"==typeof require&&require;if(!h&&b)return b(e,!0);if(k)return k(e,!0);h=Error("Cannot find module '"+e+"'");throw h.code="MODULE_NOT_FOUND", 21 | h;}h=x[e]={exports:{}};r[e][0].call(h.exports,function(b){return l(r[e][1][b]||b)},h,h.exports,m,r,x,a)}return x[e].exports}for(var k="function"==typeof require&&require,f=0;f=e.length||b.willBreak())&&k();return!1}function k(d){h=-1;e.length=0;e=[];b.status(null!=d?d:"done")}function f(){const a=e[h];if(null==a)return!1; 22 | const f=function(){null!==d&&(cancelAnimationFrame(d),d=null);b.doWork(a.item,function(){d=requestAnimationFrame(l)})||l()};if(a.cancelable)if(b.willBreak())k("stopped");else if(null==d)d=requestAnimationFrame(f);else return!1;else f();return!0}a.prototype.isReady=function(){return 0===e.length||-1===h};a.prototype.getJobs=function(){return e};a.prototype.setJobs=function(d){0a.priority?1:a.priority>b.priority?-1:0});f.taskCheck()};f.taskCheck=function(){for(let e=0;e=a)break}}return this};g.ajax=function(c){let b;b=d.isNoU(c)||d.isNoU(c.url)?c:c.url;const a=new XMLHttpRequest;a.open("GET",b);a.onload=function(){200===a.status?d.isFunction(c.success)&&c.success(a.responseText):d.isFunction(c.error)&&c.error(a);d.isFunction(c.then)&&c.then(a)};a.send();return this};g.hasClass=function(c,b){b=b.match(/\S+/g)||[];let a=!1;g.each(b,function(b,d){if(a=c.classList?c.classList.contains(d):(new RegExp("(^| )"+ 46 | d+"( |$)","gi")).test(c.className))return!1});return a};g.classExists=function(c){c=c.match(/\S+/g)||[];let b=!1;g.each(c,function(c,a){c=document.styleSheets;if(null!=c)for(let d=0;dd.right-b||e.right+1d.bottom-b||e.bottom+1a?0:+a,b.length)===b});r.exports=g},{"./Logger":2,"./Util.js":4}],6:[function(m,r,x){m=m("./zuix/Zuix.js");"object"===typeof r&&r.exports?r.exports=m.call(this):this.zuix=m.call(this)},{"./zuix/Zuix.js":12}],7:[function(m, 56 | r,x){r.exports=function(a){return null}},{}],8:[function(m,r,x){function a(b,a,e){h=b;this._options=null;this.contextId=null==a||null==a.contextId?null:a.contextId;this.componentId=null;this.trigger=function(b,a,c){"function"===typeof e&&e(b,a,c)};this.behavior=this._controller=this._style=this._css=this._view=this._model=this._container=null;this._eventMap=[];this._behaviorMap=[];this._c=null;this.options(a);return this}const l=m("../helpers/Logger")("ComponentContext.js"),k=m("./OptionAttributes")(), 57 | f=m("../helpers/ZxQuery"),e=m("../helpers/Util");let h=null;a.prototype.container=function(b){if(null==b)return this._container;b instanceof f.ZxQuery&&(b=b.get());this._container=b;return this};a.prototype.view=function(b){if("undefined"===typeof b)return this._view;b instanceof f.ZxQuery&&(b=b.get());l.t(this.componentId,"view:attach","timer:view:start");if("string"===typeof b){b={content:b};this.trigger(this,"html:parse",b);b=b.content;const a=f.wrapElement("div",b);null!=a.firstElementChild&& 58 | (null!=a.firstElementChild.getAttribute(k.dataUiView)?1===a.children.length&&(b=a.firstElementChild.innerHTML):b=a.innerHTML);null!=this._container?(this._view=this._container,this._view.innerHTML+=b):null!=this._view?this._view.innerHTML=b:this._view=a;f(this._view).find("script").each(function(b,a){"true"!==this.attr("zuix-loaded")&&(this.attr("zuix-loaded","true"),eval.call(window,a.innerHTML))});this.trigger(this,"view:process",f(this._view))}else b instanceof f.ZxQuery&&(b=b.get()),null!=this._container? 59 | (this._view=f.wrapElement("div",b.outerHTML).firstElementChild,this._view.removeAttribute(k.dataUiView),this._container.appendChild(this._view),this._view=this._container):this._view=b;b=f(this._view);!1===this._options.css?b.addClass("zuix-css-ignore"):b.removeClass("zuix-css-ignore");b.find("["+k.dataUiLoad+"]").each(function(b,a){this.attr(k.dataUiLoaded,"false")});this.modelToView();l.t(this.componentId,"view:attach","timer:view:stop");return this};a.prototype.style=function(b){if("undefined"=== 60 | typeof b)return this._style;l.t(this.componentId,"view:style","timer:view:start");null==b||b instanceof Element?(this._css=b instanceof Element?b.innerText:b,this._style=f.appendCss(b,this._style,this.componentId)):"string"===typeof b&&(this._css=b,b={content:b},this.trigger(this,"css:parse",b),b=b.content,b=f.wrapCss("["+k.dataUiComponent+'="'+this.componentId+'"]:not(.zuix-css-ignore)',b),this._style=f.appendCss(b,this._style,this.componentId));l.t(this.componentId,"view:style","timer:view:stop"); 61 | return this};a.prototype.model=function(b){if("undefined"===typeof b)return this._model;this._model=b;this.modelToView();null!=this._c&&e.isFunction(this._c.update)&&this._c.update.call(this._c,this._c);return this};a.prototype.controller=function(b){if("undefined"===typeof b)return this._controller;this._controller=b;return this};a.prototype.options=function(b){if(null==b)return this._options;const a=this._options=this._options||{};f.each(b,function(b,d){a[b]=d});null!=a.componentId&&(this.componentId= 62 | a.componentId);this.container(a.container);this.view(a.view);"undefined"!==typeof a.css&&this.style(a.css);this.controller(a.controller);this.model(a.model);return this};a.prototype.on=function(b,a){this._c.on(b,a);return this};a.prototype.loadCss=function(b,a){const d=this;e.isNoU(b)&&(b={});e.isNoU(b.caching)||(a=b.caching);let k=d.componentId+".css";e.isNoU(b.path)||(k=b.path);a||(k+="?"+(new Date).getTime());f.ajax({url:h.getResourcePath(k),success:function(a){d.style(a);e.isFunction(b.success)&& 63 | b.success.call(d,a,d)},error:function(a){l.e(a,d);e.isFunction(b.error)&&b.error.call(d,a,d)},then:function(){e.isFunction(b.then)&&b.then.call(d,d)}});return this};a.prototype.loadHtml=function(b,a){const d=this;let m=d.componentId;e.isNoU(b)&&(b={});e.isNoU(b.caching)||(a=b.caching);e.isNoU(b.path)||(m=b.path);var g=h.store("zuix.inlineViews");null==g&&(g=[],h.store("zuix.inlineViews",g));if(null!=g[m])d.view(g[m]),e.isFunction(b.success)&&b.success.call(d,g[m],d),e.isFunction(b.then)&&b.then.call(d, 64 | d);else{const c=f().find("["+k.dataUiView+'="'+m+'"]:not(['+k.dataUiComponent+'*=""])');0a.indexOf("://")&&(a=(null!=b&&null!=b.resourcePath?b.resourcePath:"")+a);return a}function e(a,b){let n=g(a.componentId);null!==n&&null==b.controller&&null==a.controller()&&(a.controller(n.controller), 87 | q.t(a.componentId+":js","component:cached:js"));if(p.isNoU(b.view)){if(null!==n&&(null!=n.view&&(a.view(n.view),q.t(a.componentId+":html","component:cached:html")),!1!==b.css&&(b.css=!1,n.css_applied||(n.css_applied=!0,a.style(n.css),q.t(a.componentId+":css","component:cached:css")))),p.isNoU(a.view()))return O("resource-loader").queue(a.componentId+":html",function(){y[a.componentId]=this;a.loadHtml({cext:b.cext,caching:I,success:function(d){null==n&&(n=C(a));n.view=d;delete n.controller;!1!==b.css? 88 | (y[a.componentId].step(a.componentId+":css"),a.loadCss({caching:I,success:function(a){n.css=a},error:function(b){q.e(b,a)},then:function(){c(a,y[a.componentId])}})):c(a,y[a.componentId])},error:function(c){q.e(c,a);p.isFunction(b.error)&&a.error.call(a,c,a)}})},b.priority),a}else a.view(b.view);null==a.controller()?O("resource-loader").queue(a.componentId+":js",function(){y[a.componentId]=this;c(a,y[a.componentId])},K.length):c(a);return a}function h(a){if(a instanceof Element){const b=a;a=zuix.context(b); 89 | v.dequeue(b)}p.isNoU(a)||(p.isNoU(a._c)||(p.isNoU(a._c.view())||(a._c.view().attr(A.dataUiComponent,null),a._c.view().reset(),p.isNoU(a._c._fieldCache)||u.each(a._c._fieldCache,function(a,b){b.reset()}),a._c.view().detach()),p.isFunction(a._c.destroy)&&a._c.destroy.call(a,a)),a=a.container(),null!=a&&null!=a.parentNode&&a.parentNode.removeChild(a))}function b(a){a=new w(zuix,a,B);K.push(a);return a}function d(a,b){let c=null;if(a instanceof u.ZxQuery)a=a.get();else if("string"===typeof a){const b= 90 | u.find("["+A.dataUiContext+'="'+a+'"]');0=e.length||b.willBreak())&&k();return!1}function k(d){h=-1;e.length=0;e=[];b.status(null!=d?d:"done")}function f(){const a=e[h];if(null==a)return!1; 22 | const f=function(){null!==d&&(cancelAnimationFrame(d),d=null);b.doWork(a.item,function(){d=requestAnimationFrame(l)})||l()};if(a.cancelable)if(b.willBreak())k("stopped");else if(null==d)d=requestAnimationFrame(f);else return!1;else f();return!0}a.prototype.isReady=function(){return 0===e.length||-1===h};a.prototype.getJobs=function(){return e};a.prototype.setJobs=function(d){0a.priority?1:a.priority>b.priority?-1:0});f.taskCheck()};f.taskCheck=function(){for(let e=0;e=a)break}}return this};g.ajax=function(c){let b;b=d.isNoU(c)||d.isNoU(c.url)?c:c.url;const a=new XMLHttpRequest;a.open("GET",b);a.onload=function(){200===a.status?d.isFunction(c.success)&&c.success(a.responseText):d.isFunction(c.error)&&c.error(a);d.isFunction(c.then)&&c.then(a)};a.send();return this};g.hasClass=function(c,b){b=b.match(/\S+/g)||[];let a=!1;g.each(b,function(b,d){if(a=c.classList?c.classList.contains(d):(new RegExp("(^| )"+ 46 | d+"( |$)","gi")).test(c.className))return!1});return a};g.classExists=function(c){c=c.match(/\S+/g)||[];let b=!1;g.each(c,function(c,a){c=document.styleSheets;if(null!=c)for(let d=0;dd.right-b||e.right+1d.bottom-b||e.bottom+1a?0:+a,b.length)===b});r.exports=g},{"./Logger":2,"./Util.js":4}],6:[function(m,r,x){m=m("./zuix/Zuix.js");"object"===typeof r&&r.exports?r.exports=m.call(this):this.zuix=m.call(this)},{"./zuix/Zuix.js":12}],7:[function(m, 56 | r,x){r.exports=function(a){return null}},{}],8:[function(m,r,x){function a(b,a,e){h=b;this._options=null;this.contextId=null==a||null==a.contextId?null:a.contextId;this.componentId=null;this.trigger=function(b,a,c){"function"===typeof e&&e(b,a,c)};this.behavior=this._controller=this._style=this._css=this._view=this._model=this._container=null;this._eventMap=[];this._behaviorMap=[];this._c=null;this.options(a);return this}const l=m("../helpers/Logger")("ComponentContext.js"),k=m("./OptionAttributes")(), 57 | f=m("../helpers/ZxQuery"),e=m("../helpers/Util");let h=null;a.prototype.container=function(b){if(null==b)return this._container;b instanceof f.ZxQuery&&(b=b.get());this._container=b;return this};a.prototype.view=function(b){if("undefined"===typeof b)return this._view;b instanceof f.ZxQuery&&(b=b.get());l.t(this.componentId,"view:attach","timer:view:start");if("string"===typeof b){b={content:b};this.trigger(this,"html:parse",b);b=b.content;const a=f.wrapElement("div",b);null!=a.firstElementChild&& 58 | (null!=a.firstElementChild.getAttribute(k.dataUiView)?1===a.children.length&&(b=a.firstElementChild.innerHTML):b=a.innerHTML);null!=this._container?(this._view=this._container,this._view.innerHTML+=b):null!=this._view?this._view.innerHTML=b:this._view=a;f(this._view).find("script").each(function(b,a){"true"!==this.attr("zuix-loaded")&&(this.attr("zuix-loaded","true"),eval.call(window,a.innerHTML))});this.trigger(this,"view:process",f(this._view))}else b instanceof f.ZxQuery&&(b=b.get()),null!=this._container? 59 | (this._view=f.wrapElement("div",b.outerHTML).firstElementChild,this._view.removeAttribute(k.dataUiView),this._container.appendChild(this._view),this._view=this._container):this._view=b;b=f(this._view);!1===this._options.css?b.addClass("zuix-css-ignore"):b.removeClass("zuix-css-ignore");b.find("["+k.dataUiLoad+"]").each(function(b,a){this.attr(k.dataUiLoaded,"false")});this.modelToView();l.t(this.componentId,"view:attach","timer:view:stop");return this};a.prototype.style=function(b){if("undefined"=== 60 | typeof b)return this._style;l.t(this.componentId,"view:style","timer:view:start");null==b||b instanceof Element?(this._css=b instanceof Element?b.innerText:b,this._style=f.appendCss(b,this._style,this.componentId)):"string"===typeof b&&(this._css=b,b={content:b},this.trigger(this,"css:parse",b),b=b.content,b=f.wrapCss("["+k.dataUiComponent+'="'+this.componentId+'"]:not(.zuix-css-ignore)',b),this._style=f.appendCss(b,this._style,this.componentId));l.t(this.componentId,"view:style","timer:view:stop"); 61 | return this};a.prototype.model=function(b){if("undefined"===typeof b)return this._model;this._model=b;this.modelToView();null!=this._c&&e.isFunction(this._c.update)&&this._c.update.call(this._c,this._c);return this};a.prototype.controller=function(b){if("undefined"===typeof b)return this._controller;this._controller=b;return this};a.prototype.options=function(b){if(null==b)return this._options;const a=this._options=this._options||{};f.each(b,function(b,d){a[b]=d});null!=a.componentId&&(this.componentId= 62 | a.componentId);this.container(a.container);this.view(a.view);"undefined"!==typeof a.css&&this.style(a.css);this.controller(a.controller);this.model(a.model);return this};a.prototype.on=function(b,a){this._c.on(b,a);return this};a.prototype.loadCss=function(b,a){const d=this;e.isNoU(b)&&(b={});e.isNoU(b.caching)||(a=b.caching);let k=d.componentId+".css";e.isNoU(b.path)||(k=b.path);a||(k+="?"+(new Date).getTime());f.ajax({url:h.getResourcePath(k),success:function(a){d.style(a);e.isFunction(b.success)&& 63 | b.success.call(d,a,d)},error:function(a){l.e(a,d);e.isFunction(b.error)&&b.error.call(d,a,d)},then:function(){e.isFunction(b.then)&&b.then.call(d,d)}});return this};a.prototype.loadHtml=function(b,a){const d=this;let m=d.componentId;e.isNoU(b)&&(b={});e.isNoU(b.caching)||(a=b.caching);e.isNoU(b.path)||(m=b.path);var g=h.store("zuix.inlineViews");null==g&&(g=[],h.store("zuix.inlineViews",g));if(null!=g[m])d.view(g[m]),e.isFunction(b.success)&&b.success.call(d,g[m],d),e.isFunction(b.then)&&b.then.call(d, 64 | d);else{const c=f().find("["+k.dataUiView+'="'+m+'"]:not(['+k.dataUiComponent+'*=""])');0a.indexOf("://")&&(a=(null!=b&&null!=b.resourcePath?b.resourcePath:"")+a);return a}function e(a,b){let n=g(a.componentId);null!==n&&null==b.controller&&null==a.controller()&&(a.controller(n.controller), 87 | q.t(a.componentId+":js","component:cached:js"));if(p.isNoU(b.view)){if(null!==n&&(null!=n.view&&(a.view(n.view),q.t(a.componentId+":html","component:cached:html")),!1!==b.css&&(b.css=!1,n.css_applied||(n.css_applied=!0,a.style(n.css),q.t(a.componentId+":css","component:cached:css")))),p.isNoU(a.view()))return O("resource-loader").queue(a.componentId+":html",function(){y[a.componentId]=this;a.loadHtml({cext:b.cext,caching:I,success:function(d){null==n&&(n=C(a));n.view=d;delete n.controller;!1!==b.css? 88 | (y[a.componentId].step(a.componentId+":css"),a.loadCss({caching:I,success:function(a){n.css=a},error:function(b){q.e(b,a)},then:function(){c(a,y[a.componentId])}})):c(a,y[a.componentId])},error:function(c){q.e(c,a);p.isFunction(b.error)&&a.error.call(a,c,a)}})},b.priority),a}else a.view(b.view);null==a.controller()?O("resource-loader").queue(a.componentId+":js",function(){y[a.componentId]=this;c(a,y[a.componentId])},K.length):c(a);return a}function h(a){if(a instanceof Element){const b=a;a=zuix.context(b); 89 | v.dequeue(b)}p.isNoU(a)||(p.isNoU(a._c)||(p.isNoU(a._c.view())||(a._c.view().attr(A.dataUiComponent,null),a._c.view().reset(),p.isNoU(a._c._fieldCache)||u.each(a._c._fieldCache,function(a,b){b.reset()}),a._c.view().detach()),p.isFunction(a._c.destroy)&&a._c.destroy.call(a,a)),a=a.container(),null!=a&&null!=a.parentNode&&a.parentNode.removeChild(a))}function b(a){a=new w(zuix,a,B);K.push(a);return a}function d(a,b){let c=null;if(a instanceof u.ZxQuery)a=a.get();else if("string"===typeof a){const b= 90 | u.find("["+A.dataUiContext+'="'+a+'"]');0