removed jquery, added new design
This commit is contained in:
parent
f262509adb
commit
8d124c01d9
10 changed files with 1053 additions and 23759 deletions
File diff suppressed because it is too large
Load diff
243
css/screen.css
243
css/screen.css
|
@ -1,37 +1,236 @@
|
||||||
img {
|
html, body {
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#full header *, #full2 header * {
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
min-height: 100%;
|
||||||
|
font-family: FeuraSans, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
#full header, #full2 header {
|
.red { background: #e74c3c; color: #ecf0f1; }
|
||||||
border-bottom: 1px solid #aaa;
|
.white { background: #ecf0f1; color: #2c3e50; }
|
||||||
margin-bottom: 1em;
|
.blue { background: #3498db; color: #ecf0f1; }
|
||||||
padding-bottom: 1em;
|
.yellow { background: #f1c40f; color: #2c3e50; }
|
||||||
}
|
|
||||||
|
|
||||||
#full h1, #full2 h1 {
|
a {
|
||||||
font-weight: normal;
|
outline: none;
|
||||||
font-size: 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#full h1 a, #full2 h1 a {
|
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#list .ui-li-heading {
|
.red a { color: #ecf0f1; }
|
||||||
font-weight: normal;
|
.white a { color: #2c3e50; }
|
||||||
|
.blue a { color: #ecf0f1; }
|
||||||
|
.yellow a { color: #2c3e50; }
|
||||||
|
|
||||||
|
.button {
|
||||||
|
outline: none;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: none;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 0;
|
||||||
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#list .unread .ui-li-heading {
|
header .button, footer .button {
|
||||||
font-weight: bold;
|
width: auto;
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.red .button { background: #c0392b; color: #ecf0f1; }
|
||||||
|
.white .button { background: #bdc3c7; color: #2c3e50; }
|
||||||
|
.blue .button { background: #2980b9; color: #ecf0f1; }
|
||||||
|
.yellow .button { background: #f39c12; color: #2c3e50; }
|
||||||
|
|
||||||
|
.red .bar .button { background: #e74c3c; color: #ecf0f1; }
|
||||||
|
.white .bar .button { background: #ecf0f1; color: #2c3e50; }
|
||||||
|
.blue .bar .button { background: #3498db; color: #ecf0f1; }
|
||||||
|
.yellow .bar .button { background: #f1c40f; color: #2c3e50; }
|
||||||
|
|
||||||
.smallogo { text-align: center; margin: 0; padding: 0; }
|
.smallogo { text-align: center; margin: 0; padding: 0; }
|
||||||
.smallogo img { width: 50%; }
|
.smallogo img { width: 50%; }
|
||||||
|
|
||||||
.count { font-size: 0.8em; padding-top: 0.6em; padding-right: 0.2em; text-shadow: 0 0 2px black; }
|
button:active, a:active. .button:active {
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login article, #settings article {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
section > header {
|
||||||
|
background: #c0392b;
|
||||||
|
text-align: left;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.red .bar { background: #c0392b; }
|
||||||
|
.white .bar { background: #bdc3c7; }
|
||||||
|
.blue .bar { background: #2980b9; }
|
||||||
|
.yellow .bar { background: #f39c12; }
|
||||||
|
|
||||||
|
section > header h1 {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: lighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bar {
|
||||||
|
margin: 0;
|
||||||
|
padding: 10px;
|
||||||
|
display: block;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
section > footer {
|
||||||
|
padding: 10px;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
width: 80px;
|
||||||
|
height: 40px;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list article {
|
||||||
|
padding-bottom: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list p {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list p {
|
||||||
|
font-weight: normal;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: block;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list h2 {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list li {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list li:after {
|
||||||
|
content: "›";
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
top: 0.1em;
|
||||||
|
font-weight: 100;
|
||||||
|
font-size: 3em;
|
||||||
|
font-family: "Open Sans";
|
||||||
|
}
|
||||||
|
|
||||||
|
#list li > a {
|
||||||
|
display: block;
|
||||||
|
padding: 5px 25px 5px 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#list .unread h2 {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
#full > article {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#full h1 {
|
||||||
|
font-size: 1.3em;
|
||||||
|
font-weight: normal;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#full h1 a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#full blockquote {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 1em;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
#full .article a {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#settings ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding-left: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#settings li {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#settings ul a.color-red {
|
||||||
|
background: #e74c3c;
|
||||||
|
border: 20px solid #c0392b;
|
||||||
|
border-width: 1px 20px 1px 1px;
|
||||||
|
color: #ecf0f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#settings ul a.color-white {
|
||||||
|
background: #ecf0f1;
|
||||||
|
border: 20px solid #bdc3c7;
|
||||||
|
border-width: 1px 20px 1px 1px;
|
||||||
|
color: #2c3e50;
|
||||||
|
}
|
||||||
|
|
||||||
|
#settings ul a.color-blue {
|
||||||
|
background: #3498db;
|
||||||
|
border: 20px solid #2980b9;
|
||||||
|
border-width: 1px 20px 1px 1px;
|
||||||
|
color: #ecf0f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#settings ul a.color-yellow {
|
||||||
|
background: #f1c40f;
|
||||||
|
border: 20px solid #f39c12;
|
||||||
|
border-width: 1px 20px 1px 1px;
|
||||||
|
color: #2c3e50;
|
||||||
|
}
|
||||||
|
|
128
index.html
128
index.html
|
@ -7,85 +7,87 @@
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||||
<title>FeedMonkey</title>
|
<title>FeedMonkey</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="css/jquery.mobile.css" />
|
|
||||||
<link rel="stylesheet" href="css/screen.css" />
|
<link rel="stylesheet" href="css/screen.css" />
|
||||||
|
|
||||||
<script src="js/jquery.js"></script>
|
|
||||||
<script src="js/jquery.mobile.js"></script>
|
|
||||||
|
|
||||||
<script src="js/App.js"></script>
|
<script src="js/App.js"></script>
|
||||||
<script src="js/TinyTinyRSS.js"></script>
|
<script src="js/TinyTinyRSS.js"></script>
|
||||||
<script src="js/Login.js"></script>
|
<script src="js/Login.js"></script>
|
||||||
<script src="js/application.js"></script>
|
<script src="js/jester.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div data-role="page" id="list">
|
<section id="list" class="active">
|
||||||
<div data-theme="a" data-role="header">
|
<article>
|
||||||
<a data-role="button" href="#list" data-icon="refresh" data-iconpos="right" class="ui-btn-left" id="reload">
|
<ul></ul>
|
||||||
Reload
|
</article>
|
||||||
</a>
|
<footer class="bar">
|
||||||
<h3>
|
<a class="button" href="#reload">Reload</a>
|
||||||
FeedMonkey
|
<a class="button" href="#settings">Settings</a>
|
||||||
</h3>
|
<canvas></canvas>
|
||||||
<span class="ui-btn-right count" data-theme="a">0 / 0</span>
|
</footer>
|
||||||
</div>
|
</section>
|
||||||
<div data-role="content">
|
|
||||||
<ul data-role="listview" data-inset="false">
|
|
||||||
<li><a href="#full">Loading ...</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div data-role="page" id="login" data-close-btn="none">
|
<section id="settings">
|
||||||
<div data-theme="a" data-role="header" data-close-btn="none">
|
<header class="bar">
|
||||||
<h3>
|
<a class="button" href="#list">Back</a>
|
||||||
Please log in
|
</header>
|
||||||
</h3>
|
<article>
|
||||||
</div>
|
<ul>
|
||||||
<div data-role="content">
|
<li><a href="#logout" class="button">Log out</a></li>
|
||||||
<form>
|
<li><a href="#reset-info" class="button">View those info bubbles again</a></li>
|
||||||
<div>
|
<li><a href="#color-white" class="color-white button">White colors</a></li>
|
||||||
<p class="smallogo"><img src="img/splash.png" alt=""></p>
|
<li><a href="#color-blue" class="color-blue button">Blue colors</a></li>
|
||||||
|
<li><a href="#color-yellow" class="color-yellow button">Yellow colors</a></li>
|
||||||
|
<li><a href="#color-red" class="color-red button">Red colors (default)</a></li>
|
||||||
|
</ul>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
<label for="url" class="ui-hidden-accessible">URL:</label>
|
<section id="login">
|
||||||
<input type="text" name="url" id="url" value="" placeholder="http://example.com/tt-rss/" data-theme="a" />
|
<header class="bar">
|
||||||
|
<h1>Please log in</h1>
|
||||||
|
</header>
|
||||||
|
<article>
|
||||||
|
<form>
|
||||||
|
<p class="smallogo">
|
||||||
|
<img src="img/splash.png" alt="Logo, an ape head">
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="url">URL:</label>
|
||||||
|
<input class="button" type="text" name="url" id="url" value="" placeholder="http://example.com/tt-rss/" />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="un">Username:</label>
|
||||||
|
<input class="button" type="text" name="user" id="un" value="" placeholder="username" />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="pw">Password:</label>
|
||||||
|
<input class="button" type="password" name="pass" id="pw" value="" placeholder="password" />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<button class="button" type="submit">Sign in</button>
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
<label for="un" class="ui-hidden-accessible">Username:</label>
|
<section id="full">
|
||||||
<input type="text" name="user" id="un" value="" placeholder="username" data-theme="a" />
|
<header class="bar">
|
||||||
|
<a class="button" href="#list">Back</a>
|
||||||
<label for="pw" class="ui-hidden-accessible">Password:</label>
|
<a class="button" href="#unread">Set unread</a>
|
||||||
<input type="password" name="pass" id="pw" value="" placeholder="password" data-theme="a" />
|
<canvas></canvas>
|
||||||
|
</header>
|
||||||
<button type="submit" data-theme="b">Sign in</button>
|
<article>
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div data-role="page" id="full">
|
|
||||||
<div data-theme="a" data-role="header">
|
|
||||||
<a data-role="button" data-transition="slide" data-direction="reverse" href="#list"
|
|
||||||
data-icon="home" data-iconpos="left" class="ui-btn-left back">
|
|
||||||
List
|
|
||||||
</a>
|
|
||||||
<h3 class="feed_title"></h3>
|
|
||||||
<span class="ui-btn-right count" data-theme="a">0 / 0</span>
|
|
||||||
</div>
|
|
||||||
<div data-role="content">
|
|
||||||
<header>
|
<header>
|
||||||
<p><span class="feed_title"></span> <span class="author"></span></p>
|
<p><span class="feed_title"></span> <span class="author"></span></p>
|
||||||
<h1><a class="title" href="" target="_blank"></a></h1>
|
<h1><a class="title" href="" target="_blank"></a></h1>
|
||||||
<p><timedate class="date"></timedate></p>
|
<p><timedate class="date"></timedate></p>
|
||||||
</header>
|
</header>
|
||||||
<article class="article"></article>
|
<div class="article"></div>
|
||||||
</div>
|
<article>
|
||||||
|
</section>
|
||||||
|
|
||||||
<div data-role="popup" id="popup" class="ui-content">
|
<script src="js/application.js"></script>
|
||||||
<p><span>✔</span> set unread</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
183
js/App.js
183
js/App.js
|
@ -2,49 +2,98 @@
|
||||||
function App() {
|
function App() {
|
||||||
this.login = new Login(this);
|
this.login = new Login(this);
|
||||||
this.currentIndex = -1;
|
this.currentIndex = -1;
|
||||||
this.page = 2;
|
|
||||||
|
var color = localStorage.color;
|
||||||
|
if(!color) color = "red";
|
||||||
|
this.setColor(color);
|
||||||
|
|
||||||
var _this = this;
|
var _this = this;
|
||||||
$("#reload").on("vclick", function() {
|
|
||||||
$(this).removeClass('ui-btn-active ui-focus');
|
jester($("#full")).flick(function(touches, direction) {
|
||||||
_this.reload();
|
if(direction == "left") _this.showNext();
|
||||||
|
else _this.showPrevious();
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#full").bind("swipeleft", this.showNext.bind(this));
|
window.onhashchange = function(e) {
|
||||||
$("#full").bind("swiperight", this.showPrevious.bind(this));
|
// do not reload page
|
||||||
$("#full").bind("taphold", this.setCurrentUnread.bind(this));
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
$(".back").on("vclick", this.setCurrentRead.bind(this));
|
var url = window.location.hash;
|
||||||
|
|
||||||
var _this = this;
|
if(url == "#list") {
|
||||||
var aop = function(event, ui) { setTimeout(function() { $("#popup").popup("close") }, 2000) };
|
_this.changeToPage("#list");
|
||||||
$("#popup").popup({ afteropen: aop});
|
} else if(url == "#reload") {
|
||||||
|
_this.reload();
|
||||||
|
} else if(url == "#settings") {
|
||||||
|
_this.changeToPage("#settings");
|
||||||
|
} else if(url.indexOf("#color-") == 0) {
|
||||||
|
var color = url.replace("#color-", "");
|
||||||
|
_this.setColor(color);
|
||||||
|
} else if(url.indexOf("#full-") == 0) {
|
||||||
|
var i = parseInt(url.replace("#full-", ""), 10);
|
||||||
|
_this.showFull(_this.unread_articles[i]);
|
||||||
|
} else if(url == "#unread") {
|
||||||
|
_this.setCurrentUnread();
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
App.prototype.authenticate = function() {
|
App.prototype.authenticate = function() {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
App.prototype.toString = function() {
|
|
||||||
return "App";
|
|
||||||
};
|
|
||||||
|
|
||||||
App.prototype.after_login = function() {
|
App.prototype.after_login = function() {
|
||||||
$.mobile.changePage($("#list"));
|
this.changeToPage("#list");
|
||||||
|
|
||||||
this.ttrss = new TinyTinyRSS(this, localStorage.server_url, localStorage.session_id);
|
this.ttrss = new TinyTinyRSS(this, localStorage.server_url, localStorage.session_id);
|
||||||
this.reload();
|
this.reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
App.prototype.changeToPage = function(page) {
|
||||||
|
|
||||||
|
// FIXME
|
||||||
|
var active = $(".active");
|
||||||
|
if(active.id == "list") {
|
||||||
|
this.saveScrollTop = document.body.scrollTop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(page == "#list") {
|
||||||
|
document.body.scrollTop = this.saveScrollTop;
|
||||||
|
} else {
|
||||||
|
window.scroll(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
active.removeClass("active");
|
||||||
|
$(page).addClass("active");
|
||||||
|
};
|
||||||
|
|
||||||
|
App.prototype.setColor = function(color) {
|
||||||
|
localStorage.color = color;
|
||||||
|
document.body.className = "";
|
||||||
|
document.body.addClass(color);
|
||||||
|
this.updatePieChart();
|
||||||
|
};
|
||||||
|
|
||||||
App.prototype.reload = function() {
|
App.prototype.reload = function() {
|
||||||
this.unread_articles = [];
|
this.unread_articles = [];
|
||||||
this.ttrss.getUnreadFeeds(this.gotUnreadFeeds.bind(this));
|
this.ttrss.getUnreadFeeds(this.gotUnreadFeeds.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
App.prototype.gotUnreadFeeds = function(new_articles) {
|
App.prototype.gotUnreadFeeds = function(new_articles) {
|
||||||
|
|
||||||
if(new_articles == null) { // on error load the saved unread articles.
|
if(new_articles == null) { // on error load the saved unread articles.
|
||||||
this.unread_articles = JSON.parse(localStorage.unread_articles);
|
|
||||||
|
var old_articles = localStorage.unread_articles;
|
||||||
|
if(old_articles) {
|
||||||
|
this.unread_articles = JSON.parse(old_articles);
|
||||||
|
}
|
||||||
this.populateList();
|
this.populateList();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
this.unread_articles = this.unread_articles.concat(new_articles);
|
this.unread_articles = this.unread_articles.concat(new_articles);
|
||||||
|
|
||||||
if(new_articles.length > 0) {
|
if(new_articles.length > 0) {
|
||||||
this.ttrss.getUnreadFeeds(this.gotUnreadFeeds.bind(this), this.unread_articles.length);
|
this.ttrss.getUnreadFeeds(this.gotUnreadFeeds.bind(this), this.unread_articles.length);
|
||||||
} else {
|
} else {
|
||||||
|
@ -55,62 +104,97 @@ App.prototype.gotUnreadFeeds = function(new_articles) {
|
||||||
};
|
};
|
||||||
|
|
||||||
App.prototype.populateList = function() {
|
App.prototype.populateList = function() {
|
||||||
var ul = $("#list ul");
|
|
||||||
var html_str = "";
|
var html_str = "";
|
||||||
for (var i = 0; i < this.unread_articles.length; i++) {
|
for (var i = 0; i < this.unread_articles.length; i++) {
|
||||||
var article = this.unread_articles[i];
|
var article = this.unread_articles[i];
|
||||||
html_str += "<li"+ (article.unread ? " class='unread'" : "") +"><a href='#full-"+i+"'><p class='ui-li-desc'><strong>" + article.feed_title + "</strong></p><h3 class='ui-li-heading'>" + article.title + "</h3><p class='ui-li-desc'>" + article.excerpt + "</p></a></li>";
|
html_str += "<li"+ (article.unread ? " class='unread'" : "") +">";
|
||||||
|
html_str += "<a href='#full-"+i+"'>";
|
||||||
|
html_str += "<p class='title'>";
|
||||||
|
html_str += "<strong>" + article.feed_title + "</strong>";
|
||||||
|
html_str += "</p>";
|
||||||
|
html_str += "<h2>" + article.title + "</h2>";
|
||||||
|
html_str += "<p class='excerpt'>" + article.excerpt + "</p>";
|
||||||
|
html_str += "</a></li>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$("#list ul").innerHTML = html_str;
|
||||||
|
|
||||||
ul.html(html_str);
|
this.updatePieChart();
|
||||||
|
|
||||||
ul.listview("refresh");
|
|
||||||
|
|
||||||
$(".count").html(this.unread_articles.length + " / " + this.unread_articles.length);
|
|
||||||
//$(".count").button("refresh");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
App.prototype.updateList = function() {
|
App.prototype.updateList = function() {
|
||||||
var unread = 0;
|
var unread = 0;
|
||||||
var _this = this;
|
var _this = this;
|
||||||
$("#list ul li").each(function(i, o) {
|
$$("#list ul li").forEach(function(o, i) {
|
||||||
if(!_this.unread_articles[i].unread) $(this).removeClass("unread");
|
if(!this.unread_articles[i].unread) o.removeClass("unread");
|
||||||
else {
|
else {
|
||||||
unread++;
|
unread++;
|
||||||
$(this).addClass("unread");
|
o.addClass("unread");
|
||||||
}
|
}
|
||||||
});
|
}, this);
|
||||||
|
|
||||||
//$("#list ul").listview("refresh");
|
this.updatePieChart();
|
||||||
|
};
|
||||||
|
|
||||||
$(".count").html(unread + " / " + this.unread_articles.length);
|
App.prototype.updatePieChart = function(all, unread) {
|
||||||
//$(".count").button("refresh");
|
|
||||||
|
var all = this.unread_articles.length;
|
||||||
|
var unread = 0;
|
||||||
|
for (var i = 0; i < all; i++) {
|
||||||
|
if(this.unread_articles[i].unread) unread++;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var a = 100 / all * unread;
|
||||||
|
var b = 100 / all * (all - unread);
|
||||||
|
|
||||||
|
var bg = window.getComputedStyle($("body"), null).backgroundColor;
|
||||||
|
var fg = window.getComputedStyle($(".bar"), null).backgroundColor;
|
||||||
|
|
||||||
|
var myColor = [bg, fg];
|
||||||
|
|
||||||
|
var data = [a, b];
|
||||||
|
|
||||||
|
$$("canvas").forEach(function(canvas) {
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
var lastend = 0;
|
||||||
|
var myTotal = 0;
|
||||||
|
|
||||||
|
for(var e = 0; e < data.length; e++) myTotal += data[e];
|
||||||
|
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
ctx.fillStyle = myColor[i];
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(canvas.width/2, canvas.height/2);
|
||||||
|
ctx.arc(canvas.width/2, canvas.height/2, canvas.height/2, lastend, lastend+(Math.PI*2*(data[i]/myTotal)), false);
|
||||||
|
ctx.lineTo(canvas.width/2, canvas.height/2);
|
||||||
|
ctx.fill();
|
||||||
|
lastend += Math.PI*2*(data[i]/myTotal);
|
||||||
|
}
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
App.prototype.showFull = function(article, slide_back) {
|
App.prototype.showFull = function(article, slide_back) {
|
||||||
|
|
||||||
|
this.changeToPage("#full");
|
||||||
|
|
||||||
this.currentIndex = this.unread_articles.indexOf(article);
|
this.currentIndex = this.unread_articles.indexOf(article);
|
||||||
|
|
||||||
var page_id = "#full";
|
var page_id = "#full";
|
||||||
|
|
||||||
$(page_id + " .date").html("");
|
$(page_id + " .date").innerHTML = (new Date(parseInt(article.updated, 10) * 1000)).toLocaleString();
|
||||||
$(page_id + " .title").html("");
|
|
||||||
$(page_id + " .title").attr("href", "");
|
var title = $(page_id + " .title");
|
||||||
$(page_id + " .title").attr("title", "");
|
title.innerHTML = article.title;
|
||||||
$(page_id + " .feed_title").html("");
|
title.href = article.link;
|
||||||
$(page_id + " .author").html("");
|
|
||||||
$(page_id + " .article").html("");
|
$(page_id + " .feed_title").innerHTML = article.feed_title;
|
||||||
|
|
||||||
$(page_id + " .date").html((new Date(parseInt(article.updated, 10) * 1000)).toLocaleString());
|
|
||||||
$(page_id + " .title").html(article.title);
|
|
||||||
$(page_id + " .title").prop("href", article.link);
|
|
||||||
$(page_id + " .title").prop("title", article.link);
|
|
||||||
$(page_id + " .feed_title").html(article.feed_title);
|
|
||||||
if(article.author && article.author.length > 0)
|
if(article.author && article.author.length > 0)
|
||||||
$(page_id + " .author").html("– " + article.author);
|
$(page_id + " .author").innerHTML = "– " + article.author;
|
||||||
$(page_id + " .article").html(article.content);
|
|
||||||
|
|
||||||
$.mobile.changePage($(page_id), { transition: "slide", reverse: slide_back });
|
$(page_id + " .article").innerHTML = article.content;
|
||||||
};
|
};
|
||||||
|
|
||||||
App.prototype.showNext = function() {
|
App.prototype.showNext = function() {
|
||||||
|
@ -152,11 +236,10 @@ App.prototype.setCurrentUnread = function() {
|
||||||
article.unread = true;
|
article.unread = true;
|
||||||
article.set_unread = true;
|
article.set_unread = true;
|
||||||
this.updateList();
|
this.updateList();
|
||||||
$("#popup").popup("open");
|
|
||||||
var _this = this;
|
var _this = this;
|
||||||
setTimeout(function() { _this.ttrss.setArticleUnread(article.id); }, 100);
|
setTimeout(function() { _this.ttrss.setArticleUnread(article.id); }, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
App.prototype.goToList = function() {
|
App.prototype.goToList = function() {
|
||||||
$.mobile.changePage("#list", {transition: "slide", reverse: true});
|
this.changeToPage("#list");
|
||||||
};
|
};
|
||||||
|
|
14
js/Login.js
14
js/Login.js
|
@ -17,14 +17,18 @@ Login.prototype.is_logged_in = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
Login.prototype.log_in = function() {
|
Login.prototype.log_in = function() {
|
||||||
$.mobile.changePage("#login", { role: "dialog", transition: "flip", "close-btn": "none" });
|
this.app.changeToPage("#login");
|
||||||
$("#login form").on('submit', this.authenticate.bind(this));
|
$("#login form").addEventListener('submit', this.authenticate.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
Login.prototype.authenticate = function(e) {
|
Login.prototype.authenticate = function(e) {
|
||||||
var server_url = $(e.target).find("#url").val();
|
// do not reload page
|
||||||
var user = $(e.target).find("#un").val();
|
e.preventDefault();
|
||||||
var password = $(e.target).find("#pw").val();
|
e.stopPropagation();
|
||||||
|
|
||||||
|
var server_url = $("#url").value;
|
||||||
|
var user = $("#un").value;
|
||||||
|
var password = $("#pw").value;
|
||||||
|
|
||||||
if(!this.onLine()) {
|
if(!this.onLine()) {
|
||||||
alert("You need to be on line to log in to your server.");
|
alert("You need to be on line to log in to your server.");
|
||||||
|
|
|
@ -48,7 +48,6 @@ TinyTinyRSS.prototype.doOperation = function(operation, new_options, callback) {
|
||||||
var xhr = new XMLHttpRequest({mozSystem: true});
|
var xhr = new XMLHttpRequest({mozSystem: true});
|
||||||
xhr.onreadystatechange = function() {
|
xhr.onreadystatechange = function() {
|
||||||
if(xhr.readyState == 4) {
|
if(xhr.readyState == 4) {
|
||||||
$.mobile.loading("hide");
|
|
||||||
if(xhr.status == 200) {
|
if(xhr.status == 200) {
|
||||||
if(callback)
|
if(callback)
|
||||||
callback(JSON.parse(xhr.responseText).content);
|
callback(JSON.parse(xhr.responseText).content);
|
||||||
|
@ -61,7 +60,6 @@ TinyTinyRSS.prototype.doOperation = function(operation, new_options, callback) {
|
||||||
}
|
}
|
||||||
xhr.open("POST", url, true);
|
xhr.open("POST", url, true);
|
||||||
xhr.send(JSON.stringify(options));
|
xhr.send(JSON.stringify(options));
|
||||||
$.mobile.loading("show");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TinyTinyRSS.prototype.getUnreadFeeds = function(callback, skip) {
|
TinyTinyRSS.prototype.getUnreadFeeds = function(callback, skip) {
|
||||||
|
@ -122,7 +120,6 @@ TinyTinyRSS.login = function(server_url, user, password, callback) {
|
||||||
var xhr = new XMLHttpRequest({mozSystem: true});
|
var xhr = new XMLHttpRequest({mozSystem: true});
|
||||||
xhr.onreadystatechange = function() {
|
xhr.onreadystatechange = function() {
|
||||||
if(xhr.readyState == 4) {
|
if(xhr.readyState == 4) {
|
||||||
$.mobile.loading("hide");
|
|
||||||
if(xhr.status == 200) {
|
if(xhr.status == 200) {
|
||||||
callback(JSON.parse(xhr.responseText).content)
|
callback(JSON.parse(xhr.responseText).content)
|
||||||
} else {
|
} else {
|
||||||
|
@ -132,5 +129,4 @@ TinyTinyRSS.login = function(server_url, user, password, callback) {
|
||||||
}
|
}
|
||||||
xhr.open("POST", url, true);
|
xhr.open("POST", url, true);
|
||||||
xhr.send(JSON.stringify(options));
|
xhr.send(JSON.stringify(options));
|
||||||
$.mobile.loading("show");
|
|
||||||
}
|
}
|
|
@ -5,35 +5,34 @@ function debug(obj) {
|
||||||
alert(obj)
|
alert(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle login stuff if needed
|
function $(obj) {
|
||||||
$(document).on("pageshow", function() {
|
if(typeof obj == "string") return document.querySelector(obj);
|
||||||
if(!window.app) window.app = new App();
|
else return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function $$(obj) {
|
||||||
|
if(typeof obj == "string") return document.querySelectorAll(obj);
|
||||||
|
else return new NodeList(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.getOwnPropertyNames(Array.prototype).forEach(function(methodName) {
|
||||||
|
NodeList.prototype[methodName] = Array.prototype[methodName];
|
||||||
});
|
});
|
||||||
|
|
||||||
// Listen for any attempts to call changePage().
|
Node.prototype.hasClass = function(cls) {
|
||||||
$(document).bind( "pagebeforechange", function( e, data ) {
|
return this.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
|
||||||
|
};
|
||||||
|
|
||||||
// We only want to handle changePage() calls where the caller is
|
Node.prototype.addClass = function(cls) {
|
||||||
// asking us to load a page by URL.
|
if (!this.hasClass(cls)) this.className += " " + cls;
|
||||||
if ( typeof data.toPage === "string" ) {
|
};
|
||||||
|
|
||||||
// We are being asked to load a page by URL, but we only
|
Node.prototype.removeClass = function(cls) {
|
||||||
// want to handle URLs that request the data for a specific
|
if (this.hasClass(cls)) {
|
||||||
// category.
|
var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
|
||||||
var u = $.mobile.path.parseUrl( data.toPage ),
|
this.className = this.className.replace(reg,' ');
|
||||||
re = /^#full-/;
|
|
||||||
|
|
||||||
if ( u.hash.search(re) !== -1 ) {
|
|
||||||
|
|
||||||
// We're being asked to display the items for a specific category.
|
|
||||||
// Call our internal method that builds the content for the category
|
|
||||||
// on the fly based on our in-memory category data structure.
|
|
||||||
var i = parseInt(u.hash.split("-")[1], 10);
|
|
||||||
app.showFull(app.unread_articles[i], false);
|
|
||||||
|
|
||||||
// Make sure to tell changePage() we've handled this call so it doesn't
|
|
||||||
// have to do anything.
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if(!window.app) window.app = new App();
|
||||||
|
|
||||||
|
|
599
js/jester.js
Normal file
599
js/jester.js
Normal file
|
@ -0,0 +1,599 @@
|
||||||
|
/*
|
||||||
|
* Jester JavaScript Library v0.3
|
||||||
|
* http://github.com/plainview/Jester
|
||||||
|
*
|
||||||
|
* Easy JavaScript gesture recognition.
|
||||||
|
*
|
||||||
|
* Released under MIT License
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 by Scott Seaward
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
(function(container, undefined) {
|
||||||
|
var Jester = container.Jester = {
|
||||||
|
cache : {},
|
||||||
|
cacheId : "Jester" + (new Date()).getTime(),
|
||||||
|
guid : 0,
|
||||||
|
|
||||||
|
// The Jester constructor
|
||||||
|
Watcher : function(element, options) {
|
||||||
|
|
||||||
|
var that = this,
|
||||||
|
cacheId = Jester.cacheId,
|
||||||
|
cache = Jester.cache,
|
||||||
|
gestures = "swipe flick tap doubletap pinchnarrow pinchwiden pinchend";
|
||||||
|
|
||||||
|
if(!element || !element.nodeType) {
|
||||||
|
throw new TypeError("Jester: no element given.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this element hasn't had Jester called on it before,
|
||||||
|
// set it up with a cache entry and give it the expando
|
||||||
|
if(typeof element[cacheId] !== "number") {
|
||||||
|
element[cacheId] = Jester.guid;
|
||||||
|
Jester.guid++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var elementId = element[cacheId];
|
||||||
|
|
||||||
|
if(!(elementId in cache)) {
|
||||||
|
Jester.cache[elementId] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var elementCache = Jester.cache[elementId];
|
||||||
|
|
||||||
|
if(!("options" in elementCache)) {
|
||||||
|
elementCache.options = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
options = options || elementCache.options || {};
|
||||||
|
|
||||||
|
// cache the option values for reuse or, if options already
|
||||||
|
// exist for this element, replace those that have been
|
||||||
|
// specified
|
||||||
|
if(elementCache.options !== options) {
|
||||||
|
for(var prop in options) {
|
||||||
|
if(elementCache.options[prop]) {
|
||||||
|
if(elementCache.options[prop] !== options[prop]) {
|
||||||
|
elementCache.options[prop] = options[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
elementCache.options[prop] = options[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!("eventSet" in elementCache) || !(elementCache.eventSet instanceof Jester.EventSet)) {
|
||||||
|
elementCache.eventSet = new Jester.EventSet(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!elementCache.touchMonitor) {
|
||||||
|
elementCache.touchMonitor = new Jester.TouchMonitor(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
var events = elementCache.eventSet;
|
||||||
|
var touches = elementCache.touchMonitor;
|
||||||
|
|
||||||
|
this.id = element[cacheId];
|
||||||
|
|
||||||
|
this.bind = function(evt, fn) {
|
||||||
|
if(evt && typeof evt === "string" && typeof fn === "function") {
|
||||||
|
events.register(evt, fn);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
// create shortcut bind methods for all gestures
|
||||||
|
gestures.split(" ").forEach(function(gesture) {
|
||||||
|
this[gesture] = function(fn) {
|
||||||
|
return this.bind(gesture, fn);
|
||||||
|
};
|
||||||
|
}, that);
|
||||||
|
|
||||||
|
this.start = function(fn) {
|
||||||
|
return this.bind("start", fn);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.during = function(fn) {
|
||||||
|
return this.bind("during", fn);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.end = function(fn) {
|
||||||
|
return this.bind("end", fn);
|
||||||
|
};
|
||||||
|
|
||||||
|
// wrapper to cover all three pinch methods
|
||||||
|
this.pinch = function(fns) {
|
||||||
|
if(typeof fns !== "undefined") {
|
||||||
|
// if its just a function it gets assigned to pinchend
|
||||||
|
if(typeof fns === "function") {
|
||||||
|
that.pinchend(fns);
|
||||||
|
}
|
||||||
|
else if(typeof fns === "object") {
|
||||||
|
var method;
|
||||||
|
"narrow widen end".split(" ").forEach(function(eventExt) {
|
||||||
|
method = "pinch" + eventExt;
|
||||||
|
if(typeof fns[eventExt] === "function") {
|
||||||
|
that[method](fns[eventExt]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.halt = function() {
|
||||||
|
touches.stopListening();
|
||||||
|
events.clear();
|
||||||
|
delete elementCache.eventSet;
|
||||||
|
delete elementCache.touchMonitor;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
EventSet : function(element) {
|
||||||
|
// all event names and their associated functions in an array i.e. "swipe" : [fn1, fn2, fn2]
|
||||||
|
var eventsTable = {};
|
||||||
|
this.eventsTable = eventsTable;
|
||||||
|
|
||||||
|
// register a handler with an event
|
||||||
|
this.register = function(eventName, fn) {
|
||||||
|
// if the event exists and has handlers attached to it, add this one to the array of them
|
||||||
|
if(eventsTable[eventName] && eventsTable[eventName].push) {
|
||||||
|
// make sure multiple copies of the same handler aren't inserted
|
||||||
|
if(!~eventsTable[eventName].indexOf(fn)) {
|
||||||
|
eventsTable[eventName].push(fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// create a new array bound to the event containing only the handler passed in
|
||||||
|
eventsTable[eventName] = [fn];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.release = function(eventName, fn) {
|
||||||
|
if(typeof eventName === "undefined") return;
|
||||||
|
|
||||||
|
// if a handler hasn't been specified, remove all handlers
|
||||||
|
if(typeof fn === "undefined") {
|
||||||
|
for(var handlers in eventsTable.eventName) {
|
||||||
|
delete eventsTable.eventName[handlers];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// pull the given handler from the given event
|
||||||
|
if(eventsTable[eventName] && ~eventsTable[eventName].indexOf(fn))
|
||||||
|
{
|
||||||
|
eventsTable[eventName].splice(eventsTable[eventName].indexOf(fn), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the event has no more handlers registered to it, get rid of the event completely
|
||||||
|
if(eventsTable[eventName] && eventsTable[eventName].length === 0) {
|
||||||
|
delete eventsTable[eventName];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// completely remove all events and their handlers
|
||||||
|
this.clear = function() {
|
||||||
|
var events;
|
||||||
|
for(events in eventsTable) {
|
||||||
|
delete eventsTable[events];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// get all the handlers associated with an event
|
||||||
|
// return an empty array if nothing is registered with the given event name
|
||||||
|
this.getHandlers = function(eventName) {
|
||||||
|
if(eventsTable[eventName] && eventsTable[eventName].length) {
|
||||||
|
return eventsTable[eventName];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// inject an array of handlers into the event table for the given event
|
||||||
|
// this will klobber all current handlers associated with the event
|
||||||
|
this.setHandlers = function(eventName, handlers) {
|
||||||
|
eventsTable[eventName] = handlers;
|
||||||
|
};
|
||||||
|
|
||||||
|
// execute all handlers associated with an event, passing each handler the arguments provided after the event's name.
|
||||||
|
this.execute = function(eventName) {
|
||||||
|
if(typeof eventName === "undefined") return;
|
||||||
|
|
||||||
|
// if the event asked for exists in the events table
|
||||||
|
if(eventsTable[eventName] && eventsTable[eventName].length) {
|
||||||
|
// get the arguments sent to the function
|
||||||
|
var args = Array.prototype.slice.call(arguments, 1);
|
||||||
|
|
||||||
|
// iterate throuh all the handlers
|
||||||
|
for(var i = 0; i < eventsTable[eventName].length; i++) {
|
||||||
|
// check current handler is a function
|
||||||
|
if(typeof eventsTable[eventName][i] === "function") {
|
||||||
|
// execute handler with the provided arguments
|
||||||
|
eventsTable[eventName][i].apply(element, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
TouchMonitor : function(element)
|
||||||
|
{
|
||||||
|
var cacheId = Jester.cacheId,
|
||||||
|
elementId = element[cacheId],
|
||||||
|
cache = Jester.cache,
|
||||||
|
elementCache = cache[elementId],
|
||||||
|
opts = elementCache.options;
|
||||||
|
|
||||||
|
opts.move = opts.move || {};
|
||||||
|
opts.scale = opts.scale || {};
|
||||||
|
|
||||||
|
opts.tapDistance = opts.tapDistance || 0;
|
||||||
|
opts.tapTime = opts.tapTime || 20;
|
||||||
|
|
||||||
|
opts.doubleTapTime = opts.doubleTapTime || 300;
|
||||||
|
|
||||||
|
opts.swipeDistance = opts.swipeDistance || 200;
|
||||||
|
|
||||||
|
opts.flickTime = opts.flickTime || 300;
|
||||||
|
opts.flickDistance = opts.flickDistance || 200;
|
||||||
|
|
||||||
|
opts.deadX = opts.deadX || 0;
|
||||||
|
opts.deadY = opts.deadY || 0;
|
||||||
|
|
||||||
|
if(opts.capture !== false) opts.capture = true;
|
||||||
|
if(typeof opts.preventDefault !== "undefined" && opts.preventDefault !== false) opts.preventDefault = true;
|
||||||
|
if(typeof opts.preventDefault !== "undefined" && opts.stopPropagation !== false) opts.stopPropagation = true;
|
||||||
|
|
||||||
|
var eventSet = elementCache.eventSet;
|
||||||
|
|
||||||
|
var touches;
|
||||||
|
var previousTapTime = 0;
|
||||||
|
|
||||||
|
var touchStart = function(evt) {
|
||||||
|
touches = new Jester.TouchGroup(evt);
|
||||||
|
|
||||||
|
eventSet.execute("start", touches, evt);
|
||||||
|
|
||||||
|
if(opts.preventDefault) evt.preventDefault();
|
||||||
|
if(opts.stopPropagation) evt.stopPropagation();
|
||||||
|
};
|
||||||
|
|
||||||
|
var touchMove = function(evt) {
|
||||||
|
touches.update(evt);
|
||||||
|
|
||||||
|
eventSet.execute("during", touches, evt);
|
||||||
|
|
||||||
|
if(opts.preventDefault) evt.preventDefault();
|
||||||
|
if(opts.stopPropagation) evt.stopPropagation();
|
||||||
|
|
||||||
|
if(touches.numTouches() == 2) {
|
||||||
|
// pinchnarrow
|
||||||
|
if(touches.delta.scale() < 0.0) {
|
||||||
|
eventSet.execute("pinchnarrow", touches);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pinchwiden
|
||||||
|
else if(touches.delta.scale() > 0.0) {
|
||||||
|
eventSet.execute("pinchwiden", touches);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var touchEnd = function(evt) {
|
||||||
|
|
||||||
|
var swipeDirection;
|
||||||
|
|
||||||
|
eventSet.execute("end", touches, evt);
|
||||||
|
|
||||||
|
if(opts.preventDefault) evt.preventDefault();
|
||||||
|
if(opts.stopPropagation) evt.stopPropagation();
|
||||||
|
|
||||||
|
if(touches.numTouches() == 1) {
|
||||||
|
// tap
|
||||||
|
if(touches.touch(0).total.x() <= opts.tapDistance && touches.touch(0).total.y() <= opts.tapDistance && touches.touch(0).total.time() < opts.tapTime) {
|
||||||
|
eventSet.execute("tap", touches);
|
||||||
|
}
|
||||||
|
|
||||||
|
// doubletap
|
||||||
|
if(touches.touch(0).total.time() < opts.tapTime) {
|
||||||
|
var now = (new Date()).getTime();
|
||||||
|
if(now - previousTapTime <= opts.doubleTapTime) {
|
||||||
|
eventSet.execute("doubletap", touches);
|
||||||
|
}
|
||||||
|
previousTapTime = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
// swipe left/right
|
||||||
|
if(Math.abs(touches.touch(0).total.x()) >= opts.swipeDistance) {
|
||||||
|
swipeDirection = touches.touch(0).total.x() < 0 ? "left" : "right";
|
||||||
|
eventSet.execute("swipe", touches, swipeDirection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// swipe up/down
|
||||||
|
if(Math.abs(touches.touch(0).total.y()) >= opts.swipeDistance) {
|
||||||
|
swipeDirection = touches.touch(0).total.y() < 0 ? "up" : "down";
|
||||||
|
eventSet.execute("swipe", touches, swipeDirection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// flick
|
||||||
|
if(Math.abs(touches.touch(0).total.x()) >= opts.flickDistance && touches.touch(0).total.time() <= opts.flickTime) {
|
||||||
|
var flickDirection = touches.touch(0).total.x() < 0 ? "left" : "right";
|
||||||
|
eventSet.execute("flick", touches, flickDirection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(touches.numTouches() == 2) {
|
||||||
|
// pinchend
|
||||||
|
if(touches.current.scale() !== 1.0) {
|
||||||
|
var pinchDirection = touches.current.scale() < 1.0 ? "narrowed" : "widened";
|
||||||
|
eventSet.execute("pinchend", touches, pinchDirection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var stopListening = function() {
|
||||||
|
element.removeEventListener("touchstart", touchStart, opts.capture);
|
||||||
|
element.removeEventListener("touchmove", touchMove, opts.capture);
|
||||||
|
element.removeEventListener("touchend", touchEnd, opts.capture);
|
||||||
|
};
|
||||||
|
|
||||||
|
element.addEventListener("touchstart", touchStart, opts.capture);
|
||||||
|
element.addEventListener("touchmove", touchMove, opts.capture);
|
||||||
|
element.addEventListener("touchend", touchEnd, opts.capture);
|
||||||
|
|
||||||
|
return {
|
||||||
|
stopListening: stopListening
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
TouchGroup : function(event) {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
var numTouches = event.touches.length;
|
||||||
|
|
||||||
|
var midpointX = 0;
|
||||||
|
var midpointY = 0;
|
||||||
|
|
||||||
|
var scale = event.scale;
|
||||||
|
var prevScale = scale;
|
||||||
|
var deltaScale = scale;
|
||||||
|
|
||||||
|
for(var i = 0; i < numTouches; i++) {
|
||||||
|
this["touch" + i] = new Jester.Touch(event.touches[i].pageX, event.touches[i].pageY);
|
||||||
|
midpointX = event.touches[i].pageX;
|
||||||
|
midpointY = event.touches[i].pageY;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNumTouches() {
|
||||||
|
return numTouches;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTouch(num) {
|
||||||
|
return that["touch" + num];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMidPointX() {
|
||||||
|
return midpointX;
|
||||||
|
}
|
||||||
|
function getMidPointY() {
|
||||||
|
return midpointY;
|
||||||
|
}
|
||||||
|
function getScale() {
|
||||||
|
return scale;
|
||||||
|
}
|
||||||
|
function getDeltaScale() {
|
||||||
|
return deltaScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTouches(event) {
|
||||||
|
var mpX = 0;
|
||||||
|
var mpY = 0;
|
||||||
|
|
||||||
|
for(var i = 0; i < event.touches.length; i++) {
|
||||||
|
if(i < numTouches) {
|
||||||
|
that["touch" + i].update(event.touches[i].pageX, event.touches[i].pageY);
|
||||||
|
mpX += event.touches[i].pageX;
|
||||||
|
mpY += event.touches[i].pageY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
midpointX = mpX / numTouches;
|
||||||
|
midpointY = mpY / numTouches;
|
||||||
|
|
||||||
|
prevScale = scale;
|
||||||
|
scale = event.scale;
|
||||||
|
deltaScale = scale - prevScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
numTouches: getNumTouches,
|
||||||
|
touch: getTouch,
|
||||||
|
current: {
|
||||||
|
scale: getScale,
|
||||||
|
midX: getMidPointX,
|
||||||
|
midY: getMidPointY
|
||||||
|
},
|
||||||
|
delta: {
|
||||||
|
scale: getDeltaScale
|
||||||
|
},
|
||||||
|
update: updateTouches
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
Touch : function(_startX, _startY) {
|
||||||
|
var startX = _startX,
|
||||||
|
startY = _startY,
|
||||||
|
startTime = now(),
|
||||||
|
currentX = startX,
|
||||||
|
currentY = startY,
|
||||||
|
currentTime = startTime,
|
||||||
|
currentSpeedX = 0,
|
||||||
|
currentSpeedY = 0,
|
||||||
|
prevX = startX,
|
||||||
|
prevY = startX,
|
||||||
|
prevTime = startTime,
|
||||||
|
prevSpeedX = 0,
|
||||||
|
prevSpeedY = 0,
|
||||||
|
deltaX = 0,
|
||||||
|
deltaY = 0,
|
||||||
|
deltaTime = 0,
|
||||||
|
deltaSpeedX = 0,
|
||||||
|
deltaSpeedY = 0,
|
||||||
|
totalX = 0,
|
||||||
|
totalY = 0,
|
||||||
|
totalTime = 0;
|
||||||
|
|
||||||
|
// position getters
|
||||||
|
function getStartX() {
|
||||||
|
return startX;
|
||||||
|
}
|
||||||
|
function getStartY() {
|
||||||
|
return startY;
|
||||||
|
}
|
||||||
|
function getCurrentX() {
|
||||||
|
return currentX;
|
||||||
|
}
|
||||||
|
function getCurrentY() {
|
||||||
|
return currentY;
|
||||||
|
}
|
||||||
|
function getPrevX() {
|
||||||
|
return prevX;
|
||||||
|
}
|
||||||
|
function getPrevY() {
|
||||||
|
return prevY;
|
||||||
|
}
|
||||||
|
function getDeltaX() {
|
||||||
|
return deltaX;
|
||||||
|
}
|
||||||
|
function getDeltaY() {
|
||||||
|
return deltaY;
|
||||||
|
}
|
||||||
|
function getTotalX() {
|
||||||
|
return totalX;
|
||||||
|
}
|
||||||
|
function getTotalY() {
|
||||||
|
return totalY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// time getters
|
||||||
|
function now() {
|
||||||
|
return (new Date()).getTime();
|
||||||
|
}
|
||||||
|
function getStartTime() {
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
function getCurrentTime() {
|
||||||
|
return currentTime;
|
||||||
|
}
|
||||||
|
function getPrevTime() {
|
||||||
|
return prevTime;
|
||||||
|
}
|
||||||
|
function getDeltaTime() {
|
||||||
|
return deltaTime;
|
||||||
|
}
|
||||||
|
function getTotalTime() {
|
||||||
|
return totalTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// speed getters
|
||||||
|
function getCurrentSpeedX() {
|
||||||
|
return currentSpeedX;
|
||||||
|
}
|
||||||
|
function getCurrentSpeedY() {
|
||||||
|
return currentSpeedY;
|
||||||
|
}
|
||||||
|
function getPrevSpeedX() {
|
||||||
|
return prevSpeedX;
|
||||||
|
}
|
||||||
|
function getPrevSpeedY() {
|
||||||
|
return prevSpeedY;
|
||||||
|
}
|
||||||
|
function getDeltaSpeedX() {
|
||||||
|
return deltaSpeedX;
|
||||||
|
}
|
||||||
|
function getDeltaSpeedY() {
|
||||||
|
return deltaSpeedY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: {
|
||||||
|
x: getStartX,
|
||||||
|
y: getStartY,
|
||||||
|
speedX: 0,
|
||||||
|
speedY: 0,
|
||||||
|
time: getStartTime
|
||||||
|
},
|
||||||
|
current: {
|
||||||
|
x: getCurrentX,
|
||||||
|
y: getCurrentY,
|
||||||
|
time: getCurrentTime,
|
||||||
|
speedX: getCurrentSpeedX,
|
||||||
|
speedY: getCurrentSpeedY
|
||||||
|
},
|
||||||
|
prev: {
|
||||||
|
x: getPrevX,
|
||||||
|
y: getPrevY,
|
||||||
|
time: getPrevTime,
|
||||||
|
speedX: getPrevSpeedX,
|
||||||
|
speedY: getPrevSpeedY
|
||||||
|
},
|
||||||
|
delta: {
|
||||||
|
x: getDeltaX,
|
||||||
|
y: getDeltaY,
|
||||||
|
speedX: getDeltaSpeedX,
|
||||||
|
speedY: getDeltaSpeedY,
|
||||||
|
time: getDeltaTime
|
||||||
|
},
|
||||||
|
total: {
|
||||||
|
x: getTotalX,
|
||||||
|
y: getTotalY,
|
||||||
|
time: getTotalTime
|
||||||
|
},
|
||||||
|
update: function(_x, _y) {
|
||||||
|
prevX = currentX;
|
||||||
|
prevY = currentY;
|
||||||
|
currentX = _x;
|
||||||
|
currentY = _y;
|
||||||
|
deltaX = currentX - prevX;
|
||||||
|
deltaY = currentY - prevY;
|
||||||
|
totalX = currentX - startX;
|
||||||
|
totalY = currentY - startY;
|
||||||
|
|
||||||
|
prevTime = currentTime;
|
||||||
|
currentTime = now();
|
||||||
|
deltaTime = currentTime - prevTime;
|
||||||
|
totalTime = currentTime - startTime;
|
||||||
|
|
||||||
|
prevSpeedX = currentSpeedX;
|
||||||
|
prevSpeedY = currentSpeedY;
|
||||||
|
currentSpeedX = deltaX / (deltaTime/1000);
|
||||||
|
currentSpeedY = deltaY / (deltaTime/1000);
|
||||||
|
deltaSpeedX = currentSpeedX - prevSpeedX;
|
||||||
|
deltaSpeedY = currentSpeedY - prevSpeedY;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
container.jester = function(el, opts) {
|
||||||
|
return new Jester.Watcher(el, opts);
|
||||||
|
};
|
||||||
|
|
||||||
|
}(window));
|
9003
js/jquery.js
vendored
9003
js/jquery.js
vendored
File diff suppressed because it is too large
Load diff
11215
js/jquery.mobile.js
11215
js/jquery.mobile.js
File diff suppressed because it is too large
Load diff
Reference in a new issue