Commit 3d458921 authored by dimich@chromium.org's avatar dimich@chromium.org

Refactor Notifications Galore to simplify, amke more hackable and add 'recording'.

BUG=
R=dewittj@chromium.org

Review URL: https://codereview.chromium.org/315053006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@276736 0039d316-1c4b-4281-b951-d872f2087c98
parent bb635de2
...@@ -2,242 +2,359 @@ ...@@ -2,242 +2,359 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
var Galore = Galore || {}; var STOPPED = "Stopped";
var RECORDING = "Recording";
Galore.controller = { var PAUSED_RECORDING = "Recording Paused";
/** @constructor */ var PAUSED_PLAYING = "Playing Paused";
create: function() { var PLAYING = "Playing";
var controller = Object.create(this);
controller.api = chrome; var recordingState = STOPPED;
controller.counter = 0;
return controller; // Timestamp when current segment started.
}, var segmentStart;
// Segment duration accumulated before pause button was hit.
createWindow: function() { var pausedDuration;
chrome.storage.sync.get('settings', this.onSettingsFetched_.bind(this)); // The array of segments, with delay and action.
}, var recordingList;
// When this timer fires, the next segment from recordingList should be played.
/** @private */ var playingTimer;
onSettingsFetched_: function(items) { var currentSegmentIndex;
// A set of web Notifications - used to delete them during playback by id.
var webNotifications = {};
var recorderButtons = [ "play", "record", "pause", "stop"];
var recorderButtonStates = [
{ state: STOPPED, enabled: "play record" },
{ state: RECORDING, enabled: "pause stop" },
{ state: PAUSED_RECORDING, enabled: "record stop" },
{ state: PAUSED_PLAYING, enabled: "play stop" },
{ state: PLAYING, enabled: "pause stop" }
];
// This function forms 2 selector lists - one that includes enabled buttons
// and one that includes disabled ones. Then it applies "disabled" attribute to
// corresponding sets of buttons.
function updateButtonsState() {
recorderButtonStates.map(function(entry) {
if (entry.state != recordingState)
return;
// Found entry with current recorder state. Now compute the sets
// of enabled/disabled buttons.
// Copy a list of all buttons.
var disabled = recorderButtons.slice(0);
// Get an array of enabled buttons for the state.
var enabled = entry.enabled.split(" ");
// Remove enabled buttons from disabled list, prefix them with "#" so they
// form proper id selectors.
for (var i = 0; i < enabled.length; i++) {
disabled.splice(disabled.indexOf(enabled[i]), 1);
enabled[i] = "#" + enabled[i];
}
// Prefix remaining disabled ids to form proper id selectors.
for (var i = 0; i < disabled.length; i++) {
disabled[i] = "#" + disabled[i];
}
getElements(disabled.join(", ")).forEach(function(element) {
element.setAttribute("disabled", "true")
})
getElements(enabled.join(", ")).forEach(function(element) {
element.removeAttribute("disabled")
})
})
}
function setRecordingState(newState) {
setRecorderStatusText(newState);
recordingState = newState;
updateButtonsState();
}
function updateRecordingStats(context) {
var length = 0;
var segmentCnt = 0;
recordingList.slice(currentSegmentIndex).forEach(function(segment) {
length += segment.delay || 0;
segmentCnt++;
})
updateRecordingStatsDisplay(context + ": " + (segmentCnt-1) + " segments, " +
Math.floor(length/1000) + " seconds.");
}
function loadRecording() {
chrome.storage.local.get("recording", function(items) {
recordingList = JSON.parse(items["recording"] || "[]");
setRecordingState(STOPPED);
updateRecordingStats("Loaded record");
})
}
function finalizeRecording() {
chrome.storage.local.set({"recording": JSON.stringify(recordingList)});
updateRecordingStats("Recorded");
}
function setPreviousSegmentDuration() {
var now = new Date().getTime();
var delay = now - segmentStart;
segmentStart = now;
recordingList[recordingList.length - 1].delay = delay;
}
function recordCreate(kind, id, options) {
if (recordingState != RECORDING)
return;
setPreviousSegmentDuration();
recordingList.push({ type: "create", kind: kind, id: id, options: options });
updateRecordingStats("Recording");
}
function recordDelete(kind, id) {
if (recordingState != RECORDING)
return;
setPreviousSegmentDuration();
recordingList.push({ type: "delete", kind: kind, id: id });
updateRecordingStats("Recording");
}
function startPlaying() {
if (recordingList.length < 2)
return false;
setRecordingState(PLAYING);
if (playingTimer)
clearTimeout(playingTimer);
webNotifications = {};
currentSegmentIndex = 0;
playingTimer = setTimeout(playNextSegment,
recordingList[currentSegmentIndex].delay);
updateRecordingStats("Playing");
}
function playNextSegment() {
currentSegmentIndex++;
var segment = recordingList[currentSegmentIndex];
if (!segment) {
stopPlaying();
return;
}
if (segment.type == "create") {
createNotificationForPlay(segment.kind, segment.id, segment.options);
} else { // type == "delete"
deleteNotificationForPlay(segment.kind, segment.id);
}
playingTimer = setTimeout(playNextSegment,
recordingList[currentSegmentIndex].delay);
segmentStart = new Date().getTime();
updateRecordingStats("Playing");
}
function deleteNotificationForPlay(kind, id) {
if (kind == 'web') {
webNotifications[id].close();
} else {
chrome.notifications.clear(id, function(wasClosed) {
// nothing to do
});
}
}
function createNotificationForPlay(kind, id, options) {
if (kind == 'web') {
webNotifications[id] = createWebNotification(id, options);
} else {
var type = options.type;
var priority = options.priority;
createRichNotification(id, type, priority, options);
}
}
function stopPlaying() {
currentSegmentIndex = 0;
clearTimeout(playingTimer);
updateRecordingStats("Record");
setRecordingState(STOPPED);
}
function pausePlaying() {
clearTimeout(playingTimer);
pausedDuration = new Date().getTime() - segmentStart;
setRecordingState(PAUSED_PLAYING);
}
function unpausePlaying() {
var remainingInSegment =
recordingList[currentSegmentIndex].delay - pausedDuration;
if (remainingInSegment < 0)
remainingInSegment = 0;
playingTimer = setTimeout(playNextSegment, remainingInSegment);
segmentStart = new Date().getTime() - pausedDuration;
}
function onRecord() {
if (recordingState == STOPPED) {
segmentStart = new Date().getTime();
pausedDuration = 0;
// This item is only needed to keep a duration of the delay between start
// and first action.
recordingList = [ { type:"start" } ];
} else if (recordingState == PAUSED_RECORDING) {
segmentStart = new Date().getTime() - pausedDuration;
pausedDuration = 0;
} else {
return;
}
updateRecordingStats("Recording");
setRecordingState(RECORDING);
}
function pauseRecording() {
pausedDuration = new Date().getTime() - segmentStart;
segmentStart = 0;
setRecordingState(PAUSED_RECORDING);
}
function onPause() {
if (recordingState == RECORDING) {
pauseRecording();
} else if (recordingState == PLAYING) {
pausePlaying();
} else {
return;
}
}
function onStop() {
switch (recordingState) {
case PAUSED_RECORDING:
segmentStart = new Date().getTime() - pausedDuration;
// fall through
case RECORDING:
finalizeRecording();
break;
case PLAYING:
case PAUSED_PLAYING:
stopPlaying();
break;
}
setRecordingState(STOPPED);
}
function onPlay() {
if (recordingState == STOPPED) {
if (!startPlaying())
return;
} else if (recordingState == PAUSED_PLAYING) {
unpausePlaying();
}
setRecordingState(PLAYING);
}
function createWindow() {
chrome.storage.local.get('settings', onSettingsFetched);
}
function onSettingsFetched(items) {
settings = items.settings || settings;
var request = new XMLHttpRequest(); var request = new XMLHttpRequest();
var settings = items.settings || {}; var source = '/data/data.json';
var source = settings.data || '/data/' + this.getDataVersion_();
request.open('GET', source, true); request.open('GET', source, true);
request.responseType = 'text'; request.responseType = 'text';
request.onload = this.onDataFetched_.bind(this, settings, request); request.onload = onDataFetched;
request.send(); request.send();
}, }
/** @private */ function onDataFetched() {
onDataFetched_: function(settings, request) { var data = JSON.parse(this.response);
var count = 0; createAppWindow(function() {
var data = JSON.parse(request.response); // Create notification buttons.
data.forEach(function(section) { data.forEach(function(section) {
(section.notificationOptions || []).forEach(function(options) {
++count;
this.fetchImages_(options, function() {
if (--count == 0)
this.onImagesFetched_(settings, data);
}.bind(this));
}, this);
}, this);
},
/** @private */
onImagesFetched_: function(settings, data) {
this.settings = settings;
this.view = Galore.view.create(this.settings, function() {
// Create buttons.
data.forEach(function(section) {
var defaults = section.globals || data[0].globals;
var type = section.notificationType; var type = section.notificationType;
(section.notificationOptions || []).forEach(function(options) { (section.notificationOptions || []).forEach(function(options) {
var defaulted = this.getDefaultedOptions_(options, defaults); addNotificationButton(section.sectionName,
var create = this.createNotification_.bind(this, type, defaulted); options.title,
this.view.addNotificationButton(section.sectionName, options.iconUrl,
defaulted.title, function() { createNotification(type, options) });
defaulted.iconUrl,
create);
}, this);
}, this);
// Set the API entry point and use it to set event listeners.
this.api = this.getApi_(data);
if (this.api)
this.addListeners_(this.api, data[0].events);
// Display the completed and ready window.
this.view.showWindow();
}.bind(this), this.onSettingsChange_.bind(this));
},
/** @private */
fetchImages_: function(options, onFetched) {
var count = 0;
var replacements = {};
this.mapStrings_(options, function(string) {
if (string.indexOf("/images/") == 0 || string.search(/https?:\//) == 0) {
++count;
this.fetchImage_(string, function(url) {
replacements[string] = url;
if (--count == 0) {
this.mapStrings_(options, function(string) {
return replacements[string] || string;
}); });
onFetched.call(this, options);
}
}); });
} loadRecording();
addListeners();
showWindow();
}); });
}, }
/** @private */ function onSettingsChange(settings) {
fetchImage_: function(url, onFetched) { chrome.storage.local.set({settings: settings});
var request = new XMLHttpRequest(); }
request.open('GET', url, true);
request.responseType = 'blob'; function createNotification(type, options) {
request.onload = function() { var id = getNextId();
var url = window.URL.createObjectURL(request.response); var priority = Number(settings.priority || 0);
onFetched.call(this, url); if (type == 'web')
}.bind(this); createWebNotification(id, options);
request.send();
},
/** @private */
onSettingsChange_: function(settings) {
this.settings = settings;
chrome.storage.sync.set({settings: this.settings});
},
/** @private */
createNotification_: function(type, options) {
var id = this.getNextId_();
var priority = Number(this.settings.priority || 0);
var expanded = this.getExpandedOptions_(options, id, type, priority);
if (type == 'webkit')
this.createWebKitNotification_(expanded);
else else
this.createRichNotification_(expanded, id, type, priority); createRichNotification(id, type, priority, options);
}, }
/** @private */ function createWebNotification(id, options) {
createWebKitNotification_: function(options) {
var iconUrl = options.iconUrl; var iconUrl = options.iconUrl;
var title = options.title; var title = options.title;
var message = options.message; var message = options.message;
new Notification(title, { var n = new Notification(title, {
body: message, body: message,
icon: iconUrl icon: iconUrl,
tag: id
}); });
this.handleEvent_('create', '?', 'title: "' + title + '"'); n.onshow = function() { logEvent('WebNotification #' + id + ': onshow'); }
}, n.onclick = function() { logEvent('WebNotification #' + id + ': onclick'); }
n.onclose = function() {
logEvent('WebNotification #' + id + ': onclose');
recordDelete('web', id);
}
logCreate('Web', id, 'title: "' + title + '"');
recordCreate('web', id, options);
return n;
}
/** @private */ function createRichNotification(id, type, priority, options) {
createRichNotification_: function(options, id, type, priority) { options["type"] = type;
this.api.create(id, options, function() { options["priority"] = priority;
chrome.notifications.create(id, options, function() {
var argument1 = 'type: "' + type + '"'; var argument1 = 'type: "' + type + '"';
var argument2 = 'priority: ' + priority; var argument2 = 'priority: ' + priority;
var argument3 = 'title: "' + options.title + '"'; var argument3 = 'title: "' + options.title + '"';
this.handleEvent_('create', id, argument1, argument2, argument3); logCreate('Rich', id, argument1, argument2, argument3);
}.bind(this));
},
/** @private */
getNextId_: function() {
this.counter += 1;
return String(this.counter);
},
/** @private */
getDefaultedOptions_: function(options, defaults) {
var defaulted = this.deepCopy_(options);
Object.keys(defaults || {}).forEach(function (key) {
defaulted[key] = options[key] || defaults[key];
}); });
return defaulted; recordCreate('rich', id, options);
}, }
/** @private */ var counter = 0;
getExpandedOptions_: function(options, id, type, priority) { function getNextId() {
var expanded = this.deepCopy_(options); return String(counter++);
return this.mapStrings_(expanded, function(string) { }
return this.getExpandedOption_(string, id, type, priority);
}, this); function addListeners() {
}, chrome.notifications.onClosed.addListener(onClosed);
chrome.notifications.onClicked.addListener(onClicked);
/** @private */ chrome.notifications.onButtonClicked.addListener(onButtonClicked);
getExpandedOption_: function(option, id, type, priority) { }
if (option == '$!') {
option = priority; // Avoids making priorities into strings. function logCreate(kind, id, var_args) {
} else { logEvent(kind + ' Notification #' + id + ': created ' + '(' +
option = option.replace(/\$#/g, id); Array.prototype.slice.call(arguments, 2).join(', ') + ')');
option = option.replace(/\$\?/g, type); }
option = option.replace(/\$\!/g, priority);
} function onClosed(id) {
return option; logEvent('Notification #' + id + ': onClosed');
}, recordDelete('rich', id);
}
/** @private */
deepCopy_: function(value) { function onClicked(id) {
var copy = value; logEvent('Notification #' + id + ': onClicked');
if (Array.isArray(value)) { }
copy = value.map(this.deepCopy_, this);
} else if (value && typeof value === 'object') {
copy = {}
Object.keys(value).forEach(function (key) {
copy[key] = this.deepCopy_(value[key]);
}, this);
}
return copy;
},
/** @private */
mapStrings_: function(value, map) {
var mapped = value;
if (typeof value === 'string') {
mapped = map.call(this, value);
mapped = (typeof mapped !== 'undefined') ? mapped : value;
} else if (value && typeof value == 'object') {
Object.keys(value).forEach(function (key) {
mapped[key] = this.mapStrings_(value[key], map);
}, this);
}
return mapped;
},
/** @private */
addListeners_: function(api, events) {
(events || []).forEach(function(event) {
var listener = this.handleEvent_.bind(this, event);
if (api[event])
api[event].addListener(listener);
else
console.log('Event ' + event + ' not defined.');
}, this);
},
/** @private */
handleEvent_: function(event, id, var_args) {
this.view.logEvent('Notification #' + id + ': ' + event + '(' +
Array.prototype.slice.call(arguments, 2).join(', ') +
')');
},
/** @private */
getDataVersion_: function() {
var version = navigator.appVersion.replace(/^.* Chrome\//, '');
return (version > '28.0.1500.70') ? '28.0.1500.70.json' :
(version > '27.0.1433.1') ? '27.0.1433.1.json' :
(version > '27.0.1432.2') ? '27.0.1432.2.json' :
'27.0.0.0.json';
},
/** @private */
getApi_: function(data) {
var path = data[0].api || 'notifications';
var api = chrome;
path.split('.').forEach(function(key) { api = api && api[key]; });
if (!api)
this.view.logError('No API found - chrome.' + path + ' is undefined');
return api;
}
}; function onButtonClicked(id, index) {
logEvent('Notification #' + id + ': onButtonClicked, btn: ' + index);
}
[
{
"copyright": [
"Copyright (c) 2013 The Chromium Authors. All rights reserved.",
"Use of this source code is governed by a BSD-style license that can be",
"found in the LICENSE file."
],
"api": "experimental.notification",
"events": [
"onDisplayed",
"onClosed",
"onClicked",
"onButtonClicked"
],
"globals": {
"templateType": "$?",
"priority": "$!"
}
},
{
"sectionName": "WebKit Notifications",
"notificationType": "webkit",
"notificationOptions": [
{
"iconUrl": "/images/man1-40x40.jpg",
"title": "Althe Frazon",
"message": "Lorem ipsum"
},
{
"iconUrl": "/images/woman1-40x40.jpg",
"title": "Kathrine Doiss",
"message": "Dolor sit amet"
},
{
"iconUrl": "https://www.google.com/images/icons/product/googlemail-64.png",
"title": "New mail from Brant Hodestrine: Easy Hike in S.F. next Saturday!",
"message": "Hey, The trail starts from 'Merrie Way' Outer Richmond side. We can do brunch before in the Inner Richmond, maybe at that Russian place we used to go to after fencing."
},
{
"iconUrl": "https://calendar.google.com/googlecalendar/images/about-alerts.gif",
"title": "Google Calendar reminder",
"message": "Team Meeting (Brant Hodestrine) is starting at 10:25pm in SFO-CEN-3-Triptych (12), NYC-WES-2-Wegman (8), PAR-OPR-4-Cézanne http://www.example.com/talk/meet/example"
},
{
"iconUrl": "/images/fruit1-40x40.jpg",
"title": "Notification #$#: Pears!",
"message": "Pyrus"
},
{
"iconUrl": "/images/fruit2-40x40.jpg",
"title": "Notification #$#: Oranges!",
"message": "Citrus sinensis"
},
{
"iconUrl": "/images/fruit3-40x40.jpg",
"title": "Notification #$#: Strawberries!",
"message": "Fragaria ananassa"
},
{
"iconUrl": "/images/fruit4-80x80.jpg",
"title": "Notification #$#: Raspberries!",
"message": "Rubus idaeus"
},
{
"iconUrl": "/images/fruit5-360x360.jpg",
"title": "Notification #$#: Blueberries - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Vaccinium cyanococcus - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
},
{
"sectionName": "Simple Notifications",
"notificationType": "simple",
"notificationOptions": [
{
"iconUrl": "/images/man1-40x40.jpg",
"title": "Althe Frazon",
"message": "Lorem ipsum"
},
{
"iconUrl": "/images/woman1-40x40.jpg",
"title": "Kathrine Doiss",
"message": "Dolor sit amet"
},
{
"iconUrl": "https://www.google.com/images/icons/product/googlemail-64.png",
"title": "New mail from Brant Hodestrine: Easy Hike in S.F. next Saturday!",
"message": "Hey, The trail starts from 'Merrie Way' Outer Richmond side. We can do brunch before in the Inner Richmond, maybe at that Russian place we used to go to after fencing."
},
{
"iconUrl": "https://calendar.google.com/googlecalendar/images/about-alerts.gif",
"title": "Google Calendar reminder",
"message": "Team Meeting (Brant Hodestrine) is starting at 10:25pm in SFO-CEN-3-Triptych (12), NYC-WES-2-Wegman (8), PAR-OPR-4-Cézanne http://www.example.com/talk/meet/example"
},
{
"iconUrl": "/images/fruit1-40x40.jpg",
"title": "Notification #$#: Pears!",
"message": "Pyrus"
},
{
"iconUrl": "/images/fruit2-40x40.jpg",
"title": "Notification #$#: Oranges!",
"message": "Citrus sinensis"
},
{
"iconUrl": "/images/fruit3-40x40.jpg",
"title": "Notification #$#: Strawberries!",
"message": "Fragaria ananassa"
},
{
"iconUrl": "/images/fruit4-80x80.jpg",
"title": "Notification #$#: Raspberries!",
"message": "Rubus idaeus"
},
{
"iconUrl": "/images/fruit5-360x360.jpg",
"title": "Notification #$#: Blueberries - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Vaccinium cyanococcus - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
},
{
"sectionName": "Basic Notifications",
"notificationType": "basic",
"notificationOptions": [
{
"iconUrl": "/images/man1-80x80.jpg",
"title": "Althe Frazon",
"message": "Lorem ipsum",
"buttons": [
{"title": "Call", "iconUrl": "/images/call-16x16.png"},
{"title": "Send Email", "iconUrl": "/images/send-16x16.png"}
]
},
{
"iconUrl": "/images/woman1-80x80.jpg",
"title": "Kathrine Doiss",
"message": "Dolor sit amet"
},
{
"iconUrl": "/images/woman2-80x80.jpg",
"title": "Jamie Haynig",
"message": "Consectetur adipisicing elit"
},
{
"iconUrl": "/images/woman3-80x80.jpg",
"title": "Maricia Rilari",
"message": "Sed do eiusmod tempor incididunt"
},
{
"iconUrl": "/images/fruit1-80x80.jpg",
"title": "Notification #$#: Pears!",
"message": "Pyrus"
},
{
"iconUrl": "/images/fruit2-80x80.jpg",
"title": "Notification #$#: Oranges!",
"message": "Citrus sinensis"
},
{
"iconUrl": "/images/fruit3-80x80.jpg",
"title": "Notification #$#: Strawberries!",
"message": "Fragaria ananassa"
},
{
"iconUrl": "/images/fruit4-80x80.jpg",
"title": "Notification #$#: Raspberries!",
"message": "Rubus idaeus"
},
{
"iconUrl": "/images/fruit5-360x360.jpg",
"title": "Notification #$#: Blueberries - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Vaccinium cyanococcus - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
},
{
"sectionName": "Image Notifications",
"notificationType": "image",
"notificationOptions": [
{
"iconUrl": "/images/woman3-80x80.jpg",
"title": "Maricia Rilari",
"message": "Pictures from Tahoe",
"imageUrl": "/images/tahoe-300x225.jpg"
},
{
"iconUrl": "/images/flower1-80x80.jpg",
"title": "Notification #$#: Daffodils!",
"message": "Narcissus",
"imageUrl": "/images/image1-300x225.jpg",
"buttons": [
{"title": "Lorem Ipsum Dolor Sit Amet Consectetur Adipisicing"},
{"title": "Elit Sed Do"}
]
},
{
"iconUrl": "/images/flower2-80x80.jpg",
"title": "Notification #$#: Sunflowers!",
"message": "Helianthus annuus",
"imageUrl": "/images/image2-300x225.jpg"
},
{
"iconUrl": "/images/flower3-80x80.jpg",
"title": "Notification #$#: Poinsettias!",
"message": "Euphorbia pulcherrima",
"imageUrl": "/images/image3-300x172.jpg"
},
{
"iconUrl": "/images/flower4-80x80.jpg",
"title": "Notification #$#: Heather - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Calluna vulgaris - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
"imageUrl": "/images/image4-200x300.jpg"
}
]
},
{
"sectionName": "List Notifications",
"notificationType": "list",
"notificationOptions": [
{
"iconUrl": "/images/inbox-00-80x80.png",
"title": "5 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"}
],
"buttons": [
{"title": "Send Message", "iconUrl": "/images/send-16x16.png"}
]
},
{
"iconUrl": "/images/inbox-01-80x80.png",
"title": "1 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"}
]
},
{
"iconUrl": "/images/inbox-02-80x80.png",
"title": "2 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing elit"}
]
},
{
"iconUrl": "/images/inbox-03-80x80.png",
"title": "3 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incididu"}
]
},
{
"iconUrl": "/images/inbox-05-80x80.png",
"title": "5 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"}
]
},
{
"iconUrl": "/images/inbox-08-80x80.png",
"title": "8 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"},
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incididu"}
]
},
{
"iconUrl": "/images/inbox-13-80x80.png",
"title": "13 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"},
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"},
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incididu"}
]
},
{
"iconUrl": "/images/plant1-80x80.jpg",
"title": "Notification #$#: Yucca!",
"message": "Asparagaceae agavoideae",
"items": [
{"title": "One", "message": "Unus"},
{"title": "Two", "message": "Duo"},
{"title": "Three", "message": "Tres"}
]
},
{
"iconUrl": "/images/plant2-80x80.jpg",
"title": "Notification #$#: Basil - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Ocimum basilicum - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
"items": [
{
"title": "One - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
"message": "Unus - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
},
{
"title": "Two - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
"message": "Duo - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
},
{
"title": "Three - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
"message": "Tres - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
}
]
}
]
}
]
[
{
"copyright": [
"Copyright (c) 2013 The Chromium Authors. All rights reserved.",
"Use of this source code is governed by a BSD-style license that can be",
"found in the LICENSE file."
],
"api": "notifications",
"events": [
"onDisplayed",
"onClosed",
"onClicked",
"onButtonClicked"
],
"globals": {
"templateType": "$?",
"priority": "$!"
}
},
{
"sectionName": "WebKit Notifications",
"notificationType": "webkit",
"notificationOptions": [
{
"iconUrl": "/images/man1-40x40.jpg",
"title": "Althe Frazon",
"message": "Lorem ipsum"
},
{
"iconUrl": "/images/woman1-40x40.jpg",
"title": "Kathrine Doiss",
"message": "Dolor sit amet"
},
{
"iconUrl": "https://www.google.com/images/icons/product/googlemail-64.png",
"title": "New mail from Brant Hodestrine: Easy Hike in S.F. next Saturday!",
"message": "Hey, The trail starts from 'Merrie Way' Outer Richmond side. We can do brunch before in the Inner Richmond, maybe at that Russian place we used to go to after fencing."
},
{
"iconUrl": "https://calendar.google.com/googlecalendar/images/about-alerts.gif",
"title": "Google Calendar reminder",
"message": "Team Meeting (Brant Hodestrine) is starting at 10:25pm in SFO-CEN-3-Triptych (12), NYC-WES-2-Wegman (8), PAR-OPR-4-Cézanne http://www.example.com/talk/meet/example"
},
{
"iconUrl": "/images/fruit1-40x40.jpg",
"title": "Notification #$#: Pears!",
"message": "Pyrus"
},
{
"iconUrl": "/images/fruit2-40x40.jpg",
"title": "Notification #$#: Oranges!",
"message": "Citrus sinensis"
},
{
"iconUrl": "/images/fruit3-40x40.jpg",
"title": "Notification #$#: Strawberries!",
"message": "Fragaria ananassa"
},
{
"iconUrl": "/images/fruit4-80x80.jpg",
"title": "Notification #$#: Raspberries!",
"message": "Rubus idaeus"
},
{
"iconUrl": "/images/fruit5-360x360.jpg",
"title": "Notification #$#: Blueberries - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Vaccinium cyanococcus - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
},
{
"sectionName": "Simple Notifications",
"notificationType": "simple",
"notificationOptions": [
{
"iconUrl": "/images/man1-40x40.jpg",
"title": "Althe Frazon",
"message": "Lorem ipsum"
},
{
"iconUrl": "/images/woman1-40x40.jpg",
"title": "Kathrine Doiss",
"message": "Dolor sit amet"
},
{
"iconUrl": "https://www.google.com/images/icons/product/googlemail-64.png",
"title": "New mail from Brant Hodestrine: Easy Hike in S.F. next Saturday!",
"message": "Hey, The trail starts from 'Merrie Way' Outer Richmond side. We can do brunch before in the Inner Richmond, maybe at that Russian place we used to go to after fencing."
},
{
"iconUrl": "https://calendar.google.com/googlecalendar/images/about-alerts.gif",
"title": "Google Calendar reminder",
"message": "Team Meeting (Brant Hodestrine) is starting at 10:25pm in SFO-CEN-3-Triptych (12), NYC-WES-2-Wegman (8), PAR-OPR-4-Cézanne http://www.example.com/talk/meet/example"
},
{
"iconUrl": "/images/fruit1-40x40.jpg",
"title": "Notification #$#: Pears!",
"message": "Pyrus"
},
{
"iconUrl": "/images/fruit2-40x40.jpg",
"title": "Notification #$#: Oranges!",
"message": "Citrus sinensis"
},
{
"iconUrl": "/images/fruit3-40x40.jpg",
"title": "Notification #$#: Strawberries!",
"message": "Fragaria ananassa"
},
{
"iconUrl": "/images/fruit4-80x80.jpg",
"title": "Notification #$#: Raspberries!",
"message": "Rubus idaeus"
},
{
"iconUrl": "/images/fruit5-360x360.jpg",
"title": "Notification #$#: Blueberries - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Vaccinium cyanococcus - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
},
{
"sectionName": "Basic Notifications",
"notificationType": "basic",
"notificationOptions": [
{
"iconUrl": "/images/man1-80x80.jpg",
"title": "Althe Frazon",
"message": "Lorem ipsum",
"buttons": [
{"title": "Call", "iconUrl": "/images/call-16x16.png"},
{"title": "Send Email", "iconUrl": "/images/send-16x16.png"}
]
},
{
"iconUrl": "/images/woman1-80x80.jpg",
"title": "Kathrine Doiss",
"message": "Dolor sit amet"
},
{
"iconUrl": "/images/woman2-80x80.jpg",
"title": "Jamie Haynig",
"message": "Consectetur adipisicing elit"
},
{
"iconUrl": "/images/woman3-80x80.jpg",
"title": "Maricia Rilari",
"message": "Sed do eiusmod tempor incididunt"
},
{
"iconUrl": "/images/fruit1-80x80.jpg",
"title": "Notification #$#: Pears!",
"message": "Pyrus"
},
{
"iconUrl": "/images/fruit2-80x80.jpg",
"title": "Notification #$#: Oranges!",
"message": "Citrus sinensis"
},
{
"iconUrl": "/images/fruit3-80x80.jpg",
"title": "Notification #$#: Strawberries!",
"message": "Fragaria ananassa"
},
{
"iconUrl": "/images/fruit4-80x80.jpg",
"title": "Notification #$#: Raspberries!",
"message": "Rubus idaeus"
},
{
"iconUrl": "/images/fruit5-360x360.jpg",
"title": "Notification #$#: Blueberries - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Vaccinium cyanococcus - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
},
{
"sectionName": "Image Notifications",
"notificationType": "image",
"notificationOptions": [
{
"iconUrl": "/images/woman3-80x80.jpg",
"title": "Maricia Rilari",
"message": "Pictures from Tahoe",
"imageUrl": "/images/tahoe-300x225.jpg"
},
{
"iconUrl": "/images/flower1-80x80.jpg",
"title": "Notification #$#: Daffodils!",
"message": "Narcissus",
"imageUrl": "/images/image1-300x225.jpg",
"buttons": [
{"title": "Lorem Ipsum Dolor Sit Amet Consectetur Adipisicing"},
{"title": "Elit Sed Do"}
]
},
{
"iconUrl": "/images/flower2-80x80.jpg",
"title": "Notification #$#: Sunflowers!",
"message": "Helianthus annuus",
"imageUrl": "/images/image2-300x225.jpg"
},
{
"iconUrl": "/images/flower3-80x80.jpg",
"title": "Notification #$#: Poinsettias!",
"message": "Euphorbia pulcherrima",
"imageUrl": "/images/image3-300x172.jpg"
},
{
"iconUrl": "/images/flower4-80x80.jpg",
"title": "Notification #$#: Heather - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Calluna vulgaris - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
"imageUrl": "/images/image4-200x300.jpg"
}
]
},
{
"sectionName": "List Notifications",
"notificationType": "list",
"notificationOptions": [
{
"iconUrl": "/images/inbox-00-80x80.png",
"title": "5 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"}
],
"buttons": [
{"title": "Send Message", "iconUrl": "/images/send-16x16.png"}
]
},
{
"iconUrl": "/images/inbox-01-80x80.png",
"title": "1 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"}
]
},
{
"iconUrl": "/images/inbox-02-80x80.png",
"title": "2 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing elit"}
]
},
{
"iconUrl": "/images/inbox-03-80x80.png",
"title": "3 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incididu"}
]
},
{
"iconUrl": "/images/inbox-05-80x80.png",
"title": "5 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"}
]
},
{
"iconUrl": "/images/inbox-08-80x80.png",
"title": "8 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"},
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incididu"}
]
},
{
"iconUrl": "/images/inbox-13-80x80.png",
"title": "13 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"},
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"},
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incididu"}
]
},
{
"iconUrl": "/images/plant1-80x80.jpg",
"title": "Notification #$#: Yucca!",
"message": "Asparagaceae agavoideae",
"items": [
{"title": "One", "message": "Unus"},
{"title": "Two", "message": "Duo"},
{"title": "Three", "message": "Tres"}
]
},
{
"iconUrl": "/images/plant2-80x80.jpg",
"title": "Notification #$#: Basil - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Ocimum basilicum - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
"items": [
{
"title": "One - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
"message": "Unus - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
},
{
"title": "Two - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
"message": "Duo - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
},
{
"title": "Three - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
"message": "Tres - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
}
]
}
]
}
]
[
{
"copyright": [
"Copyright (c) 2013 The Chromium Authors. All rights reserved.",
"Use of this source code is governed by a BSD-style license that can be",
"found in the LICENSE file."
],
"api": "notifications",
"events": [
"onDisplayed",
"onClosed",
"onClicked",
"onButtonClicked"
],
"globals": {
"type": "$?",
"priority": "$!"
}
},
{
"sectionName": "WebKit Notifications",
"notificationType": "webkit",
"notificationOptions": [
{
"iconUrl": "/images/man1-40x40.jpg",
"title": "Althe Frazon",
"message": "Lorem ipsum"
},
{
"iconUrl": "/images/woman1-40x40.jpg",
"title": "Kathrine Doiss",
"message": "Dolor sit amet"
},
{
"iconUrl": "https://www.google.com/images/icons/product/googlemail-64.png",
"title": "New mail from Brant Hodestrine: Easy Hike in S.F. next Saturday!",
"message": "Hey, The trail starts from 'Merrie Way' Outer Richmond side. We can do brunch before in the Inner Richmond, maybe at that Russian place we used to go to after fencing."
},
{
"iconUrl": "https://calendar.google.com/googlecalendar/images/about-alerts.gif",
"title": "Google Calendar reminder",
"message": "Team Meeting (Brant Hodestrine) is starting at 10:25pm in SFO-CEN-3-Triptych (12), NYC-WES-2-Wegman (8), PAR-OPR-4-Cézanne http://www.example.com/talk/meet/example"
},
{
"iconUrl": "/images/fruit1-40x40.jpg",
"title": "Notification #$#: Pears!",
"message": "Pyrus"
},
{
"iconUrl": "/images/fruit2-40x40.jpg",
"title": "Notification #$#: Oranges!",
"message": "Citrus sinensis"
},
{
"iconUrl": "/images/fruit3-40x40.jpg",
"title": "Notification #$#: Strawberries!",
"message": "Fragaria ananassa"
},
{
"iconUrl": "/images/fruit4-80x80.jpg",
"title": "Notification #$#: Raspberries!",
"message": "Rubus idaeus"
},
{
"iconUrl": "/images/fruit5-360x360.jpg",
"title": "Notification #$#: Blueberries - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Vaccinium cyanococcus - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
},
{
"sectionName": "Simple Notifications",
"notificationType": "simple",
"notificationOptions": [
{
"iconUrl": "/images/man1-40x40.jpg",
"title": "Althe Frazon",
"message": "Lorem ipsum"
},
{
"iconUrl": "/images/woman1-40x40.jpg",
"title": "Kathrine Doiss",
"message": "Dolor sit amet"
},
{
"iconUrl": "https://www.google.com/images/icons/product/googlemail-64.png",
"title": "New mail from Brant Hodestrine: Easy Hike in S.F. next Saturday!",
"message": "Hey, The trail starts from 'Merrie Way' Outer Richmond side. We can do brunch before in the Inner Richmond, maybe at that Russian place we used to go to after fencing."
},
{
"iconUrl": "https://calendar.google.com/googlecalendar/images/about-alerts.gif",
"title": "Google Calendar reminder",
"message": "Team Meeting (Brant Hodestrine) is starting at 10:25pm in SFO-CEN-3-Triptych (12), NYC-WES-2-Wegman (8), PAR-OPR-4-Cézanne http://www.example.com/talk/meet/example"
},
{
"iconUrl": "/images/fruit1-40x40.jpg",
"title": "Notification #$#: Pears!",
"message": "Pyrus"
},
{
"iconUrl": "/images/fruit2-40x40.jpg",
"title": "Notification #$#: Oranges!",
"message": "Citrus sinensis"
},
{
"iconUrl": "/images/fruit3-40x40.jpg",
"title": "Notification #$#: Strawberries!",
"message": "Fragaria ananassa"
},
{
"iconUrl": "/images/fruit4-80x80.jpg",
"title": "Notification #$#: Raspberries!",
"message": "Rubus idaeus"
},
{
"iconUrl": "/images/fruit5-360x360.jpg",
"title": "Notification #$#: Blueberries - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Vaccinium cyanococcus - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
},
{
"sectionName": "Basic Notifications",
"notificationType": "basic",
"notificationOptions": [
{
"iconUrl": "/images/man1-80x80.jpg",
"title": "Althe Frazon",
"message": "Lorem ipsum",
"buttons": [
{"title": "Call", "iconUrl": "/images/call-16x16.png"},
{"title": "Send Email", "iconUrl": "/images/send-16x16.png"}
]
},
{
"iconUrl": "/images/woman1-80x80.jpg",
"title": "Kathrine Doiss",
"message": "Dolor sit amet"
},
{
"iconUrl": "/images/woman2-80x80.jpg",
"title": "Jamie Haynig",
"message": "Consectetur adipisicing elit"
},
{
"iconUrl": "/images/woman3-80x80.jpg",
"title": "Maricia Rilari",
"message": "Sed do eiusmod tempor incididunt"
},
{
"iconUrl": "/images/fruit1-80x80.jpg",
"title": "Notification #$#: Pears!",
"message": "Pyrus"
},
{
"iconUrl": "/images/fruit2-80x80.jpg",
"title": "Notification #$#: Oranges!",
"message": "Citrus sinensis"
},
{
"iconUrl": "/images/fruit3-80x80.jpg",
"title": "Notification #$#: Strawberries!",
"message": "Fragaria ananassa"
},
{
"iconUrl": "/images/fruit4-80x80.jpg",
"title": "Notification #$#: Raspberries!",
"message": "Rubus idaeus"
},
{
"iconUrl": "/images/fruit5-360x360.jpg",
"title": "Notification #$#: Blueberries - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Vaccinium cyanococcus - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
},
{
"sectionName": "Image Notifications",
"notificationType": "image",
"notificationOptions": [
{
"iconUrl": "/images/woman3-80x80.jpg",
"title": "Maricia Rilari",
"message": "Pictures from Tahoe",
"imageUrl": "/images/tahoe-300x225.jpg"
},
{
"iconUrl": "/images/flower1-80x80.jpg",
"title": "Notification #$#: Daffodils!",
"message": "Narcissus",
"imageUrl": "/images/image1-300x225.jpg",
"buttons": [
{"title": "Lorem Ipsum Dolor Sit Amet Consectetur Adipisicing"},
{"title": "Elit Sed Do"}
]
},
{
"iconUrl": "/images/flower2-80x80.jpg",
"title": "Notification #$#: Sunflowers!",
"message": "Helianthus annuus",
"imageUrl": "/images/image2-300x225.jpg"
},
{
"iconUrl": "/images/flower3-80x80.jpg",
"title": "Notification #$#: Poinsettias!",
"message": "Euphorbia pulcherrima",
"imageUrl": "/images/image3-300x172.jpg"
},
{
"iconUrl": "/images/flower4-80x80.jpg",
"title": "Notification #$#: Heather - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Calluna vulgaris - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
"imageUrl": "/images/image4-200x300.jpg"
}
]
},
{
"sectionName": "List Notifications",
"notificationType": "list",
"notificationOptions": [
{
"iconUrl": "/images/inbox-00-80x80.png",
"title": "5 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"}
],
"buttons": [
{"title": "Send Message", "iconUrl": "/images/send-16x16.png"}
]
},
{
"iconUrl": "/images/inbox-01-80x80.png",
"title": "1 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"}
]
},
{
"iconUrl": "/images/inbox-02-80x80.png",
"title": "2 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing elit"}
]
},
{
"iconUrl": "/images/inbox-03-80x80.png",
"title": "3 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incididu"}
]
},
{
"iconUrl": "/images/inbox-05-80x80.png",
"title": "5 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"}
]
},
{
"iconUrl": "/images/inbox-08-80x80.png",
"title": "8 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"},
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incididu"}
]
},
{
"iconUrl": "/images/inbox-13-80x80.png",
"title": "13 new messages",
"message": "ramon.widdel@example.com",
"items": [
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"},
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incidid"},
{"title": "Kelly Seiken", "message": "Ut labore et dolore magna ali"},
{"title": "Maricia Rilari", "message": "Ut enim ad minim veniam"},
{"title": "Althe Frazon", "message": "Lorem ipsum dolor sit amet"},
{"title": "Kathrine Doiss", "message": "Consectetur adipisicing eli"},
{"title": "Jamie Haynig", "message": "Sed do eiusmod tempor incididu"}
]
},
{
"iconUrl": "/images/plant1-80x80.jpg",
"title": "Notification #$#: Yucca!",
"message": "Asparagaceae agavoideae",
"items": [
{"title": "One", "message": "Unus"},
{"title": "Two", "message": "Duo"},
{"title": "Three", "message": "Tres"}
]
},
{
"iconUrl": "/images/plant2-80x80.jpg",
"title": "Notification #$#: Basil - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum!",
"message": "Ocimum basilicum - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
"items": [
{
"title": "One - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
"message": "Unus - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
},
{
"title": "Two - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
"message": "Duo - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
},
{
"title": "Three - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum",
"message": "Tres - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
}
]
}
]
}
]
[ [
{ {
"copyright": [ "sectionName": "Web Notifications",
"Copyright (c) 2013 The Chromium Authors. All rights reserved.", "notificationType": "web",
"Use of this source code is governed by a BSD-style license that can be",
"found in the LICENSE file."
],
"api": "notifications",
"events": [
"onDisplayed",
"onClosed",
"onClicked",
"onButtonClicked"
],
"globals": {
"type": "$?",
"priority": "$!"
}
},
{
"sectionName": "WebKit Notifications",
"notificationType": "webkit",
"notificationOptions": [ "notificationOptions": [
{ {
"iconUrl": "/images/man1-40x40.jpg", "iconUrl": "/images/man1-40x40.jpg",
......
...@@ -2,9 +2,5 @@ ...@@ -2,9 +2,5 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
(function() { chrome.app.runtime.onLaunched.addListener(createWindow);
var controller = Galore.controller.create(); chrome.app.runtime.onRestarted.addListener(createWindow);
var listener = controller.createWindow.bind(controller);
chrome.app.runtime.onLaunched.addListener(listener);
chrome.app.runtime.onRestarted.addListener(listener);
}());
...@@ -3,18 +3,27 @@ ...@@ -3,18 +3,27 @@
* found in the LICENSE file. */ * found in the LICENSE file. */
/* Globals ********************************************************************/ /* Globals ********************************************************************/
html {
height: 100%
}
body { body {
-webkit-app-region: drag;
cursor: default; cursor: default;
margin: 0; margin: 0px;
padding: 15px 4px 4px; padding: 0px 4px 4px;
overflow:hidden;
height: 100%;
} }
.section { .section {
margin: 12px 0 0; overflow:hidden;
position: relative; margin:14px 0 12px 0;
padding: 23px 0 0; }
.subsection {
margin:2px;
padding:3px;
border:1px solid lightgrey;
} }
h1 { h1 {
...@@ -24,12 +33,8 @@ h1 { ...@@ -24,12 +33,8 @@ h1 {
white 65%, white); white 65%, white);
font: normal 16px 'Arimo', 'Gill Sans', 'Open Sans', font: normal 16px 'Arimo', 'Gill Sans', 'Open Sans',
'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
left: 0; margin: 0 0 8px 0;
margin: 0;
position: absolute;
right: 0;
text-align: center; text-align: center;
top: 0;
} }
h1 span { h1 span {
...@@ -37,32 +42,32 @@ h1 span { ...@@ -37,32 +42,32 @@ h1 span {
padding: 0 4px; padding: 0 4px;
} }
button { button.borderless {
background: none; background-color: white;
border: 1px solid white; border:1px solid rgba(0,0,0,0.1);
margin: 0; margin: 3px;
padding: 3px; padding: 3px;
} }
::-webkit-scrollbar { button.borderless:hover {
display: none !important; border:1px solid rgba(0,0,0,1);
}
button.borderless:hover[disabled] {
border:1px solid rgba(0,0,0,0.1);
} }
/* Template section (invisible) ***********************************************/ /* Template section (invisible) ***********************************************/
#templates { #templates {
position: absolute; display: none;
visibility: hidden;
} }
/* Priority section ***********************************************************/ /* Priority section ***********************************************************/
#priority { #priority {
font-size: 0; /* To collapse the spaces between buttons. */ font-size: 0; /* To collapse the spaces between buttons. */
} text-align: center;
#priority .priority:first-of-type {
margin: 0 0 0 96px; /* Leftmost button is 96 pixels in. */
} }
button.priority { button.priority {
...@@ -72,14 +77,30 @@ button.priority { ...@@ -72,14 +77,30 @@ button.priority {
width: 48px; width: 48px;
} }
/* Notification sections ******************************************************/ /* Recorder *******************************************************************/
#recording-status {
font-size:18pt;
text-align: center;
}
button.notification { #recording-stats {
height: 48px; font-size:9pt;
width: 48px; text-align: center;
}
button.control img {
display: block;
margin: 0;
padding: 0;
}
button.control[disabled="true"] {
opacity: 0.2;
} }
img { /* Notification sections ******************************************************/
button.notification img {
display: block; display: block;
height: 40px; height: 40px;
margin: 0; margin: 0;
...@@ -90,32 +111,13 @@ img { ...@@ -90,32 +111,13 @@ img {
/* Events section *************************************************************/ /* Events section *************************************************************/
#events { #events {
position: relative; margin:0;
height: 183px;
}
#events-scroll {
bottom: 4px;
font-weight: lighter; font-weight: lighter;
left: 4px;
padding: 0; padding: 0;
max-height: 190px; height:180px;
overflow: scroll; overflow-y: auto;
position: absolute; overflow-x: hidden;
right: 4px; background-color: gold;
-webkit-user-select: text;
}
#events-fade {
background: -webkit-linear-gradient(rgba(255, 255, 255, 1),
rgba(255, 255, 255, 1) 50%,
rgba(255, 255, 255, 0));
height: 46px;
left: 0;
pointer-events: none;
position: absolute;
right: 0;
top: 0;
} }
.event { .event {
...@@ -131,116 +133,7 @@ img { ...@@ -131,116 +133,7 @@ img {
text-align: center; text-align: center;
} }
/* Menu ***********************************************************************/
body[data-active="menu"] #popup,
body[data-popup="true"] #popup {
bottom: 0;
left: 0;
position: absolute;
right: 0;
top: 0;
}
body:not([data-active="menu"]):not([data-popup="true"]) #popup {
left: -9999px !important;
position: absolute !important;
top: -9999px !important;
}
#shadow {
background: gray;
bottom: 0;
left: 0;
opacity: 0.33;
position: absolute;
right: 0;
top: 0;
}
#menu {
left: 12px;
padding: 0;
position: absolute;
top: 26px;
width: auto;
}
#menu-items {
background: white;
box-shadow: 0px 8px 24px rgba(0, 0, 0, 0.7);
margin: 7px 0 0;
padding: 4px;
}
#menu-items button {
display: block;
text-align: left;
width: 100%;
}
#show-settings {
/* TODO(dharcourt): Add a settings panel and make this open it. */
display: none !important;
}
#arrow {
border-bottom: 7px solid white;
border-left: 7px solid transparent;
border-right: 7px solid transparent;
height: 0;
position: absolute;
top: 0;
width: 0;
}
/* Menu and close buttons *****************************************************/
#show-menu,
#close {
border: 1px solid transparent;
height: 16px;
opacity: 0.15;
position: absolute;
top: 11px;
width: 16px;
}
#show-menu {
background: url("/images/menu-14x14.png");
left: 11px;
}
#close {
background: url("/images/close-14x14.png");
right: 11px;
}
#show-menu:hover,
#close:hover {
opacity: 0.6;
}
body[data-active="close"] #close,
body[data-active="menu"] #show-menu {
opacity: 1;
}
/* Highlighting ***************************************************************/ /* Highlighting ***************************************************************/
body[data-active=""] button[data-hover="true"],
body[data-active="close"] button.close[data-hover="true"],
body[data-active="menu"] button.menu[data-hover="true"],
body[data-active="notification"] button.notification[data-hover="true"],
body[data-active="priority"] button.priority[data-hover="true"] {
border: 1px solid black !important;
}
body[data-active="notification"] button.notification[data-hover="true"],
body[data-active="priority"] button.priority[data-hover="true"] {
opacity: 0.5;
}
body[data-priority="-2"] button.priority[data-priority="-2"], body[data-priority="-2"] button.priority[data-priority="-2"],
body[data-priority="-1"] button.priority[data-priority="-1"], body[data-priority="-1"] button.priority[data-priority="-1"],
body[data-priority="0"] button.priority[data-priority="0"], body[data-priority="0"] button.priority[data-priority="0"],
...@@ -249,20 +142,3 @@ body[data-priority="2"] button.priority[data-priority="2"] { ...@@ -249,20 +142,3 @@ body[data-priority="2"] button.priority[data-priority="2"] {
background: rgb(255, 255, 85); background: rgb(255, 255, 85);
-webkit-box-shadow: inset 3px 3px 0 white, inset -3px -3px 0 white; -webkit-box-shadow: inset 3px 3px 0 white, inset -3px -3px 0 white;
} }
/* Cursor and dragging control ************************************************/
body:not([data-active=""]),
body:not([data-active="menu"]):not([data-popup="true"]) button,
button.menu,
button.close {
-webkit-app-region: no-drag;
cursor: pointer;
}
body:not([data-active="menu"]):not([data-popup="true") #events {
-webkit-app-region: no-drag;
cursor: text;
}
/* That's all folks! **********************************************************/
...@@ -2,233 +2,134 @@ ...@@ -2,233 +2,134 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
var Galore = Galore || {}; var mainWindow;
var sections = [];
Galore.view = {
/** @constructor */ var settings = {}
create: function(settings, onload, onSettingsChange) { settings.priority = "0";
var view = Object.create(this);
view.actions = []; function onMainWindowClosed() {
view.sections = {}; mainWindow = null;
view.settings = settings; sections = [];
view.onload = onload; }
view.onsettings = onSettingsChange;
function createAppWindow(onLoad) {
chrome.app.window.create('window.html', { chrome.app.window.create('window.html', {
id: 'window', id: 'window',
frame: 'none', defaultWidth: 440, minWidth: 440, maxWidth: 840,
defaultWidth: 440, minWidth: 440, maxWidth: 440, defaultHeight: 640, minHeight: 640, maxHeight: 940,
defaultHeight: 640, minHeight: 640, maxHeight: 640,
hidden: true hidden: true
}, function(appWindow) { }, function(w) {
view.window = appWindow; mainWindow = w;
view.addListener_(appWindow.contentWindow, 'load', 'onLoad_'); mainWindow.contentWindow.onload = function() {
}.bind(this)); setButtonHandlers();
return view; getElement("body").dataset.priority = settings.priority;
}, onLoad();
};
addNotificationButton: function(sectionTitle, mainWindow.onClosed.addListener(onMainWindowClosed)
});
}
function resovleImageUrl(imageUrl, callback) {
if (imageUrl.substr(0,4) != "http") {
callback(imageUrl);
return;
}
var xhr = new XMLHttpRequest();
xhr.open("GET", imageUrl);
xhr.responseType = "blob";
xhr.onload = function() {
callback(URL.createObjectURL(this.response));
}
xhr.send();
}
function addNotificationButton(sectionTitle,
buttonTitle, buttonTitle,
iconUrl, iconUrl,
onClick) { onClickHandler) {
var button = this.getElement_('#templates .notification').cloneNode(true); var button = getElement('#templates .notification').cloneNode(true);
var image = button.querySelector('img'); var image = button.querySelector('img');
resovleImageUrl(iconUrl, function(url) { image.src = url });
image.src = iconUrl; image.src = iconUrl;
image.alt = buttonTitle; image.alt = buttonTitle;
button.name = buttonTitle; button.name = buttonTitle;
button.dataset.actionIndex = this.actions.push(onClick) - 1; button.onclick = onClickHandler;
this.addButtonListeners_(button); getSection(sectionTitle).appendChild(button);
this.getSection_(sectionTitle).appendChild(button); }
},
function showWindow() {
showWindow: function() { if (mainWindow)
if (this.window) mainWindow.show();
this.window.show(); }
},
function logEvent(message) {
logEvent: function(message) { var event = getElement('#templates .event').cloneNode(true);
var event = this.getElement_('#templates .event').cloneNode(true);
event.textContent = message; event.textContent = message;
this.getElement_('#events-scroll').appendChild(event).scrollIntoView(); getElement('#events').appendChild(event).scrollIntoView();
}, }
logError: function(message) { function logError(message) {
var events = this.getElement_('#events-scroll'); var events = getElement('#events');
var error = this.getElement_('#templates .error').cloneNode(true); var error = getElement('#templates .error').cloneNode(true);
error.textContent = message; error.textContent = message;
events.appendChild(error).scrollIntoView(); events.appendChild(error).scrollIntoView();
}, }
/** @private */ function setButtonHandlers() {
onLoad_: function() { setButtonAction('.priority', changePriority);
this.dataset = this.window.contentWindow.document.body.dataset; setButtonAction('#clear-events', clearEvents);
this.dataset.priority = this.settings.priority || '0'; setButtonAction('#record', onRecord);
this.addListener_('body', 'mousedown', 'onBodyMouseDown_'); setButtonAction('#pause', onPause);
this.addListener_('body', 'mouseup', 'onBodyMouseUp_'); setButtonAction('#stop', onStop);
this.addListener_('#shadow', 'mousemove', 'onButtonMouseMove_'); setButtonAction('#play', onPlay);
this.addButtonListeners_('button, #shadow'); }
this.setButtonAction_('.priority', 'changePriority_');
this.setButtonAction_('#shadow', 'toggleMenu_'); function setRecorderStatusText(text) {
this.setButtonAction_('#clear-events', 'clearEvents_'); getElement("#recording-status").innerText = text;
this.setButtonAction_('#show-menu', 'toggleMenu_'); }
this.setButtonAction_('#close', 'close', this.window.contentWindow);
if (this.onload) function updateRecordingStatsDisplay(text) {
this.onload.call(this, this); getElement("#recording-stats").innerText = text;
}, }
/** function changePriority(event) {
* Handling our own mouse events is fun! It also allows us to keep the cursor settings.priority = event.currentTarget.dataset.priority || '0';
* appropriately indicating whether a button press or window drag is happening getElement("body").dataset.priority = settings.priority;
* or will happen on mousedown. As a bonus, it allows button to have a }
* highlight-as-you-drag behavior similar to menu items.
* function clearEvents() {
* @private */ var events = getElement('#events');
onButtonMouseDown_: function(event) {
// Record the fact that a button in this button's group is active, which
// allows onButtonMouseUp_ to do the right thing and CSS rules to correctly
// set cursor types and button highlighting.
var element = event.currentTarget;
this.dataset.active = element.classList[0] || '';
this.dragging = false;
},
/**
* See the comment for onButtonMouseDown_() above.
*
* @private */
onButtonMouseMove_: function(event) {
// Buttons that support dragging add this as a listener to their mousemove
// events so a flag can be set during dragging to prevent their actions from
// being fired by the mouseup event that completes the dragging.
this.dragging = true;
},
/**
* See the comment for onButtonMouseDown_() above.
*
* @private */
onButtonMouseOut_: function(event) {
// Record the fact that the mouse is not over this button any more to allow
// CSS rules to stop highlighting it.
event.currentTarget.dataset.hover = 'false';
},
/**
* See the comment for onButtonMouseDown_() above.
*
* @private */
onButtonMouseOver_: function(event) {
// Record the fact that the mouse is over this button to allow CSS rules to
// highlight it if appropriate.
event.currentTarget.dataset.hover = 'true';
},
/**
* See the comment for onButtonMouseDown_() above.
*
* @private */
onButtonMouseUp_: function(event) {
// Send a button action if the button in which the mouseup happened is in
// the same group as the one in which the mousedown happened. The regular
// click handling which this replaces would send the action only if the
// mouseup happened in the same button as the mousedown.
var element = event.currentTarget;
var group = (element.classList[0] || 'x');
if (group == this.dataset.active && !this.dragging)
this.actions[element.dataset.actionIndex].call(element, event);
},
/**
* See the comment for onButtonMouseDown_() above.
*
* @private */
onBodyMouseUp_: function(event) {
// Record the fact that no button is active, which allows onButtonMouseUp_
// to do the right thing and CSS rules to correctly set cursor types and
// button highlighting.
this.dataset.active = '';
},
/** @private */
onBodyMouseDown_: function(event) {
// Prevents the cursor from becoming a text cursor during drags.
if (window.getComputedStyle(event.target).cursor != 'text')
event.preventDefault();
},
/** @private */
changePriority_: function(event) {
this.settings.priority = event.currentTarget.dataset.priority || '0';
this.dataset.priority = this.settings.priority;
if (this.onsettings)
this.onsettings.call(this, this.settings);
},
/** @private */
toggleMenu_: function() {
this.dataset.popup = String(this.dataset.popup != 'true');
},
/** @private */
clearEvents_: function() {
var events = this.getElement_('#events-scroll');
while (events.lastChild) while (events.lastChild)
events.removeChild(events.lastChild); events.removeChild(events.lastChild);
this.dataset.popup = 'false'; }
},
function getSection(title) {
/** @private */ sections[title] = (sections[title] || makeSection(title));
getSection_: function(title) { return sections[title];
this.sections[title] = (this.sections[title] || this.makeSection_(title)); }
return this.sections[title];
}, function makeSection(title) {
var section = getElement('#templates .section').cloneNode(true);
/** @private */
makeSection_: function(title) {
var section = this.getElement_('#templates .section').cloneNode(true);
section.querySelector('span').textContent = title; section.querySelector('span').textContent = title;
return this.getElement_('#notifications').appendChild(section); return getElement('#notifications').appendChild(section);
}, }
/** @private */
addButtonListeners_: function(buttons) {
this.addListener_(buttons, 'mousedown', 'onButtonMouseDown_');
this.addListener_(buttons, 'mouseout', 'onButtonMouseOut_');
this.addListener_(buttons, 'mouseover', 'onButtonMouseOver_');
this.addListener_(buttons, 'mouseup', 'onButtonMouseUp_');
},
/** @private */
setButtonAction_: function(elements, action, target) {
var index = this.actions.push(this.bind_(action, target)) - 1;
this.getElements_(elements).forEach(function(element) {
element.dataset.actionIndex = index;
});
},
/** @private */ function setButtonAction(elements, action) {
addListener_: function(elements, event, action, target) { getElements(elements).forEach(function(element) {
var listener = this.bind_(action, target); element.onclick = action;
this.getElements_(elements).forEach(function(element) {
element.addEventListener(event, listener);
}); });
}, }
/** @private */ function getElement(element) {
bind_: function(action, target) { return getElements(element)[0];
return (target || this)[action].bind(target || this); }
},
/** @private */ function getElements(elements) {
getElement_: function(element) {
return this.getElements_(element)[0];
},
/** @private */
getElements_: function(elements) {
if (typeof elements === 'string') if (typeof elements === 'string')
elements = this.window.contentWindow.document.querySelectorAll(elements); elements = mainWindow.contentWindow.document.querySelectorAll(elements);
if (String(elements) === '[object NodeList]') if (String(elements) === '[object NodeList]')
elements = Array.prototype.slice.call(elements); elements = Array.prototype.slice.call(elements);
return Array.isArray(elements) ? elements : [elements]; return Array.isArray(elements) ? elements : [elements];
} }
};
...@@ -7,41 +7,40 @@ ...@@ -7,41 +7,40 @@
<title>Notifications Galore!</title> <title>Notifications Galore!</title>
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
</head> </head>
<body data-active="" data-popup="false"> <body data-active="">
<div id="templates"> <div id="templates">
<div class="section"><h1><span/></h1></div> <div class="section"><h1><span/></h1></div>
<div class="event"></div> <div class="event"></div>
<div class="error"></div> <div class="error"></div>
<div class="spacer"></div> <div class="spacer"></div>
<button class="notification"> <button class="notification borderless">
<img src="images/white-40x40.png"> <img src="images/white-40x40.png">
</button> </button>
</div> </div>
<div id="priority" class="section"> <div id="priority" class="section">
<h1><span>Priority</span></h1> <h1><span>Priority</span></h1>
<button class="priority" data-priority="-2">-2</button> <button class="priority borderless" data-priority="-2">-2</button>
<button class="priority" data-priority="-1">-1</button> <button class="priority borderless" data-priority="-1">-1</button>
<button class="priority" data-priority="0">0</button> <button class="priority borderless" data-priority="0">0</button>
<button class="priority" data-priority="1">1</button> <button class="priority borderless" data-priority="1">1</button>
<button class="priority" data-priority="2">2</button> <button class="priority borderless" data-priority="2">2</button>
</div> </div>
<div id="notifications"></div> <div id="other-controls" xclass="section">
<div id="events" class="section"> <h1><span>Controls</span></h1>
<div id="events-scroll"></div> <div class="subsection">
<div id="events-fade"></div> <button id="clear-events">Clear Events</button>
<h1><span>Events</span></h1>
</div>
<div id="popup">
<div id="shadow" class="shadow"></div>
<div id="menu">
<div id="menu-items">
<button id="show-settings" class="menu">Settings...</button>
<button id="clear-events" class="menu">Clear Events</button>
</div> </div>
<div id="arrow"></div> <div class="subsection">
<button id="record" class="control borderless"><img src="images/record.png"></img></button>
<button id="pause" class="control borderless"><img src="images/pause.png"></img></button>
<button id="stop" class="control borderless"><img src="images/stop.png"></img></button>
<button id="play" class="control borderless"><img src="images/play.png"></img></button>
<sup id="recording-status">Stopped</sup>
<div id="recording-stats"> </div>
</div> </div>
</div> </div>
<button id="close" class="close" name="Close"></button> <div id="notifications"></div>
<button id="show-menu" class="menu" name="Show Menu"></button> <h1><span>Events</span></h1>
<div id="events" class="section"></div>
</body> </body>
</html> </html>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment