├── .gitignore
├── images
├── fb.png
├── chrome.png
├── email.png
├── calendar.png
└── screenshot.png
├── README.md
├── js
└── notification.js
├── index.html
└── css
└── style.css
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
--------------------------------------------------------------------------------
/images/fb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/girliemac/html5-notifications-webOS-style/HEAD/images/fb.png
--------------------------------------------------------------------------------
/images/chrome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/girliemac/html5-notifications-webOS-style/HEAD/images/chrome.png
--------------------------------------------------------------------------------
/images/email.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/girliemac/html5-notifications-webOS-style/HEAD/images/email.png
--------------------------------------------------------------------------------
/images/calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/girliemac/html5-notifications-webOS-style/HEAD/images/calendar.png
--------------------------------------------------------------------------------
/images/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/girliemac/html5-notifications-webOS-style/HEAD/images/screenshot.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Web Notifications Demo v2
4 |
5 | W3C Web Notifications API demo in webOS UI style.
6 |
7 | In the original demo, I implemented the notifications with webOS style, which allowed a user to swipe to close the window. However, this v2 demo no longer supports the swipable notifications because the simplified new Web Notifications spcification only allows text and icon, and external HTML files are no longer permitted.
8 |
9 | ## Supported Browsers
10 |
11 | - Firefox 22+ (both desktop and mobile)
12 | - Chrome 32+ (Desktop only)
13 |
14 | ## Demo
15 |
16 | [girliemac.github.com/html5-notifications-webOS-style](http://girliemac.github.com/html5-notifications-webOS-style)
17 |
18 | ## History
19 |
20 | - v.2 (March 2014) - using the [new Web Notification API specs](http://www.w3.org/TR/notifications)
21 | - v.1 (March 2012) - using the old Web Notification API specs, which is now deprecated.
22 |
23 | For detailed changelog, check [Releases](https://github.com/girliemac/html5-notifications-webOS-style/releases).
24 |
25 | ## Known Problems
26 |
27 | - Chrome for Android does not support the feature
28 | - Firefox on Android does support, however, only one line (the last line) is displayed on the native notification bar on top. No extra UI or window from browser.
29 | - On Chrome (tested on 33), `close()` method does not seem to work. Notification windows fails to close automatically.
30 |
31 |
32 |
33 | ### Firefox on Android
34 |
35 | Notifications appear in the native notification bar, one at a time, instead of popup windows from browser.
36 |
37 | The problem is that if a notificatin contains more than one lines one messages (when both `title` and `body` are set), only the last line (`body`) is displayed, instead of the main title. (When the notification bar is expanded by a user, both subject and body text are visible).
38 |
39 | Also, custom icons aren't shown either. The icon on the notification is always Firefox icon.
40 |
41 |
42 | 
43 |
--------------------------------------------------------------------------------
/js/notification.js:
--------------------------------------------------------------------------------
1 | (function() {
2 |
3 | var permToggle = document.getElementById('permission'),
4 | emailToggle = document.getElementById('email'),
5 | calendarToggle = document.getElementById('calendar'),
6 | fbToggle = document.getElementById('fb');
7 |
8 | var showNotificationsButton = document.getElementById('showNotifications');
9 |
10 | var allowNotifications = false;
11 |
12 | //var query = $('input').val();
13 |
14 | // Notification feature detection
15 | if (typeof Notification === 'function') {
16 | checkPermission();
17 | } else {
18 | disableAllToggles();
19 | alert('Your browser does not support Web Notifications API.');
20 | return;
21 | }
22 |
23 | permToggle.addEventListener('change', function(e) {
24 | checkPermission();
25 | });
26 |
27 |
28 | showNotificationsButton.addEventListener('click', function(e) {
29 | showNotifications();
30 | });
31 |
32 | function disableAllToggles(){
33 | permToggle.checked = false;
34 | emailToggle.checked = false;
35 | calendarToggle.checked = false;
36 | fbToggle.checked = false;
37 |
38 | permToggle.setAttribute('disabled', 'disabled');
39 | emailToggle.setAttribute('disabled', 'disabled');
40 | calendarToggle.setAttribute('disabled', 'disabled');
41 | fbToggle.setAttribute('disabled', 'disabled');
42 | showNotificationsButton.setAttribute('disabled', 'disabled');
43 | }
44 |
45 | function checkPermission() {
46 | if(permToggle.checked === false) {
47 | showNotificationsButton.setAttribute('disabled', 'disabled');
48 | return;
49 | }
50 | Notification.requestPermission(function (status) {
51 | if (Notification.permission !== status) {
52 | Notification.permission = status;
53 | }
54 | if (Notification.permission === 'granted') {
55 | showNotificationsButton.removeAttribute('disabled');
56 | } else {
57 | disableAllToggles();
58 | }
59 | });
60 | }
61 |
62 | function showNotifications() {
63 |
64 | var ms = 15000; // close notification after 15 sec
65 |
66 | if(emailToggle.checked) {
67 | var en = new Notification('Confirm Your Payment of $500,000', {
68 | body: 'From: Nigerian Prince',
69 | icon: 'images/email.png'
70 | });
71 | en.onshow = function() { setTimeout(en.close, ms) }
72 | }
73 | if(calendarToggle.checked) {
74 | var cn = new Notification('Shaolin Kung-Fu Class', {
75 | body: 'Sunday, March 23 5:30 PM',
76 | icon: 'images/calendar.png'
77 | });
78 | cn.onshow = function() { setTimeout(cn.close, ms) }
79 | }
80 | if(fbToggle.checked) {
81 | var fn = new Notification('Chuck Norris poked you', {
82 | icon: 'images/fb.png' }
83 | );
84 | fn.onshow = function() { setTimeout(fn.close, ms) }
85 | }
86 | }
87 | })();
88 |
89 |
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | (webOS-esque) HTML5 Web Notifications
17 |
18 |
19 |
20 |
21 |
22 |
What is the Web Notifications API? -Read the spec by W3C.
23 |
24 |
UPDATED (March 2014): I needed to rewrite this demo using the new Web Notification API, since the spec has been modified since I initially wrote this demo 2 years ago. The new API only allows text and icon, and using HTML is now deprecated. So my demo no longer has the webOS style swipable notifications , as I created originally.
25 |
26 |
Supported browsers: Firefox 22+ and Chrome 32+ (close() fails)
27 |
28 |
Blog: girliemac.com
29 |
30 |
31 |
32 |
33 | Browser Setting
34 |
35 |
Enable Notifications *
36 |
37 |
38 |
41 |
42 |
43 |
44 |
45 |
46 |
Email
47 |
48 |
49 |
52 |
53 |
54 |
55 |
56 |
Calendar
57 |
58 |
59 |
62 |
63 |
64 |
65 |
66 |
Facebook
67 |
68 |
69 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | * Actual permission setting is stored in browser. If you "deny" the permission in the first time, and want to enable it, you need to change your configuration in the browser's Preference setting.
83 |
84 |
85 | Chrome - chrome://settings/contentExceptions#notifications
86 |
87 | Firefox - about:permissions
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/css/style.css:
--------------------------------------------------------------------------------
1 | * { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
2 |
3 | body {
4 | margin: 0;
5 | padding: 0;
6 | color: #444;
7 | background-color: #efefef;
8 | font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif;
9 | font-size: 18px;
10 | line-height: 1.4;
11 | }
12 | header {
13 | text-align: center;
14 | margin-bottom: 2em;
15 | margin: 0 0 1.5em 0;
16 | padding: .5rem;
17 | text-shadow: 0px 2px 2px #fff;
18 | background: #dcdcdc;
19 | background: -moz-linear-gradient(top, #efefef, #cacaca);
20 | background: -webkit-linear-gradient(top, #efefef, #cacaca);
21 | border-top: 1px solid #fff;
22 | border-bottom: 1px solid #aaa;
23 | box-shadow: 0 2px 10px rgba(0, 0, 0, .25);
24 | }
25 | h1 {
26 | margin: 0;
27 | display: inline-block;
28 | font-size: 1.5em;
29 | line-height: 48px;
30 | font-weight: normal;
31 | }
32 | .main {
33 | width: 100%;
34 | max-width: 620px;
35 | padding: 0 10px;
36 | margin: 0 auto 2em;
37 | }
38 | #intro {
39 | margin-bottom: 2em;
40 | text-align: left;
41 | text-shadow: 0 1px 1px #deeaea;
42 | }
43 | footer {
44 | margin-top: 5em;
45 | background: #dfdfdf;
46 | border-top: 1px solid #777;
47 | padding: 1.5em;
48 | line-height: 1.5em;
49 | text-shadow: 1px 1px 0 #fff;
50 | }
51 | a {
52 | color: #3B5998;
53 | text-decoration: none;
54 | }
55 |
56 | img {
57 | border: 0;
58 | }
59 |
60 |
61 | /* webOS-like Stylies */
62 |
63 | .preference {
64 | margin-bottom: 2em;
65 | border: 1px solid silver;
66 | border-radius: 8px;
67 | min-height: 90px;
68 | font-size: 1rem;
69 | }
70 | .preference h2 {
71 | font-size: .9em;
72 | background-color: #aaa;
73 | color: #fff;
74 | padding: 7px 10px;
75 | -webkit-border-top-left-radius: 8px;
76 | -webkit-border-top-right-radius: 8px;
77 | box-shadow: inset -1px 2px 3px rgba(0,0,0,.25);
78 | text-transform: uppercase;
79 | margin: 0;
80 | }
81 | .caption {
82 | font-size: 1.3em;
83 | line-height: 75px;
84 | margin: 0 1em;
85 | }
86 | .caption, .toggle-button {
87 | display: inline-block;
88 | }
89 | .preference > div {
90 | position: relative;
91 | }
92 | .preference > div:not(:last-child) {
93 | border-bottom: 1px silver solid;
94 | }
95 | .preference > div:not(:first-child) {
96 | border-top: 1px #fff solid;
97 | }
98 | label {
99 | position: absolute;
100 | right: 10px;
101 | top: 15px;
102 | }
103 |
104 | /* Checkboxes as Toggle-buttons */
105 |
106 | input[type=checkbox] {
107 | display: none;
108 | }
109 | .toggle-button {
110 | cursor: pointer;
111 | background: #6ca3c6;
112 | background: -moz-linear-gradient(top, #1d466f, #6ca3c6);
113 | background: -webkit-linear-gradient(top, #1d466f, #6ca3c6);
114 | border-radius: 6px;
115 | border: 1px solid #555555;
116 | width: 110px;
117 | position: relative;
118 | height: 44px;
119 | color: #fff;
120 | line-height: 42px;
121 | font-size: 18px;
122 | text-shadow: 0 -1px 1px #093B5C;
123 | }
124 | .toggle-button:before {
125 | content: "ON";
126 | padding-left: 18px;
127 |
128 | }
129 | .toggle-button:after {
130 | content: "OFF";
131 | padding-left: 14px;
132 | }
133 |
134 | .toggle-button .switch {
135 | display: block;
136 | width: 44px;
137 | height: 40px;
138 | border-radius: 5px;
139 | background: #b8d4e8;
140 | background: -moz-linear-gradient(top, #fefefe, #b8d4e8);
141 | background: -webkit-linear-gradient(top, #fefefe, #b8d4e8);
142 | border: 1px solid #fff;
143 | position: absolute;
144 | top: 1px;
145 | left: 1px;
146 | }
147 | input[type="checkbox"]:checked + .toggle-button .switch {
148 | left: 63px;
149 | }
150 | input[type="checkbox"]:not(:checked) + .toggle-button {
151 | background: -moz-linear-gradient(top, #565656, #aeaeae);
152 | background: -webkit-linear-gradient(top, #565656, #aeaeae);
153 | }
154 | input[type="checkbox"]:not(:checked) + .toggle-button .switch {
155 | background: -moz-linear-gradient(top, #ececec, #d9d9d9);
156 | background: -webkit-linear-gradient(top, #ececec, #d9d9d9);
157 | }
158 | input[type="checkbox"]:disabled + .toggle-button {
159 | opacity: .25;
160 | }
161 |
162 | /* Button */
163 |
164 | input[type="text"], input[type="button"] {
165 | font-size: 1rem;
166 | padding: .3em;
167 | border-radius: 8px;
168 | margin: 1em .5em;
169 | font-family: 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, sans-serif;
170 | }
171 | input[type="button"] {
172 | display: block;
173 | width: 100%;
174 | margin: 0 auto;
175 | text-transform: uppercase;
176 | padding: 1em;
177 | border: 0;
178 | background: #3e779d;
179 | background: -webkit-linear-gradient(top, #6ca3c6, #1d466f);
180 | background: -moz-linear-gradient(top, #6ca3c6, #1d466f);
181 | color: white;
182 | box-shadow: black 0 1px 0;
183 | text-shadow: rgba(0,0,0,.5) 0 1px 0;
184 | }
185 | input[type="button"]:active {
186 | background: #28597a;
187 | }
188 | input[type="button"]:disabled, input[disabled], input[disabled]:active {
189 | opacity: .25;
190 | background: gray;
191 | }
--------------------------------------------------------------------------------