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 |
2 | home
3 |
4 |
5 | search
6 |
7 |
8 | notifications
9 |
10 |
11 | info
12 |
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 |
11 | more_vert
12 |
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 |
11 | more_vert
12 |
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 |
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 |
3 |
4 |
5 |
DevUser
6 |
@devrocks
7 |
8 | 123 Following
9 | 456 Followers
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | account_circle
19 | Profile
20 |
21 |
22 |
23 | assignment
24 | Lists
25 |
26 |
27 |
28 | bookmark
29 | Bookmarks
30 |
31 |
32 |
33 | flash_on
34 | Moments
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | Settings and privacy
45 |
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 |
39 |
41 |
42 |
43 | bookmark_border
44 | Save for later
45 |
46 |
47 | share
48 | Share
49 |
50 |
51 | open_in_new
52 | Open link
53 |
54 |
55 | not_interested
56 | Hide items from this source
57 |
58 |
59 | thumb_up
60 | More like this
61 |
62 |
63 | thumb_down
64 | Less like this
65 |
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 |
100 |
101 |
102 | Turn on JavaScript to access this site content.
103 |
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 |
98 |
99 |
100 | Turn on JavaScript to access this site content.
101 |
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 |
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":"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",
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