versioned resources for release

This commit is contained in:
jrburke 2011-03-29 10:56:34 -07:00
Родитель ba8b4aa78d
Коммит 0f51114160
177 изменённых файлов: 21720 добавлений и 5 удалений

Просмотреть файл

@ -11,8 +11,8 @@ import = %(here)s/private.ini
smtp_server = localhost
error_email_from = paste@localhost
oauth_failure = /0.3.3/auth.html#oauth_failure
oauth_success = /0.3.3/auth.html#oauth_success
oauth_failure = /0.3.4/auth.html#oauth_failure
oauth_success = /0.3.4/auth.html#oauth_success
# Register with twitter at http://dev.twitter.com/apps/new
oauth.twitter.com.request = https://twitter.com/oauth/request_token

Просмотреть файл

@ -28,7 +28,7 @@ except ImportError:
use_setuptools()
from setuptools import setup, find_packages
VERSION='0.3.3'
VERSION='0.3.4'
setup(
name='linkdrop',

Просмотреть файл

@ -11,8 +11,8 @@ import = %(here)s/private.ini
smtp_server = localhost
error_email_from = paste@localhost
oauth_failure = /0.3.3/auth.html#oauth_failure
oauth_success = /0.3.3/auth.html#oauth_success
oauth_failure = /0.3.4/auth.html#oauth_failure
oauth_success = /0.3.4/auth.html#oauth_success
# Register with twitter at http://dev.twitter.com/apps/new
oauth.twitter.com.request = https://twitter.com/oauth/request_token

323
web/0.3.4/auth.html Normal file
Просмотреть файл

@ -0,0 +1,323 @@
<!DOCTYPE html>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is Raindrop.
-
- The Initial Developer of the Original Code is
- Mozilla Messaging, Inc..
- Portions created by the Initial Developer are Copyright (C) 2009
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- -->
<html>
<head>
<title>Firefox Share OAuthorization</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<script src="/0.3.4/scripts/requireplugins-jquery.js" charset="utf-8"></script>
<style>
html, body {
background-color: #fff;
height: 100%;
color: #0A0A0A;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 21px;
overflow: hidden;
}
.connecting {
margin-top: 60px;
text-align: center;
}
.connecting img {
vertical-align: middle;
}
.hidden {
display: none;
}
.invisible {
visibility: hidden;
}
#oauth {
background-color: #fff;
width: 100%;
position: absolute;
top: 50%;
left: 50%;
margin-left: -150px;
margin-top: -95px;
width: 300px;
background-image: url("/0.3.4/i/f1Logo.png");
background-position: center top;
background-repeat: no-repeat;
padding: 100px 0 0 0;
}
#oauth .text {
display: block;
margin: 0 0 7px 0;
}
#oauth .subtext {
margin-left: 7px;
color: #666666;
font-family: "Lucida Grande", Verdana, sans-serif;
font-size: 12px;
}
.controls {
width: 300px;
}
button {
height: 30px;
border-width: 1px 1px 1px 0;
border-style: solid;
border-color: #888;
cursor: pointer;
padding: 0 10px;
-moz-border-radius: 0 2px 2px 0;
-webkit-border-radius: 0 2px 2px 0;
border-radius: 0 2px 2px 0;
background-image: -moz-linear-gradient(center top , #fafafa 0%, #ddd 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fafafa), color-stop(100%, #ddd));
}
button:active {
-moz-box-shadow: 0 0 1px #666666 inset;
-webkit-box-shadow: 0 0 1px #666666 inset;
box-shadow: 0 0 1px #666666 inset;
background-image: -moz-linear-gradient(center top , #eee 0%, #ccc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eee), color-stop(100%, #ccc));
}
input {
border-width: 1px;
border-style: solid;
border-color: #888;
font-family: "Lucida Grande", Verdana, sans-serif;
font-size: 12px;
line-height: 18px;
padding: 3px;
margin: 0;
-moz-border-radius: 2px 0 0 2px;
-moz-box-shadow:0 3px 3px -3px rgba(0, 0, 0, 0.25) inset, 0 1px 0 #fff;
}
input:focus {
-moz-box-shadow: 0 0 0 3px rgba(0, 162, 255, 0.25) inset, 0 1px 0 #fff;
}
input.google {
background-image: url("/0.3.4/i/sprite.png");
background-position: 5px -159px;
background-repeat: no-repeat;
padding: 0 0 0 26px;
}
.hbox {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-align: stretch;
display: box;
box-orient: horizontal;
box-align: stretch;
}
.hbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.vbox {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-align: stretch;
display: box;
box-orient: vertical;
box-align: stretch;
}
.vbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.spacer {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.reverse {
-webkit-box-direction: reverse;
-moz-box-direction: reverse;
box-direction: reverse;
}
.boxFlex0 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
}
.boxFlex1, .boxFlex {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.boxFlex2 {
-webkit-box-flex: 2;
-moz-box-flex: 2;
box-flex: 2;
}
.boxGroup1 {
-webkit-box-flex-group: 1;
-moz-box-flex-group: 1;
box-flex-group: 1;
}
.boxGroup2 {
-webkit-box-flex-group: 2;
-moz-box-flex-group: 2;
box-flex-group: 2;
}
.start {
-webkit-box-pack: start;
-moz-box-pack: start;
box-pack: start;
}
.end {
-webkit-box-pack: end;
-moz-box-pack: end;
box-pack: end;
}
.center {
-webkit-box-pack: center;
-moz-box-pack: center;
box-pack: center;
}
</style>
<script>
require(["require", "jquery", "blade/url", "services", "jquery.cookie"],
function (require, $, url, services) {
var target = window.location.href.split('#')[1];
if (target && (target === 'oauth_success' || target === 'oauth_failure')) {
//TODO: ideally lock down the domain be location.hostname, but
//a problem for 127 addresses?
// XXX hacky way to handle fennec, since we didn't open a window,
// catch the exception when using window.opener and redirect
var data = {
target: target,
account: JSON.parse($.cookie("account_tokens"))
};
window.opener.postMessage(JSON.stringify(data), '*');
// clear the cookie, we no longer want it around
$.cookie("account_tokens", "", {"path": "/"});
window.close();
}
var search = window.location.href.split('?')[1];
if (search) {
search = search.split('#')[0];
var args = url.queryToObject(search),
domain = args.domain;
$(function () {
if (domain) {
// add a force login param to the form if asked.
if (args.forceLogin) {
var forceLogin = services.domains[domain].forceLogin;
if (forceLogin) {
$('<input type="hidden" name="' +
forceLogin.name +
'" value="' + forceLogin.value + '">').appendTo('[name="authForm"]');
}
}
$("#domain").attr("value", args['domain']);
if (args['domain'] == 'googleapps.com') {
// show UI for googleapp
$('#oauth').removeClass('hidden');
$('#message').addClass('hidden');
$('#submitbtn').click(function (evt) {
$('#oauth').addClass('hidden');
$('#message').removeClass('hidden');
document.authForm.submit();
});
} else {
document.authForm.submit();
}
}
});
}
});
</script>
</head>
<body class="settings">
<div id="oauth" class="authorize hidden">
<form name="authForm" action="/api/account/authorize" method="POST">
<input type="hidden" name="domain" id="domain" value="">
<span class="text">Enter your Google Apps domain</span>
<div class="controls hbox">
<input class="boxFlex google" name="openid_identifier" id="openid_identifier" value="">
<input class="boxFlex google" type="hidden" name="end_point_success" value="/0.3.4/auth.html#oauth_success">
<input class="boxFlex google" type="hidden" name="end_point_auth_failure" value="/0.3.4/auth.html#oauth_failure">
<button id='submitbtn' type="submit">submit</button>
</div>
<span class="subtext">ex: yourappdomain.com</span>
</form>
</div>
<div style="clear: both"/>
</div>
<div id='message' class="connecting"><img src="i/loader-w.gif"> connecting...</div>
</body>
</html>

8
web/0.3.4/blank.html Normal file
Просмотреть файл

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
</html>

10
web/0.3.4/build.js Normal file
Просмотреть файл

@ -0,0 +1,10 @@
({
baseUrl: "scripts/",
paths: {
"index": "../index",
"jquery": "requireplugins-jquery"
},
name: "index",
exclude: ['jquery'],
out: './index.js'
})

Двоичные данные
web/0.3.4/favicon.ico Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Двоичные данные
web/0.3.4/favicon.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 469 B

Двоичные данные
web/0.3.4/i/LinkedIn_Logo16px.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 716 B

Двоичные данные
web/0.3.4/i/check.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 494 B

Двоичные данные
web/0.3.4/i/cornerBottomLeft.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 142 B

Двоичные данные
web/0.3.4/i/cornerBottomRight.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 139 B

Двоичные данные
web/0.3.4/i/cornerTopLeft.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 136 B

Двоичные данные
web/0.3.4/i/cornerTopRight.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 139 B

Двоичные данные
web/0.3.4/i/f1Icon.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 389 B

Двоичные данные
web/0.3.4/i/f1Logo.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.7 KiB

Двоичные данные
web/0.3.4/i/f1LogoVert.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.4 KiB

Двоичные данные
web/0.3.4/i/facebookIcon.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 448 B

Двоичные данные
web/0.3.4/i/fancybox/blank.gif Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 43 B

Двоичные данные
web/0.3.4/i/fancybox/fancy_close.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Двоичные данные
web/0.3.4/i/fancybox/fancy_loading.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 10 KiB

Двоичные данные
web/0.3.4/i/fancybox/fancy_nav_left.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
web/0.3.4/i/fancybox/fancy_nav_right.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
web/0.3.4/i/fancybox/fancy_shadow_e.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 107 B

Двоичные данные
web/0.3.4/i/fancybox/fancy_shadow_n.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 106 B

Двоичные данные
web/0.3.4/i/fancybox/fancy_shadow_ne.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 347 B

Двоичные данные
web/0.3.4/i/fancybox/fancy_shadow_nw.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 324 B

Двоичные данные
web/0.3.4/i/fancybox/fancy_shadow_s.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 111 B

Двоичные данные
web/0.3.4/i/fancybox/fancy_shadow_se.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 352 B

Двоичные данные
web/0.3.4/i/fancybox/fancy_shadow_sw.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 340 B

Двоичные данные
web/0.3.4/i/fancybox/fancy_shadow_w.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 103 B

Двоичные данные
web/0.3.4/i/fancybox/fancy_title_left.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 503 B

Двоичные данные
web/0.3.4/i/fancybox/fancy_title_main.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 96 B

Двоичные данные
web/0.3.4/i/fancybox/fancy_title_over.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 70 B

Двоичные данные
web/0.3.4/i/fancybox/fancy_title_right.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 506 B

Двоичные данные
web/0.3.4/i/fancybox/fancybox-x.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 203 B

Двоичные данные
web/0.3.4/i/fancybox/fancybox-y.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 176 B

Двоичные данные
web/0.3.4/i/fancybox/fancybox.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 15 KiB

Двоичные данные
web/0.3.4/i/gmailIcon.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 468 B

Двоичные данные
web/0.3.4/i/loader-w.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.7 KiB

Двоичные данные
web/0.3.4/i/panel/f1accounts.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 67 KiB

Двоичные данные
web/0.3.4/i/panel/f1panel.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 62 KiB

Двоичные данные
web/0.3.4/i/panel/step-01.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.4 KiB

Двоичные данные
web/0.3.4/i/panel/step-02.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 27 KiB

Двоичные данные
web/0.3.4/i/panel/step-022.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 23 KiB

Двоичные данные
web/0.3.4/i/panel/step-03.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.2 KiB

Двоичные данные
web/0.3.4/i/screenshot_01.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 27 KiB

Двоичные данные
web/0.3.4/i/shareIcon.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичные данные
web/0.3.4/i/sprite.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.1 KiB

Двоичные данные
web/0.3.4/i/step-01.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.1 KiB

Двоичные данные
web/0.3.4/i/step-02.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.2 KiB

Двоичные данные
web/0.3.4/i/step-03.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.4 KiB

Двоичные данные
web/0.3.4/i/toolbar-button.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 390 B

Двоичные данные
web/0.3.4/i/twitterIcon.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 494 B

172
web/0.3.4/index.html Normal file
Просмотреть файл

@ -0,0 +1,172 @@
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is Raindrop.
-
- The Initial Developer of the Original Code is
- Mozilla Messaging, Inc..
- Portions created by the Initial Developer are Copyright (C) 2009
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- -->
<!DOCTYPE html>
<html xmlns:og="http://opengraphprotocol.org/schema/"
xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<link rel="stylesheet" type="text/css" href="/0.3.4/style.css">
<link rel="stylesheet" type="text/css" href="/0.3.4/jquery.fancybox-1.3.4.css">
<link rel="stylesheet" type="text/css" href="resource://ffshare/chrome/skin/web/installed.css">
<title>Mozilla F1</title>
<script type="text/javascript" data-main="/0.3.4/index.js" src="/0.3.4/scripts/requireplugins-jquery.js"></script>
<link rel="icon" type="image/x-icon" href="/0.3.4/favicon.png" />
<!-- https://github.com/mozilla/f1/wiki/Page-Meta-Properties -->
<link rel="shortlink" href="http://bit.ly/mozillaF1"/>
<link rel="canonical" href="http://f1.mozillamessaging.com/"/>
<meta property="og:title" content="Mozilla F1"/>
<meta property="og:type" content="website"/>
<meta property="og:url" content="http://f1.mozillamessaging.com/"/>
<meta property="og:image" content="http://f1.mozillamessaging.com/i/f1LogoVert.png"/>
<meta property="og:site_name" content="Mozilla F1"/>
<meta property="og:description"
content="F1 is a browser extension that allows you to share links in a
fast and fun way. Share links from within the browser, from any
webpage, using the same services you already know and love."/>
<meta property="fb:app_id" content="173375079345318,146290642084944"/>
<meta name="title" content="Mozilla F1"/>
<meta name="description"
content="F1 is a browser extension that allows you to share links in a
fast and fun way. Share links from within the browser, from any
webpage, using the same services you already know and love."/>
<meta name="application-url" content="http://f1.mozillamessaging.com/"/>
<link rel="image_src" href="http://f1.mozillamessaging.com/i/f1LogoVert.png"/>
</head>
<body>
<div id="wrapper">
<div id="header" class="row">
<div class="c2 logo">
/ <a href="http://mozillalabs.com/messaging/">F1 Blog &raquo;</a>
</div>
<div class="c1 dl">
<button id="downloadFF4" class="download downloadXpi">
Install Mozilla F1
<span class="meta">available for Firefox 4 beta</span>
</button>
<button id="firefox" class="download">
Get Firefox 4 beta to use <br>this add-on
</button>
<a id="no36" href="#info36">*Firefox 3.6 is no longer supported</a>
<div id="noButtonFF4">
<img src="/0.3.4/i/check.png"> status: installed
</div>
</div>
</div>
<div class="row headline">
<div class="c1 description">
<h1>Share links fast.</h1>
<h2>So, what&rsquo;s F1?</h2>
F1 is a browser extension that allows you to share links in a fast and fun way. Share links from within the browser, from any webpage, using the same services you already know and love. Mozilla F1 is made by Mozilla Messaging.
<button class="fancybox">watch demo</button>
</div>
<div class="c2">
<img src="/i/panel/f1panel.png">
</div>
</div>
<div class="row">
<hr>
<div class="c2 description">
<img src="/i/panel/f1accounts.png">
</div>
<div class="c1 description">
<h2>Share with your<br> favorite services</h2>
With support for Facebook, Twitter, Gmail, Google Apps, Yahoo Mail and LinkedIn, we have your favorite services covered&mdash;and we're adding more services with every release.
</div>
</div>
<div class="row about">
<hr>
<div class="c3 description">
<h2>Once you've installed F1 sharing is as easy as...</h2>
</div>
<div class="c1 description steps">
<span class="step">1</span> Hit the F1 icon in the URL bar
<img src="i/panel/step-01.png">
</div>
<div class="c1 description steps">
<span class="step">2</span> Choose your service in the menu
<img src="i/panel/step-022.png">
</div>
<div class="c1 description steps">
<span class="step">3</span> Express yourself and hit share!
<img src="i/panel/step-03.png">
</div>
</div>
<div id="info36" class="row">
<div class="c3">
<strong>*Firefox 3.6 support</strong>: F1 uses some advanced technology
and UI capabilities that are not possible in Firefox 3.6 and earlier.
If you installed the previous version of F1 that works with Firefox 3.6,
it will continue to work while Firefox 4 is in beta. Once Firefox 4 is
released, the older 3.6 compatible extension will be phased out.
</div>
</div>
<div id="footer" class="row">
<div class="c3">
<a href="http://mozillamessaging.com">Mozilla Messaging 2011</a> | <a href="/0.3.4/service/privacy.html">Privacy Policy</a>
</div>
</div>
</div>
<iframe id="installFrame" src="/0.3.4/blank.html"></iframe>
<!-- START OF SmartSource Data Collector TAG -->
<!-- Copyright (c) 1996-2011 WebTrends Inc. All rights reserved. -->
<!-- Version: 9.3.0 -->
<!-- Tag Builder Version: 3.1 -->
<!-- Created: 3/15/2011 5:10:56 PM -->
<script src="/0.3.4/scripts/webtrends.js" type="text/javascript"></script>
<!-- ----------------------------------------------------------------------------------- -->
<!-- Warning: The two script blocks below must remain inline. Moving them to an external -->
<!-- JavaScript include file can cause serious problems with cross-domain tracking. -->
<!-- ----------------------------------------------------------------------------------- -->
<script type="text/javascript">
//<![CDATA[
var _tag=new WebTrends();
_tag.dcsGetId();
//]]>
</script>
<script type="text/javascript">
//<![CDATA[
_tag.dcsCustom=function(){
// Add custom parameters here.
//_tag.DCSext.param_name=param_value;
}
_tag.dcsCollect();
//]]>
</script>
<noscript>
<div><img alt="DCSIMG" id="DCSIMG" width="1" height="1" src="http://statse.webtrendslive.com/dcsjd66bq10000k73ngwoin8k_7d1l/njs.gif?dcsuri=/nojavascript&amp;WT.js=No&amp;WT.tv=9.3.0&amp;WT.dcssip=www.mozillamessaging.com"/></div>
</noscript>
<!-- END OF SmartSource Data Collector TAG -->
</body>
</html>

32
web/0.3.4/index.js Normal file
Просмотреть файл

@ -0,0 +1,32 @@
define("hashDispatch",[],function(){return function(b){function g(){var i=location.href.split("#")[1]||"_default",l,f;f=i.indexOf(":");if(f!==-1){l=i.substring(f+1,i.length);i=i.substring(0,f)}if(i in b)b[i](l);else b._catchAll&&b._catchAll(i,l)}g();window.addEventListener("hashchange",g,false)}});
(function(b){var g,i,l,f,x,m,D,o,A,B,r=0,e={},p=[],q=0,d={},n=[],F=null,u=new Image,J=/\.(jpg|gif|png|bmp|jpeg)(.*)?$/i,W=/[^\.]\.(swf)\s*$/i,K,L=1,z=0,v="",s,k,j=false,C=b.extend(b("<div/>")[0],{prop:0}),M=b.browser.msie&&b.browser.version<7&&!window.XMLHttpRequest,N=function(){i.hide();u.onerror=u.onload=null;F&&F.abort();g.empty()},O=function(){if(false===e.onError(p,r,e)){i.hide();j=false}else{e.titleShow=false;e.width="auto";e.height="auto";g.html('<p id="fancybox-error">The requested content cannot be loaded.<br />Please try again later.</p>');
E()}},I=function(){var a=p[r],c,h,t,G,P,w;N();e=b.extend({},b.fn.fancybox.defaults,typeof b(a).data("fancybox")=="undefined"?e:b(a).data("fancybox"));w=e.onStart(p,r,e);if(w===false)j=false;else{if(typeof w=="object")e=b.extend(e,w);t=e.title||(a.nodeName?b(a).attr("title"):a.title)||"";if(a.nodeName&&!e.orig)e.orig=b(a).children("img:first").length?b(a).children("img:first"):b(a);if(t===""&&e.orig&&e.titleFromAlt)t=e.orig.attr("alt");c=e.href||(a.nodeName?b(a).attr("href"):a.href)||null;if(/^(?:javascript)/i.test(c)||
c=="#")c=null;if(e.type){h=e.type;if(!c)c=e.content}else if(e.content)h="html";else if(c)h=c.match(J)?"image":c.match(W)?"swf":b(a).hasClass("iframe")?"iframe":c.indexOf("#")===0?"inline":"ajax";if(h){if(h=="inline"){a=c.substr(c.indexOf("#"));h=b(a).length>0?"inline":"ajax"}e.type=h;e.href=c;e.title=t;if(e.autoDimensions)if(e.type=="html"||e.type=="inline"||e.type=="ajax"){e.width="auto";e.height="auto"}else e.autoDimensions=false;if(e.modal){e.overlayShow=true;e.hideOnOverlayClick=false;e.hideOnContentClick=
false;e.enableEscapeButton=false;e.showCloseButton=false}e.padding=parseInt(e.padding,10);e.margin=parseInt(e.margin,10);g.css("padding",e.padding+e.margin);b(".fancybox-inline-tmp").unbind("fancybox-cancel").bind("fancybox-change",function(){b(this).replaceWith(m.children())});switch(h){case "html":g.html(e.content);E();break;case "inline":if(b(a).parent().is("#fancybox-content")===true){j=false;return}b('<div class="fancybox-inline-tmp" />').hide().insertBefore(b(a)).bind("fancybox-cleanup",function(){b(this).replaceWith(m.children())}).bind("fancybox-cancel",
function(){b(this).replaceWith(g.children())});b(a).appendTo(g);E();break;case "image":j=false;b.fancybox.showActivity();u=new Image;u.onerror=function(){O()};u.onload=function(){j=true;u.onerror=u.onload=null;X()};u.src=c;break;case "swf":e.scrolling="no";G='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+e.width+'" height="'+e.height+'"><param name="movie" value="'+c+'"></param>';P="";b.each(e.swf,function(y,H){G+='<param name="'+y+'" value="'+H+'"></param>';P+=" "+y+'="'+
H+'"'});G+='<embed src="'+c+'" type="application/x-shockwave-flash" width="'+e.width+'" height="'+e.height+'"'+P+"></embed></object>";g.html(G);E();break;case "ajax":j=false;b.fancybox.showActivity();e.ajax.win=e.ajax.success;F=b.ajax(b.extend({},e.ajax,{url:c,data:e.ajax.data||{},error:function(y){y.status>0&&O()},success:function(y,H,Q){if((typeof Q=="object"?Q:F).status==200){if(typeof e.ajax.win=="function"){w=e.ajax.win(c,y,H,Q);if(w===false){i.hide();return}else if(typeof w=="string"||typeof w==
"object")y=w}g.html(y);E()}}}));break;case "iframe":R();break}}else O()}},E=function(){var a=e.width,c=e.height;a=a.toString().indexOf("%")>-1?parseInt((b(window).width()-e.margin*2)*parseFloat(a)/100,10)+"px":a=="auto"?"auto":a+"px";c=c.toString().indexOf("%")>-1?parseInt((b(window).height()-e.margin*2)*parseFloat(c)/100,10)+"px":c=="auto"?"auto":c+"px";g.wrapInner('<div style="width:'+a+";height:"+c+";overflow: "+(e.scrolling=="auto"?"auto":e.scrolling=="yes"?"scroll":"hidden")+';position:relative;"></div>');
e.width=g.width();e.height=g.height();R()},X=function(){e.width=u.width;e.height=u.height;b("<img />").attr({id:"fancybox-img",src:u.src,alt:e.title}).appendTo(g);R()},R=function(){var a,c;i.hide();if(f.is(":visible")&&false===d.onCleanup(n,q,d)){b.event.trigger("fancybox-cancel");j=false}else{j=true;b(m.add(l)).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");f.is(":visible")&&d.titlePosition!=="outside"&&f.css("height",f.height());n=p;q=r;d=e;if(d.overlayShow){l.css({"background-color":d.overlayColor,
opacity:d.overlayOpacity,cursor:d.hideOnOverlayClick?"pointer":"auto",height:b(document).height()});if(!l.is(":visible")){M&&b("select:not(#fancybox-tmp select)").filter(function(){return this.style.visibility!=="hidden"}).css({visibility:"hidden"}).one("fancybox-cleanup",function(){this.style.visibility="inherit"});l.show()}}else l.hide();k=Y();Z();if(f.is(":visible")){b(D.add(A).add(B)).hide();a=f.position();s={top:a.top,left:a.left,width:f.width(),height:f.height()};c=s.width==k.width&&s.height==
k.height;m.fadeTo(d.changeFade,0.3,function(){var h=function(){m.html(g.contents()).fadeTo(d.changeFade,1,S)};b.event.trigger("fancybox-change");m.empty().removeAttr("filter").css({"border-width":d.padding,width:k.width-d.padding*2,height:e.autoDimensions?"auto":k.height-z-d.padding*2});if(c)h();else{C.prop=0;b(C).animate({prop:1},{duration:d.changeSpeed,easing:d.easingChange,step:T,complete:h})}})}else{f.removeAttr("style");m.css("border-width",d.padding);if(d.transitionIn=="elastic"){s=V();m.html(g.contents());
f.show();if(d.opacity)k.opacity=0;C.prop=0;b(C).animate({prop:1},{duration:d.speedIn,easing:d.easingIn,step:T,complete:S})}else{d.titlePosition=="inside"&&z>0&&o.show();m.css({width:k.width-d.padding*2,height:e.autoDimensions?"auto":k.height-z-d.padding*2}).html(g.contents());f.css(k).fadeIn(d.transitionIn=="none"?0:d.speedIn,S)}}}},$=function(a){if(a&&a.length){if(d.titlePosition=="float")return'<table id="fancybox-title-float-wrap" cellpadding="0" cellspacing="0"><tr><td id="fancybox-title-float-left"></td><td id="fancybox-title-float-main">'+
a+'</td><td id="fancybox-title-float-right"></td></tr></table>';return'<div id="fancybox-title-'+d.titlePosition+'">'+a+"</div>"}return false},Z=function(){v=d.title||"";z=0;o.empty().removeAttr("style").removeClass();if(d.titleShow!==false){v=b.isFunction(d.titleFormat)?d.titleFormat(v,n,q,d):$(v);if(!(!v||v==="")){o.addClass("fancybox-title-"+d.titlePosition).html(v).appendTo("body").show();switch(d.titlePosition){case "inside":o.css({width:k.width-d.padding*2,marginLeft:d.padding,marginRight:d.padding});
z=o.outerHeight(true);o.appendTo(x);k.height+=z;break;case "over":o.css({marginLeft:d.padding,width:k.width-d.padding*2,bottom:d.padding}).appendTo(x);break;case "float":o.css("left",parseInt((o.width()-k.width-40)/2,10)*-1).appendTo(f);break;default:o.css({width:k.width-d.padding*2,paddingLeft:d.padding,paddingRight:d.padding}).appendTo(f);break}}}o.hide()},aa=function(){if(d.enableEscapeButton||d.enableKeyboardNav)b(document).bind("keydown.fb",function(a){if(a.keyCode==27&&d.enableEscapeButton){a.preventDefault();
b.fancybox.close()}else if((a.keyCode==37||a.keyCode==39)&&d.enableKeyboardNav&&a.target.tagName!=="INPUT"&&a.target.tagName!=="TEXTAREA"&&a.target.tagName!=="SELECT"){a.preventDefault();b.fancybox[a.keyCode==37?"prev":"next"]()}});if(d.showNavArrows){if(d.cyclic&&n.length>1||q!==0)A.show();if(d.cyclic&&n.length>1||q!=n.length-1)B.show()}else{A.hide();B.hide()}},S=function(){if(!b.support.opacity){m.get(0).style.removeAttribute("filter");f.get(0).style.removeAttribute("filter")}e.autoDimensions&&
m.css("height","auto");f.css("height","auto");v&&v.length&&o.show();d.showCloseButton&&D.show();aa();d.hideOnContentClick&&m.bind("click",b.fancybox.close);d.hideOnOverlayClick&&l.bind("click",b.fancybox.close);b(window).bind("resize.fb",b.fancybox.resize);d.centerOnScroll&&b(window).bind("scroll.fb",b.fancybox.center);if(d.type=="iframe")b('<iframe id="fancybox-frame" name="fancybox-frame'+(new Date).getTime()+'" frameborder="0" hspace="0" '+(b.browser.msie?'allowtransparency="true""':"")+' scrolling="'+
e.scrolling+'" src="'+d.href+'"></iframe>').appendTo(m);f.show();j=false;b.fancybox.center();d.onComplete(n,q,d);ba()},ba=function(){var a,c;if(n.length-1>q){a=n[q+1].href;if(typeof a!=="undefined"&&a.match(J)){c=new Image;c.src=a}}if(q>0){a=n[q-1].href;if(typeof a!=="undefined"&&a.match(J)){c=new Image;c.src=a}}},T=function(a){var c={width:parseInt(s.width+(k.width-s.width)*a,10),height:parseInt(s.height+(k.height-s.height)*a,10),top:parseInt(s.top+(k.top-s.top)*a,10),left:parseInt(s.left+(k.left-
s.left)*a,10)};if(typeof k.opacity!=="undefined")c.opacity=a<0.5?0.5:a;f.css(c);m.css({width:c.width-d.padding*2,height:c.height-z*a-d.padding*2})},U=function(){return[b(window).width()-d.margin*2,b(window).height()-d.margin*2,b(document).scrollLeft()+d.margin,b(document).scrollTop()+d.margin]},Y=function(){var a=U(),c={},h=d.autoScale,t=d.padding*2;c.width=d.width.toString().indexOf("%")>-1?parseInt(a[0]*parseFloat(d.width)/100,10):d.width+t;c.height=d.height.toString().indexOf("%")>-1?parseInt(a[1]*
parseFloat(d.height)/100,10):d.height+t;if(h&&(c.width>a[0]||c.height>a[1]))if(e.type=="image"||e.type=="swf"){h=d.width/d.height;if(c.width>a[0]){c.width=a[0];c.height=parseInt((c.width-t)/h+t,10)}if(c.height>a[1]){c.height=a[1];c.width=parseInt((c.height-t)*h+t,10)}}else{c.width=Math.min(c.width,a[0]);c.height=Math.min(c.height,a[1])}c.top=parseInt(Math.max(a[3]-20,a[3]+(a[1]-c.height-40)*0.5),10);c.left=parseInt(Math.max(a[2]-20,a[2]+(a[0]-c.width-40)*0.5),10);return c},ca=function(a){var c=a.offset();
c.top+=parseInt(a.css("paddingTop"),10)||0;c.left+=parseInt(a.css("paddingLeft"),10)||0;c.top+=parseInt(a.css("border-top-width"),10)||0;c.left+=parseInt(a.css("border-left-width"),10)||0;c.width=a.width();c.height=a.height();return c},V=function(){var a=e.orig?b(e.orig):false,c={};if(a&&a.length){a=ca(a);c={width:a.width+d.padding*2,height:a.height+d.padding*2,top:a.top-d.padding-20,left:a.left-d.padding-20}}else{a=U();c={width:d.padding*2,height:d.padding*2,top:parseInt(a[3]+a[1]*0.5,10),left:parseInt(a[2]+
a[0]*0.5,10)}}return c},da=function(){if(i.is(":visible")){b("div",i).css("top",L*-40+"px");L=(L+1)%12}else clearInterval(K)};b.fn.fancybox=function(a){if(!b(this).length)return this;b(this).data("fancybox",b.extend({},a,b.metadata?b(this).metadata():{})).unbind("click.fb").bind("click.fb",function(c){c.preventDefault();if(!j){j=true;b(this).blur();p=[];r=0;c=b(this).attr("rel")||"";if(!c||c==""||c==="nofollow")p.push(this);else{p=b("a[rel="+c+"], area[rel="+c+"]");r=p.index(this)}I()}});return this};
b.fancybox=function(a,c){if(!j){j=true;c=typeof c!=="undefined"?c:{};p=[];r=parseInt(c.index,10)||0;if(b.isArray(a)){for(var h=0,t=a.length;h<t;h++)if(typeof a[h]=="object")b(a[h]).data("fancybox",b.extend({},c,a[h]));else a[h]=b({}).data("fancybox",b.extend({content:a[h]},c));p=jQuery.merge(p,a)}else{if(typeof a=="object")b(a).data("fancybox",b.extend({},c,a));else a=b({}).data("fancybox",b.extend({content:a},c));p.push(a)}if(r>p.length||r<0)r=0;I()}};b.fancybox.showActivity=function(){clearInterval(K);
i.show();K=setInterval(da,66)};b.fancybox.hideActivity=function(){i.hide()};b.fancybox.next=function(){return b.fancybox.pos(q+1)};b.fancybox.prev=function(){return b.fancybox.pos(q-1)};b.fancybox.pos=function(a){if(!j){a=parseInt(a);p=n;if(a>-1&&a<n.length){r=a;I()}else if(d.cyclic&&n.length>1){r=a>=n.length?0:n.length-1;I()}}};b.fancybox.cancel=function(){if(!j){j=true;b.event.trigger("fancybox-cancel");N();e.onCancel(p,r,e);j=false}};b.fancybox.close=function(){function a(){l.fadeOut("fast");o.empty().hide();
f.hide();b.event.trigger("fancybox-cleanup");m.empty();d.onClosed(n,q,d);n=e=[];q=r=0;d=e={};j=false}if(!(j||f.is(":hidden"))){j=true;if(d&&false===d.onCleanup(n,q,d))j=false;else{N();b(D.add(A).add(B)).hide();b(m.add(l)).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");m.find("iframe").attr("src",M&&/^https/i.test(window.location.href||"")?"javascript:void(false)":"about:blank");d.titlePosition!=="inside"&&o.empty();f.stop();if(d.transitionOut=="elastic"){s=V();var c=
f.position();k={top:c.top,left:c.left,width:f.width(),height:f.height()};if(d.opacity)k.opacity=1;o.empty().hide();C.prop=1;b(C).animate({prop:0},{duration:d.speedOut,easing:d.easingOut,step:T,complete:a})}else f.fadeOut(d.transitionOut=="none"?0:d.speedOut,a)}}};b.fancybox.resize=function(){l.is(":visible")&&l.css("height",b(document).height());b.fancybox.center(true)};b.fancybox.center=function(a){var c,h;if(!j){h=a===true?1:0;c=U();!h&&(f.width()>c[0]||f.height()>c[1])||f.stop().animate({top:parseInt(Math.max(c[3]-
20,c[3]+(c[1]-m.height()-40)*0.5-d.padding)),left:parseInt(Math.max(c[2]-20,c[2]+(c[0]-m.width()-40)*0.5-d.padding))},typeof a=="number"?a:200)}};b.fancybox.init=function(){if(!b("#fancybox-wrap").length){b("body").append(g=b('<div id="fancybox-tmp"></div>'),i=b('<div id="fancybox-loading"><div></div></div>'),l=b('<div id="fancybox-overlay"></div>'),f=b('<div id="fancybox-wrap"></div>'));x=b('<div id="fancybox-outer"></div>').append('<div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div>').appendTo(f);
x.append(m=b('<div id="fancybox-content"></div>'),D=b('<a id="fancybox-close"></a>'),o=b('<div id="fancybox-title"></div>'),A=b('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),B=b('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>'));D.click(b.fancybox.close);i.click(b.fancybox.cancel);A.click(function(a){a.preventDefault();b.fancybox.prev()});B.click(function(a){a.preventDefault();b.fancybox.next()});
b.fn.mousewheel&&f.bind("mousewheel.fb",function(a,c){if(j)a.preventDefault();else if(b(a.target).get(0).clientHeight==0||b(a.target).get(0).scrollHeight===b(a.target).get(0).clientHeight){a.preventDefault();b.fancybox[c>0?"prev":"next"]()}});b.support.opacity||f.addClass("fancybox-ie");if(M){i.addClass("fancybox-ie6");f.addClass("fancybox-ie6");b('<iframe id="fancybox-hide-sel-frame" src="'+(/^https/i.test(window.location.href||"")?"javascript:void(false)":"about:blank")+'" scrolling="no" border="0" frameborder="0" tabindex="-1"></iframe>').prependTo(x)}}};
b.fn.fancybox.defaults={padding:10,margin:40,opacity:false,modal:false,cyclic:false,scrolling:"auto",width:560,height:340,autoScale:true,autoDimensions:true,centerOnScroll:false,ajax:{},swf:{wmode:"transparent"},hideOnOverlayClick:true,hideOnContentClick:false,overlayShow:true,overlayOpacity:0.7,overlayColor:"#777",titleShow:true,titlePosition:"float",titleFormat:null,titleFromAlt:false,transitionIn:"fade",transitionOut:"fade",speedIn:300,speedOut:300,changeSpeed:300,changeFade:"fast",easingIn:"swing",
easingOut:"swing",showCloseButton:true,showNavArrows:true,enableEscapeButton:true,enableKeyboardNav:true,onStart:function(){},onCancel:function(){},onComplete:function(){},onCleanup:function(){},onClosed:function(){},onError:function(){}};b(document).ready(function(){b.fancybox.init()})})(jQuery);define("jquery.fancybox-1.3.4",function(){});
define("index",["require","jquery","hashDispatch","jquery.fancybox-1.3.4"],function(b,g){g(function(){var i=!!navigator.buildID,l=i&&navigator.userAgent.match(/Firefox\/([^\s]+)/);if(i&&l){l=parseFloat(l[1]);i=l>3.99}if(!i){g("#downloadFF4").hide();g("#no36").show();g("#info36").show();g("#firefox").show()}g(".fancybox").fancybox({type:"iframe",href:"http://player.vimeo.com/video/21374067?title=0&amp;byline=0&amp;portrait=0&amp;autoplay=true",width:700,height:468,autoScale:false,autoDimensions:false});
g("body").delegate("#firefox","click",function(){location="http://www.mozilla.com/en-US/firefox/beta/"}).delegate(".downloadXpi","click",function(f){var x=location.href;location=x.indexOf("staging")!==-1||x.indexOf("linkdrop")!==-1?"/ffshare.xpi":"https://addons.mozilla.org/services/install.php?addon_id=252539&addon_name=F1%20by%20Mozilla%20Labs&src=external-f1home";f.preventDefault()})})});

Просмотреть файл

@ -0,0 +1,359 @@
/*
* FancyBox - jQuery Plugin
* Simple and fancy lightbox alternative
*
* Examples and documentation at: http://fancybox.net
*
* Copyright (c) 2008 - 2010 Janis Skarnelis
* That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated.
*
* Version: 1.3.4 (11/11/2010)
* Requires: jQuery v1.3+
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
#fancybox-loading {
position: fixed;
top: 50%;
left: 50%;
width: 40px;
height: 40px;
margin-top: -20px;
margin-left: -20px;
cursor: pointer;
overflow: hidden;
z-index: 1104;
display: none;
}
#fancybox-loading div {
position: absolute;
top: 0;
left: 0;
width: 40px;
height: 480px;
background-image: url('i/fancybox/fancybox.png');
}
#fancybox-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
z-index: 1100;
display: none;
}
#fancybox-tmp {
padding: 0;
margin: 0;
border: 0;
overflow: auto;
display: none;
}
#fancybox-wrap {
position: absolute;
top: 0;
left: 0;
padding: 20px 10px 10px 20px;
z-index: 1101;
outline: none;
display: none;
}
#fancybox-outer {
position: relative;
width: 100%;
height: 100%;
background: #fff;
}
#fancybox-content {
width: 0;
height: 0;
padding: 0;
outline: none;
position: relative;
overflow: hidden;
z-index: 1102;
border: 0px solid #fff;
}
#fancybox-hide-sel-frame {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: transparent;
z-index: 1101;
}
#fancybox-close {
position: absolute;
top: -15px;
right: -25px;
width: 30px;
height: 30px;
background: transparent url('i/fancybox/fancybox.png') -40px 0px;
cursor: pointer;
z-index: 1103;
display: none;
}
#fancybox-error {
color: #444;
font: normal 12px/20px Arial;
padding: 14px;
margin: 0;
}
#fancybox-img {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
border: none;
outline: none;
line-height: 0;
vertical-align: top;
}
#fancybox-frame {
width: 100%;
height: 100%;
border: none;
display: block;
}
#fancybox-left, #fancybox-right {
position: absolute;
bottom: 0px;
height: 100%;
width: 35%;
cursor: pointer;
outline: none;
background: transparent url('i/fancybox/blank.gif');
z-index: 1102;
display: none;
}
#fancybox-left {
left: 0px;
}
#fancybox-right {
right: 0px;
}
#fancybox-left-ico, #fancybox-right-ico {
position: absolute;
top: 50%;
left: -9999px;
width: 30px;
height: 30px;
margin-top: -15px;
cursor: pointer;
z-index: 1102;
display: block;
}
#fancybox-left-ico {
background-image: url('i/fancybox/fancybox.png');
background-position: -40px -30px;
}
#fancybox-right-ico {
background-image: url('i/fancybox/fancybox.png');
background-position: -40px -60px;
}
#fancybox-left:hover, #fancybox-right:hover {
visibility: visible; /* IE6 */
}
#fancybox-left:hover span {
left: 20px;
}
#fancybox-right:hover span {
left: auto;
right: 20px;
}
.fancybox-bg {
position: absolute;
padding: 0;
margin: 0;
border: 0;
width: 20px;
height: 20px;
z-index: 1001;
}
#fancybox-bg-n {
top: -20px;
left: 0;
width: 100%;
background-image: url('i/fancybox/fancybox-x.png');
}
#fancybox-bg-ne {
top: -20px;
right: -20px;
background-image: url('i/fancybox/fancybox.png');
background-position: -40px -162px;
}
#fancybox-bg-e {
top: 0;
right: -20px;
height: 100%;
background-image: url('i/fancybox/fancybox-y.png');
background-position: -20px 0px;
}
#fancybox-bg-se {
bottom: -20px;
right: -20px;
background-image: url('i/fancybox/fancybox.png');
background-position: -40px -182px;
}
#fancybox-bg-s {
bottom: -20px;
left: 0;
width: 100%;
background-image: url('i/fancybox/fancybox-x.png');
background-position: 0px -20px;
}
#fancybox-bg-sw {
bottom: -20px;
left: -20px;
background-image: url('i/fancybox/fancybox.png');
background-position: -40px -142px;
}
#fancybox-bg-w {
top: 0;
left: -20px;
height: 100%;
background-image: url('i/fancybox/fancybox-y.png');
}
#fancybox-bg-nw {
top: -20px;
left: -20px;
background-image: url('i/fancybox/fancybox.png');
background-position: -40px -122px;
}
#fancybox-title {
font-family: Helvetica;
font-size: 12px;
z-index: 1102;
}
.fancybox-title-inside {
padding-bottom: 10px;
text-align: center;
color: #333;
background: #fff;
position: relative;
}
.fancybox-title-outside {
padding-top: 10px;
color: #fff;
}
.fancybox-title-over {
position: absolute;
bottom: 0;
left: 0;
color: #FFF;
text-align: left;
}
#fancybox-title-over {
padding: 10px;
background-image: url('i/fancybox/fancy_title_over.png');
display: block;
}
.fancybox-title-float {
position: absolute;
left: 0;
bottom: -20px;
height: 32px;
}
#fancybox-title-float-wrap {
border: none;
border-collapse: collapse;
width: auto;
}
#fancybox-title-float-wrap td {
border: none;
white-space: nowrap;
}
#fancybox-title-float-left {
padding: 0 0 0 15px;
background: url('i/fancybox/fancybox.png') -40px -90px no-repeat;
}
#fancybox-title-float-main {
color: #FFF;
line-height: 29px;
font-weight: bold;
padding: 0 0 3px 0;
background: url('i/fancybox/fancybox-x.png') 0px -40px;
}
#fancybox-title-float-right {
padding: 0 0 0 15px;
background: url('i/fancybox/fancybox.png') -55px -90px no-repeat;
}
/* IE6 */
.fancybox-ie6 #fancybox-close { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_close.png', sizingMethod='scale'); }
.fancybox-ie6 #fancybox-left-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_nav_left.png', sizingMethod='scale'); }
.fancybox-ie6 #fancybox-right-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_nav_right.png', sizingMethod='scale'); }
.fancybox-ie6 #fancybox-title-over { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_title_over.png', sizingMethod='scale'); zoom: 1; }
.fancybox-ie6 #fancybox-title-float-left { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_title_left.png', sizingMethod='scale'); }
.fancybox-ie6 #fancybox-title-float-main { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_title_main.png', sizingMethod='scale'); }
.fancybox-ie6 #fancybox-title-float-right { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_title_right.png', sizingMethod='scale'); }
.fancybox-ie6 #fancybox-bg-w, .fancybox-ie6 #fancybox-bg-e, .fancybox-ie6 #fancybox-left, .fancybox-ie6 #fancybox-right, #fancybox-hide-sel-frame {
height: expression(this.parentNode.clientHeight + "px");
}
#fancybox-loading.fancybox-ie6 {
position: absolute; margin-top: 0;
top: expression( (-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px');
}
#fancybox-loading.fancybox-ie6 div { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_loading.png', sizingMethod='scale'); }
/* IE6, IE7, IE8 */
.fancybox-ie .fancybox-bg { background: transparent !important; }
.fancybox-ie #fancybox-bg-n { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_shadow_n.png', sizingMethod='scale'); }
.fancybox-ie #fancybox-bg-ne { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_shadow_ne.png', sizingMethod='scale'); }
.fancybox-ie #fancybox-bg-e { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_shadow_e.png', sizingMethod='scale'); }
.fancybox-ie #fancybox-bg-se { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_shadow_se.png', sizingMethod='scale'); }
.fancybox-ie #fancybox-bg-s { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_shadow_s.png', sizingMethod='scale'); }
.fancybox-ie #fancybox-bg-sw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_shadow_sw.png', sizingMethod='scale'); }
.fancybox-ie #fancybox-bg-w { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_shadow_w.png', sizingMethod='scale'); }
.fancybox-ie #fancybox-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='i/fancybox/fancy_shadow_nw.png', sizingMethod='scale'); }

57
web/0.3.4/play/ac.html Normal file
Просмотреть файл

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<title>Autocomplete test</title>
<script src="../scripts/requireplugins-jquery.js"></script>
<script src="../scripts/jquery-ui-1.8.7.min.js"></script>
<script>
var options = {
a: [
'alpha',
'amature'
],
b: [
'bass',
'bicycle'
]
},
options2 = [
'alpha',
'amature',
'bass',
'bicycle'
];
//HTML5-style autocomplete, does not do want is desired though.
$(function () {
var ac = $('.ac')[0],
dynamic = $('#dynamic')[0];
$('body').delegate('.ac', 'input', function (evt) {
var value = ac.value,
args = value.split(','),
others = args.slice(0, args.length - 1).join(',') || '',
last = args[args.length - 1],
list = options[last.charAt(0)],
html = '';
if (list) {
list.forEach(function (item) {
html += '<option value="' + (others ? others + ',' : '') + item + '">' + (others ? others + ',' : '') + item + '</option>';
})
dynamic.innerHTML = html;
}
console.log("INPUT: ", evt);
});
});
</script>
</head>
<body>
<form>
<input class="ac" list="dynamic" name="dynamicAc">
<datalist id="dynamic">
</datalist>
</form>
</body>
</html>

Двоичные данные
web/0.3.4/play/designs/i/background.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 17 KiB

Двоичные данные
web/0.3.4/play/designs/i/bryanAvatar.jpg Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 607 B

Двоичные данные
web/0.3.4/play/designs/i/linkdropiconfaded.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 302 B

Двоичные данные
web/0.3.4/play/designs/i/settings.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 235 B

Просмотреть файл

@ -0,0 +1,581 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
* {
margin: 0;
padding: 0;
outline: none;
border: none;
border-collapse: collapse;
position: relative;
font-family: inherit;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
vertical-align: top;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
list-style-type: none;
}
body {
font-size: 11px;
font-family: "lucida grande";
max-height: 128px;
overflow: hidden;
background-color: #fff;
background-position: bottom center;
background-repeat: no-repeat;
background-color: #fff;
}
button::-moz-focus-inner {
border: 0;
}
a {
text-decoration: none;
outline: none;
}
#tabs {
overflow: hidden;
border-bottom: 1px solid #515151;
}
#twitter, #facebook, #gmail, #settings {
/* background-image: -moz-linear-gradient(top, #d0d0d0 0%, #a8a8a8 100%); */
background-color: #a7a7a7;
/*
border-top: 1px solid #515151;
-moz-box-shadow: 0 2px 0 -1px #e3e3e3 inset;
*/
}
ul.nav {
-moz-box-shadow:0 2px 0 -1px #CDCDCD inset;
background-color:#A7A7A7;
display: block;
width: 100%;
padding: 0 10px;
}
ul.nav .username {
font-size: 11px;
line-height: 24px;
padding: 0 10px;
margin: 4px 10px;
border-left: 1px dotted #888;
display: inline-block;
}
ul.nav .username img {
border: 1px solid #fff;
-moz-box-shadow: 0 1px 1px rgba(0,0,0,0.25);
width: 23px;
height: 23px;
margin-right: 5px;
}
ul.nav .username .userId {
color: #000;
font-weight: bold;
text-shadow: 1px 1px 0 #bbb;
}
ul.nav .navWrap {
width: 960px;
/*
background-image: url("i/logo.gif");
background-repeat: no-repeat;
background-position: right center;
*/
position: relative;
left: 50%;
margin-left: -480px;
}
ul.nav li {
width: auto;
display: inline-block;
float: left;
list-style-type: none;
margin: 3px 0;
font-size: 11px;
line-height: 24px;
background-image: -moz-linear-gradient(center top , #FDFDFD 0%, #AAAAAA 100%);
border-width: 1px;
border-style: solid;
border-color: #666;
-moz-box-shadow: 0 1px 0 #CDCDCD;
}
ul.nav li:hover {
background-color: rgba(255,255,255,0.5);
}
ul.nav li.ui-tabs-selected {
background-image: -moz-linear-gradient(center top , #bbb 0%, #aaa 100%);
-moz-box-shadow: 0 0 3px #666 inset,0 1px 0 #CDCDCD;
}
ul.nav li:first-child {
z-index: 1;
-moz-border-radius: 3px 0 0 3px;
}
ul.nav li:nth-child(2) {
z-index: 2;
border-left: none;
border-right: none;
}
ul.nav li:nth-child(3) {
z-index: 1;
-moz-border-radius: 0 3px 3px 0;
}
ul.nav li a {
color: #fff;
}
ul.nav li a.icon {
width: 36px;
height: 24px;
background-repeat: no-repeat;
background-position: center center;
display: block;
}
ul.nav li a.icon.twitter {
background-image: url("../share/i/twitterIcon.png");
}
ul.nav li a.icon.facebook {
background-image: url("../share/i/facebookIcon.png");
}
ul.nav li a.icon.gmail {
background-image: url("../share/i/gmailIcon.png");
}
ul.nav li a.icon.settings {
background-image: url("../share/i/settingsIcon.png");
}
ul.nav li.debug {
position: absolute;
right: 46px;
top: 0;
width: 60px;
text-align: center;
}
ul.nav li.debug span.name {
display: block;
padding: 0;
text-align: center;
font-weight: normal;
color: #fff;
}
ul.nav li.debug a.icon {
width: auto;
}
ul.nav li span.name {
display: none;
}
ul.nav li.ui-tabs-selected span.name {
display: none;
}
ul.nav li.settings,
ul.nav li.settings.ui-tabs-selected {
position: absolute;
right: 0;
top: 0;
text-align: center;
-moz-border-radius: 3px;
}
ul.nav li.settings:hover span.name,
ul.nav li.settings.ui-tabs-selected span.name {
opacity: 1;
}
ul.nav li.settings span.name {
display: none;
}
ul.nav li.ui-tabs-selected {
}
ul.nav li span.name {
opacity: 0.5;
}
ul.nav li.ui-tabs-selected a.icon,
ul.nav li.ui-tabs-selected span.name {
opacity: 1;
}
ul.nav li span.name {
font-weight: bold;
color: #fff;
}
ul.nav li.ui-tabs-selected span.name {
color: #0a0a0a;
}
ul.nav span.name {
display: block;
padding-left: 24px;
}
ul.nav li.ui-tabs-selected.settings span.name {
display: none;
}
ul.nav li.ui-tabs-selected a.twitter,
ul.nav li:hover a.twitter {
background-image: url("../share/i/twitterIconColor.png");
}
ul.nav li.ui-tabs-selected a.facebook,
ul.nav li:hover a.facebook {
background-image: url("../share/i/facebookIconColor.png");
}
ul.nav li.ui-tabs-selected a.gmail,
ul.nav li:hover a.gmail {
background-image: url(".../share/i/gmailIconColor.png");
}
ul.nav li.ui-tabs-selected a {
color: #0a0a0a;
}
div.user {
font-size: small;
width: 140px;
overflow: hidden;
}
div.user.inactive {
opacity: 0.5;
background: -moz-repeating-linear-gradient(top left -45deg, #aaa, #aaa 5px, #fff 5px, #fff 10px) #aaa no-repeat fixed;
-moz-border-radius: 1%;
cursor: pointer;
}
div.user .username {
color: #444;
font-weight: bold;
}
td.image {
width: 90px;
}
.thumbnail {
height: 71px;
padding: 4px;
border: 1px solid #999;
margin: 0 5px 0 0;
-moz-border-radius: 3px;
background-color: #ccc;
}
div.thumb {
border: 1px solid #aaa;
background-color: #fff;
height: 61px;
width: 90px;
display: inline-block;
}
ul.info {
display: inline-block;
width: 150px;
font-size: 11px;
padding: 0 5px 0 10px;
}
.info .description {
color: #000;
font-size: 10px;
}
.thumb .title {
color: #3B5998;
text-decoration: underline;
font-size: small;
cursor: pointer;
}
.thumb .description {
color: #808080;
font-size: x-small;
}
button {
padding: 2px 15px;
font-family: "helvetica neue", helvetica, arial, sans-serif;
font-size: 11px;
line-height:24px;
background-image: -moz-linear-gradient(top,#fdfdfd 0%,#aaa 100%);
border-width: 1px;
border-style: solid;
border-color: #5C5C5C #888 #666;
-moz-border-radius: 3px;
margin-left: 5px;
cursor: pointer;
}
button.share {
-moz-border-radius: 0 3px 3px 0;
-moz-box-shadow: 0 1px 0 #cdcdcd;
border-left: none;
margin-left: 0;
}
/*
button:hover, button:active {
border: 1px solid #999;
}
*/
button:active {
-moz-box-shadow: 0 0 0 1px rgba(255,255,255,0.35) inset, 0 0 3px rgba(0,0,0,0.75) inset;
}
textarea, input[type="text"] {
-moz-box-shadow: 0 2px 2px -2px #555 inset, 0 1px 0 #cdcdcd;
border-width: 1px;
border-style: solid;
border-color: #5c5c5c #929292 #929292;
font-family: "lucida grande"
font-size: 12px;
line-height: 18px;
padding: 3px;
margin: 0;
width: 100%;
-moz-border-radius: 3px;
}
textarea.message {
min-height: 71px;
-moz-border-radius: 3px 0 0 3px;
font-size: 14px;
}
textarea:focus, input[type="text"]:focus {
}
.inputs {
margin: 0 5px 0 0;
}
input[type="text"] {
height: 26px;
width: 238px;
display: block;
}
input[type="text"]#to {
margin-bottom: 5px;
}
.entry {
padding: 5px 0;
width: 960px;
left: 50%;
margin-left: -480px;
position: relative;
min-height: 71px;
}
.entry .urlConfirmation {
padding: 1px 5px;
-moz-border-radius: 10px;
background-image: -moz-linear-gradient(top, #fafafa 0%, #e6e6e6 100%);
border: 1px solid #bebebe;
color: green;
position: absolute;
left: 5px;
bottom: 5px;
z-index: 1;
color: green;
font-size: 10px;
cursor: pointer;
display: none;
}
.entry .urlConfirmation span {
color: #333;
}
#settings .entry ul li {
display: inline-block;
float: left;
}
#settings .entry ul li button {
margin: 0 10px 0 0;
width: 128px;
}
.entry h1 {
margin: 0 0 10px 0;
}
/* START hbox/vbox normalization from http://alex.dojotoolkit.org/2009/08/css-3-progress/ */
/* hbox and vbox classes */
.hbox {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-align: stretch;
display: box;
box-orient: horizontal;
box-align: stretch;
}
.hbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.vbox {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-align: stretch;
display: box;
box-orient: vertical;
box-align: stretch;
}
.vbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.spacer {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.reverse {
-webkit-box-direction: reverse;
-moz-box-direction: reverse;
box-direction: reverse;
}
.boxFlex0 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
}
.boxFlex1, .boxFlex {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.boxFlex2 {
-webkit-box-flex: 2;
-moz-box-flex: 2;
box-flex: 2;
}
.boxGroup1 {
-webkit-box-flex-group: 1;
-moz-box-flex-group: 1;
box-flex-group: 1;
}
.boxGroup2 {
-webkit-box-flex-group: 2;
-moz-box-flex-group: 2;
box-flex-group: 2;
}
.start {
-webkit-box-pack: start;
-moz-box-pack: start;
box-pack: start;
}
.end {
-webkit-box-pack: end;
-moz-box-pack: end;
box-pack: end;
}
.center {
-webkit-box-pack: center;
-moz-box-pack: center;
box-pack: center;
}
/* END hbox/vbox normalization from http://alex.dojotoolkit.org/2009/08/css-3-progress/ */
/* clearfix */
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
html[xmlns] .clearfix {
display: block;
}
* html .clearfix {
height: 1%;
}

Просмотреть файл

@ -0,0 +1,112 @@
<!DOCTYPE html>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is Raindrop.
-
- The Initial Developer of the Original Code is
- Mozilla Messaging, Inc..
- Portions created by the Initial Developer are Copyright (C) 2009
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- -->
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css" href="nativeShare.css">
<script type="text/javascript">
$(document).ready(function() {
$("#tabs").tabs(/* { fx: { opacity: 'toggle', duration: 0 } } */);
});
</script>
<style>
.ui-tabs .ui-tabs-hide { display: none; }
</style>
</head>
<body>
<div id="tabs" class="tabs-left">
<ul class="nav clearfix">
<div class="navWrap clearfix">
<li><a class="icon twitter" title="share on twitter" href="#twitter"><span class="name">Twitter</span></a></li>
<li><a class="icon facebook" title="share on facebook" href="#facebook"><span class="name">Facebook</span></a></li>
<li><a class="icon gmail" title="share on Gmail" href="#gmail"><span class="name">Gmail</span></a></li>
<li class="settings"><a class="icon settings" href="#settings"><span class="name"><img src="i/settings.png"></span></a></li>
<div class="username"><img src="i/bryanAvatar.jpg"><span class="userId">@clarkbw</span></div>
</div>
</ul>
<div id="twitter">
<div class="entry hbox">
<div class="boxFlex">
<textarea class="message"></textarea>
<span class="urlConfirmation"><span>re-insert link</span></span>
</div>
<button class="share">share</button>
</div>
</div>
<div id="facebook">
<div class="entry hbox">
<div class="thumbnail">
<div class="thumb"></div>
<ul class="info">
<li class="title">Title</li>
<li class="description">Description</li>
</ul>
</div>
<textarea class="message boxFlex"></textarea>
<button class="share">share</button>
</div>
</div>
<div id="gmail">
<div class="entry hbox">
<div class="inputs">
<input id="to" type="text" value="to"/>
<input id="subject" type="text" value="subject"/>
</div>
<div class="boxFlex">
<textarea class="message"></textarea>
<span class="urlConfirmation"><span>re-insert link</span></span>
</div>
<button class="share">share</button>
</div>
</div>
<div id="settings">
<div class="entry">
<h1>Settings</h1>
<ul>
<li><button>Add Twitter</button></li>
<li><button>Add Facebook</button></li>
<li><button>Add GMail</button></li>
<li><button>Add FFFFound</button></li>
</ul>
</div>
</div>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,630 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
* {
margin: 0;
padding: 0;
outline: none;
border: none;
border-collapse: collapse;
position: relative;
font-family: inherit;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
vertical-align: top;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
list-style-type: none;
}
body {
font-size: 11px;
font-family: "lucida grande";
max-height: 128px;
overflow: hidden;
background-color: #fff;
background-position: bottom center;
background-repeat: no-repeat;
background-color: #fff;
}
button::-moz-focus-inner {
border: 0;
}
a {
text-decoration: none;
outline: none;
color: #00A0FF;
}
a:hover {
text-decoration: underline;
}
#tabs {
overflow: hidden;
width: 100%;
border-bottom: 1px solid #777;
background-color: #ddd;
-moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);
background-image:-moz-linear-gradient(center top , #EEEEEE 0%, #DDDDDD 100%);
}
#twitter, #facebook, #gmail, #settings {
}
ul.nav {
display: block;
width: 100%;
padding: 0 10px;
}
ul.nav .username {
font-size: 11px;
line-height: 24px;
padding: 0 10px;
margin: 4px 10px;
border-left: 1px dotted #888;
display: inline-block;
}
ul.nav .username img {
border: 1px solid #fff;
-moz-box-shadow: 0 1px 1px rgba(0,0,0,0.25);
width: 23px;
height: 23px;
margin-right: 5px;
}
ul.nav .username .userId {
color: #000;
font-weight: bold;
/* text-shadow: 1px 1px 0 #bbb; */
}
ul.nav .navWrap {
position: relative;
/*
width: 960px;
left: 50%;
margin-left: -480px;
*/
}
ul.nav li {
width: auto;
display: inline-block;
float: left;
list-style-type: none;
margin: 3px 0;
font-size: 11px;
line-height: 24px;
background-image: -moz-linear-gradient(center top , #fafafa 0%, #ddd 100%);
border-width: 1px;
border-style: solid;
border-color: #888;
-moz-box-shadow: 0 1px 0 #fff;
}
ul.nav li:hover {
background-color: rgba(255,255,255,0.5);
}
ul.nav li.ui-tabs-selected {
-moz-box-shadow:0 0 1px #666666 inset, 0 1px 0 #FFFFFF;
background-image:-moz-linear-gradient(center top , #EEEEEE 0%, #CCCCCC 100%);
}
ul.nav li:first-child {
z-index: 1;
-moz-border-radius: 2px 0 0 2px;
}
ul.nav li:nth-child(2) {
z-index: 2;
border-left: none;
border-right: none;
}
ul.nav li:nth-child(3) {
z-index: 1;
-moz-border-radius: 0 2px 2px 0;
}
ul.nav li a {
color: #fff;
}
ul.nav li a.icon {
width: 36px;
height: 24px;
background-repeat: no-repeat;
background-position: center center;
display: block;
}
ul.nav li a.icon.twitter {
background-image: url("../share/i/twitterIcon.png");
}
ul.nav li a.icon.facebook {
background-image: url("../share/i/facebookIcon.png");
}
ul.nav li a.icon.gmail {
background-image: url("../share/i/gmailIcon.png");
}
ul.nav li a.icon.settings {
background-image: url("../share/i/settingsIcon.png");
}
ul.nav li.debug {
position: absolute;
right: 46px;
top: 0;
width: 60px;
text-align: center;
}
ul.nav li.debug span.name {
display: block;
padding: 0;
text-align: center;
font-weight: normal;
color: #fff;
}
ul.nav li.debug a.icon {
width: auto;
}
ul.nav li span.name {
display: none;
}
ul.nav li.ui-tabs-selected span.name {
display: none;
}
ul.nav li.settings,
ul.nav li.settings.ui-tabs-selected {
position: absolute;
right: 0;
top: 0;
text-align: center;
-moz-border-radius: 2px;
}
ul.nav li.settings:hover span.name,
ul.nav li.settings.ui-tabs-selected span.name {
opacity: 1;
}
ul.nav li.settings span.name {
display: none;
}
ul.nav li span.name {
opacity: 0.5;
}
ul.nav li.ui-tabs-selected a.icon,
ul.nav li.ui-tabs-selected span.name {
opacity: 1;
}
ul.nav li span.name {
font-weight: bold;
color: #fff;
}
ul.nav li.ui-tabs-selected span.name {
color: #0a0a0a;
}
ul.nav span.name {
display: block;
padding-left: 24px;
}
ul.nav li.ui-tabs-selected.settings span.name {
display: none;
}
ul.nav li.ui-tabs-selected a.twitter,
ul.nav li:hover a.twitter {
background-image: url("../share/i/twitterIconColor.png");
}
ul.nav li.ui-tabs-selected a.facebook,
ul.nav li:hover a.facebook {
background-image: url("../share/i/facebookIconColor.png");
}
ul.nav li.ui-tabs-selected a.gmail,
ul.nav li:hover a.gmail {
background-image: url("../share/i/gmailIconColor.png");
}
ul.nav li.ui-tabs-selected a {
color: #0a0a0a;
}
div.user {
font-size: small;
width: 140px;
overflow: hidden;
}
div.user.inactive {
opacity: 0.5;
background: -moz-repeating-linear-gradient(top left -45deg, #aaa, #aaa 5px, #fff 5px, #fff 10px) #aaa no-repeat fixed;
-moz-border-radius: 1%;
cursor: pointer;
}
div.user .username {
color: #444;
font-weight: bold;
}
td.image {
width: 90px;
}
.thumbnail {
height: 71px;
padding: 4px;
border: 1px solid #bbb;
margin: 0 5px 0 0;
-moz-border-radius: 2px;
background-image: -moz-linear-gradient(center top , #EEEEEE 0%, #DDDDDD 100%);
}
div.thumb {
border: 1px solid #aaa;
background-color: #fff;
height: 61px;
width: 90px;
display: inline-block;
}
ul.info {
display: inline-block;
width: 150px;
font-size: 11px;
padding: 0 5px 0 10px;
}
.info .description {
color: #444;
font-size: 10px;
}
.thumb .title {
color: #3B5998;
text-decoration: underline;
font-size: small;
cursor: pointer;
}
.thumb .description {
color: #808080;
font-size: x-small;
}
button {
padding: 2px 15px;
background-image: -moz-linear-gradient(center top , #FAFAFA 0%, #DDDDDD 100%);
border-width: 1px;
border-style: solid;
border-color: #888;
-moz-border-radius: 2px;
margin-left: 5px;
cursor: pointer;
-moz-box-shadow: 0 1px 0 #fff;
}
button.share {
-moz-border-radius: 0 2px 2px 0;
border-left: none;
margin-left: 0;
}
button:active {
background-image: -moz-linear-gradient(center top , #EEEEEE 0%, #CCCCCC 100%);
-moz-box-shadow:0 0 1px #666666 inset, 0 1px 0 #FFFFFF;
}
textarea, input[type="text"] {
border-width: 1px;
border-style: solid;
border-color: #888;
font-family: "lucida grande"
font-size: 12px;
line-height: 18px;
padding: 3px;
margin: 0;
width: 100%;
-moz-border-radius: 2px;
-moz-box-shadow:0 3px 3px -3px rgba(0, 0, 0, 0.25) inset, 0 1px 0 #fff;
}
textarea.message {
min-height: 71px;
-moz-border-radius: 2px 0 0 2px;
font-size: 14px;
}
textarea:focus, input[type="text"]:focus {
}
.inputs {
margin: 0 5px 0 0;
}
input[type="text"] {
height: 26px;
width: 238px;
display: block;
}
input[type="text"]#to {
margin-bottom: 5px;
}
.entry {
padding: 5px 10px;
width: 100%;
/*
width: 960px;
left: 50%;
margin-left: -480px;
*/
position: relative;
min-height: 71px;
}
.entry .urlConfirmation {
padding: 1px 5px;
-moz-border-radius: 10px;
background-image: -moz-linear-gradient(top, #fafafa 0%, #e6e6e6 100%);
border: 1px solid #bebebe;
color: green;
position: absolute;
left: 5px;
bottom: 5px;
z-index: 1;
color: green;
font-size: 10px;
cursor: pointer;
display: none;
}
.entry .urlConfirmation span {
color: #333;
}
#settings .entry ul {
min-width: 660px;
}
#settings .entry ul li {
display: inline-block;
float: left;
width: 220px;
min-height: 71px;
}
#settings .entry ul li:nth-child(1) {
padding: 0 10px 0 0;
}
#settings .entry ul li:nth-child(2) {
padding: 0 10px 0;
}
#settings .entry ul li:nth-child(3) {
padding: 0 0 0 10px;
}
#settings .entry ul li button {
margin: 0;
width: 100%;
padding: 5px 0;
}
#settings .entry ul li h1 {
margin: 0 0 10px 0;
}
.entry h1 {
font-weight: bold;
margin: 0 0 5px 0;
color: #0a0a0a;
padding: 5px 0 0 0;
/* border-top: 1px dotted #888; */
}
.entry h1 a {
font-weight: normal;
}
.entry h1 img {
margin-top: -1px;
}
#settings .entry .settings {
width: 253px;
margin: 0 0 0 10px;
padding: 0 0 0 10px;
border-left: 1px dotted #888;
color: #444;
}
#settings .entry .success {
width: 100%;
line-height: 24px;
color: #54B851;
font-weight: bold;
}
#settings .entry .success span.check {
width: 24px;
background-color: #54B851;
color: #fff;
-moz-border-radius: 12px;
display: inline-block;
font-size: 12px;
font-weight: normal;
text-align: center;
}
/* START hbox/vbox normalization from http://alex.dojotoolkit.org/2009/08/css-3-progress/ */
/* hbox and vbox classes */
.hbox {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-align: stretch;
display: box;
box-orient: horizontal;
box-align: stretch;
}
.hbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.vbox {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-align: stretch;
display: box;
box-orient: vertical;
box-align: stretch;
}
.vbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.spacer {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.reverse {
-webkit-box-direction: reverse;
-moz-box-direction: reverse;
box-direction: reverse;
}
.boxFlex0 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
}
.boxFlex1, .boxFlex {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.boxFlex2 {
-webkit-box-flex: 2;
-moz-box-flex: 2;
box-flex: 2;
}
.boxGroup1 {
-webkit-box-flex-group: 1;
-moz-box-flex-group: 1;
box-flex-group: 1;
}
.boxGroup2 {
-webkit-box-flex-group: 2;
-moz-box-flex-group: 2;
box-flex-group: 2;
}
.start {
-webkit-box-pack: start;
-moz-box-pack: start;
box-pack: start;
}
.end {
-webkit-box-pack: end;
-moz-box-pack: end;
box-pack: end;
}
.center {
-webkit-box-pack: center;
-moz-box-pack: center;
box-pack: center;
}
/* END hbox/vbox normalization from http://alex.dojotoolkit.org/2009/08/css-3-progress/ */
/* clearfix */
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
html[xmlns] .clearfix {
display: block;
}
* html .clearfix {
height: 1%;
}

Просмотреть файл

@ -0,0 +1,120 @@
<!DOCTYPE html>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is Raindrop.
-
- The Initial Developer of the Original Code is
- Mozilla Messaging, Inc..
- Portions created by the Initial Developer are Copyright (C) 2009
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- -->
<html>
<head>
<title>F1</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.4/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css" href="neutralShare.css">
<script type="text/javascript">
$(document).ready(function() {
$("#tabs").tabs({ fx: { opacity: 'toggle', duration: 200 } });
});
</script>
<style>
.ui-tabs .ui-tabs-hide { display: none; }
</style>
</head>
<body>
<div id="tabs" class="tabs-left">
<ul class="nav clearfix">
<div class="navWrap clearfix">
<li><a class="icon twitter" title="share on twitter" href="#twitter"><span class="name">Twitter</span></a></li>
<li><a class="icon facebook" title="share on facebook" href="#facebook"><span class="name">Facebook</span></a></li>
<li><a class="icon gmail" title="share on Gmail" href="#gmail"><span class="name">Gmail</span></a></li>
<li class="settings"><a class="icon settings" href="#settings"><span class="name"><img src="i/settings.png"></span></a></li>
<div class="username"><img src="i/bryanAvatar.jpg"><span class="userId">@clarkbw</span></div>
</div>
</ul>
<div id="twitter">
<div class="entry hbox">
<div class="boxFlex">
<textarea class="message"></textarea>
<span class="urlConfirmation"><span>re-insert link</span></span>
</div>
<button class="share">share</button>
</div>
</div>
<div id="facebook">
<div class="entry hbox">
<div class="thumbnail">
<div class="thumb"></div>
<ul class="info">
<li class="title">Title</li>
<li class="description">Description</li>
</ul>
</div>
<textarea class="message boxFlex"></textarea>
<button class="share">share</button>
</div>
</div>
<div id="gmail">
<div class="entry hbox">
<div class="inputs">
<input id="to" type="text" value="to"/>
<input id="subject" type="text" value="subject"/>
</div>
<div class="boxFlex">
<textarea class="message"></textarea>
<span class="urlConfirmation"><span>re-insert link</span></span>
</div>
<button class="share">share</button>
</div>
</div>
<div id="settings">
<div class="entry hbox">
<ul class="boxFlex">
<li>
<h1><img src="../share/i/twitterIcon.png"> Twitter</h1>
<button>Add Twitter</button>
</li>
<li>
<h1><img src="../share/i/facebookIcon.png"> Facebook</h1>
<button>Add Facebook</button>
</li>
<li>
<h1><img src="../share/i/gmailIcon.png"> Gmail - <a href="#">manage</a> | <a href="#">add account</a></h1>
<div class="success">
<span title="gmail is properly configured!" class="check">&#x2714;</span> 3 accounts configured
</div>
</li>
</ul>
<div class="settings">
<h1>Advanced settings</h1>
Don't see what you need? Try the <a href="#">account manager</a> to get into the nitty gritty.
</div>
</div>
</div>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,568 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
* {
margin: 0;
padding: 0;
outline: none;
border: none;
border-collapse: collapse;
position: relative;
font-family: inherit;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
vertical-align: top;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
list-style-type: none;
}
body {
font-size: 14px;
font-family: "helvetica neue", helvetica, arial, sans-serif;
max-height: 128px;
overflow: hidden;
background-color: #fff;
background-position: bottom center;
background-repeat: no-repeat;
background-color: #fff;
}
button::-moz-focus-inner {
border: 0;
}
a {
text-decoration: none;
outline: none;
}
#tabs {
-moz-box-shadow: 0 -5px 2px -4px #DDDDDD inset;
height: 125px;
overflow: hidden;
border-bottom: 1px solid #ccc;
background-color: #f2f2f2;
}
ul.nav {
background-image: url("i/background.gif");
-moz-box-shadow: 0 -2px 3px rgba(0,0,0,0.5) inset;
display: block;
width: 100%;
padding: 0 10px;
}
ul.nav .username {
height: 24px;
font-size: 12px;
color: #fff;
font-weight: bold;
line-height: 24px;
position: absolute;
right: 35px;
top: 6px;
}
ul.nav .username img {
border: 1px solid #fff;
width: 23px;
height: 23px;
margin-left: 5px;
}
ul.nav .navWrap {
width: 962px;
position: relative;
left: 50%;
margin-left:-481px;
border-left: 1px solid #222;
border-right: 1px solid #222;
}
ul.nav li {
width: auto;
display: inline-block;
float: left;
list-style-type: none;
background-color: #444;
margin: 10px 0 0 0px;
font-size: 12px;
line-height: 24px;
-moz-border-radius: 5px 5px 0 0;
-moz-box-shadow: 0 -2px 2px rgba(0, 0, 0, 0.45);
}
ul.nav li:hover {
background-color: #555;
}
ul.nav li:nth-child(n+2) {
margin-left: -5px;
}
ul.nav li:nth-child(1) {
z-index: 1;
}
ul.nav li:nth-child(2) {
z-index: 2;
}
ul.nav li:nth-child(3) {
z-index: 1;
}
ul.nav li a {
color: #fff;
}
ul.nav li a.icon {
width: 24px;
height: 24px;
margin: 0 5px;
background-repeat: no-repeat;
background-position: center center;
display: block;
}
ul.nav li a.icon.twitter {
background-image: url("../share/i/twitter_w.png");
}
ul.nav li a.icon.facebook {
background-image: url("../share/i/facebook_w.png");
}
ul.nav li a.icon.gmail {
background-image: url("../share/i/gmail_w.png");
}
ul.nav li a.icon.settings {
background-image: url("i/settings.png");
background-position: top left;
}
ul.nav li.debug {
position: absolute;
right: 46px;
top: 0;
width: 60px;
text-align: center;
}
ul.nav li.debug span.name {
display: block;
padding: 0;
text-align: center;
font-weight: normal;
color: #fff;
}
ul.nav li.debug a.icon {
width: auto;
}
ul.nav li span.name {
display: none;
}
ul.nav li.ui-tabs-selected span.name {
display: block;
}
ul.nav li.settings,
ul.nav li.settings.ui-tabs-selected {
position: absolute;
background-color: transparent;
background-image: none;
-moz-box-shadow: none;
right: 15px;
top: 0;
width: 16px;
text-align: center;
}
ul.nav li.settings:hover span.name,
ul.nav li.settings.ui-tabs-selected span.name {
opacity: 1;
}
ul.nav li.settings span.name {
display: none;
}
ul.nav li.ui-tabs-selected {
background-color: #fff;
background-image: -moz-linear-gradient(top, #fff 0%, #f2f2f2 100%);
width: 128px;
z-index: 100;
}
ul.nav li a.icon,
ul.nav li span.name {
opacity: 0.5;
}
ul.nav li.ui-tabs-selected a.icon,
ul.nav li.ui-tabs-selected span.name {
opacity: 1;
}
ul.nav li span.name {
font-weight: bold;
color: #fff;
}
ul.nav li.ui-tabs-selected span.name {
color: #0a0a0a;
}
ul.nav span.name {
display: block;
padding-left: 24px;
}
ul.nav li.ui-tabs-selected.settings {
width: 16px;
}
ul.nav li.ui-tabs-selected.settings span.name {
display: none;
}
ul.nav li.ui-tabs-selected a.twitter {
background-image: url(".../share/i/twitter_b.png");
}
ul.nav li.ui-tabs-selected a.facebook {
background-image: url("../share/i/facebook_b.png");
}
ul.nav li.ui-tabs-selected a.gmail {
background-image: url("../share/i/gmail_b.png");
}
ul.nav li.ui-tabs-selected a {
color: #0a0a0a;
}
table {
width: 100%;
}
td.user {
width: 140px;
padding-right: 10px;
white-space: nowrap;
}
td.thumb {
width: 220px;
padding: 0 10px;
}
td.message {
width: 300px;
padding: 0 10px;
}
td.button {
padding: 1px 20px;
vertical-align: bottom;
}
div.user {
font-size: small;
width: 140px;
overflow: hidden;
}
div.user.inactive {
opacity: 0.5;
background: -moz-repeating-linear-gradient(top left -45deg, #aaa, #aaa 5px, #fff 5px, #fff 10px) #aaa no-repeat fixed;
-moz-border-radius: 1%;
cursor: pointer;
}
div.user .username {
color: #444;
font-weight: bold;
}
td.image {
width: 90px;
}
div.thumb {
border: 1px solid #aaa;
background-color: #fff;
height: 71px;
width: 90px;
display: inline-block;
}
ul.info {
display: inline-block;
width: 150px;
font-size: 12px;
padding: 0 10px;
}
.info .description {
color: #666;
font-size: 10px;
}
.thumb .title {
color: #3B5998;
text-decoration: underline;
font-size: small;
cursor: pointer;
}
.thumb .description {
color: #808080;
font-size: x-small;
}
button {
padding: 2px 15px;
font-family: "helvetica neue", helvetica, arial, sans-serif;
font-size: 12px;
line-height:24px;
background-image: -moz-linear-gradient(top,#fafafa 0%,#e6e6e6 100%);
border: 1px solid #bebebe;
-moz-box-shadow: 0 0 0 1px #fff inset;
margin-left: 10px;
cursor: pointer;
}
button:hover, button:active {
border: 1px solid #999;
}
button:active {
-moz-box-shadow: 0 0 0 1px rgba(255,255,255,0.35) inset, 0 0 3px rgba(0,0,0,0.75) inset;
}
textarea, input[type="text"] {
-moz-box-shadow: 0 0 2px #CCCCCC inset;
/* background-image: -moz-linear-gradient(center top , #FFFFFF 0%, #F2F2F2 100%); */
border: 1px solid #BEBEBE;
font-family: "helvetica neue",helvetica,arial,sans-serif;
font-size: 14px;
line-height: 24px;
padding: 3px;
margin: 0;
width: 100%;
}
textarea:focus, input[type="text"]:focus {
border: 1px solid #999;
}
.inputs {
margin: 0 10px 0 0;
}
input[type="text"] {
height: 30px;
width: 234px;
display: block;
}
input[type="text"]#to {
margin-bottom: 11px;
}
.entry {
padding: 10px;
width: 962px;
left: 50%;
margin-left: -481px;
position: relative;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
min-height: 70px;
}
.entry .urlConfirmation {
padding: 1px 5px;
-moz-border-radius: 10px;
background-image: -moz-linear-gradient(top, #fafafa 0%, #e6e6e6 100%);
border: 1px solid #bebebe;
color: green;
position: absolute;
left: 5px;
bottom: 5px;
z-index: 1;
color: green;
font-size: 10px;
cursor: pointer;
}
.entry .urlConfirmation span {
color: #333;
}
#settings .entry ul li {
display: inline-block;
float: left;
}
#settings .entry ul li button {
margin: 0 10px 0 0;
width: 128px;
}
.entry h1 {
margin: 0 0 10px 0;
}
/* START hbox/vbox normalization from http://alex.dojotoolkit.org/2009/08/css-3-progress/ */
/* hbox and vbox classes */
.hbox {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-align: stretch;
display: box;
box-orient: horizontal;
box-align: stretch;
}
.hbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.vbox {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-align: stretch;
display: box;
box-orient: vertical;
box-align: stretch;
}
.vbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.spacer {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.reverse {
-webkit-box-direction: reverse;
-moz-box-direction: reverse;
box-direction: reverse;
}
.boxFlex0 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
}
.boxFlex1, .boxFlex {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.boxFlex2 {
-webkit-box-flex: 2;
-moz-box-flex: 2;
box-flex: 2;
}
.boxGroup1 {
-webkit-box-flex-group: 1;
-moz-box-flex-group: 1;
box-flex-group: 1;
}
.boxGroup2 {
-webkit-box-flex-group: 2;
-moz-box-flex-group: 2;
box-flex-group: 2;
}
.start {
-webkit-box-pack: start;
-moz-box-pack: start;
box-pack: start;
}
.end {
-webkit-box-pack: end;
-moz-box-pack: end;
box-pack: end;
}
.center {
-webkit-box-pack: center;
-moz-box-pack: center;
box-pack: center;
}
/* END hbox/vbox normalization from http://alex.dojotoolkit.org/2009/08/css-3-progress/ */
/* clearfix */
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
html[xmlns] .clearfix {
display: block;
}
* html .clearfix {
height: 1%;
}

Просмотреть файл

@ -0,0 +1,113 @@
<!DOCTYPE html>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is Raindrop.
-
- The Initial Developer of the Original Code is
- Mozilla Messaging, Inc..
- Portions created by the Initial Developer are Copyright (C) 2009
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- -->
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css" href="share.css">
<script type="text/javascript">
$(document).ready(function() {
$("#tabs").tabs({ fx: { opacity: 'toggle', duration: 200 } });
});
</script>
<style>
.ui-tabs .ui-tabs-hide { display: none; }
</style>
</head>
<body>
<div id="tabs" class="tabs-left">
<ul class="nav clearfix">
<div class="navWrap clearfix">
<li><a class="icon twitter" href="#twitter"><span class="name">Twitter</span></a></li>
<li><a class="icon facebook" href="#facebook"><span class="name">Facebook</span></a></li>
<li><a class="icon gmail" href="#gmail"><span class="name">Gmail</span></a></li>
<li class="settings"><a class="icon settings" href="#settings"><span class="name"><img src="i/settings.png"></span></a></li>
<div class="username">@clarkbw <img src="i/bryanAvatar.jpg"></div>
</div>
</ul>
<div id="twitter">
<div class="entry hbox">
<div class="boxFlex">
<textarea class="message"></textarea>
<span class="urlConfirmation"><span>re-insert link</span></span>
</div>
<button>share</button>
</div>
</div>
<div id="facebook">
<div class="entry hbox">
<div class="thumbnail">
<div class="thumb"></div>
<ul class="info">
<li class="title">Title</li>
<li class="description">Description</li>
</ul>
</div>
<textarea class="message boxFlex"></textarea>
<button>share</button>
</div>
</div>
<div id="gmail">
<div class="entry hbox">
<div class="inputs">
<input id="to" type="text" value="to"/>
<input id="subject" type="text" value="subject"/>
</div>
<div class="boxFlex">
<textarea class="message"></textarea>
<span class="urlConfirmation"><span>re-insert link</span></span>
</div>
<button>share</button>
</div>
</div>
<div id="settings">
<div class="entry">
<h1>Settings</h1>
<ul>
<li><button>Add Twitter</button></li>
<li><button>Add Facebook</button></li>
<li><button>Add GMail</button></li>
<li><button>Add FFFFound</button></li>
</ul>
</div>
</div>
</div>
</body>
</html>

Двоичные данные
web/0.3.4/play/designs/sidebar/i/sprite.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.3 KiB

Двоичные данные
web/0.3.4/play/designs/sidebar/i/thumb.jpg Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.7 KiB

Просмотреть файл

@ -0,0 +1,231 @@
<!DOCTYPE html>
<html>
<head>
<title>F1: Sidebar</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.textOverflow.js"></script>
<script type="text/javascript" src="js/init.js"></script>
</head>
<body>
<div id="wrapper">
<div id="panel1" class="flip">
<header class="hbox">
<h1 class="boxFlex">Share</h1>
<nav>
<ul>
<li class="settings"><a class="configureToggle" href="#">configure</a></li>
<li><span class="close"></span></li>
</ul>
</nav>
</header>
<section id="pageInfo" class="hbox">
<div class="thumbnail"><img src="i/thumb.jpg"></div>
<h2 class="boxFlex overflow pageTitle">F1 by Mozilla Labs</h2>
</section>
<section id="twitter" class="account selected">
<div class="accountToggle hbox open">
<span class="arrow"></span>
<span class="icon twitter"></span>
<h3 class="boxFlex overflow">Twitter</h3>
<span class="username">_andychung</span>
</div>
<div class="accountPanel">
<div class="padding">
<label>type your message:</label>
<textarea class="compose"></textarea>
<div class="accountActions hbox">
<span class="count boxFlex">140</span>
<button>share</button>
</div>
</div>
</div>
</section>
<section id="facebook" class="account">
<div class="accountToggle hbox">
<span class="arrow"></span>
<span class="icon facebook"></span>
<h3 class="boxFlex overflow">Facebook</h3>
<span class="username">Andy Chung</span>
</div>
<div class="accountPanel">
<div class="padding">
<div class="facebookActions hbox">
<div class="to">
<label>send to:</label>
<div class="dropdownContainer">
<select class="facebookDropdown">
<option selected value="1">my wall</option>
<option value="2">group wall</option>
</select>
</div>
</div>
<div class="group boxFlex">
<label>type in the name of group:</label>
<input type="text">
</div>
<div class="list">
<label>list</label>
<button></button>
</div>
</div>
<label>type your message:</label>
<textarea class="compose"></textarea>
<div class="accountActions hbox">
<span class="count boxFlex">420</span>
<button>share</button>
</div>
</div>
</div>
</section>
<section id="google" class="account">
<div class="accountToggle hbox">
<span class="arrow"></span>
<span class="icon google"></span>
<h3 class="boxFlex overflow">Google Mail</h3>
<span class="username">animalyouth@gmail.com</span>
</div>
<div class="accountPanel">
<div class="padding">
<div class="to">
<label>to: <em>(enter emails separated by comma)</em></label>
<input type="text">
</div>
<div class="subject">
<label>subject:</label>
<input type="text">
</div>
<label>type your message:</label>
<textarea class="compose"></textarea>
<div class="accountActions hbox">
<span class="count boxFlex"></span>
<button>share</button>
</div>
</div>
</div>
</section>
<div style="position:absolute;bottom:0;">
<section id="news" class="hbox">
<div>
<span class="icon rss"></span>
</div>
<div class="boxFlex">
<h3>Latest from the F1 team</h3>
<div class="story">"F1 goes live!"</div>
</div>
</section>
</div>
</div>
<!-- begin settings panel -->
<div id="panel2" class="flip">
<header class="hbox">
<h1 class="boxFlex">Share configuration</h1>
<nav>
<ul>
<li class="settings"><a class="configureToggle" href="#">return to sharing</a></li>
<li><span class="close"></span></li>
</ul>
</nav>
</header>
<ul id="tabs" class="clearfix">
<li class="manage selected">manage</li>
<li class="add">add account</li>
<li class="settings">settings</li>
</ul>
<div id="accountPanels">
<section id="manageAccounts" class="configuration">
<h2>manage your accounts</h2>
<ul class="accountList">
<li class="accountType hbox">
<h3 class="accountName boxFlex overflow">
<span class="icon twitter"></span>
<span class="username">_andychung</span>
</h3>
<button>remove</button>
</li>
<li class="accountType hbox">
<h3 class="accountName boxFlex overflow">
<span class="icon facebook"></span>
<span class="username">Andy Chung</span>
</h3>
<button>remove</button>
</li>
<li class="accountType hbox">
<h3 class="accountName boxFlex overflow">
<span class="icon google"></span>
<span class="username">animalyouth@gmail.com</span>
</h3>
<button>remove</button>
</li>
</ul>
</section>
<section id="addAccounts" class="configuration">
<h2>add more accounts</h2>
<ul class="accountList">
<li class="accountType hbox">
<h3 class="accountName boxFlex overflow">
<span class="icon twitter"></span>
Twitter
</h3>
<button>add</button>
</li>
<li class="accountType hbox">
<h3 class="accountName boxFlex overflow">
<span class="icon facebook"></span>
Facebook
</h3>
<button>add</button>
</li>
<li class="accountType hbox">
<h3 class="accountName boxFlex overflow">
<span class="icon google"></span>
Google Mail
</h3>
<button>add</button>
</li>
</ul>
</section>
<section id="accountSettings" class="configuration">
<h2>F1 settings</h2>
<ul>
<li>
<div class="pref"><input id="bookmark" type="checkbox"> <label for="bookmark">Always bookmark the links I share</label></div>
</li>
<li>
<div class="pref"><input id="signature" type="checkbox"> <label for="signature">Include F1 email signature</label></div>
</li>
</ul>
</section>
</div>
<section id="save" class="configuration">
<div class="done hbox">
<span class="boxFlex"></span>
<button class="save">done</button>
</div>
</section>
</div>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,103 @@
$(document).ready(function($) {
// set panel min-height to full browser height
$(window).bind("load resize", function(){
var h = $(window).height();
$("#wrapper, #panel1, #panel2").css({ "min-height" : (h) });
});
// create ellipsis for gecko
$(function() {
$(".overflow").textOverflow(null,true);
});
// simple accordian menu
$(".accountToggle").click(function() {
$(".accountPanel:visible").slideUp(200);
if ($(this).next().is(":hidden")) {
$(this).next().slideDown(200);
}
});
$(".accountPanel").hide();
$(".open").trigger("click");
$(".accountToggle").click(function() {
$(this).parent().toggleClass("selected");
$(this).parent().siblings().removeClass("selected");
});
// hide and display facebook form
$(".group, .list").hide();
$("select.facebookDropdown").change(function () {
if ($(".group, .list").is(":hidden")) {
$(".group, .list").css({ "display" : "block" });
}
else {
$(".group, .list").css({ "display" : "none" });
}
});
// account manager simple tabs
$("ul#tabs li").click(function() {
$(this).addClass("selected");
$(this).siblings().removeClass("selected");
});
$("ul#tabs li.manage").click(function() {
if ($("section#manageAccounts").is(":hidden")) {
$("section#manageAccounts").fadeIn(200);
$("section#manageAccounts").siblings().fadeOut(0);
}
else {
$("section#manageAccounts").noop();
}
});
$("ul#tabs li.add").click(function() {
if ($("section#addAccounts").is(":hidden")) {
$("section#addAccounts").fadeIn(200);
$("section#addAccounts").siblings().fadeOut(0);
}
else {
$("section#addAccounts").noop();
}
});
$("ul#tabs li.settings").click(function() {
if ($("section#accountSettings").is(":hidden")) {
$("section#accountSettings").fadeIn(200);
$("section#accountSettings").siblings().fadeOut(0);
}
else {
$("section#manageAccounts").noop();
}
});
$("section#addAccounts, section#accountSettings").hide();
// 3d flip with fade fallback
$(function() {
if (jQuery.browser.webkit) {
$("a.configureToggle").bind("click", function() {
$("#panel1").toggleClass("front_flip");
$("#panel2").toggleClass("back_flip");
});
}
else {
$("a.configureToggle").bind("click", function() {
if ($("#panel1").is(":visible")) {
$("#panel1").fadeOut(100);
$("#panel2").fadeIn(100);
}
else {
$("#panel1").fadeIn(100);
$("#panel2").fadeOut(100);
}
});
}
});
// done!
});

Просмотреть файл

@ -0,0 +1,108 @@
/*!
* jQuery Text Overflow v0.7
*
* Licensed under the new BSD License.
* Copyright 2009-2010, Bram Stein
* All rights reserved.
*/
/*global jQuery, document, setInterval*/
(function ($) {
var style = document.documentElement.style,
hasTextOverflow = ('textOverflow' in style || 'OTextOverflow' in style),
domSplit = function (root, maxIndex) {
var index = 0, result = [],
domSplitAux = function (nodes) {
var i = 0, tmp;
if (index > maxIndex) {
return;
}
for (i = 0; i < nodes.length; i += 1) {
if (nodes[i].nodeType === 1) {
tmp = nodes[i].cloneNode(false);
result[result.length - 1].appendChild(tmp);
result.push(tmp);
domSplitAux(nodes[i].childNodes);
result.pop();
} else if (nodes[i].nodeType === 3) {
if (index + nodes[i].length < maxIndex) {
result[result.length - 1].appendChild(nodes[i].cloneNode(false));
} else {
tmp = nodes[i].cloneNode(false);
tmp.textContent = $.trim(tmp.textContent.substring(0, maxIndex - index));
result[result.length - 1].appendChild(tmp);
}
index += nodes[i].length;
} else {
result.appendChild(nodes[i].cloneNode(false));
}
}
};
result.push(root.cloneNode(false));
domSplitAux(root.childNodes);
return $(result.pop().childNodes);
};
$.extend($.fn, {
textOverflow: function (str, autoUpdate) {
var more = str || '&#x2026;';
if (!hasTextOverflow) {
return this.each(function () {
var element = $(this),
// the clone element we modify to measure the width
clone = element.clone(),
// we save a copy so we can restore it if necessary
originalElement = element.clone(),
originalText = element.text(),
originalWidth = element.width(),
low = 0, mid = 0,
high = originalText.length,
reflow = function () {
if (originalWidth !== element.width()) {
element.replaceWith(originalElement);
element = originalElement;
originalElement = element.clone();
element.textOverflow(str, false);
originalWidth = element.width();
}
};
element.after(clone.hide().css({
'position': 'absolute',
'width': 'auto',
'overflow': 'visible',
'max-width': 'inherit'
}));
if (clone.width() > originalWidth) {
while (low < high) {
mid = Math.floor(low + ((high - low) / 2));
clone.empty().append(domSplit(originalElement.get(0), mid)).append(more);
if (clone.width() < originalWidth) {
low = mid + 1;
} else {
high = mid;
}
}
if (low < originalText.length) {
element.empty().append(domSplit(originalElement.get(0), low - 1)).append(more);
}
}
clone.remove();
if (autoUpdate) {
setInterval(reflow, 200);
}
});
} else {
return this;
}
}
});
})(jQuery);

Просмотреть файл

@ -0,0 +1,625 @@
* {
padding: 0;
margin: 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
/*
general
*/
body {
font-family: "Lucida Grande", Verdana, Sans-serif;
font-size: 11px;
line-height: 110%;
}
#wrapper {
max-width: 400px;
min-width: 200px;
position: relative;
border-right: 1px solid #404040;
-webkit-perspective: 1500;
}
button::-moz-focus-inner {
border: 0;
}
button {
height: 24px;
border-width: 1px;
border-style: solid;
border-color: #aaa;
cursor: pointer;
padding: 0 10px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
background-image: -moz-linear-gradient(center top , #fafafa 0%, #ddd 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fafafa), color-stop(100%, #ddd));
}
button:active {
-moz-box-shadow: 0 0 1px #666666 inset;
-webkit-box-shadow: 0 0 1px #666666 inset;
box-shadow: 0 0 1px #666666 inset;
background-image: -moz-linear-gradient(center top , #eee 0%, #ccc 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eee), color-stop(100%, #ccc));
}
h2 {
font-size: 13px;
color: #535f6d;
text-shadow: 1px 1px 0 rgba(255,255,255, 0.5);
}
h3 {
font-weight: bold;
font-size: 11px;
line-height: 14px;
color: #535f6d;
}
/*
panel settings
*/
#panel1,
#panel2 {
width: 100%;
color: #535f6d;
overflow: auto;
position: absolute;
top: 0;
left: 0;
}
#panel1 {
background-color: #d4dde5;
z-index: 2;
}
#panel1 a,
#panel2 a {
color: #535f6d;
}
#panel2 {
background-color: #E9EEF2;
z-index: 1;
-webkit-transform: rotateY(180deg);
}
/*
header section
*/
header {
width: 100%;
padding: 8px 5px 10px 10px;
background-color: #d4dde5;
}
header h1 {
font-size: 11px;
}
header a {
text-decoration: none;
outline: none;
}
header a:hover {
text-decoration: underline;
}
header nav ul {
list-style-type: none;
}
header nav ul li {
display: inline-block;
padding: 0 5px;
float: left;
}
header nav ul li.settings {
border-width: 0 1px 0 0;
border-style: solid;
border-color: #535f6d;
}
header span.close {
width: 12px;
height: 13px;
background-image: url("i/sprite.png");
background-position: center 0;
display: block;
}
header span.close:active {
background-position: center -13px;
}
/*
page info
*/
section#pageInfo {
width: 100%;
padding: 10px;
}
section#pageInfo .thumbnail {
border: 1px solid #a6afb6;
-moz-box-shadow: 1px 1px 0 rgba(255,255,255, 0.5);
-webkit-box-shadow: 1px 1px 0 rgba(255,255,255, 0.5);
box-shadow: 1px 1px 0 rgba(255,255,255, 0.5);
}
section#pageInfo .thumbnail img {
float: left;
}
section#pageInfo h2 {
line-height: 60px;
margin: 0 0 0 20px;
}
/*
generic styles for account panels
*/
section {
display: block;
}
section.account {
color: #535F6D;
display: block;
border-width: 1px 0;
border-color: #a6afb6;
border-style: solid;
margin-top: -1px;
background-image: -moz-linear-gradient(top, #d4dde5 0%, #c6d1da 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #d4dde5), color-stop(100%, #c6d1da));
}
section.account:hover,
section.account.selected {
background-image: none;
}
section.account.selected {
background-color: #e9eef2;
}
section.account .username {
display: none;
}
section.account.selected .username {
display: block;
}
section.account .accountToggle {
padding: 10px;
cursor: pointer;
width: 100%;
}
span.arrow,
span.icon {
display: inline-block;
background-image: url("i/sprite.png");
background-repeat: no-repeat;
vertical-align: middle;
}
span.arrow {
width: 12px;
height: 14px;
}
span.icon {
width: 16px;
height: 14px;
margin: 0 5px;
}
section.account .accountToggle span.arrow {
background-position: center -102px;
}
section.account.selected .accountToggle span.arrow {
background-position: center -120px;
}
section.account .accountPanel {
display: block;
}
section.account .accountPanel .padding {
padding: 0 10px 10px 10px;
}
section.account textarea,
section.account input[type="text"] {
width: 100%;
font-family: "Lucida Grande", Verdana, Sans-serif;
font-size: 11px;
padding: 5px;
border-width: 1px;
border-style: solid;
border-color: #A6AFB6;
-moz-box-shadow: 0 1px 1px rgba(0,0,0,0.15) inset;
-webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.15) inset;
box-shadow: 0 1px 1px rgba(0,0,0,0.15) inset;
}
section.account textarea:focus,
section.account input[type="text"]:focus {
-moz-box-shadow: 0 0 0 2px #C2ECFF inset;
-webkit-box-shadow: 0 0 0 2px #C2ECFF inset;
box-shadow: 0 0 0 2px #C2ECFF inset;
outline: none;
}
button:focus {
outline: none;
z-index: 1;
position: relative;
}
section.account textarea {
width: 100%;
height: 80px;
}
section.account input[type="text"] {
height: 24px;
}
section.account .accountActions {
width: 100%;
margin: 10px 0 0 0;
}
section.account span.count {
line-height: 24px;
color: #535F6D;
}
section.account label {
display: block;
margin: 0 0 5px 0;
}
/*
twitter styles
*/
span.icon.twitter {
background-position: center -35px;
}
/*
facebook styles
*/
section#facebook.account .facebookActions {
margin: 0 0 10px 0;
width: 100%;
}
section#facebook.account .facebookActions .to {
width: 100px;
margin-right: 10px;
}
section#facebook.account .facebookActions .to .dropdownContainer {
height: 24px;
line-height: 24px;
display: block;
}
section#facebook.account .facebookActions .to select {
width: 100%;
}
section#facebook.account .facebookActions .list label {
visibility: hidden;
}
section#facebook.account .facebookActions .list button {
border-left: none;
width: 24px;
background-image: url("i/sprite.png"), -moz-linear-gradient(center top , #fafafa 0%, #ddd 100%);
background-image: url("i/sprite.png"), -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fafafa), color-stop(100%, #ddd));
background-position: center -157px, center top;
background-repeat: no-repeat;
-moz-border-radius: 0 2px 2px 0;
-webkit-border-radius: 0 2px 2px 0;
border-radius: 0 2px 2px 0;
}
section#facebook.account .facebookActions .list button:active {
background-image: url("i/sprite.png"), -moz-linear-gradient(center top , #eee 0%, #ccc 100%);
background-image: url("i/sprite.png"), -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eee), color-stop(100%, #ccc));
}
span.icon.facebook {
background-position: center -59px;
}
/*
google styles
*/
section#google.account .subject {
margin: 5px 0;
}
span.icon.google {
background-position: center -82px;
}
/*
account configuration
*/
ul#tabs {
width: 100%;
padding: 10px 10px 0 10px;
list-style-type: none;
background-color: #D4DDE5;
}
ul#tabs li {
padding: 7px 20px;
margin: 0 3px 0 0;
display: inline-block;
font-weight: bold;
text-align: center;
background-color: #E9EEF2;
border-width: 1px 1px 0 1px;
border-style: solid;
border-color: #A6AFB6;
-moz-border-radius: 3px 3px 0 0;
-webkit-border-radius: 3px 3px 0 0;
border-radius: 3px 3px 0 0;
float: left;
cursor: pointer;
}
ul#tabs li.selected {
position: relative;
z-index: 100;
}
#accountPanels {
padding: 10px 0 0;
border-top: 1px solid #a6afb6;
position: relative;
z-index: 90;
margin-top: -1px;
}
section.configuration {
padding: 10px;
display: block;
}
section.configuration h2 {
margin: 0 0 10px 0;
}
section.configuration ul {
background-color: #fff;
border: 1px solid #A6AFB6;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
list-style-type: none;
}
section.configuration ul li {
padding: 10px;
border-bottom: 1px solid #A6AFB6;
width: 100%;
}
section.configuration ul li:last-child {
border: none;
}
section.configuration h3 {
line-height: 24px;
}
section.configuration h3 .username {
font-weight: normal;
}
section.configuration input[type="checkbox"] {
margin-right: 5px;
}
section.configuration .done {
width: 100%;
}
section#news {
padding: 10px;
width: 100%;
}
section#news span.icon.rss {
background-position: center -183px;
margin: 0 5px 0 0;
}
section#news .story {
padding: 5px 0;
}
/*
hbox & vbox
*/
.hbox {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-align: stretch;
display: box;
box-orient: horizontal;
box-align: stretch;
}
.hbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.vbox {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-align: stretch;
display: box;
box-orient: vertical;
box-align: stretch;
}
.vbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.spacer {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.reverse {
-webkit-box-direction: reverse;
-moz-box-direction: reverse;
box-direction: reverse;
}
.boxFlex0 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
}
.boxFlex1, .boxFlex {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.boxFlex2 {
-webkit-box-flex: 2;
-moz-box-flex: 2;
box-flex: 2;
}
.boxGroup1 {
-webkit-box-flex-group: 1;
-moz-box-flex-group: 1;
box-flex-group: 1;
}
.boxGroup2 {
-webkit-box-flex-group: 2;
-moz-box-flex-group: 2;
box-flex-group: 2;
}
.start {
-webkit-box-pack: start;
-moz-box-pack: start;
box-pack: start;
}
.end {
-webkit-box-pack: end;
-moz-box-pack: end;
box-pack: end;
}
.center {
-webkit-box-pack: center;
-moz-box-pack: center;
box-pack: center;
}
/*
clearfix
*/
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
html[xmlns] .clearfix {
display: block;
}
* html .clearfix {
height: 1%;
}
/*
webkit specific styles
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
#wrapper {
background-color: #404040;
}
.overflow {
text-overflow: ellipsis;
overflow-x: hidden;
white-space: nowrap;
}
.flip {
-webkit-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
-webkit-transition: -webkit-transform 0.7s ease-in-out;
}
.front_flip {
-webkit-transform: rotateY(-180deg);
z-index: 900;
}
.back_flip {
-webkit-transform: rotateY(0deg) !important;
z-index: 1000;
}
}

Просмотреть файл

@ -0,0 +1,152 @@
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is Raindrop.
-
- The Initial Developer of the Original Code is
- Mozilla Messaging, Inc..
- Portions created by the Initial Developer are Copyright (C) 2009
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- -->
<!-- A hacky sample to attempt a send and handle auth failure automatically
then attempt a resend
-->
<!DOCTYPE html>
<html>
<head>
<title>Send a message</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<script src="../../scripts/requireplugins-jquery.js" charset="utf-8"></script>
<script>require(["index.js"]);</script>
<style>
html, body {
overflow: hidden;
}
body {
background-color: white;
}
.hidden {
display: none;
}
.invisible {
visibility: hidden;
}
</style>
</head>
<body class="settings">
<div class="row">
<div class="c4 logo">
</div>
</div>
<!-- send form -->
<div class="section send">
<form name="messageForm" id="messageForm" action="#">
<div class="row">
<div class="c1">
<input name="message">
Send via
<input type="radio" name="domain" value="twitter.com">Twitter
<input type="radio" name="domain" value="facebook.com">Facebook
<input type="radio" name="domain" value="noservice.com">No Service
<input type="hidden" name="end_point_success" value="/scratch/send/#success">
<input type="hidden" name="end_point_failure" value="/scratch/send/#failure">
<input type="hidden" name="end_point_auth_failure" value="/scratch/send/#auth_failure">
<button>send</button>
</div>
<div class="c1">
<div class="usernameError error invisible">Please enter your Twitter name</div>
</div>
</div>
</form>
</div>
<!-- send success section -->
<div class="section success hidden">
<div class="row">
<div class="c1">
<h4 class="success">Success!</h4>
<p>Your message was sent</p>
</div>
</div>
</div>
<!-- auth failure section
This is the end_point for when the *send* request fails auth (but not
when the explicit auth request fails) - when this happens we do the
explicit auth.
-->
<div class="section auth_failure hidden">
<div class="row">
<div class="c1">
<p>Authorizing...</p>
<!-- the js code arranges to submit the auth form below... -->
</div>
</div>
</div>
<div class="section auth_form hidden"> <!-- this is never made visible -->
<form name="authForm" id="authForm" action="/api/account/authorize" method="POST">
<div class="row">
<input type="hidden" name="domain">
<input type="hidden" name="end_point_success" value="/scratch/send/#auth_success">
<input type="hidden" name="end_point_auth_failure" value="/scratch/send/#final_auth_failure">
</div>
</form>
</div>
<!-- final auth failure section
This is the end_point for when the explicit auth request fails - we have
given up here...
-->
<div class="section final_auth_failure hidden">
<div class="row">
<div class="c1">
<p>Failed to authorize...</p>
</div>
</div>
</div>
<!-- auth success section
This is the end_point for when the explicit auth request succeeds - we
then attempt to retry the send.
-->
<div class="section auth_success hidden">
<div class="row">
<div class="c1">
<p>Sending...</p>
<!-- the JS code re-submits the send form -->
</div>
</div>
</div>
<!-- general failure section - an error other than auth failure...-->
<div id="resultMsg" class="section failure hidden">
<div class="row">
<div class="c1">
<p id="resultReason">Sorry - we failed for obscure reasons...</p>
</div>
</div>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,481 @@
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

Просмотреть файл

@ -0,0 +1,35 @@
The Stay-Puft Marshmallow Font
Copyright (c) 2003 by John Stracke
Not a very impressive piece of work, but fun. I sat down to fiddle
with pfaedit, and started seeing what I could do freehand, with
minimal splines. The result was all rounded (not surprising), sort of
marshmallowy, and I started thinking of it as the Stay-Puft
Marshmallow Font (see Ghostbusters if you don't get it). Once I had a
name, I felt compelled to round out the font (ISO 8859-1, at least).
The outcome looks sort of like Comic Sans MS. It's kind of cute, and
might be good for frivolous stuff such as birthday cards. I've used
it on my National Academy of Silly Walks merchandise
(http://www.cafepress.com/sillywalks/).
It is released under the terms of the GNU Lesser General Public
License (see COPYING.LIB). Where the LGPL refers to "source code", I
take that to refer to the file called StayPuft.sfd, which is a file
for editing with pfaedit (http://pfaedit.sourceforge.net/), an outline
font editor program. Thus, according to the LGPL, if you distribute
this font, you must make StayPuft.sfd available to the recipient(s)
under the terms the LGPL specifies for source availability. Each of
the download links below is an archive (tarfile or zipfile) which
includes StayPuft.sfd, the LGPL, a readme, and at least one font file
(e.g., Isabella.ttf for TrueType files). I chose the LGPL instead of
the GPL because, arguably, using the GPL might mean that PostScript
and PDF files with this font embedded would be GPLed (they're like
programs that link to a static library).
The font has ASCII, Latin-1, and a few other useful characters: left
and right quotation marks (single and double), ellipsis, long dash,
and Euro. I don't intend to round it out as much as I did with
Isabella (http://www.thibault.org/fonts/isabella/); this is a much
less interesting project. Anyone who wants to donate extra
letterforms is welcome, of course.

Двоичные данные
web/0.3.4/rdapi/f/StayPuft/StayPuft.ttf Normal file

Двоичный файл не отображается.

Двоичные данные
web/0.3.4/rdapi/i/2709984325_f5554afd53_o2.jpeg Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 285 KiB

402
web/0.3.4/rdapi/index.css Normal file
Просмотреть файл

@ -0,0 +1,402 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
/* @font-face typography */
@font-face {
font-family: StayPuft;
src: url("f/StayPuft/StayPuft.ttf");
font-weight: normal;
font-style: normal;
}
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
background: #fafafa;
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, Sans-serif;
font-size: 12px;
position: relative;
background-color: #fff;
color: #0a0a0a;
line-height: 1.5;
}
b {
font-weight: 600;
}
a {
color: #006FFF;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
h1 {
font-weight: normal;
font-size: 21px;
margin: 0;
padding: 5px 10px;
/* border: 1px solid #884D51; */
background-image: -moz-linear-gradient(center top , #FF7A7A 0%, #FF5C5C 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #FF7A7A), color-stop(100%, #FF5C5C));
border: 1px solid #D94C4C;
color: #fff;
}
h1 a {
color: #fff;
}
h2 a {
color: #0a0a0a;
}
h1 a:hover,
h2 a:hover {
text-decoration: none;
}
h1 a:visited {
color: #fff;
}
h2 a:visited {
color: black;
}
h3 .type {
font-size: smaller;
font-weight: normal;
}
.hidden {
display: none;
}
#toc {
-moz-column-count: 3;
-webkit-column-count: 3;
column-count: 3;
-moz-column-gap: 20px;
margin: 20px 0;
}
#toc a {
display: block;
}
#toc a.sectionToc {
font-size: 14px;
font-weight: bold;
}
#toc a.methodToc {
font-size: 14px;
}
#toc a.methodToc:before {
content: "- ";
}
#toc .tocItem {
margin: 0 0 10px 0;
}
#listing,
#play {
float: left;
width: 50%;
height: 100%;
padding: 10px;
overflow-y: auto;
overflow-x: hidden;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
#play {
overflow-x: auto;
background-color: #f2f2f2;
border-left: 1px solid #ccc;
}
#playInstructions {
font-weight: normal;
}
.method {
position: relative;
border-top: 1px solid #C6ADFF;
margin: 20px 0;
}
.method .try {
font-size: 14px;
font-weight: normal;
padding: 5px 0px;
position: absolute;
right: 0;
top: 0;
-moz-border-radius: 0 40px 40px 0;
-webkit-border-radius: 0 40px 40px 0;
border-radius: 0 40px 40px 0;
}
.method h2 {
font-weight: normal;
font-size: 14px;
margin: 0;
padding: 5px 10px;
/* border: 1px solid #884D51; */
background-image: -moz-linear-gradient(center top , #EDE6FF 0%, #DAC9FF 100%);
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #EDE6FF), color-stop(100%, #DAC9FF));
border: 1px solid #C6ADFF;
border-top: none;
-moz-border-radius: 0 0 10px 10px;
-webkit-border-radius: 0 0 10px 10px;
border-radius: 0 0 10px 10px;
display: table;
}
.method .section {
margin-left: 40px;
}
.method .section h3 {
margin-left: -20px;
margin-bottom: 0px;
}
.method .section > ul {
padding-left: 20px;
margin: 5px 0;
}
.method .section p {
margin: 5px 0;
}
.method .required {
color: red;
}
.apiCall {
padding: 10px ;
position: relative;
border-bottom: 1px solid #ccc;
}
.apiCall:nth-child(odd) {
background-color: #e6e6e6;
}
.apiCallClose {
position: absolute;
top: 10px;
right: 0px;
font-weight: bold;
color: #0a0a0a;
border: 0;
font-family: "helvetica neue", helvetica, arial, sans-serif;
font-size: 14px;
background-color: transparent;
}
.apiCall .apiUrlExpand {
position: absolute;
top: 15px;
right: 60px;
}
.apiCall h3 {
margin: 0;
}
.apiCall h4 {
margin: 10px 0 5px 0;
}
.apiCall .editApiUrl {
width: 50%;
margin-top: 4px;
font-weight: bold;
font-size: larger;
}
.apiCall .requestBody {
width: 100%;
min-height: 300px;
}
.apiCall .output {
margin: 10px 0;
}
.apiCall button[name=submit] {
margin: 10px 0;
}
.jsonResult .expander {
margin: 0;
padding: 0;
border: 0;
font-size: xx-small;
background-color: transparent;
cursor: pointer;
}
.jsonResult ol.array,
.jsonResult ul.object {
list-style: none;
}
.jsonResult .prop,
.jsonResult .brace,
.jsonResult .bracket {
font-weight: bold;
}
/* START hbox/vbox normalization from http://alex.dojotoolkit.org/2009/08/css-3-progress/ */
/* hbox and vbox classes */
.hbox {
display: -webkit-box;
-webkit-box-orient: horizontal;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: horizontal;
-moz-box-align: stretch;
display: box;
box-orient: horizontal;
box-align: stretch;
}
.hbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.vbox {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-align: stretch;
display: -moz-box;
-moz-box-orient: vertical;
-moz-box-align: stretch;
display: box;
box-orient: vertical;
box-align: stretch;
}
.vbox > * {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
display: block;
}
.spacer {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.reverse {
-webkit-box-direction: reverse;
-moz-box-direction: reverse;
box-direction: reverse;
}
.boxFlex0 {
-webkit-box-flex: 0;
-moz-box-flex: 0;
box-flex: 0;
}
.boxFlex1, .boxFlex {
-webkit-box-flex: 1;
-moz-box-flex: 1;
box-flex: 1;
}
.boxFlex2 {
-webkit-box-flex: 2;
-moz-box-flex: 2;
box-flex: 2;
}
.boxGroup1 {
-webkit-box-flex-group: 1;
-moz-box-flex-group: 1;
box-flex-group: 1;
}
.boxGroup2 {
-webkit-box-flex-group: 2;
-moz-box-flex-group: 2;
box-flex-group: 2;
}
.start {
-webkit-box-pack: start;
-moz-box-pack: start;
box-pack: start;
}
.end {
-webkit-box-pack: end;
-moz-box-pack: end;
box-pack: end;
}
.center {
-webkit-box-pack: center;
-moz-box-pack: center;
box-pack: center;
}
/* END hbox/vbox normalization from http://alex.dojotoolkit.org/2009/08/css-3-progress/ */

240
web/0.3.4/rdapi/index.html Normal file
Просмотреть файл

@ -0,0 +1,240 @@
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is Raindrop.
-
- The Initial Developer of the Original Code is
- Mozilla Messaging, Inc..
- Portions created by the Initial Developer are Copyright (C) 2009
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- -->
<!DOCTYPE html>
<html>
<head>
<title>Raindrop API</title>
<link type="text/css" rel="stylesheet" href="/0.3.4/rdapi/index.css">
<script src="/0.3.4/scripts/requireplugins-jquery.js" charset="utf-8"></script>
<script>
'use strict';
/*global require: false */
require({
paths: {
'index': '/0.3.4/rdapi/scripts/index',
}
},
['index']
);
</script>
</head>
<body>
<div id="listing">
<div class="header">
<h1 id="topHeading">Raindrop API</h1>
<p>This is the Raindrop API explorer. Read the important <a href="#Notes">Notes</a> first.</p>
</div>
<div id="toc">
</div>
<div id="content">
<div class="sectionContent">
<!-- The name attribute for Notes is added after we fill in the content,
otherwise Firefox has a weird box calculation problem. -->
<h1 class="section"><a id="NotesTitle" href="#Notes">Notes</a></h1>
<p><a href="http://en.wikipedia.org/wiki/JSON">JSON</a> is used for all API responses.
The request arguments are normally <a href="http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1">form-urlencoded</a>
arguments (<b>Content-Type: application/x-www-form-urlencoded; charset=UTF-8</b>), except
for APIs that only accept a request body. In those cases, the request body should be JSON,
and the Content-Type for the request should be <b>application/json; charset=UTF-8</b>. Note that UTF-8
should be used as the charset.</p>
<div class="method">
<h2><a id="StandardResponseTitle" href="#StandardResponse">Notes: Standard Response</a></h2>
<p>The success version of the Standard Response is used by a few APIs for success responses. Other APIs use
a specific success object that relates to the API. See the specific API call for more information.</p>
<p>The error version of the Standard Response is used by <b>all APIs</b> to indicate error responses.</p>
<p>A <b>success response</b> will be an object with the following properties (only used by some APIs):</p>
<ul>
<li><b>ids</b> (array): Any IDs affected by the API call. May be empty</li>
<li><b>result</b> (boolean): Value of true</li>
<li><b>error</b> (object): null</li>
</ul>
<p>An <b>error response</b> will be an object with the following properties (this is the error response
returned from all APIs):</p>
<ul>
<li><b>ids</b> (array): Any IDs affected by the API call. May be empty</li>
<li><b>result</b> (object): null if the API call has an error</li>
<li><b>error</b> (object): An object with the following properties:
<ul>
<li><b>name</b> (string): an error type name</li>
<li><b>message</b> (string): An English description of the error</li>
</ul>
</li>
</ul>
</div>
<div class="method">
<h2><a id="ConversationTitle" href="#Conversation">Notes: Conversation Object</a></h2>
<p class="required">TODO</p>
</div>
<div class="method">
<h2><a id="MessageTitle" href="#Message">Notes: Message Object</a></h2>
<p class="required">TODO</p>
</div>
<div class="method">
<h2><a id="AttachmentTitle" href="#Attachment">Notes: Attachment Object</a></h2>
<p class="required">TODO</p>
</div>
</div>
</div>
</div>
<div id="play">
<p id="playInstructions">Use a "Try It" link to try an API in this area.</p>
</div>
<form class="apiCall" action="#">
<h3 class="apiUrl"></h3>
<select class="apiUrlExpand hidden">
<option value=''>Change URL</option>
<ul class="apiUrlChoices hidden">
</ul>
</select>
<div class="parameterUrl hidden">
<h4>URL Parameters</h4>
<table>
<tbody class="urlParams"></tbody>
</table>
</div>
<div class="request">
<h4>Request Parameters</h4>
<table>
<tbody class="requestParams"></tbody>
</table>
</div>
<div class="body">
<h4>Request Body</h4>
<textarea class="requestBody"></textarea>
</div>
<button name="submit">Submit</button>
<button class="apiCallClose">close</button>
<div class="output"></div>
</form>
<div class="methodContent template" id="methodContent">
<p>{^doc}</p>
{is(routes.length) [}
<div class="section">
<h3>URL</h3>
<ul>
{routes [}
<li>{}</li>
{]}
</ul>
</div>
{]}
{and(urlargs, urlargs.length) [}
<div class="section">
<h3>URL Arguments</h3>
<ul>
{urlargs[}
<li><b class="{required [}required{]}">{name}</b> ({type}): {doc}</li>
{]}
</ul>
</div>
{]}
{and(queryargs, queryargs.length) [}
<div class="section">
<h3>Parameters</h3>
<ul>
{queryargs[}
<li><b class="{required [}required{]}">{name}</b> ({type}): {doc}</li>
{]}
</ul>
</div>
{]}
{is(body) [}
<div class="section">
{body [}
<h3>Request Body <span class="type">({type})</span></h3>
<p>{doc}</p>
{]}
{examplebody [}
<b>Example</b>:
<pre class="sampleBodyPre">{prettyJson(_)}</pre>
{]}
</div>
{]}
{response [}
<div class="section">
<h3>Response <span class="type">({type})</span></h3>
<p>{^addApiHyperlinks(doc)}</p>
</div>
{]}
</div>
<div class="tocItem template" id="sectionToc">
<a class="sectionToc" href="#{section}">{section}</a>
{methods [}
<a class="methodToc" href="#{link}">{name}</a>
{]}
</div>
<div class="sectionContent template" id="sectionContent">
<h1 class="section"><a href="#{section}" name="{section}">{section}</a></h1>
<p>{^doc}</p>
{methods [}
<div class="method">
<a class="try" href="#try:{link}">Try It!</a>
<h2><a href="#{link}" name="{link}">{section}: {name}</a></h2>
{^content}
</div>
{]}
</div>
<div class="jsonResult template" id="jsonResult">
{#jsonBranch}
</div>
<script class="template" id="jsonBranch" type="text/template">
{. _rdApiType getType(_)}
{eq(_rdApiType, 'object') [}
<span class="brace">&#123;</span> <button class="expander">&#9660;</button> <ul class="object">
{eachProp(_) [}
<li><span class="prop">{prop}</span> : {#jsonBranch value}</li>
{]}
</ul> <span class="brace">&#125;</span>
{] eq(_rdApiType, 'array') [}
<span class="bracket">[</span> <button class="expander">&#9660;</button> <ol class="array">
{_ [}
<li>{#jsonBranch}</li>
{]}
</ol> <span class="bracket">]</span>
{] [}
<span class="value">{formatSimpleType(_)}</span>
{]}
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,504 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
'use strict';
/*jslint plusplus: false, regexp: false */
/*global require: false, define: false, location: true, setTimeout: false,
alert: false, window: false, document: false */
define([ 'jquery', 'rdapi', 'blade/object', 'blade/jig'],
function ($, rdapi, object, jig) {
var docs, urlSection, toc = [],
urlParamRegExp = /\{([^\}]+)\}/g,
fragLinkRegExp = /#StandardResponse|#Attachment|#Message|#Conversation/g,
apiLinks = {
'#StandardResponse': 'Standard Response',
'#Attachment': 'Attachment',
'#Message': 'Message',
'#Conversation': 'Conversation'
};
//Add a pretty JSON method for use in templates
jig.addFn({
prettyJson: function (text) {
return JSON.stringify(JSON.parse(text), null, " ");
},
addApiHyperlinks: function (text) {
var output = '', startIndex = 0, match;
fragLinkRegExp.lastIndex = 0;
while ((match = fragLinkRegExp.exec(text))) {
match = match[0];
output += jig.htmlEscape(text.substring(startIndex, fragLinkRegExp.lastIndex - match.length));
output += '<a href="' + match + '">' + apiLinks[match] + '</a>';
startIndex = fragLinkRegExp.lastIndex;
}
if (startIndex < text.length - 1) {
output += jig.htmlEscape(text.substring(startIndex, text.length));
}
return output;
},
getType: function (it) {
if (require.isArray(it)) {
return 'array';
} else if (typeof it === "object" && it !== undefined && it !== null) {
return 'object';
} else {
return 'other';
}
},
formatSimpleType: function (it) {
if (it === null) {
return 'null';
} else if (it === 0) {
return '0';
} else if (it === undefined) {
return 'undefined';
} else if (it === true) {
return 'true';
} else if (it === false) {
return 'false';
} else {
return it;
}
}
});
//Array sorting method for method entries. Separated as a distinct
//function to make JSLint happy.
function methodSort(a, b) {
return a.name > b.name ? 1 : -1;
}
function hashUpdated() {
//Hmm, an overflow div does not jump if the hash is changed, as in
//a back/forward button press, so force it.
var hash = location.href.split('#')[1] || '',
listingNode = $('#listing')[0],
targetNode;
if (hash) {
targetNode = $('[name="' + hash + '"]')[0];
if (!targetNode) {
if (hash.indexOf('%') !== -1) {
//Try unescaping the URL.
hash = decodeURIComponent(hash);
targetNode = $('[name="' + hash + '"]')[0];
} else {
//Try escaping it
hash = encodeURIComponent(hash);
targetNode = $('[name="' + hash + '"]')[0];
}
}
}
setTimeout(function () {
if (targetNode) {
listingNode.scrollTop = listingNode.scrollTop + targetNode.getBoundingClientRect().top;
} else {
listingNode.scrollTop = 0;
}
}, 15);
}
function updateApiUrl(form, url) {
var apiUrl = form.find('.apiUrl'),
parameterUrl = form.find('.parameterUrl'),
match, urlParam, urlParams = '', urlParamObj;
//Show the API URL
apiUrl.html(url).removeClass('hidden');
parameterUrl.addClass('hidden');
//If the URL has arguments in its path, show options for it.
if (url.indexOf('{') !== -1) {
//Put in the parameterized URL and attach the source
//URL as a property on the DOM node for better perf
parameterUrl
.removeClass('hidden')
.find('.editApiUrl')
.remove()
.end()
.prepend('<input type="text" class="editApiUrl" value="' + url + '">')[0]
.apiUrl = url;
//Hide the normal h2 title
apiUrl.addClass('hidden');
//Parse out the fields in play
urlParamRegExp.lastIndex = 0;
while ((match = urlParamRegExp.exec(url))) {
urlParam = match[1];
urlParamObj = form[0].raindropApiMethod.urlargs && form[0].raindropApiMethod.urlargs[urlParam];
urlParams += '<tr><td class="urlParamName">' + urlParam + '</td><td class="urlParamValue">';
if (urlParamObj && urlParamObj.allowed) {
urlParams += '<select class="urlParamSelect" name="' + urlParam + '">' +
'<option value=""></option>';
urlParamObj.allowed.forEach(function (value) {
urlParams += '<option value="' + value + '">' + value + '</option>';
});
urlParams += '</select>';
} else {
urlParams += '<input type="text" class="urlParam" name="' + urlParam + '">';
}
urlParams += '</td></tr>';
}
form.find('.urlParams').html(urlParams);
}
}
//delegated event handler that handles changes to URL arg fields, both input text ones,
//and select elements.
function changeApiUrl(evt) {
//Handle key ups for modifying URL parameters
//Only do an update on a timed delay, so that
//the DOM is not beaten up for each key stroke.
if (!urlSection) {
urlSection = $(evt.target).parents('.parameterUrl');
setTimeout(function () {
var apiUrl = urlSection[0].apiUrl;
urlSection.find('.urlParam, .urlParamSelect').each(function (i, node) {
var value = node.value.trim();
if (value) {
apiUrl = apiUrl.replace('{' + node.name + '}', value);
}
});
//Update the final URL
urlSection.find('.editApiUrl').val(apiUrl);
urlSection = null;
}, 200);
}
}
function getCsrfToken() {
var token = /csrf=([^\; ]+)/.exec(document.cookie);
return token && token[1] ? token[1] : null;
}
rdapi('docs', {
success: function (json) {
var prop, methodName, apiSection, methods, method, tocItem, obj,
i, route, parts, urlParam;
docs = json;
//TOC is by API section and method name, build it up,
//as well as the content that goes for each section.
for (prop in docs) {
if (docs.hasOwnProperty(prop)) {
apiSection = docs[prop];
methods = apiSection.methods;
//Create the TOC item for this API section.
tocItem = {
section: prop,
doc: apiSection.doc.replace(/<h1[^<]*<\/h1>/g, ''),
value: apiSection,
methods: []
};
//Create a method section in the TOC as well as the content
//that shows up in the main document section.
for (methodName in methods) {
if (methods.hasOwnProperty(methodName)) {
method = methods[methodName];
//Create quick lookups for urlargs parameters
if (method.urlargs) {
method.urlargs.forEach(function (arg) {
method.urlargs[arg.name] = arg;
});
}
//Make sure the API routes are prefixed with /api
if (method.routes) {
for (i = 0; (route = method.routes[i]); i++) {
//For any URL methods, if only one valid value,
//then just fix it to that value. Thinking mostly
//of contacts API where @{user} is normally just @me
parts = route.split('/');
parts.forEach(function (part, j) {
urlParamRegExp.lastIndex = 0;
parts[j] = part.replace(urlParamRegExp, function (match, p1) {
if (method.urlargs) {
urlParam = method.urlargs[p1];
if (urlParam && urlParam.allowed && urlParam.allowed.length === 1) {
return urlParam.allowed[0];
}
}
return match;
});
});
route = parts.join('/');
if (route.indexOf('/api') !== 0) {
method.routes[i] = '/api' + route;
}
}
}
obj = object.create(method, [{
name: methodName,
link: encodeURIComponent(prop) + ":" + encodeURIComponent(methodName)
}]);
//Generate the HTML content for this section.
obj.content = jig(jig.cache('methodContent'), obj, {}).replace(/<h1[^<]*<\/h1>/g, '');
tocItem.methods.push(obj);
//Store a shortcut to reference the method by name.
tocItem.methods[methodName] = obj;
}
}
//Sort the methods
tocItem.methods.sort(methodSort);
//Store a shortcut to reference the section by name.
toc[prop] = tocItem;
toc.push(tocItem);
}
}
//Sort the toc contents
toc.sort(function (a, b) {
return a.section > b.section ? 1 : -1;
});
//Wait for page load to fill in the page content
$(function () {
var tocHtml = '',
html = '',
apiCallNode = $('.apiCall')[0],
play = $('#play');
//Remove the apiCall node from the DOM, since just used for clone operations.
apiCallNode.parentNode.removeChild(apiCallNode);
toc.forEach(function (tocItem) {
//Create TOC entry
tocHtml += jig(jig.cache('sectionToc'), tocItem, {});
//Create content entry
html += jig(jig.cache('sectionContent'), tocItem, {});
});
$("#toc").append(tocHtml);
$("#content").append(html);
//Add the name attributes to static sections here instead of the HTML
//to avoid a weird box sizing issue in Firefox.
['Notes', 'Conversation', 'Message', 'Attachment'].forEach(function (name) {
document.getElementById(name + 'Title').setAttribute('name', name);
});
//If have a location hash, then navigate to it now, since the links for
//all TOC values have been inserted.
hashUpdated();
window.addEventListener('hashchange', hashUpdated, false);
$('body')
//Handle the Try links
.delegate('.try', 'click', function (evt) {
evt.preventDefault();
//Get the API container
var form = $(apiCallNode.cloneNode(true)).appendTo('#play'),
params = '',
linkParts = evt.target.href.split("#")[1].split(':'),
method = toc[linkParts[1]].methods[decodeURIComponent(linkParts[2])],
routes = method.routes,
apiUrl = routes && routes[0] || '',
routeChoices = '';
//Put the API data structure on the form, for ease of referencing later.
form[0].raindropApiMethod = method;
//If more than one route, give a choice
if (routes && routes.length > 1) {
routes.forEach(function (route) {
routeChoices += '<option value="' + route + '" class="apiUrlChoice">' + route + '</option>';
});
form.find('.apiUrlExpand')
.removeClass('hidden')
.append(routeChoices);
}
updateApiUrl(form, apiUrl);
//Request options
if (!method.queryargs || !method.queryargs.length) {
form.find('.request').addClass('hidden');
} else {
method.queryargs.forEach(function (arg) {
params += '<tr><td class="paramName">' + arg.name + '</td><td class="paramValue">';
if (arg.allowed) {
params += '<select name="' + arg.name + '">' +
'<option value=""></option>';
arg.allowed.forEach(function (value) {
params += '<option value="' + value + '">' + value + '</option>';
});
params += '</select>';
} else {
params += '<input type="text" name="' + arg.name + '">';
}
params += '</td></tr>';
});
form.find('.requestParams').html(params);
}
//Request Body
if (!method.body) {
form.find('.body').addClass('hidden');
} else {
if (method.examplebody) {
form.find('.requestBody').val(method.examplebody);
}
}
//Make sure the new form is visible.
play[0].scrollTop = play[0].scrollHeight;
})
.delegate('.apiUrlExpand', 'change', function (evt) {
//Update the API URL choice.
var item = $(evt.target),
url = item.val(),
form = item.parents('form').first();
if (url) {
updateApiUrl(form, url);
}
})
.delegate('.urlParam', 'keyup', changeApiUrl)
.delegate('.urlParamSelect', 'change', changeApiUrl)
//Handle play form submissions.
.delegate('.apiCall', 'submit', function (evt) {
var form = $(evt.target),
method = form[0].raindropApiMethod,
inputs = form.find('.requestParams input, .requestParams select'),
url = form.find('.apiUrl').html(),
editableUrl = form.find('.editApiUrl'),
requestBody = form.find('.requestBody').val().trim(),
data = {},
options, csrfToken;
evt.preventDefault();
//If there was a parameterized URL, favor that
if (!form.find('.parameterUrl').hasClass('hidden') && editableUrl.length) {
url = editableUrl.val().trim();
if (url.indexOf('{') !== -1) {
alert('Please edit URL parameters to make a valid URL');
return;
}
}
//Put together the request attributes.
inputs.each(function (i, node) {
var value = $(node).val();
if (value) {
data[node.name] = value;
}
});
//If a request body, then favor that for the data
if (method.body && requestBody) {
if (inputs.length) {
//Already have some data, need to clear
//it out, add it to the URL as query args
//to the URL. This is actually a bit goofy,
//should just have all query args or all
//body args. prefs/set is one API that goes here.
url += (url.indexOf('?') === -1 ? '?' : '&') +
$.param(data);
}
data = requestBody;
}
options = {
type: 'POST',
url: url,
data: data,
processData: !method.body,
contentType: (method.body ?
'application/json; charset=UTF-8' :
'application/x-www-form-urlencoded; charset=UTF-8'),
success: function (data, textStatus, xhr) {
form.find('.output').html(jig.render(jig.cache('jsonResult'), data));
},
error: function (xhr, textStatus, errorThrown) {
form.find('.output').html(jig.render(jig.cache('jsonResult'), {
ERROR: xhr.responseText
}));
}
};
csrfToken = getCsrfToken();
if (csrfToken) {
options.beforeSend = function (xhr) {
xhr.setRequestHeader('X-CSRF', csrfToken);
};
}
//Construct the data call.
$.ajax(options);
})
//Handle close action for an API Call form
.delegate('form .apiCallClose', 'click', function (evt) {
evt.preventDefault();
$(evt.target).parents('form').remove();
})
//Handle expanding and closing of sections in the JSON response
//for API calls
.delegate('.expander', 'click', function (evt) {
var button = $(evt.target),
listNode = button.next('ul,ol')[0];
if (button.hasClass('closed')) {
listNode.style.display = '';
button.removeClass('closed');
button.html('&#9660;');
} else {
listNode.style.display = 'none';
button.addClass('closed');
button.html('&#9658;');
}
return false;
});
});
},
error: function (xhr, textStatus, errorThrown) {
$('#content').html(jig.htmlEscape(xhr.responseText));
}
});
});

2
web/0.3.4/robots.txt Normal file
Просмотреть файл

@ -0,0 +1,2 @@
User-agent: *
Disallow: /api

Просмотреть файл

@ -0,0 +1,241 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
/*jslint plusplus: false, indent: 2 */
/*global require: false, define: false, window: false, setTimeout: false */
"use strict";
define([ 'jquery', 'blade/object', 'blade/fn', 'module', 'dispatch',
'text!AutoCompleteRefresh.html'],
function ($, object, fn, module, dispatch,
refreshHtml) {
function split(val) {
return val.split(/,\s*/);
}
function extractLast(term) {
return split(term).pop();
}
return object(null, null, {
className: module.id.replace('/', '-'),
refreshShowing: false,
askRefresh: true,
init: function (node, contactService) {
this.dom = $(node);
this.attachedWidget = false;
this.acOptions = [];
// Listen for changes to the contacts.
contactService.notify(fn.bind(this, this.attachAutoComplete));
this.contactService = contactService;
dispatch.sub('optionsChanged', fn.bind(this, function (data) {
// allow refetching contacts when a new page is shared.
this.askRefresh = true;
}));
},
/**
* Updates the formatted autocomplete options and binds the
* autocomplete widget, but only on the first call.
*/
attachAutoComplete: function (contactService, contactList) {
contactList = contactList || [];
this.acOptions = [];
// Update the acOptions with formatted contact values.
contactList.forEach(fn.bind(this, function (contact) {
this.acOptions.push(contactService.formatContact(contact));
}));
if (!this.attachedWidget) {
this.attachedWidget = true;
// jQuery UI autocomplete setup from the jQuery UI demo page
this.dom
// don't navigate away from the field on tab when selecting an item,
// or when tabbing to the refresh contacts button.
.bind("keydown", fn.bind(this, function (event) {
if (event.keyCode === $.ui.keyCode.ENTER) {
// Do not submit the form on enter in the autocomplete field.
event.preventDefault();
} else if (event.keyCode === $.ui.keyCode.TAB) {
if (this.dom.data("autocomplete").menu.active) {
//autocomplete is up.
event.preventDefault();
this.dom.autocomplete().select();
} else if (this.open) {
// select the first item in the autocomplete.
var item = this.dom.autocomplete('widget').find('li');
this.dom.data("autocomplete").menu.active = item;
this.dom.autocomplete().select();
event.preventDefault();
}
// close out the refresh UI immediately so user can see the
// rest of the input form.
if (this.refreshShowing) {
this.hideRefresh();
}
} else if (event.keyCode === $.ui.keyCode.DOWN && this.refreshShowing) {
// refresh contacts showing so focus on the refresh button.
event.preventDefault();
this.focusingOnRefresh = true;
this.refreshDom.find('button').focus();
} else if (event.keyCode === $.ui.keyCode.ESCAPE && this.refreshShowing) {
this.askRefresh = false;
this.hideRefresh();
}
}))
.bind('blur', fn.bind(this, function (event) {
// be sure to close down the refresh UI if open, but do it
// on a timeout to allow button clicks in the UI. A bit hacky
// since it is a timing related thing.
if (this.refreshShowing && !this.focusingOnRefresh) {
setTimeout(fn.bind(this, function () {
this.hideRefresh();
this.focusingOnRefresh = false;
}), 500);
}
}))
.autocomplete({
minLength: 0,
source: fn.bind(this, function (request, response) {
// delegate back to autocomplete, but extract the last term
this.filtered = $.ui.autocomplete.filter(this.acOptions, extractLast(request.term));
// give the user the option to refresh the contacts
// if no matches.
if (!this.filtered.length && this.askRefresh) {
setTimeout(fn.bind(this, this.showRefresh), 0);
} else if (this.refreshShowing) {
this.hideRefresh();
}
response(this.filtered);
}),
focus: function () {
// prevent value inserted on focus
return false;
},
select: function (event, ui) {
var terms = split(this.value);
// remove the current input
terms.pop();
// add the selected item
terms.push(ui.item.value);
// add placeholder to get the comma-and-space at the end
terms.push("");
this.value = terms.join(", ");
return false;
},
open: fn.bind(this, function (event, ui) {
// Set the width of the autocomplete once shown.
if (!this.relatedWidth) {
this.determineRelatedWidth();
}
this.open = true;
this.dom.autocomplete('widget').width(this.relatedWidth);
}),
close: fn.bind(this, function (event, ui) {
this.open = false;
})
});
}
// account for a previous search waiting on a refresh.
if (this.waitingSearch) {
this.dom.autocomplete('search', this.waitingSearch);
this.dom.focus();
delete this.waitingSearch;
this.hideSpinner();
}
},
determineRelatedWidth: function () {
// Make sure to set the size of the autocomplete to not be bigger
// than the input area it is bound to.
var widthNode = this.dom[0];
while (widthNode && (this.relatedWidth = widthNode.getBoundingClientRect().width) <= 0) {
widthNode = widthNode.parentNode;
}
},
hideRefresh: function () {
this.refreshDom.hide();
},
/**
* Shows UI to allow refreshing the contacts list.
*/
showRefresh: function () {
if (!this.relatedWidth) {
this.determineRelatedWidth();
}
if (!this.refreshDom) {
this.refreshDom = $(refreshHtml)
.css({
width: this.relatedWidth + 'px'
})
.insertAfter(this.dom[0])
.find('button')
.bind('click', fn.bind(this, function (evt) {
evt.preventDefault();
this.waitingSearch = this.dom.val().trim();
this.showSpinner();
this.askRefresh = false;
this.contactService.fetch();
this.hideRefresh();
}))
.bind('blur', fn.bind(this, function (evt) {
this.hideRefresh();
}))
.end();
}
this.refreshDom.show();
this.refreshShowing = true;
},
hideSpinner: function () {
this.spinnerDom.hide();
},
showSpinner: function () {
if (!this.spinnerDom) {
this.spinnerDom = $('<div class="AutoCompleteSpinner"></div>')
.appendTo(this.dom[0].parentNode);
}
this.spinnerDom.show();
}
});
});

Просмотреть файл

@ -0,0 +1 @@
<div class="AutoCompleteRefresh">No matches. <button tabindex="-1" class="refresh">Refresh Contacts</button></div>

Просмотреть файл

@ -0,0 +1,243 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
/*jslint plusplus: false, indent: 2 */
/*global require: false, define: false, window: false */
"use strict";
define([ 'jquery', 'blade/object', 'blade/fn', 'dispatch', 'rdapi', 'accounts'],
function ($, object, fn, dispatch, rdapi, accounts) {
var Contacts;
Contacts = object(null, null, {
init: function (svc, svcAccount) {
this.svc = svc;
this.svcAccount = svcAccount;
this.callbacks = [];
this.lastUpdated = this.fromStore().lastUpdated;
// Time check is one day.
this.timeCheck = 24 * 60 * 60 * 1000;
// listen for changes in the options, and if a greater than a day,
// refresh the contacts.
this.optionsChangeSub = dispatch.sub('optionsChanged', fn.bind(this, function (options) {
if (this.needFetch()) {
this.fetch();
}
}));
},
/**
* Destroys this instance, not necessarily the data. For that, use
* clear().
* Used as an opportunity to unbind event listeners.
*/
destroy: function () {
dispatch.unsub('optionsChanged', this.optionsChangeSub);
},
clear: function () {
var acct = this.svcAccount;
accounts.setData(acct.domain, acct.userid, acct.username, 'contacts');
},
needFetch: function () {
return !this.lastUpdated || (new Date()).getTime() - this.lastUpdated > this.timeCheck;
},
/**
* Retrieves stored contacts. Should only be used internally or by subclasses.
*/
fromStore: function () {
var acct = this.svcAccount;
return accounts.getData(acct.domain, acct.userid, acct.username, 'contacts') || {};
},
/**
* Saves contacts to storage. Should only be used internally or by
* subclasses.
*
* @param {Object} data an object with a "list" property which is this
* list of contacts to store.
*/
toStore: function (data) {
var acct = this.svcAccount;
if (!data.lastUpdated) {
data.lastUpdated = this.lastUpdated;
}
accounts.setData(acct.domain, acct.userid, acct.username, 'contacts', data);
this.notifyCallbacks();
return data;
},
/**
* Includes any new names from a successful share into the autocomplete.
* By default, it does nothing, but subclasses may do something with it.
* @param {String} contactsText a comma-separated string of contacts that
* follow the format returned from findContact().
*/
incorporate: function (contactsText) {
},
/**
* Notify about changes to the autocomplete list. Can be async, so callback is needed.
* @param {Function} callback called when contacts are available.
* It will receive an array of contacts.
*/
notify: function (callback) {
this.callbacks.push(callback);
this.contacts = this.fromStore().list;
if (!this.contacts || this.needFetch()) {
this.fetch();
} else {
this.notifyCallbacks();
}
},
fetch: function () {
var acct = this.svcAccount,
svcData = accounts.getService(acct.domain, acct.userid, acct.username);
rdapi('contacts/' + acct.domain, {
type: 'POST',
data: {
username: acct.username,
userid: acct.userid,
startindex: 0,
maxresults: 500,
account: JSON.stringify(svcData)
},
//Only wait for 10 seconds, then give up.
timeout: 10000,
success: fn.bind(this, function (json) {
//Transform data to a form usable by the front end.
if (json && !json.error) {
var entries = json.result.entry;
this.contacts = this.getFormattedContacts(entries);
this.lastUpdated = (new Date()).getTime();
this.toStore({
list: this.contacts
});
}
}),
error: fn.bind(this, function (xhr, textStatus, errorThrown) {
// does not matter what the error is, just eat it and hide
// the UI showing a wait.
this.notifyCallbacks();
})
});
},
notifyCallbacks: function () {
this.callbacks.forEach(fn.bind(this, function (callback) {
callback(this, this.contacts);
}));
},
findContact: function (to) {
var contactId = to;
(this.contacts || []).some(function (contact) {
if (contact.displayName === to) {
contactId = contact.email || contact.userid || contact.username;
return true;
}
return false;
});
return contactId;
},
/**
* Translates contact data from server into a format used on the client.
* @param {Array} entries
* @returns {Array}
*/
getFormattedContacts: function (entries) {
var data = [];
entries.forEach(function (entry) {
if (entry.accounts && entry.accounts.length) {
entry.accounts.forEach(function (account) {
data.push({
displayName: entry.displayName,
email: '',
userid: account.userid,
username: account.username
});
});
}
});
return data;
},
/**
* Converts a string that was created by formatContact to real IDs
* understood by the back-end API calls.
*
* @param {String} toText a comma-separated list of contacts.
* @returns {String} a comma-separated list of ID-based contacts.
*/
convert: function (toText) {
var newrecip = [],
result = '',
recip;
if (this.contacts) {
recip = toText.split(',');
recip.forEach(fn.bind(this, function (to) {
var contactId = this.findContact(to.trim());
if (contactId) {
newrecip.push(contactId);
}
}));
}
if (newrecip.length > 0) {
result = newrecip.join(', ');
}
return result;
},
/**
* Formats the contact for display, such as for use in an autocomplete.
* Overridden by Contact overlays.
*/
formatContact: function (contact) {
return contact.displayName;
}
});
Contacts.modelVersion = '3';
return Contacts;
});

Просмотреть файл

@ -0,0 +1,133 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
/*jslint indent: 2, regexp: false */
/*global define: false */
"use strict";
define([ 'blade/object', 'Contacts', 'jquery', 'accounts', 'blade/fn'],
function (object, Contacts, $, accounts, fn) {
var bracketRegExp = /<([^>])+>/;
/**
* Overrides the formatting of contacts and converting
* one of those formatted contacts into a user ID.
*/
return object(Contacts, null, function (parent) {
return {
formatContact: function (contact) {
var value = contact.displayName;
if (contact.email !== value) {
value += ' <' + contact.email + '>';
}
return value;
},
findContact: function (to) {
return to;
},
/**
* Determines if a to string is already in the contacts array.
* @param {String} to a plain email address (no name).
* @returns {Boolean}
*/
contains: function (to) {
return this.contacts.some(function (contact) {
return contact.email === to;
});
},
incorporate: function (contactsText) {
var acct = this.svcAccount,
newContacts = [],
storedContacts,
contacts = contactsText.split(',');
contacts.forEach(fn.bind(this, function (contact) {
contact = contact.trim();
var match = bracketRegExp.exec(contact);
contact = (match && match[1]) || contact;
if (!this.contains(contact)) {
newContacts.push({
displayName: contact,
email: contact
});
}
}));
if (newContacts.length) {
// update storage of manually entered contacts.
storedContacts = accounts.getData(acct.domain,
acct.userid,
acct.username,
'enteredContacts') || [];
storedContacts = storedContacts.concat(newContacts);
accounts.setData(acct.domain, acct.userid, acct.username,
'enteredContacts', storedContacts);
// update the master merged list of contacts.
this.contacts = this.contacts.concat(newContacts);
this.toStore({
list: this.contacts
});
}
},
getFormattedContacts: function (entries) {
var data = [],
acct = this.svcAccount,
storedContacts = accounts.getData(acct.domain,
acct.userid,
acct.username,
'enteredContacts');
// convert server data to the right format.
entries.forEach(function (entry) {
if (entry.emails && entry.emails.length) {
entry.emails.forEach(function (email) {
var displayName = entry.displayName ? entry.displayName : email.value;
data.push({
displayName: displayName,
email: email.value
});
});
}
});
// add in any manually saved email addresses.
if (storedContacts) {
data = data.concat(storedContacts);
}
return data;
}
};
});
});

Просмотреть файл

@ -0,0 +1,61 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
/*jslint indent: 2 */
/*global define: false */
"use strict";
define([ 'blade/object', 'Contacts', 'jquery'],
function (object, Contacts, $) {
var idRegExp = /\@(\S+)/;
/**
* Overrides the formatting of contacts and converting
* one of those formatted contacts into a user ID.
*/
return object(Contacts, null, function (parent) {
return {
formatContact: function (contact) {
var value = '@' + contact.username;
return value;
},
findContact: function (to) {
var match = idRegExp.exec(to),
value = '',
name = (match && match[1]) || to;
if (name) {
(this.contacts || []).some(function (contact) {
if (contact.username === name) {
value = contact.userid;
return true;
}
return false;
});
}
return value;
}
};
});
});

Просмотреть файл

@ -0,0 +1,83 @@
@charset "UTF-8";
/* TODO: some of these styles, like text sizing/box sizing and colors/borders
need to be set in the app that includes a Select widget. */
.Select {
position:relative;
display: inline-block;
overflow: hidden;
padding-right: 15px;
z-index: 100;
border: 1px solid #A6AFB6;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15) inset;
height: 24px;
cursor: pointer;
background-color: white;
}
.Select.open {
overflow: visible;
padding-right: 0;
border: 0;
}
.Select ul {
list-style: none;
z-index: 100;
background-color: white;
}
.Select.open ul {
position: absolute;
border: 1px solid gray;
}
.Select li {
display: none;
height: 0;
padding: 0 5px;
white-space: nowrap;
}
.Select li.selected {
display: block;
height: 24px;
line-height: 24px;
}
.Select.open li {
display: block;
height: 24px;
line-height: 24px;
padding-right: 20px;
}
.Select.open li.selected {
/* background-color: grey; */
}
.Select.open li.selected:hover,
.Select.open li:hover {
color:white;
background-color: #535F6D;
}
.Select .triangle {
position: absolute;
right: 0;
top: 0;
width: 18px;
height: 24px;
line-height: 24px;
padding: 0 2px;
z-index: 101;
color: #A6AFB6;
background-color: white;
background-image: url("/share/i/sprite.png");
background-position: center -362px;
background-repeat: no-repeat;
}
.Select.open .triangle {
display: none;
}

Просмотреть файл

@ -0,0 +1,9 @@
<div class="{className}">
<input type="hidden" name="{name}" value="{value}">
<ul>
{options [}
<li data-value="{value}">{name}</li>
{]}
</ul>
<div class="triangle"></div>
</div>

206
web/0.3.4/scripts/Select.js Normal file
Просмотреть файл

@ -0,0 +1,206 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
/*jslint indent: 2, */
/*global define: false, document: false */
"use strict";
define([ 'blade/object', 'blade/Widget', 'blade/array', 'jquery', 'module',
'text!./Select.html', 'text!./Select.css'],
function (object, Widget, array, $, module,
template, css) {
var className = module.id.replace(/\//g, '-'),
style = document.createElement('style'),
openSelect;
//Add the css to that page.
style.type = 'text/css';
//If class name is changed since this is an anonymous module, update the
//CSS classes.
if (className !== 'Select') {
css = css.replace(/\.Select/g, '.' + className);
}
style.textContent = css;
document.getElementsByTagName('head')[0].appendChild(style);
//Set up event handlers.
$(function () {
$('body')
.delegate('.' + className + ' .triangle', 'click', function (evt) {
Widget.closest(module.id, evt, 'onTriangleClick');
evt.preventDefault();
evt.stopPropagation();
})
.delegate('.' + className + ' li', 'click', function (evt) {
Widget.closest(module.id, evt, 'onOptionClick');
evt.preventDefault();
evt.stopPropagation();
});
$(document).bind('click', function (evt) {
if (openSelect) {
openSelect.close();
}
});
});
/**
* Define the widget.
* This widget assumes its member variables include the following
* properties (passed in on create of the widget)
*
* @param {Array} options: the options to show, with each option being
* an object with "name" and "value" properties.
* @param {String} name: the name to use for the form field.
* @param {Number} selectedIndex: the index of the options that should
* be selected.
*/
return object(Widget, null, function (parent) {
return {
moduleId: module.id,
className: className,
template: template,
onCreate: function () {
if (this.value) {
var index, value = this.value;
// Find the matching index for the value.
this.options.some(function (item, i) {
if (item.value === value) {
index = i;
return true;
}
return false;
});
this.selectedIndex = index;
} else {
// No default value, work it out via selectedIndex if available.
this.selectedIndex = this.selectedIndex || 0;
this.value = this.options[this.selectedIndex].value;
}
},
onRender: function () {
this.dom = $(this.node);
//Apply selected style.
$('li', this.node).eq(this.selectedIndex).addClass('selected');
},
destroy: function () {
delete this.dom;
parent(this, "destroy", arguments);
},
/**
* Selects an item based on its index.
*/
selectIndex: function (index) {
return this.val(this.options[index].value);
},
/**
* Get or set the value for the select. Uses the value for the option.
*/
val: function (newValue) {
if (newValue === undefined) {
// Get
return $('li.selected', this.node)[0].getAttribute('data-value');
} else {
// Set the value.
var liNode, ulNode, index;
// Find the li node that corresponds with the value.
array.to.apply(null, $('li', this.dom)).some(function (node, i) {
if (node.getAttribute('data-value') === newValue) {
liNode = node;
index = i;
}
return false;
});
this.selectedIndex = index;
ulNode = liNode.parentNode;
// Find the index.
this.selectedIndex = array.to.apply(null, $('li', ulNode)).indexOf(liNode);
// Make sure the right node has the selected class
$('li', ulNode).removeClass('selected');
$(liNode).addClass('selected');
this.close();
this.dom.trigger('change');
return newValue;
}
},
close: function () {
var liNode = $('li.selected', this.node)[0];
// Put the value in the hidden input
$('input', this.node).val(liNode.getAttribute('data-value'));
// Remove the open class.
this.dom.removeClass('open');
// Remove the artificial width
this.node.style.width = '';
},
open: function () {
if (openSelect) {
openSelect.close();
}
// Since the options will position absolute, give the Select
// width so that surrounding content does not collapse around it.
this.node.style.width = this.node.getBoundingClientRect().width + 'px';
this.dom.addClass('open');
openSelect = this;
},
onTriangleClick: function (evt) {
this.open();
},
onOptionClick: function (evt) {
// Open the options if not already open.
if (!this.dom.hasClass('open')) {
this.open();
return;
}
this.val(evt.target.getAttribute('data-value'));
}
};
});
});

Просмотреть файл

@ -0,0 +1,67 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
/*jslint plusplus: false */
/*global require: false, define: false */
"use strict";
define([ 'jquery', 'blade/object', 'blade/fn'],
function ($, object, fn) {
return object(null, null, {
init: function (node, countNode, limit) {
this.dom = $(node);
this.domPlaceholderText = this.dom[0].getAttribute('placeholder') || '';
this.countDom = $(countNode);
this.limit = limit;
this.dom.bind('keyup', fn.bind(this, 'checkCount'));
this.checkCount();
},
checkCount: function () {
var value = this.dom[0].value,
count;
if (value.trim() === this.domPlaceholderText) {
value = '';
}
count = this.limit - value.length;
if (count < 0) {
this.countDom.addClass("TextCountOver");
} else {
this.countDom.removeClass("TextCountOver");
}
this.countDom.text(count === this.limit ? '' : count);
},
updateLimit: function (limit) {
this.limit = limit;
this.checkCount();
},
isOver: function () {
return this.dom[0].value.length > this.limit;
}
});
});

Просмотреть файл

@ -0,0 +1,404 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Raindrop.
*
* The Initial Developer of the Original Code is
* Mozilla Messaging, Inc..
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* */
/*jslint indent: 2, plusplus: false */
/*global require: false, define: false, window: false, location: true,
localStorage: false, opener: false, setTimeout: false */
'use strict';
define([ 'storage', 'dispatch', 'rdapi', 'services'],
function (storage, dispatch, rdapi, services) {
function isCacheMatch(cache, domain, userid, username) {
return cache.domain === domain &&
((userid && cache.userid === userid) ||
(username && cache.username === username));
}
function fromJson(value) {
if (value) {
value = JSON.parse(value);
}
return value;
}
var store = storage(), impl,
changeTypes = {
//localStorage is the most robust, since the change in localStorage
//can be listened to across windows.
'localStorage': {
accounts: function (ok, error) {
// accounts now simply provides existing accounts retreived during
// the oauth dances
var accountCache = fromJson(store.accountCache) || [],
serviceCache = fromJson(store.serviceCache);
if (!serviceCache) {
// fetch now, let the response call ok
// Set up serviceCache. This should only ever happen
// if the local store is cleared (e.g. first run, cleared cookies)
impl.fetch(ok, error);
return;
}
serviceCache = serviceCache || [];
//Call ok callback with current knowledge. If there is a change in the
//account info, then the fetch will trigger changed event later.
if (ok) {
ok(accountCache, serviceCache);
}
},
update: function (account_data) {
// XXX TODO
// get the account and push it into localstore, don't overwrite, we
// get one account at a time here
// We write into accountCache to have account.fetch continue to work.
// We also write into serviceCache which will be used by api calls
// to send the auth keys
var accountCache = fromJson(store.accountCache) || [],
serviceCache = fromJson(store.serviceCache),
existing = false,
profile, p, a, acct;
// move the profile into accountCache
profile = account_data.profile;
for (p = 0; p < accountCache.length; p++) {
acct = accountCache[p].accounts[0];
if (isCacheMatch(acct, account_data.domain, account_data.userid,
account_data.username)) {
accountCache[p] = profile;
existing = true;
break;
}
}
if (!existing) {
accountCache.push(profile);
}
store.accountCache = JSON.stringify(accountCache);
// we store the entire object in serviceCache, at some point in the
// future we will remove accountCache
if (serviceCache) {
existing = false;
for (a = 0; a < serviceCache.length; a++) {
if (isCacheMatch(serviceCache[a], account_data.domain,
account_data.userid, account_data.username)) {
serviceCache[a] = account_data;
existing = true;
break;
}
}
} else {
serviceCache = [];
}
if (!existing) {
serviceCache.push(account_data);
}
store.serviceCache = JSON.stringify(serviceCache);
impl.changed();
},
// remove this once there is time enough for all users
// to have been migrated over to the new cache.
fetch: function (ok, error) {
rdapi('account/get/full', {
success: function (json) {
if (json.error) {
json = [];
}
store.serviceCache = JSON.stringify(json);
var accountCache = [], svc, p;
for (p = 0; p < json.length; p++) {
accountCache.push(json[p].profile);
// clear the contacts cache
// remove this clearCache call when 3.6 is removed.
svc = services.domains[json[p].domain];
svc.clearCache(store);
}
store.accountCache = JSON.stringify(accountCache);
if (ok) {
ok(accountCache, json);
}
},
error: error || function () {}
});
},
remove: function (domain, userid, username) {
var accountCache = fromJson(store.accountCache),
serviceCache = fromJson(store.serviceCache),
i, cache, a, p, s, svc;
if (serviceCache) {
for (i = 0; (cache = serviceCache[i]); i++) {
if (isCacheMatch(cache, domain, userid, username)) {
serviceCache.splice(i, 1);
break;
}
}
store.serviceCache = JSON.stringify(serviceCache);
}
// eventually we will deprecate accountCache
if (accountCache) {
for (p = 0; p < accountCache.length; p++) {
s = accountCache[p].accounts;
for (a = 0; a < s.length; a++) {
if (isCacheMatch(s[a], domain, userid, username)) {
accountCache.splice(p, 1);
break;
}
}
}
store.accountCache = JSON.stringify(accountCache);
}
// clear the contacts cache
svc = services.domains[domain];
// remove this clearCache call when 3.6 is removed.
svc.clearCache(store);
// Delete auxillary data.
impl.clearData(domain, userid, username);
impl.changed();
},
/**
* Set auxillary data related to an account. Deleted when the account
* is deleted.
*/
setData: function (domain, userid, username, name, value) {
var key = [domain, userid, username].join('|') + 'Data',
data = fromJson(store[key]) || {};
if (value === undefined || value === null) {
delete data[name];
} else {
data[name] = value;
}
store[key] = JSON.stringify(data);
return value;
},
/**
* Get auxillary data related to an account.
*/
getData: function (domain, userid, username, name) {
var key = [domain, userid, username].join('|') + 'Data',
data = fromJson(store[key]) || {};
return data ? data[name] : null;
},
/**
* Clears auxillary data related to an account. Deleted when the account
* is deleted.
*/
clearData: function (domain, userid, username) {
var key = [domain, userid, username].join('|') + 'Data';
delete store[key];
},
getService: function (domain, userid, username) {
var serviceCache = fromJson(store.serviceCache),
i, cache;
if (serviceCache) {
for (i = 0; (cache = serviceCache[i]); i++) {
if (isCacheMatch(cache, domain, userid, username)) {
return cache;
}
}
}
return null;
},
changed: function () {
store.accountChanged = (new Date()).getTime();
//Force the onchange events to occur. Sometimes the storage
//events do not fire?
if (opener && !opener.closed) {
dispatch.pub('accountsChanged', null, opener);
}
dispatch.pub('accountsChanged');
},
onChange: function (action) {
//Listen to storage changes, and if a the accountChanged key
//changes, refresh.
var lastValue = store.accountChanged;
window.addEventListener('storage', function (evt) {
//Only refresh if the accounts were changed.
if (store.accountChanged !== lastValue) {
action();
}
}, false);
//Also use direct notification in case storage events fail.
dispatch.sub('accountsChanged', action);
}
},
//Some extensions mess with localStorage, so in that case, fall back to
//using dispatching.
'memory': {
accounts: function (ok, error) {
},
changed: function () {
//Use dispatching. Dispatch to current window, but also to an opener
//if available.
store.accountChanged = (new Date()).getTime();
if (opener) {
dispatch.pub('accountsChanged', null, opener);
}
dispatch.pub('accountsChanged');
},
onChange: function (action) {
dispatch.sub('accountsChanged', action);
}
}
};
impl = changeTypes[storage.type];
/**
* Gets the accounts. Can use a cached value.
* @param {Function} ok function to receive the account info.
* @param {Function} error function to call if an error.
*/
function accounts(ok, error) {
return impl.accounts(ok, error);
}
/**
* Updates the accounts from a json account object.
* @param {Object} cookie object to update from
*/
accounts.update = function (account_data) {
impl.update(account_data);
};
/**
* Remove an accounts from storage.
* @param {string} domain
* @param {string} userid
* @param {string} username
*/
accounts.remove = function (account, userid, username) {
impl.remove(account, userid, username);
};
/**
* Fetch accounts stored on server.
* DEPRECATED, interim use for auto-adding accounts that
* users have already configured
*/
accounts.fetch = function (ok, error) {
impl.fetch(ok, error);
};
/**
* Get a full service account record
* @param {string} domain
* @param {string} userid
* @param {string} username
*/
accounts.getService = function (account, userid, username) {
return impl.getService(account, userid, username);
};
/**
* Clears the account data. Use this when it is known that the server
* info is no longer valid/expired.
*/
accounts.clear = function () {
delete store.accountCache;
delete store.serviceCache;
};
/**
* Sets auxillary data associated with an account.
* @param {string} domain
* @param {string} userid
* @param {string} username
*/
accounts.setData = function (account, userid, username, name, value) {
return impl.setData(account, userid, username, name, value);
};
/**
* Gets auxillary data associated with an account.
* @param {string} domain
* @param {string} userid
* @param {string} username
*/
accounts.getData = function (account, userid, username, name) {
return impl.getData(account, userid, username, name);
};
/**
* Sets auxillary data associated with an account.
* @param {string} domain
* @param {string} userid
* @param {string} username
*/
accounts.clearData = function (account, userid, username) {
return impl.clearData(account, userid, username);
};
/**
* Called when the cache of accounts has changed.
*/
accounts.changed = function () {
return impl.changed();
};
/**
* Default action is to just reload.
*/
function defaultAction() {
location.reload();
}
/**
* Called to set up the action when accounts change.
* Call it with no args to get the default behavior, page reload.
*/
accounts.onChange = function (action) {
return impl.onChange(action || defaultAction);
};
return accounts;
});

Просмотреть файл

@ -0,0 +1,147 @@
/**
* @license blade/Widget Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* see: http://github.com/jrburke/blade for details
*/
/*jslint plusplus: false, nomen: false */
/*global define: false, document */
'use strict';
/**
* Parts of this taken from Dojo, in particular DOM work related to
* dojo._toDom()
*/
define([ 'require', './object', './jig', 'module'],
function (require, object, jig, module) {
var tempNode,
baseAttrName = 'data-' + module.id.replace(/\//g, '-') + '-' +
(Math.random() + '').replace(/\d\./, ''),
typeAttr = baseAttrName + '-wtype',
idAttr = baseAttrName + '-wid',
idCounter = 0,
registry = {},
Widget = object(null, null, {
template: null,
/**
* Creates a new instance. Should be called by any derived objects.
* data can have some special properties:
* parent: the parent node to
*
*/
init: function (data, relNode, position) {
object.mixin(this, data, true);
//Start widget lifecycle
if (this.onCreate) {
this.onCreate();
}
if (this.template) {
this.node = this.render();
if (this.onRender) {
this.onRender(relNode);
}
}
if (relNode && this.node) {
if (position === 'before') {
relNode.parentNode.insertBefore(this.node, relNode);
} else if (position === 'after') {
relNode.parentNode.insertBefore(this.node, relNode.nextSibling);
} else if (position === 'prepend' && relNode.firstChild) {
relNode.insertBefore(this.node, relNode.firstChild);
} else {
relNode.appendChild(this.node);
}
}
},
render: function (relativeNode) {
var doc, child, renderedNode, id;
if (this.template) {
//Normalize template by trimming whitespace.
this.template = this.template.trim();
doc = relativeNode && relativeNode.ownerDocument || document;
id = 'id' + idCounter++;
//Set up a temp node to hold template
if (!tempNode || tempNode.ownerDocument !== doc) {
tempNode = doc.createElement('div');
}
tempNode.innerHTML = this.templatize();
// one node shortcut => return the node itself
if (tempNode.childNodes.length === 1) {
renderedNode = tempNode.removeChild(tempNode.firstChild);
renderedNode.setAttribute(idAttr, id);
renderedNode.setAttribute(typeAttr, this.moduleId);
} else {
// return multiple nodes as a document fragment
renderedNode = doc.createDocumentFragment();
while ((child = tempNode.firstChild)) {
renderedNode.appendChild(child);
if (child.nodeType === 1) {
child.setAttribute(idAttr, id);
child.setAttribute(typeAttr, this.moduleId);
}
}
}
this._widgetId = id;
registry[id] = this;
}
return renderedNode;
},
templatize: function () {
var text = this.template,
cache = jig.cache(text) || jig.cache(text, text, this.jigOptions);
return jig.render(cache, this, this.jigOptions);
},
/**
* Destroys the widget. Derived objects should call this method
* after they do their destroy work. destroy is a nice time to
* clean up event handlers.
*/
destroy: function () {
if (this.node && this.node.parentNode) {
this.node.parentNode.removeChild(this.node);
}
delete this.node;
delete registry[this._widgetId];
}
});
Widget.closest = function (widgetType, evt, funcName) {
var refNode = evt.target,
widget;
//Walk up the list of nodes until a match with the type is found.
while (refNode) {
if (refNode.getAttribute(typeAttr) === widgetType) {
break;
}
refNode = refNode.parentNode;
}
if (refNode) {
widget = registry[refNode.getAttribute(idAttr)];
if (widget) {
widget[funcName](evt);
}
}
};
Widget.registry = registry;
return Widget;
});

Просмотреть файл

@ -0,0 +1,38 @@
/**
* @license blade/array Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* see: http://github.com/jrburke/blade for details
*/
/*jslint nomen: false, plusplus: false */
/*global define: false */
'use strict';
define([], function () {
var ostring = Object.prototype.toString,
ap = Array.prototype,
aps = ap.slice,
array = {
/**
* Determines if the input a function.
* @param {Object} it whatever you want to test to see if it is a function.
* @returns Boolean
*/
is: function (it) {
return ostring.call(it) === "[object Array]";
},
/**
* Converts an array-like thing into a real array
* @param{ArrayLike} arrayLike something that looks like an array,
* has a length and can access members via indices.
* @returns {Array}
*/
to: function (arrayLike) {
return [].concat(aps.call(arguments, 0));
}
};
return array;
});

Просмотреть файл

@ -0,0 +1,96 @@
/**
* @license blade/defer Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* see: http://github.com/jrburke/blade for details
*/
/*jslint nomen: false, plusplus: false */
/*global define: false */
'use strict';
define(['./fn', './dispatch'], function (fn, bladeDispatch) {
/**
* Creates an object representing a deferred action.
* @param {Function} [onCancel] optional function to call if the deferred
* action is canceled
* @param {Array} otherEventNames an array of event names to also allow
* sending and notifying on this type of deferred action. This allows you
* to express more complex interactions besides something that just indicates
* "ok", "error" or "cancel".
* @returns {Object} object representing the deferred action. It contains
* two properties:
* send: a function to send events. It takes a string name for the event,
* "ok", "error" or "cancel", and a value.
* listener: an object that only exposes an "ok", "error" and "cancel"
* functions that allow listening to those respective events. If otherEventNames
* specified other events, then there are listener registration functions
* for those event names too.
*/
function defer(onCancel, otherEventNames) {
var dfd = {},
sentName, i, evtName,
dispatch = bladeDispatch.make(),
makeCb = function (name) {
return function (obj, f) {
var cb = fn.bind(obj, f);
dispatch.onAfter(name, function (evt) {
return cb(evt.returnValue);
}, true);
return dfd.listener;
};
};
//Set up the cancellation action if desired.
if (onCancel) {
dispatch.onAfter('cancel', function (evt) {
return onCancel();
});
}
dfd.send = function (name, value) {
//Do not allow sending more than one message for the deferred.
if (sentName) {
throw new Error('blade/defer object already sent event: ' + sentName);
}
sentName = name;
dispatch.send({
name: name,
args: [value],
persist: true
});
//If no error handlers on this deferred, be sure to at least
//log it to allow some sort of debugging.
if (name === 'error' &&
(!dispatch._dispatchAfterQ || ! dispatch._dispatchAfterQ.error) &&
defer.onErrorDefault) {
defer.onErrorDefault(value);
}
return dfd;
};
dfd.listener = {
ok: makeCb('ok'),
error: makeCb('error'),
cancel: makeCb('cancel')
};
//Allow wiring up other event names
if (otherEventNames) {
for (i = 0; (evtName = otherEventNames[i]); i++) {
dfd.listener[evtName] = makeCb[evtName];
}
}
return dfd;
}
defer.onErrorDefault = function (err) {
throw err;
};
return defer;
});

Просмотреть файл

@ -0,0 +1,227 @@
/**
* @license blade/dispatch Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* see: http://github.com/jrburke/blade for details
*/
/*jslint nomen: false, plusplus: false */
/*global define: false */
'use strict';
define(['./object', './fn'], function (object, fn) {
var emptyFunc = function () {},
mainDispatch,
slice = Array.prototype.slice,
needBind = function (f) {
return f !== undefined && (typeof f === 'string' || fn.is(f));
},
register = function (type) {
return function (name, obj, f) {
//Adjust args to allow for a bind call
if (needBind(f)) {
f = fn.bind(obj, f);
} else {
f = obj;
}
var qName = type,
typeQ = this[qName] || (this[qName] = {}),
q = typeQ[name] || (typeQ[name] = []), index;
index = q.push(f) - 1;
q.count = q.count ? q.count + 1 : 1;
//Return an unregister function to allow removing
//a listener. Notice that it can make the q array sparsely
//populated. This should be a sparsely populated array
//to allow a callback to unregister itself without affecting
//other callbacks in the array.
return function () {
q[index] = null;
q.count -= 1;
if (q.count === 0) {
delete typeQ[name];
}
//Clean up closure references for good measure/avoid leaks.
qName = typeQ = q = null;
};
};
},
onAfter = register('_dispatchAfterQ'),
/**
* Defines the dispatch object. You can call its methods for a general
* publish/subscribe mechanism, or mixin its prototype properties
* to another object to give that object dispatch capabilities.
*/
dispatch = {
on: register('_dispatchBeforeQ'),
onAfter: function (name, obj, f, wantValue) {
var doBind = needBind(f), result, value, callback, evt;
//Adjust args if needing a bind
if (doBind) {
callback = f = fn.bind(obj, f);
} else {
wantValue = f;
callback = obj;
}
result = doBind ? onAfter.call(this, name, f, wantValue) : onAfter.call(this, name, obj, f);
if (wantValue) {
//value is the property on the object, unless it is something
//that should be immutable or does not exist, then only get a value from _dispatchPersisted
value = name in this ? this[name] :
(this._dispatchPersisted && name in this._dispatchPersisted ? this._dispatchPersisted[name] : undefined);
evt = {
preventDefault: emptyFunc,
stopPropagation: emptyFunc,
returnValue: value
};
if (value !== undefined) {
callback(evt);
}
}
return result;
},
/**
* Sends an event. An event can have its values modified by "before"
* listeners before the default action happens. A "before" listener
* can also prevent the default action from occurring. "after" listeners
* only get to be notified of the return value from the event.
*
* @param {Object||String} message the message can either be an object
* with the following properties:
* @param {String} message.name the name of the message
* @param {Array} message.args the array of arguments for the message
* @param {Boolean}message.persist the result of the send should be
* remembered, so that any subsequent listeners that listen after
* the result is rememberd can opt to get the last good value.
* @param {Function} [message.defaultAction] a default action to take
* if any of the "before" listeners do not call preventDefault()
* on the event object they receive.
*
* If message is a string, then that is like the "name" property mentioned
* above, and any additional function arguments are treated as the
* args array.
*
* If defaultAction is not passed, then the default action will be to
* either set the property value on this object that matches the name
* to the first arg value, or if the name maps to function property
* on the object, it will call that function with the args.
*
* @returns {Object} the returnValue from any
*/
send: function (message) {
if (typeof message === 'string') {
//Normalize message to object arg form.
message = {
name: message,
args: slice.call(arguments, 1)
};
}
var name = message.name,
beforeQ = this._dispatchBeforeQ && this._dispatchBeforeQ[name],
afterQ = this._dispatchAfterQ && this._dispatchAfterQ[name],
preventDefault = false, stopImmediatePropagation,
evt = {
preventDefault: function () {
preventDefault = true;
},
stopImmediatePropagation: function () {
stopImmediatePropagation = true;
},
args: message.args
},
i, result, value, args, isFunc, persisted;
//Trigger before listeners
if (beforeQ) {
for (i = 0; i < beforeQ.length; i++) {
//array can be sparse because of unregister functions
if (beforeQ[i]) {
beforeQ[i](evt);
if (stopImmediatePropagation) {
break;
}
}
}
}
//If a before handler prevents the default action, exit
//early, using any return value found in the event that may
//have been set by a before handler.
if (preventDefault) {
return evt.returnValue;
}
//Do the default action.
if (message.defaultAction) {
result = message.defaultAction.apply(this, evt.args);
} else {
//Only bother if the property already exists on the object,
//otherwise it is a catch all or just an event router
args = evt.args;
if (name in this) {
isFunc = fn.is(this[name]);
value = this[name];
if (args && args.length) {
//A set operation
result = isFunc ? value.apply(this, args) : this[name] = args[0];
} else {
//A get operation
result = isFunc ? this[name]() : value;
}
} else if (this._dispatchCatchAll) {
//Allow the catch all to get it.
result = this._dispatchCatchAll(name, args);
} else {
result = args && args[0];
}
}
//Trigger mutable after listeners first, before the immutable ones
//to allow the mutable ones to modify the result.
if (afterQ) {
stopImmediatePropagation = false;
evt.returnValue = result;
for (i = 0; i < afterQ.length; i++) {
//array can be sparse because of unregister functions
if (afterQ[i]) {
afterQ[i](evt);
if (stopImmediatePropagation) {
break;
}
}
}
result = evt.returnValue;
}
//Hold on to the result if need be. Useful for the deferred/promise
//cases where listeners can be added after the deferred completes.
if (message.persist) {
persisted = this._dispatchPersisted || (this._dispatchPersisted = {});
persisted[message.name] = result;
}
return result;
}
};
//Create a top level dispatch that can be used for "global" event routing,
//and which can make new dispatch objects that have all the methods above,
//but without the instance variables.
mainDispatch = object.create(dispatch);
mainDispatch.make = function () {
return object.create(dispatch);
};
return mainDispatch;
});

Просмотреть файл

@ -0,0 +1,58 @@
/**
* @license blade/func Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* see: http://github.com/jrburke/blade for details
*/
/*jslint nomen: false, plusplus: false */
/*global define: false */
'use strict';
define([], function () {
var slice = Array.prototype.slice,
ostring = Object.prototype.toString,
fn = {
/**
* Determines if the input a function.
* @param {Object} it whatever you want to test to see if it is a function.
* @returns Boolean
*/
is: function (it) {
return ostring.call(it) === '[object Function]';
},
/**
* Different from Function.prototype.bind in ES5 --
* it has the "this" argument listed first. This is generally
* more readable, since the "this" object is visible before
* the function body, reducing chances for error by missing it.
* If only obj has a real value then obj will be returned,
* allowing this method to be called even if you are not aware
* of the format of the obj and f types.
* It also allows the function to be a string name, in which case,
* obj[f] is used to find the function.
* @param {Object||Function} obj the "this" object, or a function.
* @param {Function||String} f the function of function name that
* should be called with obj set as the "this" value.
* @returns {Function}
*/
bind: function (obj, f) {
//Do not bother if
if (!f) {
return obj;
}
//Make sure we have a function
if (typeof f === 'string') {
f = obj[f];
}
var args = slice.call(arguments, 2);
return function () {
return f.apply(obj, args.concat(slice.call(arguments, 0)));
};
}
};
return fn;
});

Просмотреть файл

@ -0,0 +1,858 @@
/**
* @license blade/jig Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* see: http://github.com/jrburke/blade for details
*/
/*jslint nomen: false, plusplus: false */
/*global define: false, document: false, console: false, jQuery: false */
'use strict';
define(['require', './object'], function (require, object) {
//Fix unit test: something is wrong with it, says it passes, but
//with attachData change, the string is actually different now.
//TODO: for attachData, only generate a new ID when the data value changes,
//and similarly, only attach the data one time per data value.
//If have <img class="contactPhoto" src="{foo}"> browser tries to fetch
//{foo} if that is in markup. Doing a <{/}img, then FF browser treats that
//as &lt;{/}img. Using <img{/} ends up with <img{ }="" in text.
var jig, commands,
ostring = Object.prototype.toString,
decode = typeof decodeURIComponent === 'undefined' ? function () {} : decodeURIComponent,
startToken = '{',
endToken = '}',
rawHtmlToken = '^',
templateRefToken = '#',
argSeparator = ' ',
//First character in an action cannot be something that
//could be the start of a regular JS property name,
//or an array indice indicator, [, or the HTML raw output
//indicator, ^.
propertyRegExp = /[_\[\^\w]/,
defaultArg = '_',
startTagRegExp = /<\s*\w+/,
wordRegExp = /^\d+$/,
badCommentRegExp = /\/(\/)?\s*\]/,
templateCache = {},
defaultFuncs = {
openCurly: function () {
return '{';
},
closeCurly: function () {
return '}';
},
eq: function (a, b) {
return a === b;
},
gt: function (a, b) {
return a > b;
},
gte: function (a, b) {
return a >= b;
},
lt: function (a, b) {
return a < b;
},
lte: function (a, b) {
return a <= b;
},
or: function (a, b) {
return a || b;
},
and: function (a, b) {
return a && b;
},
is: function (a) {
return !!a;
},
eachProp: function (obj) {
//Converts object properties into an array
//of objects that have 'prop' and 'value' properties.
var prop, ret = [];
for (prop in obj) {
if (obj.hasOwnProperty(prop)) {
ret.push({
prop: prop,
value: obj[prop]
});
}
}
//Sort the names to be roughly alphabetic
return ret.sort(function (a, b) {
return a.prop > b.prop ? 1 : -1;
});
}
},
attachData = false,
dataIdCounter = 1,
controlIdCounter = 1,
dataRegistry = {},
tempNode = typeof document !== 'undefined' && document.createElement ?
document.createElement('div') : null,
templateClassRegExp = /(\s*)(template)(\s*)/;
function isArray(it) {
return ostring.call(it) === '[object Array]';
}
/**
* Gets a property from a context object. Allows for an alternative topContext
* object that can be used for the first part property lookup if it is not
* found in context first.
* @param {Array} parts the list of nested properties to look up on a context.
* @param {Object} context the context to start the property lookup
* @param {Object} [topContext] an object to use as an alternate context
* for the very first part property to look up if it is not found in context.
* @returns {Object}
*/
function getProp(parts, context, topContext) {
var obj = context, i, p;
for (i = 0; obj && (p = parts[i]); i++) {
obj = (typeof obj === 'object' && p in obj ? obj[p] : (topContext && i === 0 && p in topContext ? topContext[p] : undefined));
}
return obj; // mixed
}
function strToInt(value) {
return value ? parseInt(value, 10) : 0;
}
function getObject(name, data, options) {
var brackRegExp = /\[([\w0-9\.'":]+)\]/,
part = name,
parent = data,
isTop = true,
match, pre, prop, obj, startIndex, endIndex, indices, result,
parenStart, parenEnd, func, funcName, arg, args, i, firstChar;
//If asking for the default arg it means giving back the current data.
if (name === defaultArg) {
return data;
}
//If name is just an integer, just return it.
if (wordRegExp.test(name)) {
return strToInt(name);
}
//An empty string is just returned.
if (name === '') {
return '';
}
//If the name looks like a string, just return that.
firstChar = name.charAt(0);
if (firstChar === "'" || firstChar === "'") {
return name.substring(1, name.length - 1);
}
//First check for function call. Function must be globally visible.
if ((parenStart = name.indexOf('(')) !== -1) {
parenEnd = name.lastIndexOf(')');
funcName = name.substring(0, parenStart);
func = options.fn[funcName];
if (!func) {
jig.error('Cannot find function named: ' + funcName + ' for ' + name);
return '';
}
arg = name.substring(parenStart + 1, parenEnd);
if (arg.indexOf(',') !== -1) {
args = arg.split(',');
for (i = args.length - 1; i >= 0; i--) {
args[i] = getObject(args[i], data, options);
}
result = func.apply(null, args);
} else {
result = func(getObject(arg, data, options));
}
if (parenEnd < name.length - 1) {
//More data properties after the function call, fetch them
//If the part after the paren is a dot, then skip over that part
if (name.charAt(parenEnd + 1) === '.') {
parenEnd += 1;
}
return getObject(name.substring(parenEnd + 1, name.length), result, options);
} else {
return result;
}
}
//Now handle regular object references, which could have [] notation.
while ((match = brackRegExp.exec(part))) {
prop = match[1].replace(/['"]/g, '');
pre = part.substring(0, match.index);
part = part.substring(match.index + match[0].length, part.length);
if (part.indexOf('.') === 0) {
part = part.substring(1, part.length);
}
obj = getProp(pre.split('.'), parent, isTop ? options.context : null);
isTop = false;
if (!obj && prop) {
jig.error('blade/jig: No property "' + prop + '" on ' + obj);
return '';
}
if (prop.indexOf(':') !== -1) {
//An array slice action
indices = prop.split(':');
startIndex = strToInt(indices[0]);
endIndex = strToInt(indices[1]);
if (!endIndex) {
obj = obj.slice(startIndex);
} else {
obj = obj.slice(startIndex, endIndex);
}
} else {
if (options.strict && !(prop in obj)) {
jig.error('blade/jig: no property "' + prop + '"');
}
obj = obj[prop];
}
parent = obj;
}
if (!part) {
result = parent;
} else {
result = getProp(part.split('.'), parent, isTop ? options.context : null);
}
if (options.strict && result === undefined) {
jig.error('blade/jig: undefined value for property "' + name + '"');
}
return result;
}
/**
* Gets a compiled template based on the template ID. Will look in the
* DOM for an element with that ID if a template is not found already in
* the compiled cache.
* @param {String} id the ID of the template/DOM node
* @param {Object} [options]
*
* @returns {Array} the compiled template.
*/
function compiledById(id, options) {
options = options || {};
var compiled = jig.cache(id, options), node;
//Did not find the text template. Maybe it is a DOM element.
if (compiled === undefined && typeof document !== 'undefined') {
node = document.getElementById(id);
if (node) {
jig.parse([node], options);
}
compiled = jig.cache(id, options);
}
if (compiled === undefined) {
throw new Error('blade/jig: no template or node with ID: ' + id);
}
return compiled;
}
commands = {
'_default_': {
doc: 'Property reference',
action: function (args, data, options, children, render) {
var value = args[0] ? getObject(args[0], data, options) : data,
comparison = args[1] ? getObject(args[1], data, options) : undefined,
i, text = '';
//If comparing to some other value, then the value is the data,
//and need to compute if the values compare.
if (args[1]) {
comparison = value === comparison;
value = data;
} else {
//Just use the value, so the value is used in the comparison.
comparison = value;
}
//Want to allow returning 0 for values, so this next check is
//a bit verbose.
if (comparison === false || comparison === null ||
comparison === undefined || (isArray(comparison) && !comparison.length)) {
return '';
} else if (children) {
if (isArray(value)) {
for (i = 0; i < value.length; i++) {
text += render(children, value[i], options);
}
} else {
//If the value is true or false, then just use parent data.
//for the child rendering.
if (typeof value === 'boolean') {
value = data;
}
text = render(children, value, options);
}
} else {
text = value;
}
return text;
}
},
'!': {
doc: 'Not',
action: function (args, data, options, children, render) {
var value = getObject(args[0], data, options),
comparison = args[1] ? getObject(args[1], data, options) : undefined;
//If comparing to some other value, then the value is the data,
//and need to compute if the values compare.
if (args[1]) {
comparison = value === comparison;
value = data;
} else {
//Just use the value, so the value is used in the comparison.
comparison = value;
}
if (children && !comparison) {
return render(children, data, options);
}
return '';
}
},
'#': {
doc: 'Template reference',
action: function (args, data, options, children, render) {
var compiled = compiledById(args[0], options);
data = getObject(args.length > 1 ? args[1] : defaultArg, data, options);
return render(compiled, data, options);
}
},
'.': {
doc: 'Variable declaration',
action: function (args, data, options, children, render) {
options.context[args[0]] = getObject(args[1], data, options);
//TODO: allow definining a variable then doing a block with
//that variable.
return '';
}
},
'>': {
doc: 'Else',
action: function (args, data, options, children, render) {
if (children) {
return render(children, data, options);
}
return '';
}
}
};
jig = function (text, data, options) {
var id;
if (typeof text === 'string') {
if (text.charAt(0) === '#') {
//a lookup by template ID
id = text.substring(1, text.length);
text = compiledById(id, options);
} else {
text = jig.compile(text, options);
}
}
return jig.render(text, data, options);
};
jig.htmlEscape = function (text) {
return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
};
function compile(text, options) {
var compiled = [],
start = 0,
useRawHtml = false,
controlId = 0,
segment, index, match, tag, command, args, lastArg, lastChar,
children, i, tempTag;
while ((index = text.indexOf(options.startToken, start)) !== -1) {
//Output any string that is before the template tag start
if (index !== start) {
compiled.push(text.substring(start, index));
}
//Find the end of the token
segment = text.substring(index);
match = options.endRegExp.exec(segment);
if (!match) {
//Just a loose start thing could be a regular punctuation.
compiled.push(segment);
return compiled;
} else {
//Command Match!
//Increment start past the match.
start = index + match[0].length;
//Pull out the command
tag = text.substring(index + options.startToken.length, index + match[0].length - options.endToken.length).trim();
//decode in case the value was in an URL field, like an href or an img src attribute
tag = decode(tag);
//if the command is commented out end block call, that messes with stuff,
//just throw to let the user know, otherwise browser can lock up.
if (badCommentRegExp.test(tag)) {
throw new Error('blade/jig: end block tags should not be commented: ' + tag);
}
command = tag.charAt(0);
if (command === ']' && controlId) {
//In a control block, previous block was a related control block,
//so parse it without the starting ] character.
tempTag = tag.substring(1).trim();
if (tempTag === '[') {
command = '>';
} else {
command = tempTag.charAt(0);
//Remove the starting ] so it is seen as a regular tag
tag = tempTag;
}
}
if (command && !options.propertyRegExp.test(command)) {
//Have a template command
tag = tag.substring(1).trim();
} else {
command = '_default_';
//Command could contain just the raw HTML indicator.
useRawHtml = (command === options.rawHtmlToken);
}
//Allow for raw HTML output, but it is not the default.
//template references use raw by default though.
if ((useRawHtml = tag.indexOf(options.rawHtmlToken) === 0)) {
tag = tag.substring(options.rawHtmlToken.length, tag.length);
}
//However, template references use raw always
if (command === templateRefToken) {
useRawHtml = true;
}
args = tag.split(options.argSeparator);
lastArg = args[args.length - 1];
lastChar = lastArg.charAt(lastArg.length - 1);
children = null;
if (command === ']') {
//If there are no other args, this is an end tag, to close
//out a block and possibly a set of control blocks.
if (lastChar !== '[') {
//End of a block. End the recursion, let the parent know
//the place where parsing stopped.
compiled.templateEnd = start;
//Also end of a control section, indicate it as such.
compiled.endControl = true;
} else {
//End of a block. End the recursion, let the parent know
//the place where parsing stopped, before this end tag,
//so it can process it and match it to a control flow
//from previous control tag.
compiled.templateEnd = start - match[0].length;
}
return compiled;
} else if (lastChar === '[') {
//If last arg ends with a [ it means a block element.
//Assign a new control section ID if one is not in play already
if (!controlId) {
controlId = controlIdCounter++;
}
//Adjust the last arg to not have the block character.
args[args.length - 1] = lastArg.substring(0, lastArg.length - 1);
//Process the block
children = compile(text.substring(start), options);
//Skip the part of the string that is part of the child compile.
start += children.templateEnd;
}
//If this defines a template, save it off,
//if a comment (starts with /), then ignore it.
if (command === '+') {
options.templates[args[0]] = children;
} else if (command !== '/') {
//Adjust args if some end in commas, it means they are function
//args.
if (args.length > 1) {
for (i = args.length - 1; i >= 0; i--) {
if (args[i].charAt(args[i].length - 1) === ',') {
args[i] = args[i] + args[i + 1];
args.splice(i + 1, 1);
}
}
}
compiled.push({
action: options.commands[command].action,
useRawHtml: useRawHtml,
args: args,
controlId: controlId,
children: children
});
}
//If the end of a block, clear the control ID
if (children && children.endControl) {
controlId = 0;
}
}
}
if (start !== text.length - 1) {
compiled.push(text.substring(start, text.length));
}
return compiled;
}
jig.compile = function (text, options) {
//Mix in defaults
options = options || {};
object.mixin(options, {
startToken: startToken,
endToken: endToken,
rawHtmlToken: rawHtmlToken,
propertyRegExp: propertyRegExp,
commands: commands,
argSeparator: argSeparator,
templates: templateCache
});
options.endRegExp = new RegExp('[^\\r\\n]*?' + endToken);
//Do some reset to avoid a number from getting too big.
controlIdCounter = 1;
return compile(text, options);
};
/**
* Converts a node to a compiled template, and will store it in the cache. If already
* in the cache, it will give back the cached value.
*/
function nodeToCompiled(node, options) {
var text, compiled, clss,
id = node.id,
cache = options.templates || templateCache;
//If the nodes has already been cached, then just get the cached value.
if (cache[id]) {
return cache[id];
}
//Call listener to allow processing of the node before
//template complication happens.
if (options.onBeforeParse) {
options.onBeforeParse(node);
}
if (node.nodeName.toUpperCase() === 'SCRIPT') {
text = node.text.trim();
if (node.parentNode) {
node.parentNode.removeChild(node);
}
} else {
//Put node in temp node to get the innerHTML so node's element
//html is in the output.
tempNode.appendChild(node);
//Remove the id node and the template class, since this
//template text could be duplicated many times, and a
//template class is no longer useful.
node.removeAttribute('id');
clss = (node.getAttribute('class') || '').trim();
if (clss) {
node.setAttribute('class', clss.replace(templateClassRegExp, '$1$3'));
}
//Decode braces when may get URL encoded as part of hyperlinks
text = tempNode.innerHTML.replace(/%7B/g, '{').replace(/%7D/g, '}');
//Clear out the temp node for the next use.
tempNode.removeChild(node);
}
compiled = jig.compile(text, options);
jig.cache(id, compiled, options);
return compiled;
}
/**
* Parses an HTML document for templates, compiles them, and stores them
* in a cache of templates to use on the page. Only useful in browser environments.
* Script tags with type="text/template" are parsed, as well as DOM elements
* that have a class of "template" on them. The found nodes will be removed
* from the DOM as part of the parse operation.
*
* @param {Array-Like} [nodes] An array-like list of nodes. Could be a NodeList.
* @param {Object} [options] A collection of options to use for compilation.
*/
jig.parse = function (nodes, options) {
//Allow nodes to not be passed in, but still have options.
if (nodes && !nodes.length) {
options = nodes;
nodes = null;
}
options = options || {};
nodes = nodes || document.querySelectorAll('.template, script[type="text/template"]');
var node, i;
for (i = nodes.length - 1; i > -1 && (node = nodes[i]); i--) {
nodeToCompiled(node, options);
}
};
function render(compiled, data, options) {
var text = '', i, dataId, controlId, currentControlId, currentValue, lastValue;
if (typeof compiled === 'string') {
text = compiled;
} else if (isArray(compiled)) {
for (i = 0; i < compiled.length; i++) {
//Account for control blocks (if/elseif/else)
//control blocks all have the same control ID, so only call the next
//control block if the first one did not return a value.
currentControlId = compiled[i].controlId;
if (!currentControlId || currentControlId !== controlId || !lastValue) {
currentValue = render(compiled[i], data, options);
text += currentValue;
if (currentControlId) {
controlId = currentControlId;
lastValue = currentValue;
}
}
}
} else {
//A template command to run.
text = compiled.action(compiled.args, data, options, compiled.children, render);
if (!text) {
text = '';
} else if (!compiled.useRawHtml && !compiled.children) {
//Only html escape commands that are not block actions.
text = jig.htmlEscape(text.toString());
}
}
if (options.attachData) {
if (startTagRegExp.test(text)) {
dataId = 'id' + (dataIdCounter++);
text = text.replace(startTagRegExp, '$& data-blade-jig="' + dataId + '" ');
dataRegistry[dataId] = data;
}
}
return text;
}
/**
* Render a compiled template.
*
* @param {Array} compiled a compiled template
* @param {Object} data the data to use in the template
* @param {Object} options options for rendering. They include:
* @param {Object} templates a cache of compiled templates that might be
* referenced by the primary template
* @param {Object} options.fn a set of functions that might be used
* by the template(s). Each property on this object is a name of a function
* that may show up in the templates, and the value should be the function
* definition.
* @returns {String} the rendered template.
*/
jig.render = function (compiled, data, options) {
var i, result = '';
//Normalize options, filling in defaults.
options = options || {};
object.mixin(options, {
templates: templateCache,
attachData: attachData,
strict: jig.strict
});
//Mix in default functions
if (options.fn) {
object.mixin(options.fn, defaultFuncs);
} else {
options.fn = defaultFuncs;
}
//Mix in top level context object
options.context = options.context || object.create(data);
//If data is an array, then render should be called for each item
//in the array.
if (isArray(data)) {
for (i = 0; i < data.length; i++) {
result += render(compiled, data[i], options);
}
return result;
}
//Default case, just render
return render(compiled, data, options);
};
/**
* Enable strict template rendering checks. If a property does not exist on a
* data object, then an error will be logged.
*/
jig.strict = false;
/**
* Track errors by logging to console if available.
*/
jig.error = function (msg) {
throw msg;
};
/**
* Adds functions to the default set of functions that can be used inside
* a template. Newer definitions of a function will take precedence
* over the previously registered function.
* @param {Object} an object whose properties are names of functions
* and values are the functions that correspond to the names.
*/
jig.addFn = function (obj) {
object.mixin(defaultFuncs, obj, true);
};
/**
* Gets and sets the data bound to a particular rendered template. Setting
* the data does not change the already rendered template.
*
* @param {String||DOMNode} dataId the data ID, or a DOM node with a
* data-blade-jig attribute that was generated from a rendered template.
* @returns {Object} the bound data. Can return undefined if there is
* no data stored with that ID.
*/
jig.data = function (dataId, value) {
if (typeof dataId !== 'string') {
//Should be a DOM node or node list if it is not already a string.
if (!dataId.nodeType) {
dataId = dataId[0];
}
dataId = dataId.getAttribute('data-blade-jig');
}
if (value !== undefined) {
return (dataRegistry[dataId] = value);
} else {
return dataRegistry[dataId];
}
};
/**
* Removes some data that was bound to a rendered template.
* @param {String} dataId the data ID. It can be fetched from the
* data-blade-jig attribute on a rendered template.
*/
jig.removeData = function (dataId) {
delete dataRegistry[dataId];
};
/**
* Gets an object given a string representation. For example,
* jig.getObject('foo.bar', baz) will return the baz.foo.bar value.
*
* @param {String} name the string value to fetch. The following formats
* are allowed: 'foo.bar', 'foo['bar']', 'foo[0]', 'foo[2:6]'. The last one
* will return an array subset. Functions are also supported: 'doSomething(foo.bar)'
* but the doSomething function needs to be defined in the options.fn
* property, as options.fn.doSomething = function (){}
*
* @param {Object} data the object to use as the basis for the object lookup.
*
* @param {Object} options. Options to the lookup. The only supported option
* at this time is options.func, and object defining functions can could be
* called.
*
* @returns {Object} it could return null if the name is not found off the data
*/
jig.getObject = getObject;
/**
* Gets or sets a compiled template from a template cache.
* @param {String} id the template ID
* @param {String} [value] A string to compile to a template, or
* the compiled template value.
* @param {Object} [options] optional options object with a 'templates'
* property that contains some cached templates. If provided, a matching
* cache value for the ID will be used from options.templates, otherwise,
* the ID will be used to look up in the global blade/jig template cache.
* @returns {Object} a compiled template. It could return undefined if
* not match is found.
*/
jig.cache = function (id, value, options) {
//Convert the value to a compiled templated if necessary.
if (typeof value === 'string') {
value = jig.compile(value, options);
}
//If value is not an array, then a get operation, likely an options.
if (!isArray(value)) {
options = value;
value = undefined;
}
var cache = (options && options.templates) || templateCache;
if (value !== undefined) {
cache[id] = value;
}
//Return the value. For get use, the template may not be in
//the local options.templates, but in the global cache, so
//be sure to check both.
return cache[id] || templateCache[id];
};
function addToJQuery(jQuery) {
//Only handles queries where it is by a node ID, '#something'.
jQuery.fn.jig = function (data, options) {
//Convert this, which is a DOM node into a string of data
options = options || {};
var id = this.selector,
compiled;
if (id.charAt(0) !== '#') {
throw new Error('blade/jig: only ID selectors, like "#something" are allowed with jig()');
}
id = id.substring(1, id.length);
//See if the template is already compiled.
compiled = (options.templates || templateCache)[id];
if (!compiled) {
compiled = nodeToCompiled(this[0]);
}
return jQuery(jig.render(compiled, data, options));
};
}
//Set up the plugin with a RequireJS-aware jQuery module but also
//if there is a global jQuery.
//require.modify('jquery', 'jquery-jig', ['jquery'], addToJQuery);
if (typeof jQuery !== 'undefined') {
addToJQuery(jQuery);
}
return jig;
});

Просмотреть файл

@ -0,0 +1,128 @@
/**
* @license blade/object Copyright (c) 2010, The Dojo Foundation All Rights Reserved.
* Available via the MIT, GPL or new BSD license.
* see: http://github.com/jrburke/blade for details
*/
/*jslint plusplus: false */
/*global define: false */
'use strict';
define(['./fn'], function (fn) {
var empty = {},
/**
* Creates a new constructor function for generating objects of a certain type.
*
* @param {Object} base the base object to inherit from in the
* prototype chain. Pass null if no parent desired.
*
* @param {Array} mixins an array of objects to use to mix in their
* properties into the new object. Pass null if no mixins desired.
*
* @param {Function} objPropertyFunc, a function that returns an object
* whose properties should be part of this new object's prototype.
* The function will be passed the function used to call methods
* on the parent prototype used for this object. The function expects
* three arguments:
* - obj: pass the this object for this arg
* - funcName: the function name to call on the prototype object (a string)
* - args: an array of arguments. Normally just pass the arguments object.
* The parent prototype will be a combination of the base object
* with all mixins applied.
*
* @returns {Function} a constructor function.
*/
object = function (base, mixins, objPropertyFunc) {
base = base || {};
var constructor,
//Create the parent and its parentFunc calling wrapper.
//The parent function just makes it easier to call the parent
parent = object.create(base.prototype, mixins),
parentFunc = function (obj, funcName, args) {
return parent[funcName].apply(obj, args);
},
//Create a different object for the prototype instead of using
//parent, so that parent can still refer to parent object
//without the curren object's properties mixed in
//(via the objPropertyFunc) with the mixed in properties taking
//priority over the parent's properties.
proto = object.create(parent);
object.mixin(proto, (fn.is(objPropertyFunc) ? objPropertyFunc(parentFunc) : objPropertyFunc), true);
//Create the constructor function. Calls init if it is defined
//on the prototype (proto)
constructor = function () {
//Protect against a missing new
if (!(this instanceof constructor)) {
throw new Error('blade/object: constructor function called without "new" in front');
}
//Call initializer if present.
if (this.init) {
this.init.apply(this, arguments);
}
};
//Set the prototype for this constructor
constructor.prototype = proto;
return constructor;
};
/**
* Similar to ES5 create, but instead of setting property attributes
* for the second arg, allow an array of mixins to mix in properties
* to the newly created object.
* A copy of dojo.delegate
* @param {Object} parent the parent object to use as the prototype.
* @param {Array} [mixins] array of mixin objects to mix in to the new object.
*/
function Temp() {}
object.create = function (obj, mixins) {
Temp.prototype = obj;
var temp = new Temp(), i, mixin;
//Avoid any extra memory hanging around
Temp.prototype = null;
if (mixins) {
for (i = 0; (mixin = mixins[i]); i++) {
object.mixin(temp, mixin);
}
}
return temp; // Object
};
/**
* Simple function to mix in properties from source into target,
* but only if target does not already have a property of the same name,
* unless override is set to true. Borrowed from Dojo.
*
* To extend a prototype on a given object, pass in the prototype property
* to mixin. For example: object.mixin(func.prototype, {a: 'b'});
*
* @param {Object} target the object receiving the mixed in properties.
*
* @param {Object} source the object that contains the properties to mix in.
*
* @param {Boolean} [override] if set to true, then the source's properties
* will be mixed in even if a property of the same name already exists on
* the target.
*/
object.mixin = function (target, source, override) {
//TODO: consider ES5 getters and setters in here.
for (var prop in source) {
if (!(prop in empty) && (!(prop in target) || override)) {
target[prop] = source[prop];
}
}
};
return object;
});

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше