summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md281
-rw-r--r--Gruntfile.js6
-rw-r--r--css/pomf.css33
-rw-r--r--js/app.js170
-rw-r--r--js/cabinet.js66
-rw-r--r--js/cheesesteak.js232
-rw-r--r--js/pomf.js175
-rw-r--r--js/zepto.js1035
-rw-r--r--package.json3
-rw-r--r--pages/banners.swig5
-rw-r--r--pages/banners/donate.swig5
-rw-r--r--pages/banners/virusscans.swig5
-rw-r--r--pages/index.swig2
-rw-r--r--pages/layout.swig3
-rw-r--r--pages/nojs.swig2
-rw-r--r--schema.sql2
-rwxr-xr-xstatic/classes/Response.class.php24
-rw-r--r--static/classes/UploadedFile.class.php1
-rw-r--r--static/upload.php6
19 files changed, 527 insertions, 1529 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..b4b5bfb
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,281 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+This project adheres to [Semantic Versioning](http://semver.org/).
+
+## `2.1.0` - Unreleased
+
+### Added
+
+- `CHANGELOG.md`. (Juuso Lapinlampi)
+- HTML `<meta name="generator">` with Pomf version. Generated with grunt-swig.
+ (Juuso Lapinlampi)
+
+### Changed
+
+- All client-side JavaScript replaced with more efficient, smaller vanilla
+ JavaScript. (Luminarys)
+- Luminarys added to `package.json` contributors. (Juuso Lapinlampi)
+
+### Deprecated
+
+- Swig banners. Use Swig templates or an alternative. (Juuso Lapinlampi)
+- Unused file expiration (`expire`). This feature may be removed in the
+ next major version. (Juuso Lapinlampi)
+- `get_sha1()` function. This API may be changed or removed in the next
+ major version, switching to SHA-256 hashes. (Juuso Lapinlampi)
+- `csv_error`, `csv_success`, `html_error`, `html_success`, `json_error`,
+ `json_success`, `text_error` and `text_success` functions. The
+ functions will be renamed to `camelCase` format (e.g. `csvError`,
+ `htmlSuccess`). (Juuso Lapinlampi)
+
+## `2.0.2` - Unreleased
+
+### Changed
+
+- `npm bugs` URL replaced with an email address. (Juuso Lapinlampi)
+
+### Fixed
+
+- LibreJS `@source` URL to git.pantsu.cat's new cgit tree. (Juuso Lapinlampi)
+- `package.json` package name to lowercase as per NPM rules. (Juuso Lapinlampi)
+- Alphabetical order of grunt-swig options in `Gruntfile.js`. (Juuso Lapinlampi)
+- "Getting help" IRC contact for developers in `README.md`. (Juuso Lapinlampi)
+
+## `2.0.1` - 2016-01-28
+
+### Changed
+
+- Gyazo Client renamed to Gyazowin in tools page to match the actual project
+ name. (Juuso Lapinlampi)
+
+### Fixed
+
+- ShareX URL and settings in tools page. (Juuso Lapinlampi)
+- Gyazowin URL in tools page. (Juuso Lapinlampi)
+- PHPCS lint error about a missing newline after `text_error()`. (Juuso
+ Lapinlampi)
+- PHP warnings about undeclared variables in `html_success()` and
+ `text_success()`. (Juuso Lapinlampi)
+
+### Removed
+
+- Unused, commented `a:focus` `outline-offset` in CSS. (Luminarys)
+- Unused `check_fileapi.swig` inclusion in `nojs.swig`. (Juuso Lapinlampi)
+- Unused `span.old` and `section.ded` CSS rules leftover from 2.0.0 release.
+ (Eliot Whalan)
+
+## `2.0.0` - 2016-01-10
+
+### Added
+
+- "Other services" page for Pantsu.cat. (Eliot Whalan)
+- `lang` attributes for screen reader accessibility. (Eliot Whalan)
+- Configuration option `POMF_FILES_LENGTH` for number of random characters to
+ use in a generated filename. (Juuso Lapinlampi)
+- JavaScript-free upload. (Eliot Whalan)
+- HTML response API (for JavaScript-free upload). (Eliot Whalan)
+- Text response API. (Eliot Whalan)
+- limf and 1339secure to tools page. (Eliot Whalan, Juuso Lapinlampi)
+- LibreJS compatibility. (Eliot Whalan)
+- License headers in source code. (Juuso Lapinlampi)
+- Link to Pantsu.cat's Tor hidden service. (Eliot Whalan)
+- Credits, contributing, features, demo and getting help sections to
+ `README.md`. (Juuso Lapinlampi)
+- Git mailmap. (Juuso Lapinlampi)
+
+### Changed
+
+- Rebrand from Pomf.se to Pantsu.cat. (Eliot Whalan)
+- Viewports no longer have a maximum scale. (Eliot Whalan)
+- All tool configurations on tools page to use Pantsu.cat for uploading.
+ (Eliot Whalan)
+- "Autist neckbeard" warning on front page for users without JavaScript. (Eliot
+ Whalan)
+- Response Content-Type charset is now all uppercase (UTF-8). (Juuso
+ Lapinlampi)
+- npm dependencies have been updated to latest versions as of release. Fixes
+ deprecation warnings. (Eliot Whalan)
+- npm dependencies accept caret (minor release) instead of tilde (patch
+ release). (Eliot Whalan)
+- Increase user-configured maximum upload size to 128MiB. (Eliot Whalan)
+- The upload button is now a `<button>` element instead of `<a>` hyperlink.
+ Improves semantics and accessibility. (Juuso Lapinlampi)
+- Banners are no longer displayed on the FAQ page. (Juuso Lapinlampi)
+- FAQ has been rewritten from scratch to explain what Pantsu.cat is and what
+ its policies are. Semantically correct and prettier. (Juuso Lapinlampi)
+
+### Deprecated
+
+- Gyazo response API. Use text response instead. (Juuso Lapinlampi)
+- JavaScript ES5 code. A future release will update the JavaScript source to
+ modern ES6. Browser compatibility may be affected. (Juuso Lapinlampi)
+
+### Removed
+
+- All unmaintained and dead tools from tools page. (Eliot Whalan)
+- Internet Explorer 8 quirks mode compatibility in uglified JavaScript. (Juuso
+ Lapinlampi)
+- Moe panel from core, including most of the code in core for it. It is now an
+ (unsupported) extension. (Eliot Whalan, Juuso Lapinlampi)
+- Unnecessary TODO section from `README.md`. (Harry H)
+- Code and images for non-free kawaii anime girls. The latter cannot be
+ redistributed with the source. (Juuso Lapinlampi)
+- Unused Grunt `cssmin` task's banner option. (Juuso Lapinlampi)
+- Grunt HTML minification task. (Juuso Lapinlampi)
+- Unused Grunt `mkdir` task. (Juuso Lapinlampi)
+- Unused "POCKY~" CSS style rules. (Juuso Lapinlampi)
+- Unused, commented Mozilla file input JavaScript code. (Juuso Lapinlampi)
+
+### Fixed
+
+- Missing whitespace in upload button label. (Eliot Whalan)
+- Favicon HTML markup now uses modern `rel="icon"` markup. (Eliot Whalan)
+- Refactored `generate_name()` for bug fixing. (Juuso Lapinlampi)
+- Use UNIX socket in `POMF_DB_CONN` configuration option for faster database
+ queries. (Juuso Lapinlampi)
+- Format all PHP code to PSR-2 style guide, fixes lint errors. (Juuso
+ Lapinlampi)
+- Decode `&hellip;` correctly when the file is too big. (Juuso Lapinlampi)
+- Remove other `&hellip;` decoding hack in `case 413`. (Juuso Lapinlampi)
+- Whitespace in Swig templates, PHP and JavaScript. (Juuso Lapinlampi)
+- `README.md` header outline, fixes accessibility. (Juuso Lapinlampi)
+- Add missing authors to `LICENSE` and other files. (Juuso Lapinlampi)
+- Format and lint all JavaScript code to Airbnb ES5 style. About 350 lint
+ errors found, each carefully fixed by hand. (Juuso Lapinlampi)
+- Ambiguity in choice of words for licensing (MIT to Expat). No actual change
+ of license. (Eliot Whalan)
+- Use strict PHP comparison for upload `$tries`. (Juuso Lapinlampi)
+- Remove multiple instances of code duplication in JavaScript. (Juuso
+ Lapinlampi)
+- Virus scan banner is now informative (`.alert-info`), not an error
+ (`.alert-error`). (Juuso Lapinlampi)
+- Reduced `npm install` time from 15-30 seconds to mere ~5 seconds (on modern
+ Intel i7-3770K machine), resulting in faster builds. (Juuso Lapinlampi)
+- Minor `README.md` documentation errors. (Juuso Lapinlampi)
+- WCAG 2.0 contrast (section 1.4.3) in `.alert-info`. (Juuso Lapinlampi)
+- Capitalization of "ShareX" heading on tools page. (Juuso Lapinlampi)
+
+## `1.0.0+8757e9a` - 2015-08-15
+
+Last Git repository snapshot in `nokonoko/Pomf` before forking to
+`pantsu/pomf`. No formal release.
+
+### Added
+
+- Gyazo and CSV response types. (Peter Lejeck)
+- Flattr to donation banner. (Peter Lejeck)
+- Label and message to Bitcoin URL in donation banner. (Peter Lejeck)
+- CSS for donation buttons. (Peter Lejeck)
+- Moe panel for login/administration. (Eric Johansson)
+- Alternative email contact for file deletion in FAQ. (Eric Johansson)
+- CSS for old and dead tools. (Peter Lejeck)
+- Double dot file extensions support. Configurable in `settings.inc.php`. (Peter
+ Lejeck)
+- Disclaimer about unsupported web browsers in FAQ. (Eric Johansson)
+- Initial file expiration support for moe panel. (Eric Johansson)
+- MySQL schema (`schema.sql`) for installing Pomf. (Eric Johansson, cenci0)
+- MySQL schema (`update.sql`) to help migrate old databases to the new moe panel
+ schema. (cenci0, Austin Gillman)
+- HTTP compression support in `upload.php`. (cenci0)
+- Configuration option `POMF_URL`. (cenci0)
+- `diverse_array` and `refiles` API in `upload.php`. (cenci0)
+- HTML minification using grunt-contrib-htmlmin. (cenci0)
+- Instructions in `README.md` on how to enable compression in Apache webserver.
+ (cenci0)
+- Todo section to `README.md`. (Eric Johansson)
+- Advice to disable PHP execution for uploaded `.php` files. (Eric Johansson)
+- Configurable `{{max_upload_size`}} option in `Gruntfile.js` to replace
+ hardcoded 50MiB value. Defaults to value 50. (Kieran Harkin)
+
+### Changed
+
+- `POMF_DB_CONN` default host to `127.0.0.1`. (Eric Johansson)
+- Paddings on `.alert` boxes simplified. (Peter Lejeck)
+- Donation plea. (Peter Lejeck)
+- Donate buttons are unified and on a single row. (Peter Lejeck)
+- PayPal's encrypted `<form>` replaced with a link in donation banner. (Peter
+ Lejeck)
+- Virus scans banner to match the donate banner scheme.
+- Donate banner is now an `.alert-info` instead of `.alert-error`. (Peter
+ Lejeck)
+- `generate_name` algorithm. Generates random lowercase letters from `a` to `z`
+ instead of a mix of CRC-32B and random lowercase letters. (Eric Johansson)
+- Tools page tool names and API status updated. (Eric Johansson, Peter Lejeck)
+- Gyazo `generate_name` algorithm to `FxxAxxG.png`, where `x` is a random
+ lowercase letter. Removes CRC-32B checksums and `$grill` parameter from the
+ function. (Eric Johansson)
+- Increased length of `generate_name` return string by one character. (Eric
+ Johansson)
+- Default `POMF_FILES_RETRIES` increased from 5 to 15. (Eric Johansson, Peter
+ Lejeck)
+- `nav.swig` links to new places of interest of other Pomf.se projects and
+ social media. (Eric Johansson)
+- Genericize defaults function into merge utility in `cheesesteak.js`. (Peter
+ Lejeck)
+- `README.md` now uses a hyperlink to `@nekunekus` Twitter account. (Eric
+ Johansson)
+- Refactored the core PHP code in Pomf. Introduced classes. (cenci0)
+- `.alert-info`, `.alert-error`, `nav a` and `a` CSS colors to satisfy WCAG 2.0
+ requirements on contrast (section 1.4.3). Patch by Juuso Lapinlampi. (Eric
+ Johansson)
+
+### Fixed
+
+- `git clone` URL in `README.md`. (Eric Johansson)
+- PHPDoc comments in `upload.php`. (Peter Lejeck)
+- A bug in `refiles()`. Deferences `$file`. (Peter Lejeck, catboy)
+- Broken tools download URLs. (Eric Johansson)
+- Uploading files without file extension. (Eric Johansson)
+- Bitcoin wallet URI in donation banner. (Eric Johansson)
+- ShareX settings URL in tools. (Eric Johansson)
+- Gyazo Client author's Twitter URL. (Eric Johansson)
+- Code indentation in `upload.php`. (Peter Lejeck)
+- Reduntant `settings.inc.php` inclusion twice in `upload.php`. (benwaffle)
+- Moe panel incorrectly returning 5 entries instead of none in search while
+ there's no search query. (benwaffle)
+- Cross-site scripting vulnerability in moe panel from arbitrary `originalname`.
+ No CVE requested. Reported by Juuso Lapinlampi. (Eric Johansson)
+- Copy-pasted code rolled into a `for` loop in `generate_name`. (Michael
+ "wafflestealer654")
+- HTML validation for `case 413` in `pomf.js`. (cenci0)
+- `README.md` title from Pomf.se to Pomf. (Eric Johansson)
+- Pass full URL back to the client in response. (Kieran Harkin)
+
+### Removed
+
+- Link to mail newsletter in FAQ. (Eric Johansson)
+- Unused `blackniggers/kittens.php`. Previously used for Gyazo client, now
+ replaced. (Eric Johansson)
+- Unused `get_crc32` function in `UploadedFile.class.php`. Reported by Juuso
+ Lapinlampi. (Eric Johansson)
+
+## `v1.0.0` - 2013-10-31
+
+Initial unofficial release in `nokonoko/Pomf`. Changes are since initial commit.
+
+### Added
+
+- `LICENSE` with Expat license. (Eric Johansson)
+- Email and Twitter contacts to `README.md`. (Eric Johansson)
+- Frequently asked questions (FAQ). (Eric Johansson)
+- Favicon. (Eric Johansson)
+- Kawaii anime girls (`grill.php`). (Eric Johansson)
+- Web interface with JavaScript. (Eric Johansson, Peter Lejeck)
+- Tools page. (Eric Johansson)
+- `upload.php`, `UploadedFile.class.php`, `database.inc.php`,
+ `settings.inc.php`. (Eric Johansson, Peter Lejeck)
+- Gyazo support (`blackniggers/kittens.php`) with `generate_name` function.
+ (Eric Johansson)
+- Grunt buildsystem. (Peter Lejeck)
+- Swig pages. (Peter Lejeck)
+- Swig banners. (Peter Lejeck)
+- `README.md` documentation. (Peter Lejeck)
+
+### Changed
+
+- `.gitignore` will only ignore `dist/` and `node_modules`. (Peter Lejeck)
+
+### Removed
+
+- `.gitattributes`. (Eric Johansson)
diff --git a/Gruntfile.js b/Gruntfile.js
index 9e95c5b..488e5b7 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -11,6 +11,7 @@ module.exports = function (grunt) {
generateRobotstxt: false,
generateSitemap: false,
max_upload_size: 128,
+ pkgVersion: '<%= pkg.version %>',
production: false,
siteUrl: 'https://pantsu.cat/',
src: [
@@ -33,10 +34,7 @@ module.exports = function (grunt) {
dist: {
files: {
'dist/pomf.min.js': [
- 'js/zepto.js',
- 'js/cheesesteak.js',
- 'js/cabinet.js',
- 'js/pomf.js'
+ 'js/app.js'
]
}
}
diff --git a/css/pomf.css b/css/pomf.css
index 66fa382..676845e 100644
--- a/css/pomf.css
+++ b/css/pomf.css
@@ -239,7 +239,7 @@ nav > ul > li:last-child:after {
.error#upload-filelist {
color: #891A18;
}
-.error#upload-filelist .file-size {
+.error#upload-filelist .progress-percent {
color: #B94A48;
}
.error#upload-filelist .file-progress {
@@ -261,13 +261,12 @@ nav > ul > li:last-child:after {
text-overflow: ellipsis;
white-space: nowrap;
}
-.file-size,
+.file-progress,
.file-url {
display: inline-block;
float: right;
font-size: 0.9em;
margin-left: 8px;
- color: #5C5C5C;
vertical-align: middle;
}
.file-url a {
@@ -276,9 +275,29 @@ nav > ul > li:last-child:after {
.file-url a:hover {
color: #1C1C1C;
}
+.progress-percent {
+ float: right;
+}
+
+progress[value] {
+ /* Reset the default appearance */
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+
+ border: none;
+
+}
+
+progress[value]::-webkit-progress-bar {
+ background-color: #eee;
+ border-radius: 2ps;
+ box-shadow: 0 2px 5px rgba(0,0,0,0.25) inset;
+}
+
/* completed rows */
.completed .file-progress,
-.completed .file-size {
+.completed .progress-percent {
display: none;
}
.completed .file-url {
@@ -341,14 +360,8 @@ nav > ul > li:last-child:after {
margin-bottom: 12px;
}
.file-progress {
- float: left;
width: 70%;
}
- .file-size {
- float: left;
- max-width: 30%;
- overflow: hidden;
- }
.file-name, .file-url {
width: 100%;
max-width: 100%;
diff --git a/js/app.js b/js/app.js
new file mode 100644
index 0000000..5b29a63
--- /dev/null
+++ b/js/app.js
@@ -0,0 +1,170 @@
+/**
+ * Copyright (c) 2016 Luminarys <postmaster@gensok.io>
+ *
+ * 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 addRow(file) {
+ var row = document.createElement('li');
+
+ var name = document.createElement('span');
+ name.textContent = file.name;
+ name.className = 'file-name';
+
+ var progressIndicator = document.createElement('span');
+ progressIndicator.className = 'progress-percent';
+ progressIndicator.textContent = '0%';
+
+ var progressBar = document.createElement('progress');
+ progressBar.className = 'file-progress';
+ progressBar.setAttribute("max", "100");
+ progressBar.setAttribute("value", "0");
+
+ row.appendChild(name);
+ row.appendChild(progressBar);
+ row.appendChild(progressIndicator);
+
+ document.getElementById('upload-filelist').appendChild(row);
+ return row;
+}
+
+function handleUploadProgress(evt) {
+ var xhr = evt.target;
+ var bar = xhr.bar;
+ var percentIndicator = xhr.percent;
+
+ if (evt.lengthComputable) {
+ var progressPercent = Math.floor((evt.loaded / evt.total) * 100);
+ bar.setAttribute("value", progressPercent);
+ percentIndicator.textContent = progressPercent + '%';
+ }
+}
+
+function handleUploadComplete(evt) {
+ var xhr = evt.target;
+ var bar = xhr.bar;
+ var row = xhr.row;
+ var percentIndicator = xhr.percent;
+
+ percentIndicator.style.visibility = "hidden";
+ bar.style.visibility = "hidden";
+ row.removeChild(bar);
+ row.removeChild(percentIndicator);
+ var respStatus = xhr.status;
+
+ var url = document.createElement('span');
+ url.className = 'file-url';
+ row.appendChild(url);
+
+ var link = document.createElement('a');
+ if (respStatus === 200) {
+ var response = JSON.parse(xhr.responseText);
+ if (response.success) {
+ link.textContent = response.files[0].url.replace(/.*?:\/\//g, "");
+ link.href = response.files[0].url;
+ url.appendChild(link);
+ } else {
+ bar.innerHTML = 'Error: ' + response.reason;
+ }
+ } else if (respStatus === 413) {
+ link.textContent = 'File Too big!';
+ url.appendChild(link);
+ } else {
+ link.textContent = 'Server error!';
+ url.appendChild(link);
+ }
+}
+
+function uploadFile(file, row) {
+ var bar = row.querySelector('.file-progress');
+ var percentIndicator = row.querySelector('.progress-percent');
+ var xhr = new XMLHttpRequest();
+ xhr.open('POST', '/upload.php');
+
+ xhr["row"] = row;
+ xhr["bar"] = bar;
+ xhr["percent"] = percentIndicator;
+ xhr.upload["bar"] = bar;
+ xhr.upload["percent"] = percentIndicator;
+
+ xhr.addEventListener('load', handleUploadComplete, false);
+ xhr.upload.onprogress = handleUploadProgress;
+
+ var form = new FormData();
+ form.append('files[]', file);
+ xhr.send(form);
+}
+
+function stopDefaultEvent(evt) {
+ evt.stopPropagation();
+ evt.preventDefault();
+}
+
+function handleDrag(state, element, evt) {
+ stopDefaultEvent(evt);
+ if (state.dragCount == 1) {
+ element.textContent = "Drop it here~";
+ }
+ state.dragCount += 1;
+}
+
+function handleDragAway(state, element, evt) {
+ stopDefaultEvent(evt);
+ state.dragCount -= 1;
+ if (state.dragCount == 0) {
+ element.textContent = "Select or drop file(s)";
+ }
+}
+
+function handleDragDrop(state, element, evt) {
+ stopDefaultEvent(evt);
+ handleDragAway(state, element, evt);
+ var len = evt.dataTransfer.files.length;
+ for (var i = 0; i < len; i++) {
+ var file = evt.dataTransfer.files[i];
+ var row = addRow(file);
+ uploadFile(file, row);
+ }
+}
+
+function uploadFiles(evt) {
+ var len = evt.target.files.length;
+ for (var i = 0; i < len; i++) {
+ var file = evt.target.files[i];
+ var row = addRow(file);
+ uploadFile(file, row);
+ }
+}
+
+function selectFiles(target, evt) {
+ stopDefaultEvent(evt);
+ target.click();
+}
+
+var state = { dragCount: 0 };
+var uploadButton = document.getElementById('upload-btn');
+window.addEventListener('dragenter', handleDrag.bind(this, state, uploadButton), false);
+window.addEventListener('dragleave', handleDragAway.bind(this, state, uploadButton), false);
+window.addEventListener('drop', handleDragAway.bind(this, state, uploadButton), false);
+window.addEventListener('dragover', stopDefaultEvent, false);
+
+var uploadInput = document.getElementById('upload-input');
+uploadInput.addEventListener('change', uploadFiles);
+uploadButton.addEventListener('click', selectFiles.bind(this, uploadInput));
+uploadButton.addEventListener('drop', handleDragDrop.bind(this, state, uploadButton), false);
diff --git a/js/cabinet.js b/js/cabinet.js
deleted file mode 100644
index ba28a33..0000000
--- a/js/cabinet.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Copyright (c) 2013 Peter Lejeck <peter.lejeck@gmail.com>
- *
- * 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(cabinet) {
- cabinet.hasFileAPI = function hasFileAPI() {
- return Boolean(window.FormData);
- };
-
- $.fn.cabinet = function(uploadInput) {
- var $input = $(uploadInput);
-
- var _this = this;
- var passthrough = function(outer, inner, prevent, fn) {
- _this.on(outer, function(evt) {
- if (inner === 'click') {
- $input[0].click();
- } else {
- $input.trigger(inner);
- }
-
- if (prevent) {
- evt.preventDefault();
- }
-
- if (fn) {
- fn(evt);
- }
- }, false);
- };
-
- $input[0].filelist = Object.create(FileList);
-
- $input.on('change', function(evt) {
- this.filelist = evt.target.files;
- _this.change();
- });
-
- passthrough('dragenter', 'dragenter', true);
- passthrough('dragover', 'dragover', true);
- passthrough('dragleave', 'dragleave', true);
- passthrough('click', 'click', false);
- passthrough('drop', 'dragleave', true, function(evt) {
- $input[0].filelist = evt.dataTransfer.files;
- _this.change();
- });
- };
-})($);
diff --git a/js/cheesesteak.js b/js/cheesesteak.js
deleted file mode 100644
index 6e20880..0000000
--- a/js/cheesesteak.js
+++ /dev/null
@@ -1,232 +0,0 @@
-/**
- * Copyright (c) 2013 Peter Lejeck <peter.lejeck@gmail.com>
- *
- * 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() {
- // Lightweight EventEmitter implementation
- var EventEmitter = function() {};
-
- // Utility to convert bytes into human units
- var humanSize = {
- get: function humanSize() {
- var units = [
- 'B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB',
- ];
- var base = Math.floor(Math.log(this.size) / Math.log(1024));
- return (this.size / Math.pow(1024, base)).toFixed(2) + ' ' + units[base];
- },
- };
-
- var percentUploaded = {
- get: function percentUploaded() {
- return this.uploadedSize / this.size;
- },
- };
-
- // b gets merged as defaults for a
- var merge = function merge(base, overlay) {
- var out = base;
- var key;
-
- for (key in overlay) {
- if (typeof overlay[key] === 'object') {
- out[key] = merge(base[key], overlay[key]);
- } else {
- out[key] = overlay[key];
- }
- }
-
- return out;
- };
-
- var FileListUploader = function(url, files, opts) {
- var request = opts || {};
-
- this.url = url;
- this.files = files;
- this.opts = merge({
- field: 'files[]',
- method: 'POST',
- data: {},
- }, request);
- };
-
- EventEmitter.prototype.on = function(evt, fn) {
- this._events = this._events || {};
- this._events[evt] = this._events[evt] || [];
- this._events[evt].push(fn);
- };
-
- EventEmitter.prototype.off = function(evt, fn) {
- if (!this.hasOwnProperty('_events') || evt in this._events === false) {
- return;
- }
-
- this._events[evt].splice(this._events[evt].indexOf(fn), 1);
- };
-
- EventEmitter.prototype.emit = function(evt) {
- var i;
- var len;
-
- // Check whether the event we want to emit actually exists
- if (!this.hasOwnProperty('_events') || evt in this._events === false) {
- return;
- }
-
- len = this._events[evt].length;
-
- // Call all functions that are bound to the event
- for (i = 0; i < len; i++) {
- this._events[evt][i].apply(this, Array.prototype.slice.call(arguments,
- 1));
- }
- };
-
- // Copy the stuff from Array to FileList
- FileList.prototype.forEach = Array.prototype.forEach;
- FileList.prototype.every = Array.prototype.every;
- FileList.prototype.some = Array.prototype.some;
- FileList.prototype.filter = Array.prototype.filter;
- FileList.prototype.map = Array.prototype.map;
- FileList.prototype.reduce = Array.prototype.reduce;
- FileList.prototype.reduceRight = Array.prototype.reduceRight;
-
- Object.defineProperty(FileList.prototype, 'size', {
- get: function getSize() {
- return this.reduce(function(prev, curr) {
- return prev + curr.size;
- }, 0);
- },
- });
-
- Object.defineProperty(FileList.prototype, 'humanSize', humanSize);
- Object.defineProperty(File.prototype, 'humanSize', humanSize);
-
- Object.defineProperty(FileList.prototype, 'percentUploaded',
- percentUploaded);
- Object.defineProperty(File.prototype, 'percentUploaded', percentUploaded);
-
- Object.defineProperty(FileList.prototype, 'uploadedSize', {
- get: function getUploadedSize() {
- return this.reduce(function(prev, curr) {
- return prev + (curr.uploadedSize || 0);
- }, 0);
- },
- });
-
- // Object URL stuff
- Object.defineProperty(File.prototype, 'url', {
- get: function getURL() {
- return window.URL.createObjectURL(this);
- },
- });
- File.revokeURL = function revokeURL(url) {
- window.URL.revokeObjectURL(url);
- };
-
- FileListUploader.prototype = Object.create(EventEmitter.prototype);
- FileListUploader.prototype.upload = function(cb) {
- var opts = this.opts;
- var files = this.files;
- var _this = this;
- var len = files.length;
- var data = new FormData();
- var xhr = new XMLHttpRequest();
- var i;
-
- if (cb) {
- this.on('uploadcomplete', cb);
- }
-
- files.forEach(function(file) {
- data.append(opts.field, file);
- });
-
- xhr.open(opts.method, this.url, true);
-
- function initProgressBar() {
- for (i = 0; i < len; i++) {
- files[i].uploadedSize = 0;
- }
- }
-
- xhr.upload.addEventListener('loadstart', initProgressBar);
-
- function updateProgressBar(evt) {
- var size;
-
- if (evt.lengthComputable) {
- size = evt.loaded;
-
- /**
- * We know the size of the files, the order they're in, and how
- * much we've uploaded. Based on this data, we can do some magic
- * to figure out which file we're on, and how much we've uploaded
- * of that file.
- */
-
- // TODO: This math has trouble on later uploads. Leak somewhere.
- for (i = 0; i < len; i++) {
- files[i].uploadedSize = Math.min(size, files[i].size);
- size -= files[i].uploadedSize;
- if (size <= 0) {
- files.current = files[i];
- size = 0;
- }
- }
- }
-
- _this.emit('uploadprogress', evt, files);
- }
-
- xhr.upload.addEventListener('progress', updateProgressBar, false);
-
- // The upload is complete, now tell the user to wait for URLs.
- function postUpload(evt) {
- _this.emit('uploadcomplete', evt);
- }
-
- xhr.upload.addEventListener('load', postUpload);
-
- // Tell the browser the upload completed and wait for response.
- function postProgress(evt) {
- _this.emit('progress', evt);
- }
-
- xhr.addEventListener('progress', postProgress);
-
- // Send a success/error response. Nothing more to do.
- function uploadFinished(evt) {
- _this.emit('load', evt, xhr.responseText);
- }
-
- xhr.addEventListener('load', uploadFinished);
-
- xhr.send(data);
-
- // TODO: Add more event passthroughs, maybe abstract it into a helper?
- };
-
- FileList.prototype.upload = function uploadFileList(url, opts) {
- return new FileListUploader(url, this, opts);
- };
-})();
diff --git a/js/pomf.js b/js/pomf.js
deleted file mode 100644
index cf91e35..0000000
--- a/js/pomf.js
+++ /dev/null
@@ -1,175 +0,0 @@
-/**
- * Copyright (c) 2013 Peter Lejeck <peter.lejeck@gmail.com>
- * Copyright (c) 2015 the Pantsu.cat developers <hostmaster@pantsu.cat>
- *
- * 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() {
- var $uploadInput = $('#upload-input');
- var $uploadBtn = $('#upload-btn');
- var $uploadFiles = $('#upload-filelist');
-
- var $btnContent = '';
-
- var MAX_SIZE = (function(node) {
- var max = node.attr('data-max-size') || '10MiB';
- var num = parseInt(/([0-9,]+).*/.exec(max)[1].replace(',', ''), 10);
- var unit = /(?:([KMGTPEZY])(i)?B|([BKMGTPEZY]))/.exec(max) || ['B', '', ''];
-
- var oneUnit = Math.pow(
- (unit[2] === 'i' ? 1024 : 1000),
- 'BKMGTPEZY'.indexOf(unit[1])
- );
-
- return num * oneUnit;
- })($uploadInput);
-
- var createRow = function(filename, size, extra) {
- var $rowItem = $('<li class=file>');
- var $rowName = $('<span class=file-name>');
- var $rowProg = $('<div class="file-progress progress-outer">');
- var $rowSize = $('<span class=file-size>');
- var $rowUrl = $('<span class=file-url>');
-
- $rowItem.addClass(extra || '');
-
- $('<div class=progress-inner>').appendTo($rowProg);
-
- $rowItem.attr('data-filename', escape(filename));
- $rowName.text(filename);
- $rowSize.text(size);
-
- $rowItem.append($rowName, $rowProg, $rowSize, $rowUrl);
-
- return $rowItem;
- };
-
- if (!$.hasFileAPI()) {
- $('#no-file-api').show();
- $uploadBtn.hide();
- }
-
- $uploadBtn.cabinet($uploadInput);
-
- $uploadBtn.on('dragenter', function(evt) {
- if (this === evt.target) {
- $(this).addClass('drop');
- $btnContent = $(this).html();
- $(this).html('Drop it here~');
- }
- });
-
- $uploadBtn.on('drop', function() {
- $(this).trigger('dragleave');
- });
-
- $uploadBtn.on('dragleave', function(evt) {
- var node = evt.target;
- do {
- if (node === this) {
- $(this).removeClass('drop');
- $(this).html($btnContent);
- break;
- }
- } while (node === node.parentNode);
- });
-
- $uploadBtn.on('change', function() {
- var files = $uploadInput[0].filelist;
- var totalRow = createRow('', files.humanSize, 'total');
- var $totalName = $('.file-name', totalRow);
- var UPLOAD_ERR_MAX_SIZE = 'onii-chan y-your upload is t-too big&hellip;';
- var UPLOAD_ERR_FAILED = 'Something went wrong; try again later.';
- var up = files.upload('upload.php');
-
- var eachRow = function(_files, fn) {
- var hits = {};
- _files.forEach(function(file) {
- var row = $($('li[data-filename="' +
- escape(file.name) + '"]')[hits[file.name] || 0]);
- ++hits[file.name];
- fn.call(row, row, file, _files);
- });
- };
-
- $uploadFiles.empty().removeClass('error completed');
-
- files.forEach(function(file) {
- createRow(file.name, file.humanSize).appendTo($uploadFiles);
- });
-
- totalRow.appendTo($uploadFiles);
-
- if (files.size > MAX_SIZE) {
- $uploadFiles.addClass('error');
- $totalName.html(UPLOAD_ERR_MAX_SIZE);
- return;
- }
-
- up.on('uploadprogress', function(evt, _files) {
- eachRow(_files, function(row, file) {
- $('.progress-inner', row).width((file.percentUploaded * 100) + '%');
- });
-
- $('.progress-inner', totalRow).width((_files.percentUploaded * 100) + '%');
- });
-
- up.on('uploadcomplete', function() {
- $('.progress-inner').width('100%');
- $totalName.html('Grabbing URLs&hellip;');
- });
-
- up.on('load', function(evt, response) {
- var res = JSON.parse(response);
-
- switch (evt.target.status) {
- case 200:
- if (!res.success) {
- $uploadFiles.addClass('error');
- $totalName.text(UPLOAD_ERR_FAILED);
- break;
- }
-
- eachRow(res.files, function(row, file) {
- var $link = $('<a>');
-
- $link.attr('href', file.url)
- .attr('target', '_BLANK')
- .text(file.url.replace('http://', '').replace('https://', ''));
-
- $('.file-url', row).append($link);
- });
-
- $uploadFiles.addClass('completed');
- $totalName.text('Done!');
- break;
- case 413:
- $uploadFiles.addClass('error completed');
- $totalName.html(UPLOAD_ERR_MAX_SIZE);
- break;
- default:
- $uploadFiles.addClass('error completed');
- $totalName.text(UPLOAD_ERR_FAILED);
- }
- });
-
- up.upload();
- });
-});
diff --git a/js/zepto.js b/js/zepto.js
deleted file mode 100644
index ab89703..0000000
--- a/js/zepto.js
+++ /dev/null
@@ -1,1035 +0,0 @@
-/* Zepto v1.0-7-g579f376 - zepto event - zeptojs.com/license */
-
-
-var Zepto = (function() {
- var undefined, key, $, classList, emptyArray = [], slice = emptyArray.slice, filter = emptyArray.filter,
- document = window.document,
- elementDisplay = {}, classCache = {},
- getComputedStyle = document.defaultView.getComputedStyle,
- cssNumber = { 'column-count': 1, 'columns': 1, 'font-weight': 1, 'line-height': 1,'opacity': 1, 'z-index': 1, 'zoom': 1 },
- fragmentRE = /^\s*<(\w+|!)[^>]*>/,
- tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
- rootNodeRE = /^(?:body|html)$/i,
-
- // special attributes that should be get/set via method calls
- methodAttributes = ['val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset'],
-
- adjacencyOperators = [ 'after', 'prepend', 'before', 'append' ],
- table = document.createElement('table'),
- tableRow = document.createElement('tr'),
- containers = {
- 'tr': document.createElement('tbody'),
- 'tbody': table, 'thead': table, 'tfoot': table,
- 'td': tableRow, 'th': tableRow,
- '*': document.createElement('div')
- },
- readyRE = /complete|loaded|interactive/,
- classSelectorRE = /^\.([\w-]+)$/,
- idSelectorRE = /^#([\w-]*)$/,
- tagSelectorRE = /^[\w-]+$/,
- class2type = {},
- toString = class2type.toString,
- zepto = {},
- camelize, uniq,
- tempParent = document.createElement('div')
-
- zepto.matches = function(element, selector) {
- if (!element || element.nodeType !== 1) return false
- var matchesSelector = element.webkitMatchesSelector || element.mozMatchesSelector ||
- element.oMatchesSelector || element.matchesSelector
- if (matchesSelector) return matchesSelector.call(element, selector)
- // fall back to performing a selector:
- var match, parent = element.parentNode, temp = !parent
- if (temp) (parent = tempParent).appendChild(element)
- match = ~zepto.qsa(parent, selector).indexOf(element)
- temp && tempParent.removeChild(element)
- return match
- }
-
- function type(obj) {
- return obj == null ? String(obj) :
- class2type[toString.call(obj)] || "object"
- }
-
- function isFunction(value) { return type(value) == "function" }
- function isWindow(obj) { return obj != null && obj == obj.window }
- function isDocument(obj) { return obj != null && obj.nodeType == obj.DOCUMENT_NODE }
- function isObject(obj) { return type(obj) == "object" }
- function isPlainObject(obj) {
- return isObject(obj) && !isWindow(obj) && obj.__proto__ == Object.prototype
- }
- function isArray(value) { return value instanceof Array }
- function likeArray(obj) { return typeof obj.length == 'number' }
-
- function compact(array) { return filter.call(array, function(item){ return item != null }) }
- function flatten(array) { return array.length > 0 ? $.fn.concat.apply([], array) : array }
- camelize = function(str){ return str.replace(/-+(.)?/g, function(match, chr){ return chr ? chr.toUpperCase() : '' }) }
- function dasherize(str) {
- return str.replace(/::/g, '/')
- .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
- .replace(/([a-z\d])([A-Z])/g, '$1_$2')
- .replace(/_/g, '-')
- .toLowerCase()
- }
- uniq = function(array){ return filter.call(array, function(item, idx){ return array.indexOf(item) == idx }) }
-
- function classRE(name) {
- return name in classCache ?
- classCache[name] : (classCache[name] = new RegExp('(^|\\s)' + name + '(\\s|$)'))
- }
-
- function maybeAddPx(name, value) {
- return (typeof value == "number" && !cssNumber[dasherize(name)]) ? value + "px" : value
- }
-
- function defaultDisplay(nodeName) {
- var element, display
- if (!elementDisplay[nodeName]) {
- element = document.createElement(nodeName)
- document.body.appendChild(element)
- display = getComputedStyle(element, '').getPropertyValue("display")
- element.parentNode.removeChild(element)
- display == "none" && (display = "block")
- elementDisplay[nodeName] = display
- }
- return elementDisplay[nodeName]
- }
-
- function children(element) {
- return 'children' in element ?
- slice.call(element.children) :
- $.map(element.childNodes, function(node){ if (node.nodeType == 1) return node })
- }
-
- // `$.zepto.fragment` takes a html string and an optional tag name
- // to generate DOM nodes nodes from the given html string.
- // The generated DOM nodes are returned as an array.
- // This function can be overriden in plugins for example to make
- // it compatible with browsers that don't support the DOM fully.
- zepto.fragment = function(html, name, properties) {
- if (html.replace) html = html.replace(tagExpanderRE, "<$1></$2>")
- if (name === undefined) name = fragmentRE.test(html) && RegExp.$1
- if (!(name in containers)) name = '*'
-
- var nodes, dom, container = containers[name]
- container.innerHTML = '' + html
- dom = $.each(slice.call(container.childNodes), function(){
- container.removeChild(this)
- })
- if (isPlainObject(properties)) {
- nodes = $(dom)
- $.each(properties, function(key, value) {
- if (methodAttributes.indexOf(key) > -1) nodes[key](value)
- else nodes.attr(key, value)
- })
- }
- return dom
- }
-
- // `$.zepto.Z` swaps out the prototype of the given `dom` array
- // of nodes with `$.fn` and thus supplying all the Zepto functions
- // to the array. Note that `__proto__` is not supported on Internet
- // Explorer. This method can be overriden in plugins.
- zepto.Z = function(dom, selector) {
- dom = dom || []
- dom.__proto__ = $.fn
- dom.selector = selector || ''
- return dom
- }
-
- // `$.zepto.isZ` should return `true` if the given object is a Zepto
- // collection. This method can be overriden in plugins.
- zepto.isZ = function(object) {
- return object instanceof zepto.Z
- }
-
- // `$.zepto.init` is Zepto's counterpart to jQuery's `$.fn.init` and
- // takes a CSS selector and an optional context (and handles various
- // special cases).
- // This method can be overriden in plugins.
- zepto.init = function(selector, context) {
- // If nothing given, return an empty Zepto collection
- if (!selector) return zepto.Z()
- // If a function is given, call it when the DOM is ready
- else if (isFunction(selector)) return $(document).ready(selector)
- // If a Zepto collection is given, juts return it
- else if (zepto.isZ(selector)) return selector
- else {
- var dom
- // normalize array if an array of nodes is given
- if (isArray(selector)) dom = compact(selector)
- // Wrap DOM nodes. If a plain object is given, duplicate it.
- else if (isObject(selector))
- dom = [isPlainObject(selector) ? $.extend({}, selector) : selector], selector = null
- // If it's a html fragment, create nodes from it
- else if (fragmentRE.test(selector))
- dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
- // If there's a context, create a collection on that context first, and select
- // nodes from there
- else if (context !== undefined) return $(context).find(selector)
- // And last but no least, if it's a CSS selector, use it to select nodes.
- else dom = zepto.qsa(document, selector)
- // create a new Zepto collection from the nodes found
- return zepto.Z(dom, selector)
- }
- }
-
- // `$` will be the base `Zepto` object. When calling this
- // function just call `$.zepto.init, which makes the implementation
- // details of selecting nodes and creating Zepto collections
- // patchable in plugins.
- $ = function(selector, context){
- return zepto.init(selector, context)
- }
-
- function extend(target, source, deep) {
- for (key in source)
- if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
- if (isPlainObject(source[key]) && !isPlainObject(target[key]))
- target[key] = {}
- if (isArray(source[key]) && !isArray(target[key]))
- target[key] = []
- extend(target[key], source[key], deep)
- }
- else if (source[key] !== undefined) target[key] = source[key]
- }
-
- // Copy all but undefined properties from one or more
- // objects to the `target` object.
- $.extend = function(target){
- var deep, args = slice.call(arguments, 1)
- if (typeof target == 'boolean') {
- deep = target
- target = args.shift()
- }
- args.forEach(function(arg){ extend(target, arg, deep) })
- return target
- }
-
- // `$.zepto.qsa` is Zepto's CSS selector implementation which
- // uses `document.querySelectorAll` and optimizes for some special cases, like `#id`.
- // This method can be overriden in plugins.
- zepto.qsa = function(element, selector){
- var found
- return (isDocument(element) && idSelectorRE.test(selector)) ?
- ( (found = element.getElementById(RegExp.$1)) ? [found] : [] ) :
- (element.nodeType !== 1 && element.nodeType !== 9) ? [] :
- slice.call(
- classSelectorRE.test(selector) ? element.getElementsByClassName(RegExp.$1) :
- tagSelectorRE.test(selector) ? element.getElementsByTagName(selector) :
- element.querySelectorAll(selector)
- )
- }
-
- function filtered(nodes, selector) {
- return selector == null ? $(nodes) : $(nodes).filter(selector)
- }
-
- $.contains = function(parent, node) {
- return parent !== node && parent.contains(node)
- }
-
- function funcArg(context, arg, idx, payload) {
- return isFunction(arg) ? arg.call(context, idx, payload) : arg
- }
-
- function setAttribute(node, name, value) {
- value == null ? node.removeAttribute(name) : node.setAttribute(name, value)
- }
-
- // access className property while respecting SVGAnimatedString
- function className(node, value){
- var klass = node.className,
- svg = klass && klass.baseVal !== undefined
-
- if (value === undefined) return svg ? klass.baseVal : klass
- svg ? (klass.baseVal = value) : (node.className = value)
- }
-
- // "true" => true
- // "false" => false
- // "null" => null
- // "42" => 42
- // "42.5" => 42.5
- // JSON => parse if valid
- // String => self
- function deserializeValue(value) {
- var num
- try {
- return value ?
- value == "true" ||
- ( value == "false" ? false :
- value == "null" ? null :
- !isNaN(num = Number(value)) ? num :
- /^[\[\{]/.test(value) ? $.parseJSON(value) :
- value )
- : value
- } catch(e) {
- return value
- }
- }
-
- $.type = type
- $.isFunction = isFunction
- $.isWindow = isWindow
- $.isArray = isArray
- $.isPlainObject = isPlainObject
-
- $.isEmptyObject = function(obj) {
- var name
- for (name in obj) return false
- return true
- }
-
- $.inArray = function(elem, array, i){
- return emptyArray.indexOf.call(array, elem, i)
- }
-
- $.camelCase = camelize
- $.trim = function(str) {
- return str == null ? "" : String.prototype.trim.call(str)
- }
-
- // plugin compatibility
- $.uuid = 0
- $.support = { }
- $.expr = { }
-
- $.map = function(elements, callback){
- var value, values = [], i, key
- if (likeArray(elements))
- for (i = 0; i < elements.length; i++) {
- value = callback(elements[i], i)
- if (value != null) values.push(value)
- }
- else
- for (key in elements) {
- value = callback(elements[key], key)
- if (value != null) values.push(value)
- }
- return flatten(values)
- }
-
- $.each = function(elements, callback){
- var i, key
- if (likeArray(elements)) {
- for (i = 0; i < elements.length; i++)
- if (callback.call(elements[i], i, elements[i]) === false) return elements
- } else {
- for (key in elements)
- if (callback.call(elements[key], key, elements[key]) === false) return elements
- }
-
- return elements
- }
-
- $.grep = function(elements, callback){
- return filter.call(elements, callback)
- }
-
- if (window.JSON) $.parseJSON = JSON.parse
-
- // Populate the class2type map
- $.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
- class2type[ "[object " + name + "]" ] = name.toLowerCase()
- })
-
- // Define methods that will be available on all
- // Zepto collections
- $.fn = {
- // Because a collection acts like an array
- // copy over these useful array functions.
- forEach: emptyArray.forEach,
- reduce: emptyArray.reduce,
- push: emptyArray.push,
- sort: emptyArray.sort,
- indexOf: emptyArray.indexOf,
- concat: emptyArray.concat,
-
- // `map` and `slice` in the jQuery API work differently
- // from their array counterparts
- map: function(fn){
- return $($.map(this, function(el, i){ return fn.call(el, i, el) }))
- },
- slice: function(){
- return $(slice.apply(this, arguments))
- },
-
- ready: function(callback){
- if (readyRE.test(document.readyState)) callback($)
- else document.addEventListener('DOMContentLoaded', function(){ callback($) }, false)
- return this
- },
- get: function(idx){
- return idx === undefined ? slice.call(this) : this[idx >= 0 ? idx : idx + this.length]
- },
- toArray: function(){ return this.get() },
- size: function(){
- return this.length
- },
- remove: function(){
- return this.each(function(){
- if (this.parentNode != null)
- this.parentNode.removeChild(this)
- })
- },
- each: function(callback){
- emptyArray.every.call(this, function(el, idx){
- return callback.call(el, idx, el) !== false
- })
- return this
- },
- filter: function(selector){
- if (isFunction(selector)) return this.not(this.not(selector))
- return $(filter.call(this, function(element){
- return zepto.matches(element, selector)
- }))
- },
- add: function(selector,context){
- return $(uniq(this.concat($(selector,context))))
- },
- is: function(selector){
- return this.length > 0 && zepto.matches(this[0], selector)
- },
- not: function(selector){
- var nodes=[]
- if (isFunction(selector) && selector.call !== undefined)
- this.each(function(idx){
- if (!selector.call(this,idx)) nodes.push(this)
- })
- else {
- var excludes = typeof selector == 'string' ? this.filter(selector) :
- (likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector)
- this.forEach(function(el){
- if (excludes.indexOf(el) < 0) nodes.push(el)
- })
- }
- return $(nodes)
- },
- has: function(selector){
- return this.filter(function(){
- return isObject(selector) ?
- $.contains(this, selector) :
- $(this).find(selector).size()
- })
- },
- eq: function(idx){
- return idx === -1 ? this.slice(idx) : this.slice(idx, + idx + 1)
- },
- first: function(){
- var el = this[0]
- return el && !isObject(el) ? el : $(el)
- },
- last: function(){
- var el = this[this.length - 1]
- return el && !isObject(el) ? el : $(el)
- },
- find: function(selector){
- var result, $this = this
- if (typeof selector == 'object')
- result = $(selector).filter(function(){
- var node = this
- return emptyArray.some.call($this, function(parent){
- return $.contains(parent, node)
- })
- })
- else if (this.length == 1) result = $(zepto.qsa(this[0], selector))
- else result = this.map(function(){ return zepto.qsa(this, selector) })
- return result
- },
- closest: function(selector, context){
- var node = this[0], collection = false
- if (typeof selector == 'object') collection = $(selector)
- while (node && !(collection ? collection.indexOf(node) >= 0 : zepto.matches(node, selector)))
- node = node !== context && !isDocument(node) && node.parentNode
- return $(node)
- },
- parents: function(selector){
- var ancestors = [], nodes = this
- while (nodes.length > 0)
- nodes = $.map(nodes, function(node){
- if ((node = node.parentNode) && !isDocument(node) && ancestors.indexOf(node) < 0) {
- ancestors.push(node)
- return node
- }
- })
- return filtered(ancestors, selector)
- },
- parent: function(selector){
- return filtered(uniq(this.pluck('parentNode')), selector)
- },
- children: function(selector){
- return filtered(this.map(function(){ return children(this) }), selector)
- },
- contents: function() {
- return this.map(function() { return slice.call(this.childNodes) })
- },
- siblings: function(selector){
- return filtered(this.map(function(i, el){
- return filter.call(children(el.parentNode), function(child){ return child!==el })
- }), selector)
- },
- empty: function(){
- return this.each(function(){ this.innerHTML = '' })
- },
- // `pluck` is borrowed from Prototype.js
- pluck: function(property){
- return $.map(this, function(el){ return el[property] })
- },
- show: function(){
- return this.each(function(){
- this.style.display == "none" && (this.style.display = null)
- if (getComputedStyle(this, '').getPropertyValue("display") == "none")
- this.style.display = defaultDisplay(this.nodeName)
- })
- },
- replaceWith: function(newContent){
- return this.before(newContent).remove()
- },
- wrap: function(structure){
- var func = isFunction(structure)
- if (this[0] && !func)
- var dom = $(structure).get(0),
- clone = dom.parentNode || this.length > 1
-
- return this.each(function(index){
- $(this).wrapAll(
- func ? structure.call(this, index) :
- clone ? dom.cloneNode(true) : dom
- )
- })
- },
- wrapAll: function(structure){
- if (this[0]) {
- $(this[0]).before(structure = $(structure))
- var children
- // drill down to the inmost element
- while ((children = structure.children()).length) structure = children.first()
- $(structure).append(this)
- }
- return this
- },
- wrapInner: function(structure){
- var func = isFunction(structure)
- return this.each(function(index){
- var self = $(this), contents = self.contents(),
- dom = func ? structure.call(this, index) : structure
- contents.length ? contents.wrapAll(dom) : self.append(dom)
- })
- },
- unwrap: function(){
- this.parent().each(function(){
- $(this).replaceWith($(this).children())
- })
- return this
- },
- clone: function(){
- return this.map(function(){ return this.cloneNode(true) })
- },
- hide: function(){
- return this.css("display", "none")
- },
- toggle: function(setting){
- return this.each(function(){
- var el = $(this)
- ;(setting === undefined ? el.css("display") == "none" : setting) ? el.show() : el.hide()
- })
- },
- prev: function(selector){ return $(this.pluck('previousElementSibling')).filter(selector || '*') },
- next: function(selector){ return $(this.pluck('nextElementSibling')).filter(selector || '*') },
- html: function(html){
- return html === undefined ?
- (this.length > 0 ? this[0].innerHTML : null) :
- this.each(function(idx){
- var originHtml = this.innerHTML
- $(this).empty().append( funcArg(this, html, idx, originHtml) )
- })
- },
- text: function(text){
- return text === undefined ?
- (this.length > 0 ? this[0].textContent : null) :
- this.each(function(){ this.textContent = text })
- },
- attr: function(name, value){
- var result
- return (typeof name == 'string' && value === undefined) ?
- (this.length == 0 || this[0].nodeType !== 1 ? undefined :
- (name == 'value' && this[0].nodeName == 'INPUT') ? this.val() :
- (!(result = this[0].getAttribute(name)) && name in this[0]) ? this[0][name] : result
- ) :
- this.each(function(idx){
- if (this.nodeType !== 1) return
- if (isObject(name)) for (key in name) setAttribute(this, key, name[key])
- else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name)))
- })
- },
- removeAttr: function(name){
- return this.each(function(){ this.nodeType === 1 && setAttribute(this, name) })
- },
- prop: function(name, value){
- return (value === undefined) ?
- (this[0] && this[0][name]) :
- this.each(function(idx){
- this[name] = funcArg(this, value, idx, this[name])
- })
- },
- data: function(name, value){
- var data = this.attr('data-' + dasherize(name), value)
- return data !== null ? deserializeValue(data) : undefined
- },
- val: function(value){
- return (value === undefined) ?
- (this[0] && (this[0].multiple ?
- $(this[0]).find('option').filter(function(o){ return this.selected }).pluck('value') :
- this[0].value)
- ) :
- this.each(function(idx){
- this.value = funcArg(this, value, idx, this.value)
- })
- },
- offset: function(coordinates){
- if (coordinates) return this.each(function(index){
- var $this = $(this),
- coords = funcArg(this, coordinates, index, $this.offset()),
- parentOffset = $this.offsetParent().offset(),
- props = {
- top: coords.top - parentOffset.top,
- left: coords.left - parentOffset.left
- }
-
- if ($this.css('position') == 'static') props['position'] = 'relative'
- $this.css(props)
- })
- if (this.length==0) return null
- var obj = this[0].getBoundingClientRect()
- return {
- left: obj.left + window.pageXOffset,
- top: obj.top + window.pageYOffset,
- width: Math.round(obj.width),
- height: Math.round(obj.height)
- }
- },
- css: function(property, value){
- if (arguments.length < 2 && typeof property == 'string')
- return this[0] && (this[0].style[camelize(property)] || getComputedStyle(this[0], '').getPropertyValue(property))
-
- var css = ''
- if (type(property) == 'string') {
- if (!value && value !== 0)
- this.each(function(){ this.style.removeProperty(dasherize(property)) })
- else
- css = dasherize(property) + ":" + maybeAddPx(property, value)
- } else {
- for (key in property)
- if (!property[key] && property[key] !== 0)
- this.each(function(){ this.style.removeProperty(dasherize(key)) })
- else
- css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';'
- }
-
- return this.each(function(){ this.style.cssText += ';' + css })
- },
- index: function(element){
- return element ? this.indexOf($(element)[0]) : this.parent().children().indexOf(this[0])
- },
- hasClass: function(name){
- return emptyArray.some.call(this, function(el){
- return this.test(className(el))
- }, classRE(name))
- },
- addClass: function(name){
- return this.each(function(idx){
- classList = []
- var cls = className(this), newName = funcArg(this, name, idx, cls)
- newName.split(/\s+/g).forEach(function(klass){
- if (!$(this).hasClass(klass)) classList.push(klass)
- }, this)
- classList.length && className(this, cls + (cls ? " " : "") + classList.join(" "))
- })
- },
- removeClass: function(name){
- return this.each(function(idx){
- if (name === undefined) return className(this, '')
- classList = className(this)
- funcArg(this, name, idx, classList).split(/\s+/g).forEach(function(klass){
- classList = classList.replace(classRE(klass), " ")
- })
- className(this, classList.trim())
- })
- },
- toggleClass: function(name, when){
- return this.each(function(idx){
- var $this = $(this), names = funcArg(this, name, idx, className(this))
- names.split(/\s+/g).forEach(function(klass){
- (when === undefined ? !$this.hasClass(klass) : when) ?
- $this.addClass(klass) : $this.removeClass(klass)
- })
- })
- },
- scrollTop: function(){
- if (!this.length) return
- return ('scrollTop' in this[0]) ? this[0].scrollTop : this[0].scrollY
- },
- position: function() {
- if (!this.length) return
-
- var elem = this[0],
- // Get *real* offsetParent
- offsetParent = this.offsetParent(),
- // Get correct offsets
- offset = this.offset(),
- parentOffset = rootNodeRE.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset()
-
- // Subtract element margins
- // note: when an element has margin: auto the offsetLeft and marginLeft
- // are the same in Safari causing offset.left to incorrectly be 0
- offset.top -= parseFloat( $(elem).css('margin-top') ) || 0
- offset.left -= parseFloat( $(elem).css('margin-left') ) || 0
-
- // Add offsetParent borders
- parentOffset.top += parseFloat( $(offsetParent[0]).css('border-top-width') ) || 0
- parentOffset.left += parseFloat( $(offsetParent[0]).css('border-left-width') ) || 0
-
- // Subtract the two offsets
- return {
- top: offset.top - parentOffset.top,
- left: offset.left - parentOffset.left
- }
- },
- offsetParent: function() {
- return this.map(function(){
- var parent = this.offsetParent || document.body
- while (parent && !rootNodeRE.test(parent.nodeName) && $(parent).css("position") == "static")
- parent = parent.offsetParent
- return parent
- })
- }
- }
-
- // for now
- $.fn.detach = $.fn.remove
-
- // Generate the `width` and `height` functions
- ;['width', 'height'].forEach(function(dimension){
- $.fn[dimension] = function(value){
- var offset, el = this[0],
- Dimension = dimension.replace(/./, function(m){ return m[0].toUpperCase() })
- if (value === undefined) return isWindow(el) ? el['inner' + Dimension] :
- isDocument(el) ? el.documentElement['offset' + Dimension] :
- (offset = this.offset()) && offset[dimension]
- else return this.each(function(idx){
- el = $(this)
- el.css(dimension, funcArg(this, value, idx, el[dimension]()))
- })
- }
- })
-
- function traverseNode(node, fun) {
- fun(node)
- for (var key in node.childNodes) traverseNode(node.childNodes[key], fun)
- }
-
- // Generate the `after`, `prepend`, `before`, `append`,
- // `insertAfter`, `insertBefore`, `appendTo`, and `prependTo` methods.
- adjacencyOperators.forEach(function(operator, operatorIndex) {
- var inside = operatorIndex % 2 //=> prepend, append
-
- $.fn[operator] = function(){
- // arguments can be nodes, arrays of nodes, Zepto objects and HTML strings
- var argType, nodes = $.map(arguments, function(arg) {
- argType = type(arg)
- return argType == "object" || argType == "array" || arg == null ?
- arg : zepto.fragment(arg)
- }),
- parent, copyByClone = this.length > 1
- if (nodes.length < 1) return this
-
- return this.each(function(_, target){
- parent = inside ? target : target.parentNode
-
- // convert all methods to a "before" operation
- target = operatorIndex == 0 ? target.nextSibling :
- operatorIndex == 1 ? target.firstChild :
- operatorIndex == 2 ? target :
- null
-
- nodes.forEach(function(node){
- if (copyByClone) node = node.cloneNode(true)
- else if (!parent) return $(node).remove()
-
- traverseNode(parent.insertBefore(node, target), function(el){
- if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' &&
- (!el.type || el.type === 'text/javascript') && !el.src)
- window['eval'].call(window, el.innerHTML)
- })
- })
- })
- }
-
- // after => insertAfter
- // prepend => prependTo
- // before => insertBefore
- // append => appendTo
- $.fn[inside ? operator+'To' : 'insert'+(operatorIndex ? 'Before' : 'After')] = function(html){
- $(html)[operator](this)
- return this
- }
- })
-
- zepto.Z.prototype = $.fn
-
- // Export internal API functions in the `$.zepto` namespace
- zepto.uniq = uniq
- zepto.deserializeValue = deserializeValue
- $.zepto = zepto
-
- return $
-})()
-
-window.Zepto = Zepto
-'$' in window || (window.$ = Zepto)
-
-;(function($){
- var $$ = $.zepto.qsa, handlers = {}, _zid = 1, specialEvents={},
- hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' }
-
- specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents'
-
- function zid(element) {
- return element._zid || (element._zid = _zid++)
- }
- function findHandlers(element, event, fn, selector) {
- event = parse(event)
- if (event.ns) var matcher = matcherFor(event.ns)
- return (handlers[zid(element)] || []).filter(function(handler) {
- return handler
- && (!event.e || handler.e == event.e)
- && (!event.ns || matcher.test(handler.ns))
- && (!fn || zid(handler.fn) === zid(fn))
- && (!selector || handler.sel == selector)
- })
- }
- function parse(event) {
- var parts = ('' + event).split('.')
- return {e: parts[0], ns: parts.slice(1).sort().join(' ')}
- }
- function matcherFor(ns) {
- return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)')
- }
-
- function eachEvent(events, fn, iterator){
- if ($.type(events) != "string") $.each(events, iterator)
- else events.split(/\s/).forEach(function(type){ iterator(type, fn) })
- }
-
- function eventCapture(handler, captureSetting) {
- return handler.del &&
- (handler.e == 'focus' || handler.e == 'blur') ||
- !!captureSetting
- }
-
- function realEvent(type) {
- return hover[type] || type
- }
-
- function add(element, events, fn, selector, getDelegate, capture){
- var id = zid(element), set = (handlers[id] || (handlers[id] = []))
- eachEvent(events, fn, function(event, fn){
- var handler = parse(event)
- handler.fn = fn
- handler.sel = selector
- // emulate mouseenter, mouseleave
- if (handler.e in hover) fn = function(e){
- var related = e.relatedTarget
- if (!related || (related !== this && !$.contains(this, related)))
- return handler.fn.apply(this, arguments)
- }
- handler.del = getDelegate && getDelegate(fn, event)
- var callback = handler.del || fn
- handler.proxy = function (e) {
- var result = callback.apply(element, [e].concat(e.data))
- if (result === false) e.preventDefault(), e.stopPropagation()
- return result
- }
- handler.i = set.length
- set.push(handler)
- element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
- })
- }
- function remove(element, events, fn, selector, capture){
- var id = zid(element)
- eachEvent(events || '', fn, function(event, fn){
- findHandlers(element, event, fn, selector).forEach(function(handler){
- delete handlers[id][handler.i]
- element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture))
- })
- })
- }
-
- $.event = { add: add, remove: remove }
-
- $.proxy = function(fn, context) {
- if ($.isFunction(fn)) {
- var proxyFn = function(){ return fn.apply(context, arguments) }
- proxyFn._zid = zid(fn)
- return proxyFn
- } else if (typeof context == 'string') {
- return $.proxy(fn[context], fn)
- } else {
- throw new TypeError("expected function")
- }
- }
-
- $.fn.bind = function(event, callback){
- return this.each(function(){
- add(this, event, callback)
- })
- }
- $.fn.unbind = function(event, callback){
- return this.each(function(){
- remove(this, event, callback)
- })
- }
- $.fn.one = function(event, callback){
- return this.each(function(i, element){
- add(this, event, callback, null, function(fn, type){
- return function(){
- var result = fn.apply(element, arguments)
- remove(element, type, fn)
- return result
- }
- })
- })
- }
-
- var returnTrue = function(){return true},
- returnFalse = function(){return false},
- ignoreProperties = /^([A-Z]|layer[XY]$)/,
- eventMethods = {
- preventDefault: 'isDefaultPrevented',
- stopImmediatePropagation: 'isImmediatePropagationStopped',
- stopPropagation: 'isPropagationStopped'
- }
- function createProxy(event) {
- var key, proxy = { originalEvent: event }
- for (key in event)
- if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key]
-
- $.each(eventMethods, function(name, predicate) {
- proxy[name] = function(){
- this[predicate] = returnTrue
- return event[name].apply(event, arguments)
- }
- proxy[predicate] = returnFalse
- })
- return proxy
- }
-
- // emulates the 'defaultPrevented' property for browsers that have none
- function fix(event) {
- if (!('defaultPrevented' in event)) {
- event.defaultPrevented = false
- var prevent = event.preventDefault
- event.preventDefault = function() {
- this.defaultPrevented = true
- prevent.call(this)
- }
- }
- }
-
- $.fn.delegate = function(selector, event, callback){
- return this.each(function(i, element){
- add(element, event, callback, selector, function(fn){
- return function(e){
- var evt, match = $(e.target).closest(selector, element).get(0)
- if (match) {
- evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element})
- return fn.apply(match, [evt].concat([].slice.call(arguments, 1)))
- }
- }
- })
- })
- }
- $.fn.undelegate = function(selector, event, callback){
- return this.each(function(){
- remove(this, event, callback, selector)
- })
- }
-
- $.fn.live = function(event, callback){
- $(document.body).delegate(this.selector, event, callback)
- return this
- }
- $.fn.die = function(event, callback){
- $(document.body).undelegate(this.selector, event, callback)
- return this
- }
-
- $.fn.on = function(event, selector, callback){
- return !selector || $.isFunction(selector) ?
- this.bind(event, selector || callback) : this.delegate(selector, event, callback)
- }
- $.fn.off = function(event, selector, callback){
- return !selector || $.isFunction(selector) ?
- this.unbind(event, selector || callback) : this.undelegate(selector, event, callback)
- }
-
- $.fn.trigger = function(event, data){
- if (typeof event == 'string' || $.isPlainObject(event)) event = $.Event(event)
- fix(event)
- event.data = data
- return this.each(function(){
- // items in the collection might not be DOM elements
- // (todo: possibly support events on plain old objects)
- if('dispatchEvent' in this) this.dispatchEvent(event)
- })
- }
-
- // triggers event handlers on current element just as if an event occurred,
- // doesn't trigger an actual event, doesn't bubble
- $.fn.triggerHandler = function(event, data){
- var e, result
- this.each(function(i, element){
- e = createProxy(typeof event == 'string' ? $.Event(event) : event)
- e.data = data
- e.target = element
- $.each(findHandlers(element, event.type || event), function(i, handler){
- result = handler.proxy(e)
- if (e.isImmediatePropagationStopped()) return false
- })
- })
- return result
- }
-
- // shortcut methods for `.bind(event, fn)` for each event type
- ;('focusin focusout load resize scroll unload click dblclick '+
- 'mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave '+
- 'change select keydown keypress keyup error').split(' ').forEach(function(event) {
- $.fn[event] = function(callback) {
- return callback ?
- this.bind(event, callback) :
- this.trigger(event)
- }
- })
-
- ;['focus', 'blur'].forEach(function(name) {
- $.fn[name] = function(callback) {
- if (callback) this.bind(name, callback)
- else this.each(function(){
- try { this[name]() }
- catch(e) {}
- })
- return this
- }
- })
-
- $.Event = function(type, props) {
- if (typeof type != 'string') props = type, type = props.type
- var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true
- if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name])
- event.initEvent(type, bubbles, true, null, null, null, null, null, null, null, null, null, null, null, null)
- event.isDefaultPrevented = function(){ return this.defaultPrevented }
- return event
- }
-
-})(Zepto)
diff --git a/package.json b/package.json
index c3aa3b8..21894d7 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,8 @@
"Eric Johansson <neku@pomf.se>",
"Peter Lejeck <peter.lejeck@gmail.com>",
"cenci0 <alchimist94@gmail.com>",
- "Juuso Lapinlampi <wub@partyvan.eu>"
+ "Juuso Lapinlampi <wub@partyvan.eu>",
+ "Luminarys <postmaster@gensok.io>"
],
"license": "MIT",
"bugs": {
diff --git a/pages/banners.swig b/pages/banners.swig
index e8f0cbd..ce25555 100644
--- a/pages/banners.swig
+++ b/pages/banners.swig
@@ -19,6 +19,11 @@ 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.
#}
+{#
+This template is deprecated since version 2.1.0. It may be removed in a future
+release.
+#}
+
{% for banner in banners %}
{% include banner %}
{% endfor %}
diff --git a/pages/banners/donate.swig b/pages/banners/donate.swig
index f4706c9..6a9b73b 100644
--- a/pages/banners/donate.swig
+++ b/pages/banners/donate.swig
@@ -19,6 +19,11 @@ 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.
#}
+{#
+This template is deprecated since version 2.1.0. It may be removed in a future
+release.
+#}
+
<p class="alert alert-info">
<strong>pomf.se is a free service, but our hosting bill isn't</strong> &mdash; we need almost $100 a month for that. Donations help keep pomf.se free, online, and fast. Everything (after fees) goes to the hosting bill.
<span class="donate-btns">
diff --git a/pages/banners/virusscans.swig b/pages/banners/virusscans.swig
index 4a3d5a8..16a3608 100644
--- a/pages/banners/virusscans.swig
+++ b/pages/banners/virusscans.swig
@@ -19,6 +19,11 @@ 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.
#}
+{#
+This template is deprecated since version 2.1.0. It may be removed in a future
+release.
+#}
+
<p class="alert alert-info">
<strong>Virus scans are now a daily routine</strong> &mdash; if a file gets detected it will be removed without further notice.
</p>
diff --git a/pages/index.swig b/pages/index.swig
index ff7db42..d9eb263 100644
--- a/pages/index.swig
+++ b/pages/index.swig
@@ -30,7 +30,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
{% include "check_fileapi.swig" %}
{% include "upload_form.swig" %}
</div>
-{% include "banners.swig" %}
+{% include "banners.swig" %} {# Deprecated since version 2.1.0. #}
{% include "nav.swig" %}
<script src="pomf.min.js"></script>
{% endblock %}
diff --git a/pages/layout.swig b/pages/layout.swig
index 3eb9eff..348a7c9 100644
--- a/pages/layout.swig
+++ b/pages/layout.swig
@@ -1,6 +1,6 @@
{#
Copyright (c) 2013 Peter Lejeck <peter.lejeck@gmail.com>
-Copyright (c) 2015 the Pantsu.cat developers <hostmaster@pantsu.cat>
+Copyright (c) 2015, 2016 the Pantsu.cat developers <hostmaster@pantsu.cat>
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
@@ -25,6 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="generator" content="Pomf {{pkgVersion}}">
<title>Pantsu.cat &middot; {% block title %}Kawaii File Hosting{% endblock %}</title>
<link rel="icon" href="favicon.ico">
<link rel="stylesheet" href="pomf.min.css">
diff --git a/pages/nojs.swig b/pages/nojs.swig
index 9facb91..5552b11 100644
--- a/pages/nojs.swig
+++ b/pages/nojs.swig
@@ -28,6 +28,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<p class="lead">Max upload size is {{max_upload_size}}MiB, read the <a href="faq.html">FAQ</a></p>
{% include "upload_form_nojs.swig" %}
</div>
-{% include "banners.swig" %}
+{% include "banners.swig" %} {# Deprecated since version 2.1.0. #}
{% include "nav.swig" %}
{% endblock %}
diff --git a/schema.sql b/schema.sql
index f668c5e..154f095 100644
--- a/schema.sql
+++ b/schema.sql
@@ -13,7 +13,7 @@ CREATE TABLE `files` (
`filename` varchar(30) default NULL,
`size` int(10) unsigned default NULL,
`date` date default NULL,
- `expire` date default NULL,
+ `expire` date default NULL, -- Deprecated since version 2.1.0
`delid` char(40) default NULL,
`user` int(10) unsigned default '0',
`dir` int(2) default '0',
diff --git a/static/classes/Response.class.php b/static/classes/Response.class.php
index 27dbd74..f8555d6 100755
--- a/static/classes/Response.class.php
+++ b/static/classes/Response.class.php
@@ -105,11 +105,17 @@ class Response
echo $response;
}
+ /**
+ * @deprecated 2.1.0 Will be renamed to camelCase format.
+ */
private static function csv_error($description)
{
return '"error"'."\r\n"."\"$description\""."\r\n";
}
+ /**
+ * @deprecated 2.1.0 Will be renamed to camelCase format.
+ */
private static function csv_success($files)
{
$result = '"name","url","hash","size"'."\r\n";
@@ -123,11 +129,17 @@ class Response
return $result;
}
+ /**
+ * @deprecated 2.1.0 Will be renamed to camelCase format.
+ */
private static function html_error($code, $description)
{
return '<p>ERROR: ('.$code.') '.$description.'</p>';
}
+ /**
+ * @deprecated 2.1.0 Will be renamed to camelCase format.
+ */
private static function html_success($files)
{
$result = '';
@@ -139,6 +151,9 @@ class Response
return $result;
}
+ /**
+ * @deprecated 2.1.0 Will be renamed to camelCase format.
+ */
private static function json_error($code, $description)
{
return json_encode(array(
@@ -148,6 +163,9 @@ class Response
), JSON_PRETTY_PRINT);
}
+ /**
+ * @deprecated 2.1.0 Will be renamed to camelCase format.
+ */
private static function json_success($files)
{
return json_encode(array(
@@ -156,11 +174,17 @@ class Response
), JSON_PRETTY_PRINT);
}
+ /**
+ * @deprecated 2.1.0 Will be renamed to camelCase format.
+ */
private static function text_error($code, $description)
{
return 'ERROR: ('.$code.') '.$description;
}
+ /**
+ * @deprecated 2.1.0 Will be renamed to camelCase format.
+ */
private static function text_success($files)
{
$result = '';
diff --git a/static/classes/UploadedFile.class.php b/static/classes/UploadedFile.class.php
index ac39646..99020ce 100644
--- a/static/classes/UploadedFile.class.php
+++ b/static/classes/UploadedFile.class.php
@@ -37,6 +37,7 @@ class UploadedFile
/**
* Generates the SHA1 or returns the cached SHA1 hash for the file.
*
+ * @deprecated 2.1.0 To be replaced with SHA-256 hashing.
* @return string
*/
public function get_sha1()
diff --git a/static/upload.php b/static/upload.php
index a37c549..c7d5ea7 100644
--- a/static/upload.php
+++ b/static/upload.php
@@ -133,6 +133,8 @@ function upload_file($file)
// Need to change permissions for the new file to make it world readable
if (chmod(POMF_FILES_ROOT.$newname, 0644)) {
// Add it to the database
+ // 'expire' support is deprecated since version 2.1.0. It may be
+ // removed in a future release.
$q = $db->prepare('INSERT INTO files (hash, originalname, filename, size, date, '.
'expire, delid) VALUES (:hash, :orig, :name, :size, :date, '.
':exp, :del)');
@@ -143,7 +145,7 @@ function upload_file($file)
$q->bindValue(':name', $newname, PDO::PARAM_STR);
$q->bindValue(':size', $file->size, PDO::PARAM_INT);
$q->bindValue(':date', date('Y-m-d'), PDO::PARAM_STR);
- $q->bindValue(':exp', null, PDO::PARAM_STR);
+ $q->bindValue(':exp', null, PDO::PARAM_STR); // Deprecated since version 2.1.0
$q->bindValue(':del', sha1($file->tempfile), PDO::PARAM_STR);
$q->execute();
@@ -201,7 +203,7 @@ function refiles($files)
$f->tempfile = $file['tmp_name'];
$f->error = $file['error'];
// 'expire' doesn't exist neither in $_FILES nor in UploadedFile;
- // commented out for future implementation
+ // it was never implemented and has been deprecated since version 2.1.0.
//$f->expire = $file['expire'];
$result[] = $f;
}