зеркало из https://github.com/mozilla/gecko-dev.git
Bug 972020 - Loop basic UI. r=Standard8
--HG-- rename : browser/components/loop/content/libs/backbone-min.js => browser/components/loop/content/shared/libs/backbone-1.1.2.js rename : browser/components/loop/content/libs/lodash.min.js => browser/components/loop/content/shared/libs/lodash-2.4.1.js
This commit is contained in:
Родитель
0a91369aaa
Коммит
0990db56f0
|
@ -0,0 +1,65 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*global loop*/
|
||||
|
||||
var loop = loop || {};
|
||||
loop.Client = (function($) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Loop server client.
|
||||
*
|
||||
* @param {Object} settings Settings object.
|
||||
*/
|
||||
function Client(settings) {
|
||||
settings = settings || {};
|
||||
if (!settings.hasOwnProperty("baseApiUrl")) {
|
||||
throw new Error("missing required baseApiUrl");
|
||||
}
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
Client.prototype = {
|
||||
/**
|
||||
* Requests a call URL to the Loop server.
|
||||
*
|
||||
* @param {Function} cb Callback(err, callUrl)
|
||||
*/
|
||||
requestCallUrl: function(simplepushUrl, cb) {
|
||||
var endpoint = this.settings.baseApiUrl + "/call-url/",
|
||||
reqData = {simplepushUrl: simplepushUrl};
|
||||
|
||||
function validate(callUrlData) {
|
||||
if (typeof callUrlData !== "object" ||
|
||||
!callUrlData.hasOwnProperty("call_url")) {
|
||||
var message = "Invalid call url data received";
|
||||
console.error(message, callUrlData);
|
||||
throw new Error(message);
|
||||
}
|
||||
return callUrlData.call_url;
|
||||
}
|
||||
|
||||
var req = $.post(endpoint, reqData, function(callUrlData) {
|
||||
try {
|
||||
cb(null, validate(callUrlData));
|
||||
} catch (err) {
|
||||
cb(err);
|
||||
}
|
||||
}, "json");
|
||||
|
||||
req.fail(function(xhr, type, err) {
|
||||
var error = "Unknown error.";
|
||||
if (xhr && xhr.responseJSON && xhr.responseJSON.error) {
|
||||
error = xhr.responseJSON.error;
|
||||
}
|
||||
var message = "HTTP error " + xhr.status + ": " + err + "; " + error;
|
||||
console.error(message);
|
||||
cb(new Error(message));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return Client;
|
||||
})(jQuery);
|
|
@ -0,0 +1,70 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
/**
|
||||
* Data accessor for chrome resources. This is used to provide an
|
||||
* interface for l10n.js to use.
|
||||
*
|
||||
* XXX currently this file accesses chrome direct, and hence is a big
|
||||
* simplification on what it could be. When we implement
|
||||
* bug 976109 we'll likely need to do a proxy to the chrome space.
|
||||
*/
|
||||
var FirefoxCom = (function FirefoxComClosure() {
|
||||
return {
|
||||
/**
|
||||
* Handles requests for data synchronously.
|
||||
*/
|
||||
requestSync: function(action, data) {
|
||||
if (action === 'getLocale')
|
||||
return this.getLocale();
|
||||
|
||||
if (action === 'getStrings')
|
||||
return this.getStrings(data);
|
||||
|
||||
console.error('[fxcom] Action' + action + ' is unknown');
|
||||
return null;
|
||||
},
|
||||
|
||||
getLocale: function() {
|
||||
try {
|
||||
return Services.prefs.getCharPref('general.useragent.locale');
|
||||
} catch (x) {
|
||||
return 'en-US';
|
||||
}
|
||||
},
|
||||
|
||||
getStrings: function(data) {
|
||||
try {
|
||||
return JSON.stringify(this.localizedStrings[data] || null);
|
||||
} catch (e) {
|
||||
console.error('[fxcom] Unable to retrive localized strings: ' + e);
|
||||
}
|
||||
},
|
||||
|
||||
get localizedStrings() {
|
||||
var stringBundle =
|
||||
Services.strings.createBundle('chrome://browser/locale/loop/loop.properties');
|
||||
|
||||
var map = {};
|
||||
var enumerator = stringBundle.getSimpleEnumeration();
|
||||
while (enumerator.hasMoreElements()) {
|
||||
var string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement);
|
||||
var key = string.key, property = 'textContent';
|
||||
var i = key.lastIndexOf('.');
|
||||
if (i >= 0) {
|
||||
property = key.substring(i + 1);
|
||||
key = key.substring(0, i);
|
||||
}
|
||||
if (!(key in map))
|
||||
map[key] = {};
|
||||
map[key][property] = string.value;
|
||||
}
|
||||
delete this.localizedStrings;
|
||||
return this.localizedStrings = map;
|
||||
}
|
||||
};
|
||||
})();
|
|
@ -0,0 +1,146 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*global loop*/
|
||||
|
||||
var loop = loop || {};
|
||||
loop.panel = (function(_, __) {
|
||||
"use strict";
|
||||
|
||||
// XXX: baseApiUrl should be configurable (browser pref)
|
||||
var baseApiUrl = "http://localhost:5000",
|
||||
panelView;
|
||||
|
||||
/**
|
||||
* Panel initialisation.
|
||||
*/
|
||||
function init() {
|
||||
panelView = new PanelView();
|
||||
panelView.render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notification model.
|
||||
*/
|
||||
var NotificationModel = Backbone.Model.extend({
|
||||
defaults: {
|
||||
level: "info",
|
||||
message: ""
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Notification collection
|
||||
*/
|
||||
var NotificationCollection = Backbone.Collection.extend({
|
||||
model: NotificationModel
|
||||
});
|
||||
|
||||
/**
|
||||
* Notification view.
|
||||
*/
|
||||
var NotificationView = Backbone.View.extend({
|
||||
template: _.template([
|
||||
'<div class="alert alert-<%- level %>">',
|
||||
' <button class="close"></button>',
|
||||
' <p class="message"><%- message %></p>',
|
||||
'</div>'
|
||||
].join("")),
|
||||
|
||||
events: {
|
||||
"click .close": "dismiss"
|
||||
},
|
||||
|
||||
dismiss: function() {
|
||||
this.$el.addClass("fade-out");
|
||||
setTimeout(function() {
|
||||
this.collection.remove(this.model);
|
||||
this.remove();
|
||||
}.bind(this), 500);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.$el.html(this.template(this.model.toJSON()));
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Notification list view.
|
||||
*/
|
||||
var NotificationListView = Backbone.View.extend({
|
||||
initialize: function() {
|
||||
this.listenTo(this.collection, "reset add remove", this.render);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.$el.html(this.collection.map(function(notification) {
|
||||
return new NotificationView({
|
||||
model: notification,
|
||||
collection: this.collection
|
||||
}).render().$el;
|
||||
}.bind(this)));
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Panel view.
|
||||
*/
|
||||
var PanelView = Backbone.View.extend({
|
||||
el: "#default-view",
|
||||
|
||||
events: {
|
||||
"click a.get-url": "getCallUrl"
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
this.client = new loop.Client({
|
||||
baseApiUrl: baseApiUrl
|
||||
});
|
||||
this.notificationCollection = new NotificationCollection();
|
||||
this.notificationListView = new NotificationListView({
|
||||
el: this.$(".messages"),
|
||||
collection: this.notificationCollection
|
||||
});
|
||||
this.notificationListView.render();
|
||||
},
|
||||
|
||||
notify: function(message, level) {
|
||||
this.notificationCollection.add({
|
||||
level: level || "info",
|
||||
message: message
|
||||
});
|
||||
},
|
||||
|
||||
getCallUrl: function(event) {
|
||||
event.preventDefault();
|
||||
var simplepushUrl = "http://fake.url/"; // XXX: send a real simplepush url
|
||||
this.client.requestCallUrl(simplepushUrl, function(err, callUrl) {
|
||||
if (err) {
|
||||
this.notify(__("unable_retrieve_url"), "error");
|
||||
return;
|
||||
}
|
||||
this.onCallUrlReceived(callUrl);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
onCallUrlReceived: function(callUrl) {
|
||||
this.notificationCollection.reset();
|
||||
this.$(".action .invite").hide();
|
||||
this.$(".action .result input").val(callUrl);
|
||||
this.$(".action .result").show();
|
||||
this.$(".description p").text(__("share_link_url"));
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
init: init,
|
||||
NotificationModel: NotificationModel,
|
||||
NotificationCollection: NotificationCollection,
|
||||
NotificationView: NotificationView,
|
||||
NotificationListView: NotificationListView,
|
||||
PanelView: PanelView
|
||||
};
|
||||
})(_, document.mozL10n.get);
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -4,20 +4,44 @@
|
|||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Loop Panel</title>
|
||||
<link rel="stylesheet" type="text/css" href="shared/css/common.css">
|
||||
<link rel="stylesheet" type="text/css" href="shared/css/panel.css">
|
||||
</head>
|
||||
<body onload="loop.panel.init();">
|
||||
<!-- XXX (n1k0): i10n tbd later as these are temporary texts. -->
|
||||
<div id="default-view" class="share generate-url">
|
||||
<div class="description">
|
||||
<p data-l10n-id="get_link_to_share">
|
||||
Get a link to share with a friend to Video Chat.
|
||||
</p>
|
||||
</div>
|
||||
<div class="action">
|
||||
<div class="messages"></div>
|
||||
<p class="invite">
|
||||
<a class="get-url btn btn-success" href=""
|
||||
data-l10n-id="get_a_call_url">Get a call url</a>
|
||||
</p>
|
||||
<p class="result hide">
|
||||
<input id="call-url" type="url" readonly>
|
||||
<a class="get-url btn btn-info" href="" data-l10n-id="renew">Renew</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- XXX (adam): Should we import our own version of Webl10n?
|
||||
What we have here is a copy of the version from pdf.js
|
||||
(which I can't seem to reference directly, so we've copied
|
||||
it here). At the very least, if we're using the same
|
||||
library as pdf.js, we should be referring to the same
|
||||
file. -->
|
||||
<script type="text/javascript" src="js/fxcom.js"></script>
|
||||
<script type="text/javascript" src="libs/l10n.js"></script>
|
||||
<script type="text/javascript" src="libs/zepto.min.js"></script>
|
||||
<script type="text/javascript" src="libs/lodash.min.js"></script>
|
||||
<script type="text/javascript" src="libs/backbone-min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Intentionally not localisable as this is a temporary page -->
|
||||
<p>Soon you'll be able to get a url to share with your friends and chat with them</p>
|
||||
<script type="text/javascript" src="shared/libs/jquery-2.1.0.js"></script>
|
||||
<script type="text/javascript" src="shared/libs/lodash-2.4.1.js"></script>
|
||||
<script type="text/javascript" src="shared/libs/backbone-1.1.2.js"></script>
|
||||
<script type="text/javascript" src="js/client.js"></script>
|
||||
<script type="text/javascript" src="js/panel.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
Loop Shared Web Assets
|
||||
======================
|
||||
|
||||
This directory contains web assets shared across the Loop client webapp and the
|
||||
Loop Firefox Component.
|
||||
|
||||
Warning
|
||||
-------
|
||||
|
||||
Any modification in these files will have possible side effects on both the
|
||||
Firefox component and the webapp. The `css/readme.html` file uses all the shared
|
||||
styles, you should use it as a way of checking for visual regressions.
|
|
@ -0,0 +1,138 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Generic rules */
|
||||
|
||||
/**
|
||||
* "Fixes" the Box Model.
|
||||
* @see http://www.paulirish.com/2012/box-sizing-border-box-ftw/
|
||||
*/
|
||||
*, *:before, *:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans;
|
||||
font-size: 14px;
|
||||
background: #f2f2f2;
|
||||
}
|
||||
|
||||
button {
|
||||
font-size: .9em; /* for some reason, text is larger within <button> */
|
||||
}
|
||||
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Helpers */
|
||||
|
||||
/**
|
||||
* Clearfix impl. for modern browsers
|
||||
* 1. The space content is one way to avoid an Opera bug when the
|
||||
* contenteditable attribute is included anywhere else in the document.
|
||||
* Otherwise it causes space to appear at the top and bottom of elements
|
||||
* that are clearfixed.
|
||||
* 2. The use of `table` rather than `block` is only necessary if using
|
||||
* `:before` to contain the top-margins of child elements.
|
||||
*/
|
||||
.cf:before,
|
||||
.cf:after {
|
||||
content: " "; /* 1 */
|
||||
display: table; /* 2 */
|
||||
}
|
||||
|
||||
.cf:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tc {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
background: #aaa;
|
||||
border: none;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
padding: .25em .5em .3em;
|
||||
border-radius: .2em;
|
||||
}
|
||||
|
||||
.btn-info {
|
||||
background: #428BCA;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background: #5cb85c;
|
||||
}
|
||||
|
||||
.btn-warning {
|
||||
background: #f0ad4e;
|
||||
}
|
||||
|
||||
.btn-error {
|
||||
background: #d9534f;
|
||||
}
|
||||
|
||||
/* Alerts */
|
||||
.alert {
|
||||
background: #eee;
|
||||
padding: .2em 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.alert p.message {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.alert.alert-error {
|
||||
background: #f99;
|
||||
border: 1px solid #f77;
|
||||
}
|
||||
|
||||
.alert .close {
|
||||
position: relative;
|
||||
top: 0;
|
||||
right: -.8em;
|
||||
}
|
||||
|
||||
/* Misc */
|
||||
|
||||
.close {
|
||||
float: right;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
line-height: 1em;
|
||||
color: #000;
|
||||
opacity: .2;
|
||||
}
|
||||
|
||||
.close:before {
|
||||
/* \2716 is unicode representation of the close button icon */
|
||||
content: '\2716';
|
||||
}
|
||||
|
||||
button.close {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Transitions */
|
||||
.fade-out {
|
||||
transition: opacity 0.5s ease-in;
|
||||
opacity: 0;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Conversation window styles */
|
||||
|
||||
.conversation .controls {
|
||||
background: #f2f2f2;
|
||||
padding: .5em;
|
||||
}
|
||||
|
||||
.conversation .media video {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
/* Nested video elements */
|
||||
|
||||
.conversation .media.nested {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.conversation .media.nested .remote {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.conversation .media.nested .local {
|
||||
position: absolute;
|
||||
bottom: .8em;
|
||||
right: .8em;
|
||||
width: 30%;
|
||||
max-width: 140px;
|
||||
}
|
||||
|
||||
/* Side by side video elements */
|
||||
|
||||
.conversation .media.side-by-side .remote {
|
||||
width: 50%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.conversation .media.side-by-side .local {
|
||||
width: 50%;
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Panel styles */
|
||||
|
||||
.spacer {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.share {
|
||||
background: #f2f2f2;
|
||||
}
|
||||
|
||||
.share .description {
|
||||
background: #f7f7f7 url("../img/icon_32.png") no-repeat 1em 1.5em;
|
||||
border-bottom: 1px solid #c3c3c3;
|
||||
padding: 1em 1em 0 4em;
|
||||
}
|
||||
|
||||
.share .description .field {
|
||||
padding-bottom: 1em;
|
||||
border-bottom: 1px dotted #ddd;
|
||||
}
|
||||
|
||||
.share .description select {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.share .description .preview video {
|
||||
background: #ccc;
|
||||
float: right;
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.share .action {
|
||||
clear: right;
|
||||
padding: 1em;
|
||||
border-top: 1px solid #fafafa;
|
||||
}
|
||||
|
||||
.share .action p {
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
|
||||
.share .action input {
|
||||
font-size: .9em;
|
||||
width: 60%;
|
||||
padding: .4em;
|
||||
}
|
||||
|
||||
/* Specific cases */
|
||||
|
||||
.share.generate-url .action {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.share .action .messages p {
|
||||
margin: 0;
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!-- This file is intended to help frontend developers to easily identify what
|
||||
are the available styles for the Loop UI components. -->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Loop UI shared CSS information/demo</title>
|
||||
<link type="text/css" rel="stylesheet" href="common.css">
|
||||
<link type="text/css" rel="stylesheet" href="panel.css">
|
||||
<link type="text/css" rel="stylesheet" href="conversation.css">
|
||||
<style>
|
||||
body {
|
||||
width: 600px;
|
||||
margin: 1em auto;
|
||||
background: #fff;
|
||||
font-family: Helvetica, Arial, sans;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Loop UI toolkit</h1>
|
||||
|
||||
<h2>Logo icons</h2>
|
||||
|
||||
<p>
|
||||
<img src="../img/icon_32.png"> 32x32 transparent PNG
|
||||
<img src="../img/icon_64.png"> 64x64 transparent PNG
|
||||
</p>
|
||||
|
||||
<p><em><strong>Note:</strong> these are temporary.</em></p>
|
||||
|
||||
<h2>Share panel</h2>
|
||||
|
||||
<h3>Simple</h3>
|
||||
|
||||
<div class="share">
|
||||
<form class="description">
|
||||
<p>This is a simple message.</p>
|
||||
</form>
|
||||
<div class="action">
|
||||
<p><input type="url" value="http://loop.im/plop75"></p>
|
||||
<p>Your name will appear as <a href="">Unnamed</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Featuring options</h3>
|
||||
|
||||
<div class="share">
|
||||
<form class="description">
|
||||
<p class="field">
|
||||
<label>Share this link with a friend to
|
||||
<select>
|
||||
<option>browse together</option>
|
||||
<option selected="selected">video chat</option>
|
||||
<option>audio chat</option>
|
||||
<option>text chat</option>
|
||||
</select>
|
||||
</label>
|
||||
</p>
|
||||
<p class="field">
|
||||
<label>
|
||||
Use webcam <select><option>Foo</option></select>
|
||||
</label>
|
||||
</p>
|
||||
<p class="field">
|
||||
<label>Use whatever
|
||||
<select><option>Long foo is long indeed</option></select>
|
||||
</label>
|
||||
</p>
|
||||
<p class="preview cf">
|
||||
Preview <video></video>
|
||||
</p>
|
||||
</form>
|
||||
<div class="action">
|
||||
<p><input type="url" value="http://loop.im/plop75"></p>
|
||||
<p>Your name will appear as <a href="">Unnamed</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Conversation window</h2>
|
||||
|
||||
<p><em>The conversation component adapts automatically to its container to
|
||||
occupy all the available space.</em></p>
|
||||
|
||||
<h3>Large</h3>
|
||||
|
||||
<div class="conversation">
|
||||
<div class="media nested">
|
||||
<video class="remote"></video>
|
||||
<video class="local"></video>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Large with controls</h3>
|
||||
|
||||
<div class="conversation">
|
||||
<nav class="controls">
|
||||
<button class="btn">Start</button>
|
||||
<button class="btn">Stop</button>
|
||||
</nav>
|
||||
<div class="media nested">
|
||||
<video class="remote"></video>
|
||||
<video class="local"></video>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Small (think chat window)</h3>
|
||||
|
||||
<div style="width: 204px">
|
||||
<div class="conversation">
|
||||
<div class="media nested">
|
||||
<video class="remote"></video>
|
||||
<video class="local"></video>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Side by side</h3>
|
||||
|
||||
<div class="conversation">
|
||||
<div class="media side-by-side">
|
||||
<video class="remote"></video>
|
||||
<video class="local"></video>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Buttons</h2>
|
||||
|
||||
<h3>Using <code><a></code></h3>
|
||||
|
||||
<p>
|
||||
<a href="" class="btn">default</a>
|
||||
<a href="" class="btn btn-info">info</a>
|
||||
<a href="" class="btn btn-success">success</a>
|
||||
<a href="" class="btn btn-warning">warning</a>
|
||||
<a href="" class="btn btn-error">error</a>
|
||||
</p>
|
||||
|
||||
<h3>Inline</h3>
|
||||
|
||||
<p>Click <a href="" class="btn btn-info">here</a>.</p>
|
||||
|
||||
<h3>Using <code><button></code></h3>
|
||||
|
||||
<p>
|
||||
<button class="btn">default</button>
|
||||
<button class="btn btn-info">info</button>
|
||||
<button class="btn btn-success">success</button>
|
||||
<button class="btn btn-warning">warning</button>
|
||||
<button class="btn btn-error">error</button>
|
||||
</p>
|
||||
|
||||
<h2>Alerts</h2>
|
||||
|
||||
<div class="alert alert-error">
|
||||
<button class="close"
|
||||
onclick="var el=this.parentNode;el.classList.add('fade-out');setTimeout(el.remove.bind(el), 500);"></button>
|
||||
<p class="message">Oops! Something went really wrong.</p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.onload = function() {
|
||||
[].forEach.call(document.querySelectorAll("video"), function(video) {
|
||||
video.setAttribute("src", "http://v2v.cc/~j/theora_testsuite/320x240.ogg");
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 2.3 KiB |
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 4.0 KiB |
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -3,4 +3,17 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
browser.jar:
|
||||
content/browser/loop/panel.html (content/panel.html)
|
||||
content/browser/loop/panel.html (content/panel.html)
|
||||
content/browser/loop/shared/css/common.css (content/shared/css/common.css)
|
||||
content/browser/loop/shared/css/panel.css (content/shared/css/panel.css)
|
||||
content/browser/loop/shared/css/conversation.css (content/shared/css/conversation.css)
|
||||
content/browser/loop/shared/img/icon_32.png (content/shared/img/icon_32.png)
|
||||
content/browser/loop/shared/img/icon_64.png (content/shared/img/icon_64.png)
|
||||
content/browser/loop/shared/libs/lodash-2.4.1.js (content/shared/libs/lodash-2.4.1.js)
|
||||
content/browser/loop/shared/libs/jquery-2.1.0.js (content/shared/libs/jquery-2.1.0.js)
|
||||
content/browser/loop/shared/libs/backbone-1.1.2.js (content/shared/libs/backbone-1.1.2.js)
|
||||
content/browser/loop/libs/l10n.js (content/libs/l10n.js)
|
||||
content/browser/loop/js/fxcom.js (content/js/fxcom.js)
|
||||
content/browser/loop/js/client.js (content/js/client.js)
|
||||
content/browser/loop/js/panel.js (content/js/panel.js)
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* global loop, sinon */
|
||||
|
||||
var expect = chai.expect;
|
||||
|
||||
describe("loop.Client", function() {
|
||||
"use strict";
|
||||
|
||||
var sandbox, fakeXHR, requests = [];
|
||||
|
||||
beforeEach(function() {
|
||||
sandbox = sinon.sandbox.create();
|
||||
fakeXHR = sandbox.useFakeXMLHttpRequest();
|
||||
requests = [];
|
||||
// https://github.com/cjohansen/Sinon.JS/issues/393
|
||||
fakeXHR.xhr.onCreate = function (xhr) {
|
||||
requests.push(xhr);
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
describe("loop.Client", function() {
|
||||
describe("#constructor", function() {
|
||||
it("should require a baseApiUrl setting", function() {
|
||||
expect(function() {
|
||||
new loop.Client();
|
||||
}).to.Throw(Error, /required/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#requestCallUrl", function() {
|
||||
var client;
|
||||
|
||||
beforeEach(function() {
|
||||
client = new loop.Client({baseApiUrl: "http://fake.api"});
|
||||
});
|
||||
|
||||
it("should request for a call url", function() {
|
||||
var callback = sinon.spy();
|
||||
client.requestCallUrl("fakeSimplepushUrl", callback);
|
||||
|
||||
expect(requests).to.have.length.of(1);
|
||||
|
||||
requests[0].respond(200, {"Content-Type": "application/json"},
|
||||
'{"call_url": "fakeCallUrl"}');
|
||||
sinon.assert.calledWithExactly(callback, null, "fakeCallUrl");
|
||||
});
|
||||
|
||||
it("should send an error when the request fails", function() {
|
||||
var callback = sinon.spy();
|
||||
client.requestCallUrl("fakeSimplepushUrl", callback);
|
||||
|
||||
expect(requests).to.have.length.of(1);
|
||||
|
||||
requests[0].respond(400, {"Content-Type": "application/json"},
|
||||
'{"error": "my error"}');
|
||||
sinon.assert.calledWithMatch(callback, sinon.match(function(err) {
|
||||
return /HTTP error 400: Bad Request; my error/.test(err.message);
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,4 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
@ -11,18 +14,46 @@
|
|||
</div>
|
||||
<div id="messages"></div>
|
||||
<div id="fixtures"></div>
|
||||
<!-- libs -->
|
||||
<script>
|
||||
// Components won't load in unprivileged space, faking this one.
|
||||
var FirefoxCom = {
|
||||
requestSync: function(action) {
|
||||
if (action === 'getLocale')
|
||||
return "en-US";
|
||||
|
||||
if (action === 'getStrings')
|
||||
return '{}';
|
||||
},
|
||||
getLocale: function() {
|
||||
return "en-US";
|
||||
},
|
||||
getStrings: function() {
|
||||
return [];
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<script src="../../content/libs/l10n.js"></script>
|
||||
<script type="text/javascript" src="../../content/shared/libs/jquery-2.1.0.js"></script>
|
||||
<script type="text/javascript" src="../../content/shared/libs/lodash-2.4.1.js"></script>
|
||||
<script type="text/javascript" src="../../content/shared/libs/backbone-1.1.2.js"></script>
|
||||
<!-- test dependencies -->
|
||||
<script src="../vendor/mocha-1.17.1.js"></script>
|
||||
<script src="../vendor/chai-1.9.0.js"></script>
|
||||
<script src="../../content/libs/zepto.min.js"></script>
|
||||
<script src="../vendor/sinon-1.9.0.js"></script>
|
||||
<script>
|
||||
chai.Assertion.includeStack = true;
|
||||
mocha.setup('bdd');
|
||||
</script>
|
||||
<script src="sample_test.js"></script>
|
||||
<!-- App scripts -->
|
||||
<script src="../../content/js/client.js"></script>
|
||||
<script src="../../content/js/panel.js"></script>
|
||||
<!-- Test scripts -->
|
||||
<script src="panel_test.js"></script>
|
||||
<script src="client_test.js"></script>
|
||||
<script>
|
||||
mocha.run(function () {
|
||||
$("#mocha").append("<p id='complete'>complete</p>");
|
||||
$("#mocha").append("<p>Complete.</p>");
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* global loop, sinon */
|
||||
|
||||
var expect = chai.expect;
|
||||
|
||||
describe("loop.panel", function() {
|
||||
"use strict";
|
||||
|
||||
var sandbox, fakeXHR, requests = [];
|
||||
|
||||
beforeEach(function() {
|
||||
sandbox = sinon.sandbox.create();
|
||||
fakeXHR = sandbox.useFakeXMLHttpRequest();
|
||||
requests = [];
|
||||
// https://github.com/cjohansen/Sinon.JS/issues/393
|
||||
fakeXHR.xhr.onCreate = function (xhr) {
|
||||
requests.push(xhr);
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
$("#fixtures").empty();
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
describe("loop.panel.NotificationView", function() {
|
||||
describe("#render", function() {
|
||||
it("should render template with model attribute values", function() {
|
||||
var view = new loop.panel.NotificationView({
|
||||
el: $("#fixtures"),
|
||||
model: new loop.panel.NotificationModel({
|
||||
level: "error",
|
||||
message: "plop"
|
||||
})
|
||||
});
|
||||
|
||||
view.render();
|
||||
|
||||
expect(view.$(".message").text()).eql("plop");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("loop.panel.NotificationListView", function() {
|
||||
describe("Collection events", function() {
|
||||
var coll, testNotif, view;
|
||||
|
||||
beforeEach(function() {
|
||||
sandbox.stub(loop.panel.NotificationListView.prototype, "render");
|
||||
testNotif = new loop.panel.NotificationModel({
|
||||
level: "error",
|
||||
message: "plop"
|
||||
});
|
||||
coll = new loop.panel.NotificationCollection();
|
||||
view = new loop.panel.NotificationListView({collection: coll});
|
||||
});
|
||||
|
||||
it("should render on notification added to the collection", function() {
|
||||
coll.add(testNotif);
|
||||
|
||||
sinon.assert.calledOnce(view.render);
|
||||
});
|
||||
|
||||
it("should render on notification removed from the collection",
|
||||
function() {
|
||||
coll.add(testNotif);
|
||||
coll.remove(testNotif);
|
||||
|
||||
sinon.assert.calledTwice(view.render);
|
||||
});
|
||||
|
||||
it("should render on collection reset",
|
||||
function() {
|
||||
coll.reset();
|
||||
|
||||
sinon.assert.calledOnce(view.render);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("loop.panel.PanelView", function() {
|
||||
beforeEach(function() {
|
||||
$("#fixtures").append([
|
||||
'<div id="default-view" class="share generate-url">',
|
||||
' <div class="description">',
|
||||
' <p>Get a link to share with a friend to Video Chat.</p>',
|
||||
' </div>',
|
||||
' <div class="action">',
|
||||
' <div class="messages"></div>',
|
||||
' <p class="invite">',
|
||||
' <a class="get-url" href="">Get a call url</a>',
|
||||
' </p>',
|
||||
' <p class="result hide">',
|
||||
' <input id="call-url" type="url" readonly>',
|
||||
' <a class="get-url" href="">Renew</a>',
|
||||
' </p>',
|
||||
' </div>',
|
||||
'</div>'
|
||||
].join(""));
|
||||
});
|
||||
|
||||
describe("#getCallurl", function() {
|
||||
it("should request a call url to the server", function() {
|
||||
var requestCallUrl = sandbox.stub(loop.Client.prototype,
|
||||
"requestCallUrl");
|
||||
var view = new loop.panel.PanelView();
|
||||
|
||||
view.getCallUrl({preventDefault: sandbox.spy()});
|
||||
|
||||
sinon.assert.calledOnce(requestCallUrl);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#onCallUrlReceived", function() {
|
||||
it("should update the text field with the call url", function() {
|
||||
var view = new loop.panel.PanelView();
|
||||
view.render();
|
||||
|
||||
view.onCallUrlReceived("http://call.me/");
|
||||
|
||||
expect(view.$("input").val()).eql("http://call.me/");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,9 +0,0 @@
|
|||
var expect = chai.expect;
|
||||
|
||||
describe("test", function() {
|
||||
"use strict";
|
||||
|
||||
it("is true", function() {
|
||||
expect(true).eql(true);
|
||||
});
|
||||
});
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,5 @@
|
|||
get_link_to_share=Get a link to share with a friend to Video Chat.
|
||||
get_a_call_url=Get a call url
|
||||
renew=Renew
|
||||
unable_retrieve_url=Sorry, we were unable to retrieve a call url.
|
||||
share_link_url=Share the link below with your friend to start your call!
|
|
@ -64,6 +64,7 @@
|
|||
locale/browser/devtools/font-inspector.dtd (%chrome/browser/devtools/font-inspector.dtd)
|
||||
locale/browser/devtools/app-manager.dtd (%chrome/browser/devtools/app-manager.dtd)
|
||||
locale/browser/devtools/app-manager.properties (%chrome/browser/devtools/app-manager.properties)
|
||||
locale/browser/loop/loop.properties (%chrome/browser/loop/loop.properties)
|
||||
locale/browser/newTab.dtd (%chrome/browser/newTab.dtd)
|
||||
locale/browser/newTab.properties (%chrome/browser/newTab.properties)
|
||||
locale/browser/pageInfo.dtd (%chrome/browser/pageInfo.dtd)
|
||||
|
|
Загрузка…
Ссылка в новой задаче