1
0
Fork 0
mirror of https://github.com/Yetangitu/owncloud-apps.git synced 2025-10-02 14:49:17 +02:00

files_reader: v1.0.0, see CHANGELOG and appinfo/info.xml for changes and new features

This commit is contained in:
frankdelange 2017-03-16 01:30:24 +01:00
parent 30f758d419
commit aa85edee22
65 changed files with 13549 additions and 539 deletions

View file

@ -1,8 +1,27 @@
## Unreleased
## UNRELEASED
###
## 1.0.0 - 2017-03-15
### Added
- Reader now supports CBR/CBZ ('comics') files
- Book position is saved on server and restored on next invocation
- Book position ('cursor') is saved on server and restored on next invocation
- Default settings (independent of fileid) and file-specific settings are saved and restored
- Bookmarks and annotations (notes) are saved and restored (bookmarks are a type of annotation).
- Full-text search implemented.
- Framework to support more file format renderers
- hooks added to remove defaults, settings and annotations/bookmarks for deleted files or users
- epubreader
* night mode now works more reliably
* new 'day mode', ie. user-defined colours
* new font settings: font weight
* column width user-configurable
* new mode: maximize reader area, for small-screen devices
* page turn arrows optional, hidden by default
- cbreader
* supports CBR (rar) and CBZ (zip) archives
* single and double page (spread) mode, auto-adjusts to screen geometry
* optional image enhancement filters
* seamless full screen mode (where browser allows user full control of experience, ie. not on apple)
## 0.8.3 - 2017-02-02
### Fixed

6
files_reader/TODO Normal file
View file

@ -0,0 +1,6 @@
- add hook to delete book info when books are deleted
- do this for files_opds as well
- for maximize page area, disable two-column when in portrait mode
- maybe always disable two-column in portrait mode
- swipe gestures for open/close sidebar, page turn
- disable wide page turn when placing markers

Binary file not shown.

View file

@ -4,7 +4,7 @@
* ownCloud - Files_Reader App
*
* @author Frank de Lange
* @copyright 2015 Frank de Lange
* @copyright 2015 - 2017 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
@ -12,9 +12,11 @@
namespace OCA\Files_Reader\AppInfo;
use OCP\AppFramework\App;
use OCP\Util;
Util::addscript( 'files_reader', 'plugin');
\OCA\Files_Reader\Hooks::register();
Util::addscript('files_reader', 'plugin');
if(class_exists('\\OCP\\AppFramework\\Http\\EmptyContentSecurityPolicy')) {
$manager = \OC::$server->getContentSecurityPolicyManager();
@ -24,7 +26,7 @@ if(class_exists('\\OCP\\AppFramework\\Http\\EmptyContentSecurityPolicy')) {
$csp->addAllowedScriptDomain('\'self\'');
$csp->addAllowedFrameDomain('\'self\'');
$csp->addAllowedChildSrcDomain('\'self\'');
$csp->addAllowedFontDomain('\'self\'');
$csp->addAllowedImageDomain('blob:');
$manager->addDefaultPolicy($csp);
}

View file

@ -0,0 +1,203 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<database>
<name>*dbname*</name>
<create>true</create>
<overwrite>false</overwrite>
<charset>utf8</charset>
<table>
<name>*dbprefix*reader_bookmarks</name>
<declaration>
<field>
<!-- id -->
<name>id</name>
<type>integer</type>
<notnull>true</notnull>
<autoincrement>true</autoincrement>
<unsigned>true</unsigned>
<primary>true</primary>
<length>8</length>
</field>
<field>
<!-- user ID, maps bookmark to NC/OC user -->
<name>user_id</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>64</length>
</field>
<field>
<!-- file ID, maps to NC/OC file ID -->
<name>file_id</name>
<type>integer</type>
<notnull>true</notnull>
<unsigned>true</unsigned>
<length>11</length>
</field>
<field>
<!-- type (bookmark, annotation, etc) -->
<name>type</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>32</length>
</field>
<field>
<!-- name -->
<name>name</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>512</length>
</field>
<field>
<!-- value -->
<name>value</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>512</length>
</field>
<field>
<!-- content -->
<name>content</name>
<type>text</type>
<default></default>
<notnull>false</notnull>
<length>4096</length>
</field>
<field>
<!-- last_modified -->
<name>last_modified</name>
<type>integer</type>
<default>0</default>
<length>8</length>
<notnull>false</notnull>
<unsigned>true</unsigned>
</field>
<index>
<name>reader_bookmarks_file_id_index</name>
<field>
<name>file_id</name>
</field>
</index>
<index>
<name>reader_bookmarks_user_id_index</name>
<field>
<name>user_id</name>
</field>
</index>
<index>
<name>reader_bookmarks_name_index</name>
<field>
<name>name</name>
</field>
</index>
</declaration>
</table>
<table>
<name>*dbprefix*reader_preferences</name>
<declaration>
<field>
<!-- id -->
<name>id</name>
<type>integer</type>
<notnull>true</notnull>
<autoincrement>true</autoincrement>
<unsigned>true</unsigned>
<primary>true</primary>
<length>8</length>
</field>
<field>
<!-- user ID, maps preference to NC/OC user -->
<name>user_id</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>64</length>
</field>
<field>
<!-- file ID, maps to NC/OC file ID -->
<name>file_id</name>
<type>integer</type>
<notnull>true</notnull>
<unsigned>true</unsigned>
<length>11</length>
</field>
<field>
<!-- scope -->
<name>scope</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>32</length>
</field>
<field>
<!-- name -->
<name>name</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>128</length>
</field>
<field>
<!-- value -->
<name>value</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
<length>4096</length>
</field>
<field>
<!-- last_modified -->
<name>last_modified</name>
<type>integer</type>
<default>0</default>
<length>8</length>
<notnull>false</notnull>
<unsigned>true</unsigned>
</field>
<index>
<name>reader_preferences_file_id_index</name>
<field>
<name>file_id</name>
</field>
</index>
<index>
<name>reader_preferences_user_id_index</name>
<field>
<name>user_id</name>
</field>
</index>
<index>
<name>reader_preferences_scope_index</name>
<field>
<name>scope</name>
</field>
</index>
</declaration>
</table>
</database>

View file

@ -2,17 +2,126 @@
<info>
<id>files_reader</id>
<name>Reader (ebook reader)</name>
<summary>An epub-compatible ebook reader based on a pure javascript epub renderer</summary>
<namespace>Files_Reader</namespace>
<summary>A multi-format browser-based ebook reader, supports EPUB and CBR/CBZ</summary>
<description>
Reader is an ebook reader based on a pure javascript epub renderer. It only works for books formatted according to the epub standard.
<![CDATA[
# Reader
Reader is an ebook reader based on pure javascript renderers. It works for books formatted according to the following standards:
Using the futurepress epub.js renderer (https://github.com/futurepress/epub.js) it provides near-native looks, especially when used full-screen. Turn pages by pressing the left/right hand side of the screen/window or using the cursor keys (if you have those), use the sidebar to browse through chapters or bookmarks and add annotations.
- [Epub]
- [CBR and CBZ] ('comics')
Reader has a night mode (toggled by clicking or pressing the book title/author on top of the viewer) to read in the dark without waking up the neighbours. This is obviously most effective when used full-screen. The colours used for night mode are configurable in the Settings dialog.
For Epub Reader uses the futurepress [epub.js] renderer to provide near-native looks, especially when used full-screen. Turn pages by pressing the left/right hand side of the screen/window or using the cursor keys (if you have those), use the sidebar to browse through chapters or bookmarks and add annotations.
Also in Settings you'll find the option to use ignore any internal formatting in the book by forcing a given font style and size.
CBR and CBZ are supported using a custom renderer inspired by [balaclark]'s work. As with Epub, books can be navigated using the keyboard as well as mouse or touch navigation. Reader generates a visual index of all pages, show in the sidebar (thumbnail generation can be disabled for low-memory and/or -speed devices). As CBx files are often of varying quality, a set of image enhancement filters are provided.
# Features
Reader remembers the last-visited page in a book and returns to that page when the book is re-opened. As all settings are stored on the server these features are device-independent, ie. you can start reading on a mobile device, continue on a PC to finish the book on a tablet.
### Text-based formats
- seamless full-screen mode supported on browsers which allow full user-control, ie. not on Apple)
- single- and double-page viewing mode
- user-configurable font and colour settings
- night mode, toggled by clicking the book title/author on top of the viewer
- full-text search with keyword highlighting
- bookmarks (with automatic snippet generation)
- annotations
- keyboard and pointer/touch-based navigation
### CBR/CBZ ('Comics')
- seamless full-screen mode supported on browsers which allow full user-control, ie. not on Apple)
- single- and double-page viewing mode
- optional image enhancement filters
- Left-to-right and right-to-left (_manga_) modes
- visual index (thumbnail size user-configurable, can be disabled for low-memory or -cpu devices)
- keyboard and pointer/touch-based navigation
### Keyboard navigation
Reader supports both pointer/touch-based as well as keyboard-based navigation. Pointer/touch based is mostly self-explanatory,
| key | function |
| ---:| --- |
|_left_, _page-up_ | move to previous page; move to next page in RTL(_manga_) mode |
|_right_, _page-down_, _space_ | move to next page; move to previous page in RTL (_mange_) mode |
|_home_| move to first page |
|_end_| move to last page |
|s| toggle side bar |
|_esc_| close sidebar |
|f| toggle full screen|
|t| toggle toolbar |
|l| _CBR_: toggle layout |
|a| _EPUB_: annotate |
|b| _EPUB_: bookmark |
|r| _EPUB_: reflow text when sidebar is open |
|d| _EPUB_: toggle day (custom colour) mode |
|n| _EPUB_: toggle night mode |
### Defaults and Preferences
Reader stores __defaults__ - settings which are independent of _fileId_ (ie. independent of the book currently open) - and __preferences__ - _fileId_-dependent (ie. different for every book) - on the server. Defaults are not shared between renderers, ie. the CBR renderer does not share defaults with the EPUB renderer. Defaults and preferences are removed from the server when the associated book or user is deleted.
### Annotations and Bookmarks
Reader supports _annotations_ (notes linked to a given position in a book) and _bookmarks_ (position markers with automatically generated text snippets). An automatically generated bookmark (called '__ CURSOR __', not visible in the bookmarks list) is used to keep track of the current reading position. Annotations and bookmark snippets can be edited or deleted in the sidebar.
# Screenshots
### Epub
| | |
---|---
Reader showing page spread in 'night mode'|![Reader showing page spread in 'night mode'][SS01]
Epub single page, full screen on a small-screen device |![Epub single page, full screen][SS02]
Day mode color selector|![Day mode color selector][SS03]
Longing for that olde-time terminal feeling...|![Longing for that olde-time terminal feeling...][SS04]
Full-text search|![Full-text search][SS05]
Small screen device, __maximize text area__ enabled|![Small screen device, maximize text area enabled][SS06]
Search on small-screen device|![Search on small-screen device][SS07]
As close to full-screen as you can get on iOS|![As close to full-screen as you can get on iOS][SS08]
Android supports true fullscreen (as do most other systems)|![Android supports true fullscreen (as do most other systems)][SS09]
### CBR/CBZ
| | |
---|---
iOS approximation of full screen, CBR|![iOS approximation of full screen, CBR][SS10]
The same book, now in landscape mode, switch to 2-page spread is automatic|![The same book, now in landscape mode, switch to 2-page spread is automatic][SS11]
Sidebar open, showing index, landscape mode|![Sidebar open, showing index, landscape mode][SS12]
Sidebar open, showing index, portrait mode|![Sidebar open, showing index, portrait mode][SS13]
Image enhancement filters, desaturate (grayscale) active|![Image enhancement filters, desaturate (grayscale) active][SS14]
full screen (apart from iOS restrictions), controls hidden|![full screen (apart from iOS restrictions), controls hidden][SS15]
Same page, zoomed in|![Same page, zoomed in][SS16]
Small-screen, low memory (Android) device showing full-page book cover|![Small-screen, low memory Android device showing full-page book cover][SS17]
The same Android device showing a zoomed-in part of a page|![The same Android device showing a zoomed-in part of a page][SS18]
[epub.js]: https://github.com/futurepress/epub.js
[Epub]: http://idpf.org/epub
[CBR and CBZ]: https://wiki.mobileread.com/wiki/CBR_and_CBZ
[balaclark]: https://github.com/balaclark/HTML5-Comic-Book-Reader
[SS01]: https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/files_reader-1.png "Reader showing day/nighyt mode"
[SS02]: https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/files_reader-3.png "Single page full screen on a small-screen device"
[SS03]: https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/photo_2017-03-15_17-21-39.jpg "Day mode color selector"
[SS04]: https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/photo_2017-03-15_17-21-41.jpg?raw=true "Longing For that olde-time terminal feeling..."
[SS05]: https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/photo_2017-03-15_17-21-53.jpg "Full-text search"
[SS06]: https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/photo_2017-03-15_18-28-46.jpg "Small screen device, __maximize text area__ enabled"
[SS07]: https://github.com/Yetangitu/owncloud-apps/blob/master/screenshots/photo_2017-03-15_18-28-49.jpg?raw=true "Search on small-screen device"
[SS08]: https://github.com/Yetangitu/owncloud-apps/blob/master/screenshots/photo_2017-03-15_17-21-52.jpg?raw=true "As close to full-screen as you can get on iOS"
[SS09]: https://github.com/Yetangitu/owncloud-apps/blob/master/screenshots/Screenshot_2014-09-29-20-21-50.png?raw=true "Android supports true fullscreen (as do most other systems)"
[SS10]: https://github.com/Yetangitu/owncloud-apps/blob/master/screenshots/photo_2017-03-15_17-21-59.jpg?raw=true "iOS approximation of full screen, CBR"
[SS11]: https://github.com/Yetangitu/owncloud-apps/blob/master/screenshots/photo_2017-03-15_17-22-00.jpg?raw=true "The same book, now in landscape mode, switch to 2-page spread is automatic"
[SS12]: https://github.com/Yetangitu/owncloud-apps/blob/master/screenshots/photo_2017-03-15_17-22-01.jpg?raw=true "Sidebar open, showing index, landscape mode"
[SS13]: https://github.com/Yetangitu/owncloud-apps/blob/master/screenshots/photo_2017-03-15_17-22-02.jpg?raw=true "Sidebar open, showing index, portrait mode"
[SS14]: https://github.com/Yetangitu/owncloud-apps/blob/master/screenshots/photo_2017-03-15_17-22-05.jpg?raw=true "Image enhancement filters, desaturate (grayscale) active"
[SS15]: https://github.com/Yetangitu/owncloud-apps/blob/master/screenshots/photo_2017-03-15_17-22-08.jpg?raw=true "full screen (apart from iOS restrictions), controls hidden"
[SS16]: https://github.com/Yetangitu/owncloud-apps/blob/master/screenshots/photo_2017-03-15_17-22-10.jpg?raw=true "Same page, zoomed in"
[SS17]: https://github.com/Yetangitu/owncloud-apps/blob/master/screenshots/photo_2017-03-15_18-28-54.jpg?raw=true "Small-screen, low memory (Android) device showing full-page book cover"
[SS18]: https://github.com/Yetangitu/owncloud-apps/blob/master/screenshots/photo_2017-03-15_18-28-56.jpg?raw=true "The same Android device showing a zoomed-in part of a page"
]]>
</description>
<version>0.8.4</version>
<version>1.0.0</version>
<licence>AGPL</licence>
<author>Frank de Lange</author>
<documentation>
@ -21,14 +130,21 @@
<bugs>https://github.com/Yetangitu/owncloud-apps/issues</bugs>
<website>https://github.com/Yetangitu/owncloud-apps/files_reader</website>
<screenshot>https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/files_reader-1.png</screenshot>
<screenshot>https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/files_reader-2.png</screenshot>
<screenshot>https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/files_reader-3.png</screenshot>
<screenshot>https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/photo_2017-03-15_17-22-00.jpg</screenshot>
<screenshot>https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/photo_2017-03-15_17-22-02.jpg</screenshot>
<category>files</category>
<category>multimedia</category>
<category>office</category>
<types>
<filesystem/>
</types>
<dependencies>
<owncloud min-version="8.1" max-version="9.2" />
<nextcloud min-version="8.1" max-version="12"/>
<nextcloud min-version="8.1" max-version="12"/>
<database>pgsql</database>
<database>sqlite</database>
<database>mysql</database>
</dependencies>
<ocsid>167127</ocsid>
</info>

View file

@ -10,9 +10,29 @@
* later.
*/
namespace OCA\Files_Reader\AppInfo;
return ['routes' => [
['name' => 'display#showReader', 'url' => '/', 'verb' => 'GET'],
// Page
['name' => 'page#showReader', 'url' => '/', 'verb' => 'GET'],
// Bookmarks
['name' => 'bookmark#get_cursor', 'url' => '/bookmark/cursor/{fileId}', 'verb' => 'GET'],
['name' => 'bookmark#set_cursor', 'url' => '/bookmark/cursor', 'verb' => 'POST'],
['name' => 'bookmark#delete_cursor', 'url' => '/bookmark/cursor/{fileId}', 'verb' => 'DELETE'],
['name' => 'bookmark#get', 'url' => '/bookmark/{fileId}/{name}', 'verb' => 'GET', 'defaults' => ['name' => '']],
['name' => 'bookmark#get', 'url' => '/bookmark/{fileId}/{type}/{name}', 'verb' => 'GET', 'defaults' => ['name' => '']],
['name' => 'bookmark#set', 'url' => '/bookmark', 'verb' => 'POST'],
['name' => 'bookmark#delete', 'url' => '/bookmark/{fileId}/{name}', 'verb' => 'DELETE'],
// Metadata
['name' => 'metadata#get', 'url' => '/metadata/{fileId}/{name}', 'verb' => 'GET', 'defaults' => ['name' => '']],
['name' => 'metadata#set', 'url' => '/metadata/{fileId}/{name}/{value}', 'verb' => 'POST'],
// Preferences
['name' => 'preference#get_default', 'url' => '/preference/default/{scope}/{name}', 'verb' => 'GET', 'defaults' => ['name' => '']],
['name' => 'preference#set_default', 'url' => '/preference/default', 'verb' => 'POST'],
['name' => 'preference#delete_default', 'url' => '/preference/default/{scope}/{name}', 'verb' => 'DELETE'],
['name' => 'preference#get', 'url' => '/preference/{fileId}/{scope}/{name}', 'verb' => 'GET', 'defaults' => ['name' => '']],
['name' => 'preference#set', 'url' => '/preference', 'verb' => 'POST'],
['name' => 'preference#delete', 'url' => '/preference/{fileId}/{scope}/{name}', 'verb' => 'DELETE'],
]];

View file

@ -1,58 +0,0 @@
<?php
/**
* @author Frank de Lange
* @copyright 2015 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Controller;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\IRequest;
use OCP\IURLGenerator;
class DisplayController extends Controller {
/** @var IURLGenerator */
private $urlGenerator;
/**
* @param string $AppName
* @param IRequest $request
* @param IURLGenerator $urlGenerator
*/
public function __construct($AppName, IRequest $request, IURLGenerator $urlGenerator) {
parent::__construct($AppName, $request);
$this->urlGenerator = $urlGenerator;
}
/**
* @PublicPage
* @NoCSRFRequired
*
* @return TemplateResponse
*/
public function showReader() {
$params = [
'urlGenerator' => $this->urlGenerator
];
$response = new TemplateResponse($this->appName, 'reader', $params, 'blank');
$csp = new ContentSecurityPolicy();
$csp->addAllowedChildSrcDomain('\'self\'');
$csp->addAllowedScriptDomain('\'self\'');
$csp->addAllowedFrameDomain('\'self\'');
$csp->addAllowedStyleDomain('blob:');
$csp->addAllowedImageDomain('blob:');
$response->setContentSecurityPolicy($csp);
return $response;
}
}

View file

@ -1,33 +0,0 @@
/* For iPad portrait layouts only */
@media only screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation: portrait) {
#viewer iframe {
width: 460px;
height: 740px;
}
}
/*For iPad landscape layouts only */
@media only screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation: landscape) {
#viewer iframe {
width: 460px;
height: 415px;
}
}
/* For iPhone portrait layouts only */
@media only screen and (max-device-width: 480px) and (orientation: portrait) {
#viewer {
width: 256px;
height: 432px;
}
#viewer iframe {
width: 256px;
height: 432px;
}
}
/* For iPhone landscape layouts only */
@media only screen and (max-device-width: 480px) and (orientation: landscape) {
#viewer iframe {
width: 256px;
height: 124px;
}
}

View file

@ -1,31 +0,0 @@
.tooltip {
position: relative;
top: 0;
left: 0;
}
*.tooltip:hover span {
opacity: 1;
visibility: visible;
}
*.tooltip span {
z-index: 10;
padding: 1em;
bottom: 2em;
right: -10em;
width: 50%;
background-color: #222222;
color: #FFFFFF;
height: auto;
border-radius: 0.5em;
opacity: 0;
position:absolute;
visibility: hidden;
word-wrap: break-word;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
-ms-transition: all 0.5s;
-o-transition: all 0.5s;
transition: all 0.5s;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 Frank de Lange
* Copyright (c) 2015-2017 Frank de Lange
* Copyright (c) 2013-2014 Lukas Reschke <lukas@owncloud.com>
*
* This file is licensed under the Affero General Public License version 3
@ -9,17 +9,33 @@
*
*/
(function(OCA) {
OCA.FilesReader = OCA.FilesReader || {};
OCA.Files_Reader = OCA.Files_Reader || {};
var isMobile = navigator.userAgent.match(/Mobi/i);
var hasTouch = 'ontouchstart' in document.documentElement;
function actionHandler(fileName, mime, context) {
var downloadUrl = '';
if($('#isPublic').val()) {
var sharingToken = $('#sharingToken').val();
downloadUrl = OC.generateUrl('/s/{token}/download?files={files}&path={path}', {
token: sharingToken,
files: fileName,
path: context.dir
});
} else {
downloadUrl = Files.getDownloadUrl(fileName, context.dir);
}
OCA.Files_Reader.Plugin.show(downloadUrl, mime, true);
}
/**
* @namespace OCA.FilesReader.Plugin
* @namespace OCA.Files_Reader.Plugin
*/
OCA.FilesReader.Plugin = {
OCA.Files_Reader.Plugin = {
/**
* @param fileList
@ -51,10 +67,10 @@
* @param downloadUrl
* @param isFileList
*/
show: function(downloadUrl, isFileList) {
show: function(downloadUrl, mimeType, isFileList) {
var self = this;
var $iframe;
var viewer = OC.generateUrl('/apps/files_reader/?file={file}', {file: downloadUrl});
var viewer = OC.generateUrl('/apps/files_reader/?file={file}&type={type}', {file: downloadUrl, type: mimeType});
// launch in new window on mobile and touch devices...
if (isMobile || hasTouch) {
window.open(viewer, downloadUrl);
@ -86,39 +102,41 @@
_extendFileActions: function(fileActions) {
var self = this;
fileActions.registerAction({
name: 'view',
displayName: 'Favorite',
name: 'view-epub',
displayName: 'View',
mime: 'application/epub+zip',
permissions: OC.PERMISSION_READ,
actionHandler: function(fileName, context) {
var downloadUrl = '';
if($('#isPublic').val()) {
var sharingToken = $('#sharingToken').val();
downloadUrl = OC.generateUrl('/s/{token}/download?files={files}&path={path}', {
token: sharingToken,
files: fileName,
path: context.dir
});
} else {
downloadUrl = Files.getDownloadUrl(fileName, context.dir);
}
self.show(downloadUrl, true);
actionHandler: function(fileName, context){
return actionHandler(fileName, 'application/epub+zip', context);
}
});
fileActions.setDefault('application/epub+zip', 'view');
fileActions.registerAction({
name: 'view-cbr',
displayName: 'View',
mime: 'application/x-cbr',
permissions: OC.PERMISSION_READ,
actionHandler: function(fileName, context) {
return actionHandler(fileName, 'application/x-cbr', context);
}
});
fileActions.setDefault('application/epub+zip', 'view-epub');
fileActions.setDefault('application/x-cbr', 'view-cbr');
}
};
})(OCA);
OC.Plugins.register('OCA.Files.FileList', OCA.FilesReader.Plugin);
OC.Plugins.register('OCA.Files.FileList', OCA.Files_Reader.Plugin);
// FIXME: Hack for single public file view since it is not attached to the fileslist
$(document).ready(function(){
if ($('#isPublic').val() && $('#mimetype').val() === 'application/epub+zip') {
if ($('#isPublic').val() && ($('#mimetype').val() === 'application/epub+zip'|| $('#mimetype').val() === 'application/x-cbr)')) {
var sharingToken = $('#sharingToken').val();
var downloadUrl = OC.generateUrl('/s/{token}/download', {token: sharingToken});
var viewer = OCA.FilesReader.Plugin;
viewer.show(downloadUrl, false);
var viewer = OCA.Files_Reader.Plugin;
var mime = $('#mimetype').val();
viewer.show(downloadUrl, mime, false);
}
});

View file

@ -1,169 +1,139 @@
function disableStyles(doc, disable) {
for ( var i=0; i<doc.styleSheets.length; i++) {
void(doc.styleSheets.item(i).disabled=disable);
}
}
function addStyleSheet() {
var style = document.createElement("style");
// WebKit hack :(
style.appendChild(document.createTextNode(""));
document.head.appendChild(style);
return style.sheet;
}
function getCSSRule(sheet, selector, del) {
lcSelector = selector.toLowerCase();
for ( var i=0; i<sheet.cssRules.length; i++) {
if (sheet.cssRules.item(i).selectorText.toLowerCase() == lcSelector) {
if (del) {
sheet.deleteRule(i);
return null;
} else {
return sheet.cssRules.item(i);
}
}
}
return null;
}
function addCSSRule(sheet, selector, rules, index) {
if("insertRule" in sheet) {
sheet.insertRule(selector + "{" + rules + "}", index);
}
else if("addRule" in sheet) {
sheet.addRule(selector, rules, index);
}
}
function delCSSRule(sheet, selector) {
getCSSRule(sheet, selector, true);
}
document.onreadystatechange = function () {
if (document.readyState == "complete") {
// only enable close button when launched in an iframe
if (parent !== window) {
$('#close').show();
$('#close').on('click', function() { reader.book.destroy(); parent.OCA.FilesReader.Plugin.hide(); });
}
// some parameters...
EPUBJS.filePath = "js/libs/";
EPUBJS.cssPath = "css/";
if (document.readyState == "complete") {
// touch-enabled devices...
$('#touch_nav').prop('checked', !('ontouchstart' in document.documentElement));
if (!($('#touch_nav').prop('checked'))) {
$("#next").addClass("touch_nav");
$("#prev").addClass("touch_nav");
}
var type=decodeURIComponent(getUrlParameter('type')),
file=decodeURIComponent(getUrlParameter('file')),
options = {},
$session = $('.session');
// idevices...
if (navigator.userAgent.match(/(iPad|iPhone|iPod)/g)) {
$('head').append($('<link rel="stylesheet" type="text/css" />').attr('href', document.getElementsByTagName("base").item(0).href + 'css/idevice.css'));
}
options.session = {};
options.session.filename = decodeURI($session.data('filename'));
options.session.format = $session.data('filetype');
options.session.fileId = $session.data('fileid');
options.session.title = options.session.filename;
options.session.nonce = $session.data('nonce') || "";
options.session.version = $session.data('version') || "";
options.session.metadata = $session.data('metadata') || {};
options.session.annotations = $session.data('annotations') || {};
options.session.fileId = $session.data('fileid') || "";
options.session.scope = $session.data('scope') || "";
options.session.cursor = $session.data('cursor') || {};
options.session.defaults = $session.data('defaults') || {};
options.session.preferences = $session.data('preferences') || {};
options.session.defaults = $session.data('defaults') || {};
options.session.basePath = $session.data('basepath');
options.session.downloadLink = $session.data('downloadlink');
// IE < 11
if (navigator.userAgent.indexOf("MSIE") != -1) {
EPUBJS.Hooks.register("beforeChapterDisplay").wgxpath = function(callback, renderer){
wgxpath.install(renderer.render.window);
if(callback)
callback();
};
wgxpath.install(window);
}
function nightModeConfig() {
delCSSRule(EPUBJS.nightSheet, EPUBJS.nightSelector);
addCSSRule(EPUBJS.nightSheet, EPUBJS.nightSelector, 'color: ' + EPUBJS.nightModeColor + ' !important; background: ' + EPUBJS.nightModeBackground + ' !important;');
}
/* functions return jquery promises */
options.session.getPreference = function(name) {
return $.get(options.session.basePath + "preference/" + options.session.fileId + "/" + options.session.scope + "/" + name);
};
options.session.setPreference = function(name, value) {
return $.post(options.session.basePath + "preference",
{
"fileId": options.session.fileId,
"scope": options.session.scope,
"name": name,
"value": JSON.stringify(value)
});
};
options.session.deletePreference = function(name) {
return $.delete(options.session.basePath + "preference/" + options.session.fileId + "/" + options.session.scope + "/" + name);
};
options.session.getDefault = function(name) {
return $.get(options.session.basePath + "preference/default/" + options.session.scope + "/" + name);
};
options.session.setDefault = function(name, value) {
return $.post(options.session.basePath + "preference/default",
{
"scope": options.session.scope,
"name": name,
"value": JSON.stringify(value)
});
};
options.session.deleteDefault = function(name) {
return $.delete(options.session.basePath + "preference/default/" + options.session.scope + "/" + name);
};
options.session.getBookmark = function(name, type) {
return $.get(options.session.basePath + "bookmark/" + options.session.fileId + "/" + type + "/" + name);
};
options.session.setBookmark = function(name, value, type, content) {
return $.post(options.session.basePath + "bookmark",
{
"fileId": options.session.fileId,
"name": name,
"value": JSON.stringify(value),
"type": type,
"content": JSON.stringify(content)
});
};
options.session.deleteBookmark = function(name) {
return $.delete(options.session.basePath + "bookmark/" + options.session.fileId + "/" + name);
};
options.session.getCursor = function() {
return $.get(options.session.basePath + "bookmark/cursor/" + options.session.fileId);
};
options.session.setCursor = function(value) {
return $.post(options.session.basePath + "bookmark/cursor",
{
"fileId": options.session.fileId,
"value": JSON.stringify(value)
});
};
options.session.deleteCursor = function() {
return $.delete(options.session.basePath + "bookmark/cursor/" + options.session.fileId);
};
// nightMode
EPUBJS.nightMode = false;
EPUBJS.nightSheet = addStyleSheet();
EPUBJS.nightSelector = '.night *';
EPUBJS.nightModeBackground = $('#nightModeBackground').val();
EPUBJS.nightModeColor = $('#nightModeColor').val();
addCSSRule(EPUBJS.nightSheet, '.nonight', 'background: initial !important;');
nightModeConfig();
switch (type) {
case 'application/epub+zip':
options['contained'] = true;
renderEpub(file, options);
break;
case 'application/x-cbr':
renderCbr(file, options);
break;
default:
console.log(type + ' is not supported by Reader');
}
// why is there no standard library function for this?
function getUrlParameter (param) {
var pattern = new RegExp('[?&]'+param+'((=([^&]*))|(?=(&|$)))','i');
var m = window.location.search.match(pattern);
return m && ( typeof(m[3])==='undefined' ? '' : m[3] );
}
$('#nightModeBackground').on('change', function() {
EPUBJS.nightModeBackground = $('#nightModeBackground').val();
nightModeConfig();
});
// start epub.js renderer
function renderEpub(file, options) {
$('#nightModeColor').on('change', function() {
EPUBJS.nightModeColor = $('#nightModeColor').val();
nightModeConfig();
});
// some parameters...
EPUBJS.filePath = "vendor/epubjs/";
EPUBJS.cssPath = "vendor/epubjs/css/";
EPUBJS.basePath = $('.session').data('basepath');
console.log(document.getElementById("dllink").value);
var reader = ePubReader(document.getElementById("dllink").value, { contained: true });
/* device-specific boilerplate */
// enable night/day mode switch by clicking on the book title/author
// just switching in the "night" class works on some browsers but not on others, hence the trickery with
// setStyle/removeStyle...
$('#metainfo').on('click', function() {
if(EPUBJS.nightMode) {
reader.book.removeStyle("background");
reader.book.removeStyle("color");
$("#outerContainer").removeClass("night");
EPUBJS.nightMode = false;
} else {
reader.book.setStyle("background", EPUBJS.nightModeBackground);
reader.book.setStyle("color", EPUBJS.nightModeColor);
$("#outerContainer").addClass("night");
EPUBJS.nightMode = true;
}
});
// IE < 11
if (navigator.userAgent.indexOf("MSIE") != -1) {
EPUBJS.Hooks.register("beforeChapterDisplay").wgxpath = function(callback, renderer){
wgxpath.install(renderer.render.window);
if(callback)
callback();
};
wgxpath.install(window);
}
// extra-wide page turn area?
$('#touch_nav').on('click', function() {
if ($('#touch_nav').prop('checked')) {
$("#prev").removeClass("touch_nav");
$("#next").removeClass("touch_nav");
} else {
$("#prev").addClass("touch_nav");
$("#next").addClass("touch_nav");
}
});
// user-defined font
EPUBJS.ignore_css = false;
EPUBJS.bookFrame = null;
EPUBJS.user_fontFamily = $('#fontFamily').val();
EPUBJS.user_fontSize = $('#fontSize').val() + '%';
var reader = ePubReader(file, options);
}
$('#ignore_css').on('click', function() {
EPUBJS.bookFrame = document.getElementsByTagName('iframe')[0].contentDocument;
if ($('#ignore_css').prop('checked')) {
$('#fontFamily').prop('disabled',false);
$('#fontSize').prop('disabled',false);
EPUBJS.ignore_css = true;
reader.book.setStyle('font-size', EPUBJS.user_fontSize);
reader.book.setStyle('font-family', EPUBJS.user_fontFamily);
} else {
$('#fontFamily').prop('disabled',true);
$('#fontSize').prop('disabled',true);
EPUBJS.ignore_css = false;
reader.book.removeStyle('font-size');
reader.book.removeStyle('font-family');
}
disableStyles(EPUBJS.bookFrame, EPUBJS.ignore_css);
;
});
// start cbr.js renderer
function renderCbr(file, options) {
CBRJS.filePath = "vendor/cbrjs/";
$('#fontSize').on('change', function() {
EPUBJS.user_fontSize = $('#fontSize').val() + '%';
$('#font_example').css('font-size', EPUBJS.user_fontSize);
reader.book.setStyle('font-size', EPUBJS.user_fontSize);
});
$('#fontFamily').on('change', function() {
EPUBJS.user_fontFamily = $('#fontFamily').val();
$('#font_example').css('font-family', EPUBJS.user_fontFamily);
reader.book.setStyle('font-family', EPUBJS.user_fontFamily);
});
}
var reader = cbReader(file, options);
}
}
};

View file

@ -0,0 +1,124 @@
<?php
/**
* @author Frank de Lange
* @copyright 2017 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Controller;
use OCP\IRequest;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\DataResponse;
use OCA\Files_Reader\Service\BookmarkService;
class BookmarkController extends Controller {
private $bookmarkService;
/**
* @param string $AppName
* @param IRequest $request
* @param BookmarkService $bookmarkService
*/
public function __construct($AppName,
IRequest $request,
BookmarkService $bookmarkService ) {
parent::__construct($AppName, $request);
$this->bookmarkService = $bookmarkService;
}
/**
* @brief return bookmark
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param int $fileId
* @param string $name
*
* @return array|\OCP\AppFramework\Http\JSONResponse
*/
public function get($fileId, $name, $type=null) {
return $this->bookmarkService->get($fileId, $name, $type);
}
/**
* @brief write bookmark
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param int $fileId
* @param string $name
* @param string $value
*
* @return array|\OCP\AppFramework\Http\JSONResponse
*/
public function set($fileId, $name, $value, $type=null, $content=null) {
return $this->bookmarkService->set($fileId, $name, $value, $type, $content);
}
/**
* @brief return cursor for $fileId
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param int $fileId
*
* @return array|\OCP\AppFramework\Http\JSONResponse
*/
public function getCursor($fileId) {
return $this->bookmarkService->getCursor($fileId);
}
/**
* @brief write cursor for $fileId
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param int $fileId
* @param string $value
*
* @return array|\OCP\AppFramework\Http\JSONResponse
*/
public function setCursor($fileId, $value) {
return $this->bookmarkService->setCursor($fileId, $value);
}
/**
* @brief delete bookmark
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param int $fileId
* @param string name
*
*/
public function delete($fileId, $name) {
return $this->bookmarkService->delete($fileId, $name);
}
/**
* @brief delete cursor
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param int $fileId
*
*/
public function deleteCursor($fileId) {
return $this->bookmarkService->deleteCursor($fileId);
}
}

View file

@ -0,0 +1,80 @@
<?php
/**
* @author Frank de Lange
* @copyright 2017 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Controller;
use OCP\IRequest;
use OCP\AppFramework\Controller;
use OCA\Files_Reader\Service\MetadataService;
class MetadataController extends Controller {
private $metadataService;
/**
* @param string $AppName
* @param IRequest $request
* @param MetadataService $metadataService
*/
public function __construct($AppName,
IRequest $request,
MetadataService $metadataService ) {
parent::__construct($AppName, $request);
$this->metadataService = $metadataService;
}
/**
* @brief write metadata
*
* @NoAdminRequired
*
* @param int $fileId
* @param string $value
*
* @return array|\OCP\AppFramework\Http\JSONResponse
*/
public function setAll($fileId, $value) {
return $this->metadataService->setAll($fileId, $value);
}
/**
* @brief return metadata item
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param int $fileId
* @param string $name
*
* @return array|\OCP\AppFramework\Http\JSONResponse
*/
public function get($fileId, $name) {
return $this->metadataService->get($fileId, $name);
}
/**
* @brief write metadata item
*
* @NoAdminRequired
*
* @param int $fileId
* @param string $name
* @param string $value
*
* @return array|\OCP\AppFramework\Http\JSONResponse
*/
public function set($fileId, $name, $value) {
return $this->metadataService->set($fileId, $name, $value);
}
}

View file

@ -0,0 +1,147 @@
<?php
/**
* @author Frank de Lange
* @copyright 2015 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Controller;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\Files\IRootFolder;
use OCP\Share\IManager;
use OCA\Files_Reader\Service\BookmarkService;
use OCA\Files_Reader\Service\MetadataService;
use OCA\Files_Reader\Service\PreferenceService;
class PageController extends Controller {
/** @var IURLGenerator */
private $urlGenerator;
/** @var IRootFolder */
private $rootFolder;
private $shareManager;
private $userId;
private $bookmarkService;
private $metadataService;
private $preferenceService;
/**
* @param string $AppName
* @param IRequest $request
* @param IURLGenerator $urlGenerator
* @param IRootFolder $rootFolder
* @param IManager $shareManager
* @param string $UserId
* @param BookmarkService $bookmarkService
* @param PreferenceService $preferenceService
* @param MetadataService $metadataService
*/
public function __construct(
$AppName,
IRequest $request,
IURLGenerator $urlGenerator,
IRootFolder $rootFolder,
IManager $shareManager,
$UserId,
BookmarkService $bookmarkService,
PreferenceService $preferenceService,
MetadataService $metadataService) {
parent::__construct($AppName, $request);
$this->urlGenerator = $urlGenerator;
$this->rootFolder = $rootFolder;
$this->shareManager = $shareManager;
$this->userId = $UserId;
$this->bookmarkService = $bookmarkService;
$this->metadataService = $metadataService;
$this->preferenceService = $preferenceService;
}
/**
* @PublicPage
* @NoCSRFRequired
*
* @return TemplateResponse
*/
public function showReader() {
$templates= [
'application/epub+zip' => 'epubreader',
'application/x-cbr' => 'cbreader'
];
/**
* $fileInfo = [
* fileId => null,
* fileName => null,
* fileType => null
* ];
*/
$fileInfo = $this->getFileInfo($this->request->get['file']);
$fileId = $fileInfo['fileId'];
$type = $this->request->get["type"];
$scope = $template = $templates[$type];
$params = [
'urlGenerator' => $this->urlGenerator,
'downloadLink' => $this->request->get['file'],
'scope' => $scope,
'fileId' => $fileInfo['fileId'],
'fileName' => $fileInfo['fileName'],
'fileType' => $fileInfo['fileType'],
'cursor' => $this->toJson($this->bookmarkService->getCursor($fileId)),
'defaults' => $this->toJson($this->preferenceService->getDefault($scope)),
'preferences' => $this->toJson($this->preferenceService->get($scope, $fileId)),
'defaults' => $this->toJson($this->preferenceService->getDefault($scope)),
'metadata' => $this->toJson($this->metadataService->get($fileId)),
'annotations' => $this->toJson($this->bookmarkService->get($fileId))
];
$response = new TemplateResponse($this->appName, $template, $params, 'blank');
return $response;
}
/**
* @brief sharing-aware file info retriever
*
* Work around the differences between normal and shared file access
*
* @param string $path path-fragment from url
* @return array
*/
private function getFileInfo($path) {
$count = 0;
$shareToken = preg_replace("/\/index\.php\/s\/([A-Za-z0-9]{15})\/download/", "$1", $path, 1,$count);
if ($count === 1) {
$node = $this->shareManager->getShareByToken($shareToken)->getNode();
$filePath = $node->getPath();
$fileId = $node->getId();
} else {
$filePath = $path;
$fileId = $this->rootFolder->getUserFolder($this->userId)
->get(explode("/", rawurldecode($this->request->get['file']),4)[3])
->getFileInfo()
->getId();
}
return [
fileName => pathInfo($filePath, PATHINFO_FILENAME),
fileType => strtolower(pathInfo($filePath, PATHINFO_EXTENSION)),
fileId => $fileId
];
}
private function toJson($value) {
return htmlspecialchars(json_encode($value), ENT_QUOTES, 'UTF-8');
}
}

View file

@ -0,0 +1,128 @@
<?php
/**
* @author Frank de Lange
* @copyright 2017 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Controller;
use OCP\IRequest;
use OCP\IURLGenerator;
use OCP\AppFramework\Http;
use OCP\AppFramework\Controller;
use OCA\Files_Reader\Service\PreferenceService;
class PreferenceController extends Controller {
private $urlGenerator;
private $preferenceService;
/**
* @param string $AppName
* @param IRequest $request
* @param IURLGenerator $urlGenerator
* @param PreferenceService $preferenceService
*/
public function __construct($AppName,
IRequest $request,
IURLGenerator $urlGenerator,
PreferenceService $preferenceService ) {
parent::__construct($AppName, $request);
$this->urlGenerator = $urlGenerator;
$this->preferenceService = $preferenceService;
}
/**
* @brief return preference for $fileId
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param string $scope
* @param int $fileId
* @param string $name if null, return all preferences for $scope + $fileId
*
* @return array|\OCP\AppFramework\Http\JSONResponse
*/
public function get($scope, $fileId, $name) {
return $this->preferenceService->get($scope, $fileId, $name);
}
/**
* @brief write preference for $fileId
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param string $scope
* @param int $fileId
* @param string $name
* @param string $value
*
* @return array|\OCP\AppFramework\Http\JSONResponse
*/
public function set($scope, $fileId, $name, $value) {
return $this->preferenceService->set($scope, $fileId, $name, $value);
}
/**
* @brief return default preference
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param string $scope
* @param string $name if null, return all default preferences for scope
*
* @return array|\OCP\AppFramework\Http\JSONResponse
*/
public function getDefault($scope, $name) {
return $this->preferenceService->getDefault($scope, $name);
}
/**
* @brief write default preference
*
* @NoAdminRequired
* @NoCSRFRequired
*
* @param string $scope
* @param string $name
* @param string $value
*
* @return array|\OCP\AppFramework\Http\JSONResponse
*/
public function setDefault($scope, $name, $value) {
return $this->preferenceService->setDefault($scope, $name, $value);
}
/**
* @brief delete preference
*
* @param string $scope
* @param int $fileId
* @param string $name
*
*/
public function delete($scope, $fileId, $name) {
return $this->preferenceService->delete($scope, $fileId, $name);
}
/**
* @brief delete default preference
*
* @param $scope
* @param $name
*
*/
public function deleteDefault($scope, $name) {
return $this->preferenceService->deleteDefault($scope, $name);
}
}

View file

@ -0,0 +1,48 @@
<?php
/**
* @author Frank de Lange
* @copyright 2015 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Db;
use OCP\AppFramework\Db\Entity;
class Bookmark extends ReaderEntity implements \JsonSerializable {
protected $userId; // user
protected $fileId; // book (identified by fileId) for which this mark is valid
protected $type; // type, defaults to "bookmark"
protected $name; // name, defaults to $location
protected $value; // bookmark value (format-specific, eg. page number for PDF, CFI for epub, etc)
protected $content; // bookmark content (annotations etc), can be empty
protected $lastModified; // modification timestamp
public function jsonSerialize() {
return [
'id' => $this->getId(),
'userId' => $this->getUserId(),
'fileId' => $this->getFileId(),
'type' => $this->getType(),
'name' => $this->getName(),
'value' => static::conditional_json_decode($this->getValue()),
'content' => static::conditional_json_decode($this->getContent()),
'lastModified' => $this->getLastModified()
];
}
public function toService() {
return [
'name' => $this->getName(),
'type' => $this->getType(),
'value' => $this->conditional_json_decode($this->getValue()),
'content' => $this->conditional_json_decode($this->getContent()),
'lastModified' => $this->getLastModified(),
];
}
}

View file

@ -0,0 +1,121 @@
<?php
/**
* @author Frank de Lange
* @copyright 2017 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Db;
use OCP\IDBConnection;
use OCA\Files_Reader\Utility\Time;
class BookmarkMapper extends ReaderMapper {
private $userId;
/**
* @param IDbConnection $db
* @param $UserId
* @param Time $time
*/
public function __construct(IDBConnection $db, $UserId, Time $time) {
parent::__construct($db, 'reader_bookmarks', Bookmark::class, $time);
/** @var int $UserId */
$this->userId = $UserId;
}
/**
* @brief get bookmarks for $fileId+$userId(+$name)
* @param $fileId
* @param string $name
* @return array
*/
public function get($fileId, $name, $type=null) {
$sql = "SELECT * FROM `*PREFIX*reader_bookmarks` WHERE file_id=? AND `user_id`=?";
$args = [ $fileId, $this->userId ];
if (!(null === $type)) {
$sql .= " AND `type`=?";
$args[] = $type;
}
if (!(null === $name)) {
$sql .= " AND `name`=?";
$args[] = $name;
}
return $this->findEntities($sql, $args);
}
/**
* @brief write bookmark to database
*
* @param int $fileId
* @param string $name
* @param string $value
*
* @return Bookmark the newly created or updated bookmark
*/
public function set($fileId, $name, $value, $type, $content=null) {
$result = $this->get($fileId, $name);
if(empty($result)) {
// anonymous bookmarks are named after their contents
if (null === $name) {
$name = $value;
}
// default type is "bookmark"
if (null === $type) {
$type = "bookmark";
}
$bookmark = new Bookmark();
$bookmark->setFileId($fileId);
$bookmark->setUserId($this->userId);
$bookmark->setType($type);
$bookmark->setName($name);
$bookmark->setValue($value);
$bookmark->setContent($content);
$this->insert($bookmark);
} else {
$bookmark = $result[0];
$bookmark->setValue($value);
$bookmark->setContent($content);
$this->update($bookmark);
}
return $bookmark;
}
/* currently not used */
public function deleteForFileId($fileId) {
$sql = "SELECT * FROM `*PREFIX*reader_bookmarks` WHERE file_id=?";
$args = [ $fileId ];
array_map(
function($entity) {
$this->delete($entity);
}, $this->findEntities($sql, $args)
);
}
/* currently not used */
public function deleteForUserId($userId) {
$sql = "SELECT * FROM `*PREFIX*reader_bookmarks` WHERE user_id=?";
$args = [ $userId ];
array_map(
function($entity) {
$this->delete($entity);
}, $this->findEntities($sql, $args)
);
}
}

View file

@ -0,0 +1,42 @@
<?php
/**
* @author Frank de Lange
* @copyright 2015 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Db;
use OCP\AppFramework\Db\Entity;
class Preference extends ReaderEntity implements \JsonSerializable {
protected $userId; // user for whom this preference is valid
protected $scope; // scope (default or specific renderer)
protected $fileId; // file for which this preference is set
protected $name; // preference name
protected $value; // preference value
protected $lastModified; // modification timestamp
public function jsonSerialize() {
return [
'id' => $this->getId(),
'scope' => $this->getScope(),
'fileId' => $this->getFileId(),
'name' => $this->getName(),
'value' => $this->conditional_json_decode($this->getValue()),
'lastModified' => $this->getLastModified(),
];
}
public function toService() {
return [
'name' => $this->getName(),
'value' => $this->conditional_json_decode($this->getValue()),
];
}
}

View file

@ -0,0 +1,105 @@
<?php
/**
* @author Frank de Lange
* @copyright 2017 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Db;
use OCA\Files_Reader\Utility\Time;
use OCP\IDBConnection;
class PreferenceMapper extends ReaderMapper {
public function __construct(IDBConnection $db, $UserId, Time $time) {
parent::__construct($db, 'reader_preferences', Preference::class, $time);
$this->userId = $UserId;
}
/**
* @brief get preferences for $scope+$fileId+$userId(+$name)
*
* @param string $scope
* @param int $fileId
* @param string $name
* @return array
*/
public function get($scope, $fileId, $name=null) {
if(!empty($name)) {
$sql = "SELECT * FROM `*PREFIX*reader_preferences` WHERE `scope`=? AND `file_id`=? AND `user_id`=? AND `name`=?";
$args = array(
$scope,
$fileId,
$this->userId,
$name);
} else {
$sql = "SELECT * FROM `*PREFIX*reader_preferences` WHERE `scope`=? AND `file_id`=? AND `user_id`=?";
$args = array(
$scope,
$fileId,
$this->userId);
}
return $this->findEntities($sql, $args);
}
/**
* @brief write preference to database
*
* @param string $scope
* @param int $fileId
* @param string $name
* @param string $value
*
* @return Preference the newly created or updated preference
*/
public function set($scope, $fileId, $name, $value) {
$result = $this->get($scope, $fileId, $name);
if(empty($result)) {
$preference = new Preference();
$preference->setScope($scope);
$preference->setFileId($fileId);
$preference->setUserId($this->userId);
$preference->setName($name);
$preference->setValue($value);
$this->insert($preference);
} else {
$preference = $result[0];
$preference->setValue($value);
$this->update($preference);
}
return $preference;
}
/* currently not used*/
public function deleteForFileId($fileId) {
$sql = "SELECT * FROM `*PREFIX*reader_preferences` WHERE file_id=?";
$args = [ $fileId ];
array_map(
function($entity) {
$this->delete($entity);
}, $this->findEntities($sql, $args)
);
}
/* currently not used*/
public function deleteForUserId($userId) {
$sql = "SELECT * FROM `*PREFIX*reader_preferences` WHERE user_id=?";
$args = [ $userId ];
array_map(
function($entity) {
$this->delete($entity);
}, $this->findEntities($sql, $args)
);
}
}

View file

@ -0,0 +1,39 @@
<?php
/**
* @author Frank de Lange
* @copyright 2015 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Db;
use OCP\AppFramework\Db\Entity;
class ReaderEntity extends Entity {
/* returns decoded json if input is json, otherwise returns input */
public static function conditional_json_decode($el) {
$result = json_decode($el);
if (json_last_error() === JSON_ERROR_NONE) {
return $result;
} else {
return $el;
}
}
/*
public function toService() {
return [
'name' => $this->getName(),
'type' => $this->getType(),
'value' => $this->conditional_json_decode($this->getValue()),
'content' => $this->conditional_json_decode($this->getContent()),
'lastModified' => $this->getLastModified(),
];
}
*/
}

View file

@ -0,0 +1,40 @@
<?php
/**
* @author Frank de Lange
* @copyright 2017 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Db;
use OCP\IDBConnection;
use OCP\AppFramework\Db\Mapper;
use OCP\AppFramework\Db\Entity;
use OCA\Files_Reader\Utility\Time;
abstract class ReaderMapper extends Mapper {
/**
* @var Time
*/
private $time;
public function __construct(IDBConnection $db, $table, $entity, Time $time) {
parent::__construct($db, $table, $entity);
$this->time = $time;
}
public function update(Entity $entity) {
$entity->setLastModified($this->time->getMicroTime());
return parent::update($entity);
}
public function insert(Entity $entity) {
$entity->setLastModified($this->time->getMicroTime());
return parent::insert($entity);
}
}

View file

@ -0,0 +1,53 @@
<?php
/**
* @author Frank de Lange
* @copyright 2017 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader;
use OCP\IDBConnection;
use OCP\Files\Node;
use OCP\IUser;
use \OC\User\User as User;
class Hooks {
public static function register() {
\OC::$server->getRootFolder()->listen('\OC\Files', 'preDelete', function (Node $node) {
$fileId = $node->getId();
$connection = \OC::$server->getDatabaseConnection();
self::deleteFile($connection, $fileId);
});
\OC::$server->getUserManager()->listen('\OC\User', 'preDelete', function (User $user) {
$userId = $user->getUID();
$connection = \OC::$server->getDatabaseConnection();
self::deleteUser($connection, $userId);
});
}
protected static function deleteFile(IDBConnection $connection, $fileId) {
$queryBuilder = $connection->getQueryBuilder();
$queryBuilder->delete('reader_bookmarks','b')->where('b.file_id = :file_id')->setParameter(':file_id', $fileId);
$queryBuilder->execute();
$queryBuilder = $connection->getQueryBuilder();
$queryBuilder->delete('reader_preferences','p')->where('p.file_id = :file_id')->setParameter(':file_id', $fileId);
$queryBuilder->execute();
}
protected static function deleteUser(IDBConnection $connection, $userId) {
$queryBuilder = $connection->getQueryBuilder();
$queryBuilder->delete('reader_bookmarks','b')->where('b.user_id = :user_id')->setParameter(':user_id', $userId);
$queryBuilder->execute();
$queryBuilder = $connection->getQueryBuilder();
$queryBuilder->delete('reader_preferences','p')->where('p.user_id = :user_id')->setParameter(':user_id', $userId);
$queryBuilder->execute();
}
}

View file

@ -0,0 +1,113 @@
<?php
/**
* @author Frank de Lange
* @copyright 2017 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Service;
use OCA\Files_Reader\Db\BookmarkMapper;
class BookmarkService extends Service {
// "bookmark" name to use for the cursor (current reading position)
const CURSOR = '__CURSOR__';
const bookmark_type = 'bookmark';
private $bookmarkMapper;
private $userId;
public function __construct(BookmarkMapper $bookmarkMapper, $UserId) {
parent::__construct($bookmarkMapper);
$this->bookmarkMapper = $bookmarkMapper;
$this->userId = $UserId;
}
/**
* @brief get bookmark
*
* bookmark type is format-dependent, eg CFI for epub, page number for CBR/CBZ, etc
*
* @param int $fileId
* @param string $name
*
* @return array
*/
public function get($fileId, $name=null, $type=null) {
$result = $this->bookmarkMapper->get($fileId, $name, $type);
return array_map(
function($entity) {
return $entity->toService();
}, $result);
}
/**
* @brief write bookmark
*
* position type is format-dependent, eg CFI for epub, page number for CBR/CBZ, etc
*
* @param int $fileId
* @param string $name
* @param string $value
*
* @return array
*/
public function set($fileId, $name, $value, $type=null, $content=null) {
return $this->bookmarkMapper->set($fileId, $name, $value, $type, $content);
}
/**
* @brief get cursor (current position in book)
*
* @param int $fileId
*
* @return array
*/
public function getCursor($fileId) {
$result = $this->get($fileId, static::CURSOR);
if (count($result) === 1) {
return $result[0];
}
}
/**
* @brief set cursor (current position in book)
*
* @param int $fileId
* @param string $value
*
* @return array
*/
public function setCursor($fileId, $value) {
return $this->bookmarkMapper->set($fileId, static::CURSOR, $value, static::bookmark_type);
}
/**
* @brief delete bookmark
*
* @param int $fileId
* @param string $name
*
*/
public function delete($fileId, $name, $type=null) {
foreach ($this->bookmarkMapper->get($fileId, $name, $type) as $bookmark) {
$this->bookmarkMapper->delete($bookmark);
}
}
/**
* @brief delete cursor
*
* @param int $fileId
*
*/
public function deleteCursor($fileId) {
$this->delete($fileId, static::CURSOR, static::bookmark_type);
}
}

View file

@ -0,0 +1,64 @@
<?php
/**
* @author Frank de Lange
* @copyright 2017 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Service;
class MetadataService {
/**
* @brief get metadata item(s)
*
* @param int $fileId
* @param string $name
*
* @return array
*/
public function get($fileId, $name=null) {
if (class_exists('\OCA\Files_Opds\Meta')) {
if ($meta = \OCA\Files_Opds\Meta::get($fileId)) {
if (!empty($name) && array_key_exists($name, $meta)) {
return [$item => $meta[$name]];
} else {
return $meta;
}
}
}
return [];
}
/**
* @brief write metadata to database
*
* @param int $fileId
* @param array $value
*
* @return array
*/
public function setAll($fileId, $value) {
// no-op for now
return [];
}
/**
* @brief write metadata item to database
*
* @param int $fileId
* @param string $name
* @param array $value
*
* @return array
*/
public function set($fileId, $name, $value) {
// no-op for now
return [];
}
}

View file

@ -0,0 +1,117 @@
<?php
/**
* @author Frank de Lange
* @copyright 2017 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Service;
use OCA\Files_Reader\Db\PreferenceMapper;
class PreferenceService extends Service {
// (ab)use the fact that $fileId never goes below 1 by using the
// value 0 to indicate a default preference
const DEFAULTS = 0;
private $preferenceMapper;
/**
* @param PreferenceMapper $preferenceMapper
*/
public function __construct(PreferenceMapper $preferenceMapper) {
parent::__construct($preferenceMapper);
$this->preferenceMapper = $preferenceMapper;
}
/**
* @brief get preference
*
* scope identifies preference source, i.e. which renderer the preference applies to
* preference type is format-dependent, eg CFI for epub, page number for CBR/CBZ, etc
*
* @param string $scope
* @param int $fileId
* @param string $name
*
* @return array
*/
public function get($scope, $fileId, $name=null) {
$result = $this->preferenceMapper->get($scope, $fileId, $name);
return array_map(
function($entity) {
return $entity->toService();
}, $result);
}
/**
* @brief write preference
*
* scope identifies preference source, i.e. which renderer the preference applies to
* position type is format-dependent, eg CFI for epub, page number for CBR/CBZ, etc
*
* @param string $scope
* @param int $fileId
* @param string $name
* @param string $value
*
* @return array
*/
public function set($scope, $fileId, $name, $value) {
return $this->preferenceMapper->set($scope, $fileId, $name, $value);
}
/**
* @brief get default preference
*
* @param string $scope
* @param string $name
*
* @return array
*/
public function getDefault($scope, $name=null) {
return $this->get($scope, static::DEFAULTS, $name);
}
/**
* @brief set default preference
*
* @param string $scope
* @param string $name
* @param string $value
*
* @return array
*/
public function setDefault($scope, $name, $value) {
return $this->preferenceMapper->set($scope, static::DEFAULTS, $name, $value);
}
/**
* @brief delete preference
*
* @param string $scope
* @param int $fileId
* @param string $name
*
*/
public function delete($scope, $fileId, $name) {
foreach($this->preferenceMapper->get($scope, $fileId, $name) as $preference) {
$this->preferenceMapper->delete($preference);
}
}
/**
* @brief delete default
*
* @param string $scope
* @param string $name
*
*/
public function deleteDefault($scope, $name) {
$this->delete($scope, static::DEFAULTS, $name);
}
}

View file

@ -0,0 +1,25 @@
<?php
/**
* @author Frank de Lange
* @copyright 2017 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Service;
use OCA\Files_Reader\Db\ReaderMapper;
abstract class Service {
protected $mapper;
public function __construct(ReaderMapper $mapper){
$this->mapper = $mapper;
}
}

View file

@ -0,0 +1,27 @@
<?php
/**
* @author Frank de Lange
* @copyright 2017 Frank de Lange
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\Files_Reader\Utility;
class Time {
public function getTime() {
return time();
}
/**
*
* @return int the current unix time in miliseconds
*/
public function getMicroTime() {
list($millisecs, $secs) = explode(" ", microtime());
return $secs . substr($millisecs, 2, 6);
}
}

View file

@ -0,0 +1,238 @@
<?php
/** @var array $_ */
/** @var OCP\IURLGenerator $urlGenerator */
$urlGenerator = $_['urlGenerator'];
$downloadLink = $_['downloadLink'];
$fileId = $_['fileId'];
$fileName = $_['fileName'];
$fileType = $_['fileType'];
$scope = $_['scope'];
$cursor = $_['cursor'];
$defaults = $_['defaults'];
$preferences = $_['preferences'];
$metadata = $_['metadata'];
$annotations = $_['annotations'];
$title = htmlentities(basename($dllink));
$revision = '0046';
$version = \OCP\App::getAppVersion('files_reader') . '.' . $revision;
/* Mobile safari, the new IE6 */
$idevice = (strstr($_SERVER['HTTP_USER_AGENT'],'iPhone')
|| strstr($_SERVER['HTTP_USER_AGENT'],'iPad')
|| strstr($_SERVER['HTTP_USER_AGENT'],'iPod'));
/* Owncloud currently does not implement CSPv3, remove this test when it does */
$nonce = class_exists('\OC\Security\CSP\ContentSecurityPolicyNonceManager')
? \OC::$server->getContentSecurityPolicyNonceManager()->getNonce()
: 'nonce_not_implemented';
?>
<html dir="ltr">
<head class="session" data-nonce='<?php p($nonce);?>' data-downloadlink='<?php print_unescaped($downloadLink);?>' data-fileid='<?php print_unescaped($fileId);?>' data-filetype='<?php print_unescaped($fileType);?>' data-filename='<?php print_unescaped($fileName);?>' data-version='<?php print_unescaped($version);?>' data-basepath='<?php p($urlGenerator->linkTo('files_reader',''));?>' data-scope='<?php print_unescaped($scope);?>' data-cursor='<?php print_unescaped($cursor);?>' data-defaults='<?php print_unescaped($defaults);?>' data-preferences='<?php print_unescaped($preferences);?>' data-metadata='<?php print_unescaped($metadata);?>' data-annotations='<?php print_unescaped($annotations);?>'>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<base href="<?php p($urlGenerator->linkTo('files_reader',''));?>">
<title>
<?php p($_['title']);?>
</title>
<link rel="shortcut icon" href="img/book.png">
<link rel="stylesheet" href="vendor/icomoon/style.css?v=<?php p($version) ?>">
<link rel="stylesheet" href="vendor/cbrjs/css/cbr.css?v=<?php p($version) ?>">
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'js/lib/Blob.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/libs/jquery.min.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/sindresorhus/screenfull.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/pixastic/pixastic_combined.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/bitjs/archive.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/cbrjs/cbr.js')) ?>?v=<?php p($version) ?>"> </script>
<?php if ($idevice): ?>
<link rel="stylesheet" href="<?php p($urlGenerator->linkTo('files_reader', 'vendor/cbrjs/css/idevice.css')) ?>?v=<?php p($version) ?>">
<?php endif; ?>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'js/ready.js')) ?>?v=<?php p($version) ?>"> </script>
</head>
<body>
<!-- data -->
<!-- /data -->
<!-- loading progressbar -->
<div id="progressbar" style="display:none;">
<span class="progress"><span class="bar"></span></span>
<br>
<div class="message"><span class="message-icons"><span class="icon-cloud_download"></span><span class="icon-unarchive"></span></span> <span class="message-text"></span></div>
</div>
<!-- /loading progressbar -->
<!-- toolbar -->
<div class="toolbar control" name="toolbar">
<div class="pull-left">
<button data-trigger="click" data-action="openSidebar" title="open sidebar" class="icon-menu"></button>
</div>
<div class="metainfo">
<span class="book-title"></span>&nbsp;<span class="current-page"></span> / <span class="page-count"></span>
</div>
<div class="pull-right">
<div>
<button data-trigger="click" data-action="toggleLayout" title="toggle one/two pages at a time" class="icon-single_page_mode layout layout-single"></button>
<button data-trigger="click" data-action="toggleLayout" title="toggle one/two pages at a time" class="icon-double_page_mode layout layout-double"></button>
</div>
<div>
<button data-trigger="click" data-action="zoomOut" title="zoom out" class="icon-zoom_out"></button>
</div>
<div>
<button data-trigger="click" data-action="zoomIn" title="zoom in" class="icon-zoom_in"></button>
</div>
<div>
<button data-trigger="click" data-action="fitWidth" title="fit page to window width" class="icon-icon-fit-width"></button>
</div>
<div>
<button data-trigger="click" data-action="fitWindow" title="fit page to window" class="icon-icon-fit-window"></button>
</div>
<div>
<button data-trigger="click" data-action="toggleReadingMode" title="switch reading direction" class="icon-format_textdirection_l_to_r manga-false"></button>
<button data-trigger="click" data-action="toggleReadingMode" title="switch reading direction" class="icon-format_textdirection_r_to_l manga-true"></button>
</div>
<div>
<button data-trigger="click" data-action="toggleFullscreen" title="toggle fullscreen" class="icon-fullscreen fullscreen-false"></button>
<button data-trigger="click" data-action="toggleFullscreen" title="toggle fullscreen" class="icon-fullscreen_exit fullscreen-true"></button>
</div>
<div class="hide close separator"></div>
<div class="hide close">
<button data-trigger="click" data-action="close" title="close" class="icon-exit"></button>
</div>
</div>
</div>
<!-- /toolbar -->
<!-- loading overlay -->
<div id="cbr-loading-overlay" class="cbr-control control overlay" name="loadingOverlay" style="display:none"></div>
<!-- /loading overlay -->
<!-- busy overlay -->
<div id="cbr-busy-overlay" class="cbr-control control overlay" name="busyOverlay" data-trigger="click" data-action="closeSidebar" style="display:none"></div>
<!-- /busy overlay -->
<!-- navigation -->
<div data-trigger="click" data-action="navigation" data-navigate-side="left" class="cbr-control navigate navigate-left control" name="navigateLeft">
<span class="icon-navigate_before"></span>
</div>
<!-- toggle toolbar (disabled)
<div data-trigger="click" data-action="toggleToolbar" class="toggle-controls control" name="toggleToolbar"></div>
-->
<div data-trigger="click" data-action="navigation" data-navigate-side="right" class="cbr-control navigate navigate-right control" name="navigateRight">
<span class="icon-navigate_next"></span>
</div>
<!-- /navigation -->
<!-- inline progressbar -->
<div id="cbr-status" class="cbr-control control" name="progressbar" style="display:none">
<div id="cbr-progress-bar">
<div class="progressbar-value"></div>
</div>
</div>
<!-- /inline progressbar -->
<!-- sidebar -->
<div class="sidebar control" name="sidebar" id="sidebar">
<div class="panels">
<div class="pull-left">
<button data-trigger="click" data-action="showToc" title="Table of Contents" class="icon-format_list_numbered toc-view open"></button>
<button data-trigger="click" data-action="showBookSettings" title="Book settings" class="icon-rate_review book-settings-view"></button>
<button data-trigger="click" data-action="showSettings" title="Default settings" class="icon-settings settings-view"></button>
</div>
<div class="pull-right">
<button id="toc-populate" data-trigger="click" data-action="tocPopulate" title="generate thumbnails" class="icon-sync" style="display:none"></button>
<button data-trigger="click" data-action="closeSidebar" title="close sidebar" class="icon-menu"></button>
</div>
</div>
<div class="toc-view view open">
<ul id="toc">
</ul>
</div>
<div class="book-settings-view view">
<div class="metadata">
<table>
<tr>
<td>Title:</td><td class="book-title"></td>
</tr>
<tr>
<td>Format:</td><td class="book-format"></td>
</tr>
<tr>
<td>Page count:</td><td class="book-pagecount"></td>
</tr>
<tr>
<td>Size:</td><td class="book-size"></td>
</tr>
</table>
</div>
<div class="settings-container" name="enhancements" id="enhancements">
<label for="enhancements">Image enhancements</label>
<form name="image-enhancements" data-trigger="reset" data-action="resetEnhancements">
<div class="sliders">
<div class="control-group">
<label title="adjust brightness" class="icon-brightness_low"></label>
<input id="brightness" data-trigger="change" data-action="brightness" type="range" min="-100" max="100" step="1" value="0">
</div>
<div class="control-group">
<label title="adjust contrast" class="icon-contrast"></label>
<input id="contrast" data-trigger="change" data-action="brightness" type="range" min="-1" max="1" step="0.1" value="0">
</div>
<div class="control-group">
<label title="sharpen" class="icon-droplet"></label>
<input id="sharpen" data-trigger="change" data-action="sharpen" type="range" min="0" max="1" step="0.1" value="0">
</div>
</div>
<div class="control-group pull-left">
<input id="image-desaturate" type="checkbox" data-trigger="change" data-action="desaturate">
<label for="image-desaturate">desaturate</label>
<input id="image-removenoise" type="checkbox" data-trigger="change" data-action="removenoise">
<label for="image-removenoise">remove noise</label>
</div>
<div class="control-group pull-right">
<input type="reset" value="reset">
</div>
</form>
</div>
</div>
<div class="settings-view view">
<div class="settings-container" name="thumbnail-settings" id="thumbnail-settings">
<label for="thumbnail-settings">Thumbnails</label>
<div class="control-group pull-left">
<input id="thumbnail-generate" data-trigger="change" data-action="thumbnails" type="checkbox">
<label for="thumbnail-generate">Thumbnails in index </label>
</div>
<div class="control-group pull-left">
<label for="thumbnail-width">Thumbnail width:</label>
<input id="thumbnail-width" data-trigger="change" data-action="thumbnailWidth" type="number" min="50" max="500" step="10" value="200" >
<label for="thumbnail-width">px</label>
</div>
</div>
<div class="settings-container" name="sidebar-settings" id="sidebar-settings">
<label for="sidebar-settings">Sidebar</label>
<form name="sidebar-preferences" data-trigger="reset" data-action="resetSidebar">
<div class="control-group pull-left">
<input id="sidebar-wide" data-trigger="change" data-action="sidebarWide" type="checkbox">
<label for="sidebar-wide">Use extra-wide sidebar</label>
</div>
<div class="control-group pull-left">
<label for="sidebar-width">Sidebar width:</label>
<input id="sidebar-width" data-trigger="change" data-action="sidebarWidth" type="number" min="5" max="100" step="1" value="20" >
<label for="sidebar-width">%</label>
</div>
<div class="control-group pull-right">
<input type="reset" value="reset">
</div>
</form>
</div>
</div>
</div>
<!-- /sidebar -->
<canvas id="viewer" style="display:none;"></canvas>
</body>
</html>

View file

@ -0,0 +1,299 @@
<?php
/** @var array $_ */
/** @var OCP\IURLGenerator $urlGenerator */
$urlGenerator = $_['urlGenerator'];
$downloadLink = $_['downloadLink'];
$fileId = $_['fileId'];
$fileName = $_['fileName'];
$fileType = $_['fileType'];
$scope = $_['scope'];
$cursor = $_['cursor'];
$defaults = $_['defaults'];
$preferences = $_['preferences'];
$metadata = $_['metadata'];
$annotations = $_['annotations'];
$title = htmlentities(basename($dllink));
$revision = '0069';
$version = \OCP\App::getAppVersion('files_reader') . '.' . $revision;
/* Mobile safari, the new IE6 */
$idevice = (strstr($_SERVER['HTTP_USER_AGENT'],'iPhone')
|| strstr($_SERVER['HTTP_USER_AGENT'],'iPad')
|| strstr($_SERVER['HTTP_USER_AGENT'],'iPod'));
/* Owncloud currently does not implement CSPv3, remove this test when it does */
$nonce = class_exists('\OC\Security\CSP\ContentSecurityPolicyNonceManager')
? \OC::$server->getContentSecurityPolicyNonceManager()->getNonce()
: 'nonce_not_implemented';
?>
<html dir="ltr">
<head class="session" data-nonce='<?php p($nonce);?>' data-downloadlink='<?php print_unescaped($downloadLink);?>' data-fileid='<?php print_unescaped($fileId);?>' data-filetype='<?php print_unescaped($fileType);?>' data-filename='<?php print_unescaped($fileName);?>' data-version='<?php print_unescaped($version);?>' data-basepath='<?php p($urlGenerator->linkTo('files_reader',''));?>' data-scope='<?php print_unescaped($scope);?>' data-cursor='<?php print_unescaped($cursor);?>' data-defaults='<?php print_unescaped($defaults);?>' data-preferences='<?php print_unescaped($preferences);?>' data-metadata='<?php print_unescaped($metadata);?>' data-annotations='<?php print_unescaped($annotations);?>'>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<base href="<?php p($urlGenerator->linkTo('files_reader',''));?>">
<title>
<?php p($_['title']);?>
</title>
<link rel="shortcut icon" href="img/book.png">
<link rel="stylesheet" href="<?php p($urlGenerator->linkTo('files_reader', 'vendor/icomoon/style.css')) ?>?v=<?php p($version) ?>">
<link rel="stylesheet" href="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/css/main.css')) ?>?v=<?php p($version) ?>">
<link rel="stylesheet" href="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/css/sidebar.css')) ?>?v=<?php p($version) ?>">
<link rel="stylesheet" href="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/css/popup.css')) ?>?v=<?php p($version) ?>">
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'js/lib/typedarray.min.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'js/lib/Blob.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'js/lib/wgxpath.install.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/libs/jquery.min.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/bartaz/jquery.highlight.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/jquery/put-delete.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/sindresorhus/screenfull.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/libs/zip.min.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/epub.min.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/hooks.min.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/hooks/extensions/highlight.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/reader.min.js')) ?>?v=<?php p($version) ?>"> </script>
<?php if ($idevice): ?>
<link rel="stylesheet" href="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/css/idevice.css')) ?>?v=<?php p($version) ?>">
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/bgrins/spectrum.js')) ?>?v=<?php p($version) ?>"> </script>
<link rel="stylesheet" href="<?php p($urlGenerator->linkTo('files_reader', 'vendor/bgrins/spectrum.css')) ?>?v=<?php p($version) ?>">
<?php endif; ?>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'js/ready.js')) ?>?v=<?php p($version) ?>"> </script>
</head>
<body>
<div id="outerContainer">
<!-- sidebar -->
<div id="sidebar" class="sidebar">
<div id="panels" class="panels">
<div class="pull-left">
<button id="show-Toc" class="show_view icon-format_list_numbered open" title="Table of Contents" data-view="Toc"></button>
<button id="show-Bookmarks" class="show_view icon-turned_in" title="Bookmarks" data-view="Bookmarks"></button>
<button id="show-Search" class="show_view icon-search" title="Search" data-view="Search"></button>
<button id="show-Notes" class="show_view icon-comment" title="Notes" data-view="Notes"></button>
<button id="show-Settings" class="show_view icon-settings" title="Settings" data-view="Settings"></button>
</div>
<div class="pull-right">
<button id="hide-Sidebar" class="close_sidebar icon-arrow-left2" title="Close sidebar"></button>
</div>
</div>
<div id="views">
<div id="tocView" class="toc-view view open">
</div>
<div id="bookmarksView" class="bookmarks-view view">
<ul id="bookmarks" class="bookmarks">
</ul>
</div>
<div id="searchView" class="view search-view">
<div>
<div class="search-input">
<input id="searchBox" class="searchbox" placeholder="search..." type="input">
<span title="Clear">x</span>
<button id="clear_search" class="icon-cancel pull-right" title="Clear"></button>
</div>
<ul id="searchResults" class="search-results">
</ul>
</div>
</div>
<div id="notesView" class="notes-view view">
<div>
<div class="notes-input">
<textarea id="note-text" class="note-text" placeholder="Write note, press 'marker' button and select position in text to link note."></textarea>
<button id="note-anchor" class="note-anchor icon-room pull-right"></button>
</div>
<ol id="notes" class="notes">
</ol>
</div>
</div>
<div id="settingsView" class="settings-view view">
<fieldset class="settings-container" name="font-settings">
<legend>font</legend>
<div class="control-group">
<div>
<input type="checkbox" id="custom_font_family" name="font_family">
<label for="custom_font_family">custom font</label>
<select id="font_family" disabled="">
<option value="verdana, trebuchet, droid sans serif, sans, sans-serif"> sans </option>
<option value="georgia, times new roman, droid serif, serif"> serif </option>
<option value="monospace"> monospace </option>
</select>
</div>
<div>
<input type="checkbox" id="custom_font_size" name="font_size">
<label for="custom_font_size">font size</label>
<input type="number" id="font_size" value="100" min="50" max="150" disabled=""> %
</div>
<div>
<input type="checkbox" id="custom_font_weight" name="font_weight">
<label for="custom_font_weight">font weight</label>
<select id="font_weight" disabled="">
<option value="100">thin</option>
<option value="200">extra light</option>
<option value="300">light</option>
<option value="400">normal</option>
<option value="500">medium</option>
<option value="600">semi-bold</option>
<option value="700">bold</option>
<option value="800">extra bold</option>
<option value="900">black</option>
</select>
</div>
<div id="font_example" class="user font_example">
<div>
Et nos esse veri viri scire volemus
</div>
</div>
</div>
</fieldset>
<fieldset class="settings-container" name="colour-settings">
<legend>colors</legend>
<fieldset>
<legend>normal</legend>
<div class="control-group">
<input type="checkbox" id="use_custom_colors" name="use_custom_colors">
<label for="use_custom_colors">
Use custom colors
</label>
<div class="center-box">
<input type="color" id="day_color" value="#0a0a0a">
on
<input type="color" id="day_background" value="#f0f0f0">
</div>
<div id="day_example" class="day font_example">
<div>
Et nos esse veri viri scire volemus
</div>
</div>
</div>
</fieldset>
<fieldset>
<legend>night</legend>
<div class="control-group">
<div class="center-box nightshift">
nightmode can be toggled by clicking the book title
</div>
<div class="center-box">
<input type="color" id="night_color" value="#3a516b">
on
<input type="color" id="night_background" value="#000000">
</div>
<div id="night_example" class="night font_example">
<div>
Et nos esse veri viri scire volemus
</div>
</div>
</div>
</fieldset>
</fieldset>
<fieldset class="settings-container" name="display-settings">
<legend>display</legend>
<fieldset>
<legend>page width</legend>
<div class="control-group center-box">
maximum <input type="number" id="page_width" value="72" min="25" max="200"> characters
</div>
<div class="control-group">
<input type="checkbox" id="maximize_page" name="maximize_page">
<label for="custom_margins">maximize page area</label>
</div>
</fieldset>
<div class="control-group">
<input type="checkbox" id="sidebarReflow" name="sidebarReflow">
<label for="sidebarReflow">
reflow text when sidebars are open
</label>
</div>
<div class="control-group">
<input type="checkbox" id="touch_nav" name="touch_nav">
<label for="touch_nav">
disable extra-wide page turn areas
</label>
</div>
<div class="control-group">
<input type="checkbox" id="page_turn_arrows" name="page_turn_arrows">
<label for="page_turn_arrows">
show page turn arrows
</label>
</div>
</fieldset>
</div>
</div> <!-- views -->
</div> <!-- sidebar -->
<!-- /sidebar -->
<!-- main -->
<div id="main">
<!-- titlebar -->
<div id="titlebar">
<div id="opener" class="pull-left">
<a id="slider" class="icon-menu">
<?php p($l->t("menu")); ?>
</a>
</div>
<div id="metainfo" class="nightshift">
<span id="book-title">
</span>
<span id="title-seperator">
    
</span>
<span id="chapter-title">
</span>
</div>
<div id="title-controls" class="pull-right">
<a id="note" class="icon-comment">
</a>
<a id="bookmark" class="icon-turned_in_not">
</a>
<a id="fullscreen" class="icon-fullscreen">
</a>
<a id="close" class="icon-exit" style="display:none">
</a>
</div>
</div>
<!-- /titlebar -->
<!-- divider -->
<div id="divider">
</div>
<!-- /divider -->
<!-- navigation + viewer -->
<div id="prev" class="arrow">
<div class="translucent">
</div>
</div>
<div id="viewer">
</div>
<div id="next" class="arrow">
<div class="translucent">
</div>
</div>
<div id="loader">
<img src="img/loading.gif">
</div>
<!-- /navigation + viewer -->
</div>
<!-- /main -->
<div class="overlay">
</div>
</div>
</body>
</html>

View file

@ -1,197 +0,0 @@
<?php
/** @var array $_ */
/** @var OCP\IURLGenerator $urlGenerator */
$urlGenerator = $_['urlGenerator'];
$version = \OCP\App::getAppVersion('files_reader');
$dllink = isset($_GET['file']) ? $_GET['file'] : '';
$title = htmlentities(basename($dllink));
/* Owncloud currently does not implement CSPv3, remove this test when it does */
$nonce = class_exists('\OC\Security\CSP\ContentSecurityPolicyNonceManager')
? \OC::$server->getContentSecurityPolicyNonceManager()->getNonce()
: 'nonce_not_implemented';
?>
<html dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<base href="<?php p($urlGenerator->linkTo('files_reader',''));?>">
<title>
<?php p($title);?>
</title>
<link rel="shortcut icon" href="img/book.png">
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/popup.css">
<link rel="stylesheet" href="css/tooltip.css">
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'js/lib/typedarray.min.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'js/lib/Blob.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'js/lib/wgxpath.install.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/libs/jquery.min.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/libs/screenfull.min.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/libs/zip.min.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/epub.min.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/hooks.min.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/hooks/extensions/highlight.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'vendor/epubjs/reader.min.js')) ?>?v=<?php p($version) ?>"> </script>
<script type="text/javascript" nonce="<?php p($nonce) ?>" src="<?php p($urlGenerator->linkTo('files_reader', 'js/ready.js')) ?>?v=<?php p($version) ?>"> </script>
</head>
<body>
<input type="hidden" id="dllink" value="<?php print_unescaped($dllink);?>">
<div id="outerContainer">
<div id="sidebar">
<div id="panels">
<input id="searchBox" placeholder="not implemented yet" type="search" disabled="">
<a id="show-Search" class="show_view icon-search" data-view="Search">
<?php p($l->t("Search")); ?>
</a>
<a id="show-Toc" class="show_view icon-list-1 active" data-view="Toc">
<?php p($l->t("TOC")); ?>
</a>
<a id="show-Bookmarks" class="show_view icon-bookmark" data-view="Bookmarks">
<?php p($l->t("Bookmarks")); ?>
</a>
<a id="show-Notes" class="show_view icon-edit" data-view="Notes">
<?php p($l->t("Notes")); ?>
</a>
</div>
<div id="tocView" class="view">
</div>
<div id="searchView" class="view">
<ul id="searchResults">
</ul>
</div>
<div id="bookmarksView" class="view">
<ul id="bookmarks">
</ul>
</div>
<div id="notesView" class="view">
<div id="new-note">
<textarea id="note-text">
</textarea>
<button id="note-anchor">
<?php p($l->t("Anchor")); ?>
</button>
</div>
<ol id="notes">
</ol>
</div>
</div>
<div id="main">
<div id="titlebar">
<div id="opener">
<a id="slider" class="icon-menu">
<?php p($l->t("Menu")); ?>
</a>
</div>
<div id="metainfo">
<span id="book-title">
</span>
<span id="title-seperator">
    
</span>
<span id="chapter-title">
</span>
</div>
<div id="title-controls">
<a id="bookmark" class="icon-bookmark-empty">
<?php p($l->t("Bookmark")); ?>
</a>
<a id="setting" class="icon-cog">
<?php p($l->t("Settings")); ?>
</a>
<a id="fullscreen" class="icon-resize-full">
<?php p($l->t("Fullscreen")); ?>
</a>
<a id="close" class="icon-cancel-circled2" style="display:none">
<?php p($l->t("Close")); ?>
</a>
</div>
</div>
<div id="divider">
</div>
<div id="prev" class="arrow nonight">
<div class="nonight">
</div>
</div>
<div id="viewer">
</div>
<div id="next" class="arrow nonight">
<div class="nonight">
</div>
</div>
<div id="loader" class="nonight">
<img src="img/loading.gif">
</div>
</div>
<div class="modal md-effect-1" id="settings-modal">
<div class="md-content">
<h3>
<?php p($l->t("Settings")); ?>
</h3>
<div>
<p>
<input type="checkbox" id="ignore_css" name="ignore_css">
<label for="ignore_css">
<?php p($l->t("Always use")); ?>
</label>
<select id="fontFamily" disabled="">
<option value="verdana, trebuchet, droid sans serif, sans, sans-serif">
Sans
</option>
<option value="georgia, times new roman, droid serif, serif">
Serif
</option>
<option value="monospace">
Monospace
</option>
</select>
<?php p($l->t("font scaled to")); ?>
<input type="number" id="fontSize" value="100" min="50" max="150" disabled="">
%
</p>
<div id="font_example" class="user">
<?php p($l->t("Et nos esse veri viri scire volemus")); ?>
</div>
<p>
<input type="checkbox" id="sidebarReflow" name="sidebarReflow">
<label for="sidebarReflow">
<?php p($l->t("Reflow text when sidebars are open.")); ?>
</label>
</p>
<p>
<?php p($l->t("Night mode background")); ?>
<input type="color" id="nightModeBackground" value="#000000">
<?php p($l->t("and text")); ?>
<input type="color" id="nightModeColor" value="#3A516B">
<?php p($l->t("colour")); ?>
</p>
<div id="nightModeExample" class="night">
<div>
Et nos esse veri viri scire volemus
</div>
</div>
<p>
<input type="checkbox" id="touch_nav" name="touch_nav">
<label for="touch_nav" class="tooltip">
<?php p($l->t("Disable extra-wide page turn areas")); ?>
<span>
<?php p($l->t("The extra-wide page turn areas as used by default on touch-screen devices interfere with the ability to select links in ebooks. When this option is enabled, the page-turn area is always outside the ebook margins so links are reachable.")); ?>
</span>
</label>
</p>
</div>
<div class="closer icon-cancel-circled nonight">
</div>
</div>
</div>
<div class="overlay nonight">
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,108 @@
/*
* jQuery Highlight plugin
*
* Based on highlight v3 by Johann Burkard
* http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
*
* Code a little bit refactored and cleaned (in my humble opinion).
* Most important changes:
* - has an option to highlight only entire words (wordsOnly - false by default),
* - has an option to be case sensitive (caseSensitive - false by default)
* - highlight element tag and class names can be specified in options
*
* Usage:
* // wrap every occurrance of text 'lorem' in content
* // with <span class='highlight'> (default options)
* $('#content').highlight('lorem');
*
* // search for and highlight more terms at once
* // so you can save some time on traversing DOM
* $('#content').highlight(['lorem', 'ipsum']);
* $('#content').highlight('lorem ipsum');
*
* // search only for entire word 'lorem'
* $('#content').highlight('lorem', { wordsOnly: true });
*
* // don't ignore case during search of term 'lorem'
* $('#content').highlight('lorem', { caseSensitive: true });
*
* // wrap every occurrance of term 'ipsum' in content
* // with <em class='important'>
* $('#content').highlight('ipsum', { element: 'em', className: 'important' });
*
* // remove default highlight
* $('#content').unhighlight();
*
* // remove custom highlight
* $('#content').unhighlight({ element: 'em', className: 'important' });
*
*
* Copyright (c) 2009 Bartek Szopka
*
* Licensed under MIT license.
*
*/
jQuery.extend({
highlight: function (node, re, nodeName, className) {
if (node.nodeType === 3) {
var match = node.data.match(re);
if (match) {
var highlight = document.createElement(nodeName || 'span');
highlight.className = className || 'highlight';
var wordNode = node.splitText(match.index);
wordNode.splitText(match[0].length);
var wordClone = wordNode.cloneNode(true);
highlight.appendChild(wordClone);
wordNode.parentNode.replaceChild(highlight, wordNode);
return 1; //skip added node in parent
}
} else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
!/(script|style)/i.test(node.tagName) && // ignore script and style nodes
!(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
for (var i = 0; i < node.childNodes.length; i++) {
i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
}
}
return 0;
}
});
jQuery.fn.unhighlight = function (options) {
var settings = { className: 'highlight', element: 'span' };
jQuery.extend(settings, options);
return this.find(settings.element + "." + settings.className).each(function () {
var parent = this.parentNode;
parent.replaceChild(this.firstChild, this);
parent.normalize();
}).end();
};
jQuery.fn.highlight = function (words, options) {
var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
jQuery.extend(settings, options);
if (words.constructor === String) {
words = [words];
}
words = jQuery.grep(words, function(word, i){
return word != '';
});
words = jQuery.map(words, function(word, i) {
return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
});
if (words.length == 0) { return this; };
var flag = settings.caseSensitive ? "" : "i";
var pattern = "(" + words.join("|") + ")";
if (settings.wordsOnly) {
pattern = "\\b" + pattern + "\\b";
}
var re = new RegExp(pattern, flag);
return this.each(function () {
jQuery.highlight(this, re, settings.element, settings.className);
});
};

507
files_reader/vendor/bgrins/spectrum.css vendored Normal file
View file

@ -0,0 +1,507 @@
/***
Spectrum Colorpicker v1.8.0
https://github.com/bgrins/spectrum
Author: Brian Grinstead
License: MIT
***/
.sp-container {
position:absolute;
top:0;
left:0;
display:inline-block;
*display: inline;
*zoom: 1;
/* https://github.com/bgrins/spectrum/issues/40 */
z-index: 9999994;
overflow: hidden;
}
.sp-container.sp-flat {
position: relative;
}
/* Fix for * { box-sizing: border-box; } */
.sp-container,
.sp-container * {
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
/* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */
.sp-top {
position:relative;
width: 100%;
display:inline-block;
}
.sp-top-inner {
position:absolute;
top:0;
left:0;
bottom:0;
right:0;
}
.sp-color {
position: absolute;
top:0;
left:0;
bottom:0;
right:20%;
}
.sp-hue {
position: absolute;
top:0;
right:0;
bottom:0;
left:84%;
height: 100%;
}
.sp-clear-enabled .sp-hue {
top:33px;
height: 77.5%;
}
.sp-fill {
padding-top: 80%;
}
.sp-sat, .sp-val {
position: absolute;
top:0;
left:0;
right:0;
bottom:0;
}
.sp-alpha-enabled .sp-top {
margin-bottom: 18px;
}
.sp-alpha-enabled .sp-alpha {
display: block;
}
.sp-alpha-handle {
position:absolute;
top:-4px;
bottom: -4px;
width: 6px;
left: 50%;
cursor: pointer;
border: 1px solid black;
background: white;
opacity: .8;
}
.sp-alpha {
display: none;
position: absolute;
bottom: -14px;
right: 0;
left: 0;
height: 8px;
}
.sp-alpha-inner {
border: solid 1px #333;
}
.sp-clear {
display: none;
}
.sp-clear.sp-clear-display {
background-position: center;
}
.sp-clear-enabled .sp-clear {
display: block;
position:absolute;
top:0px;
right:0;
bottom:0;
left:84%;
height: 28px;
}
/* Don't allow text selection */
.sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button {
-webkit-user-select:none;
-moz-user-select: -moz-none;
-o-user-select:none;
user-select: none;
}
.sp-container.sp-input-disabled .sp-input-container {
display: none;
}
.sp-container.sp-buttons-disabled .sp-button-container {
display: none;
}
.sp-container.sp-palette-buttons-disabled .sp-palette-button-container {
display: none;
}
.sp-palette-only .sp-picker-container {
display: none;
}
.sp-palette-disabled .sp-palette-container {
display: none;
}
.sp-initial-disabled .sp-initial {
display: none;
}
/* Gradients for hue, saturation and value instead of images. Not pretty... but it works */
.sp-sat {
background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0)));
background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0));
background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0));
background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0));
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)";
filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81');
}
.sp-val {
background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0)));
background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0));
background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0));
background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0));
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)";
filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000');
}
.sp-hue {
background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000));
background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
}
/* IE filters do not support multiple color stops.
Generate 6 divs, line them up, and do two color gradients for each.
Yes, really.
*/
.sp-1 {
height:17%;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00');
}
.sp-2 {
height:16%;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00');
}
.sp-3 {
height:17%;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff');
}
.sp-4 {
height:17%;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff');
}
.sp-5 {
height:16%;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff');
}
.sp-6 {
height:17%;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000');
}
.sp-hidden {
display: none !important;
}
/* Clearfix hack */
.sp-cf:before, .sp-cf:after { content: ""; display: table; }
.sp-cf:after { clear: both; }
.sp-cf { *zoom: 1; }
/* Mobile devices, make hue slider bigger so it is easier to slide */
@media (max-device-width: 480px) {
.sp-color { right: 40%; }
.sp-hue { left: 63%; }
.sp-fill { padding-top: 60%; }
}
.sp-dragger {
border-radius: 5px;
height: 5px;
width: 5px;
border: 1px solid #fff;
background: #000;
cursor: pointer;
position:absolute;
top:0;
left: 0;
}
.sp-slider {
position: absolute;
top:0;
cursor:pointer;
height: 3px;
left: -1px;
right: -1px;
border: 1px solid #000;
background: white;
opacity: .8;
}
/*
Theme authors:
Here are the basic themeable display options (colors, fonts, global widths).
See http://bgrins.github.io/spectrum/themes/ for instructions.
*/
.sp-container {
border-radius: 0;
background-color: #ECECEC;
border: solid 1px #f0c49B;
padding: 0;
}
.sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear {
font: normal 12px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.sp-top {
margin-bottom: 3px;
}
.sp-color, .sp-hue, .sp-clear {
border: solid 1px #666;
}
/* Input */
.sp-input-container {
float:right;
width: 100px;
margin-bottom: 4px;
}
.sp-initial-disabled .sp-input-container {
width: 100%;
}
.sp-input {
font-size: 12px !important;
border: 1px inset;
padding: 4px 5px;
margin: 0;
width: 100%;
background:transparent;
border-radius: 3px;
color: #222;
}
.sp-input:focus {
border: 1px solid orange;
}
.sp-input.sp-validation-error {
border: 1px solid red;
background: #fdd;
}
.sp-picker-container , .sp-palette-container {
float:left;
position: relative;
padding: 10px;
padding-bottom: 300px;
margin-bottom: -290px;
}
.sp-picker-container {
width: 172px;
border-left: solid 1px #fff;
}
/* Palettes */
.sp-palette-container {
border-right: solid 1px #ccc;
}
.sp-palette-only .sp-palette-container {
border: 0;
}
.sp-palette .sp-thumb-el {
display: block;
position:relative;
float:left;
width: 24px;
height: 15px;
margin: 3px;
cursor: pointer;
border:solid 2px transparent;
}
.sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active {
border-color: orange;
}
.sp-thumb-el {
position:relative;
}
/* Initial */
.sp-initial {
float: left;
border: solid 1px #333;
}
.sp-initial span {
width: 30px;
height: 25px;
border:none;
display:block;
float:left;
margin:0;
}
.sp-initial .sp-clear-display {
background-position: center;
}
/* Buttons */
.sp-palette-button-container,
.sp-button-container {
float: right;
}
/* Replacer (the little preview div that shows up instead of the <input>) */
.sp-replacer {
margin:0;
overflow:hidden;
cursor:pointer;
padding: 4px;
display:inline-block;
*zoom: 1;
*display: inline;
border: solid 1px #91765d;
background: #eee;
color: #333;
vertical-align: middle;
}
.sp-replacer:hover, .sp-replacer.sp-active {
border-color: #F0C49B;
color: #111;
}
.sp-replacer.sp-disabled {
cursor:default;
border-color: silver;
color: silver;
}
.sp-dd {
padding: 2px 0;
height: 16px;
line-height: 16px;
float:left;
font-size:10px;
}
.sp-preview {
position:relative;
width:25px;
height: 20px;
border: solid 1px #222;
margin-right: 5px;
float:left;
z-index: 0;
}
.sp-palette {
*width: 220px;
max-width: 220px;
}
.sp-palette .sp-thumb-el {
width:16px;
height: 16px;
margin:2px 1px;
border: solid 1px #d0d0d0;
}
.sp-container {
padding-bottom:0;
}
/* Buttons: http://hellohappy.org/css3-buttons/ */
.sp-container button {
background-color: #eeeeee;
background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);
background-image: -moz-linear-gradient(top, #eeeeee, #cccccc);
background-image: -ms-linear-gradient(top, #eeeeee, #cccccc);
background-image: -o-linear-gradient(top, #eeeeee, #cccccc);
background-image: linear-gradient(to bottom, #eeeeee, #cccccc);
border: 1px solid #ccc;
border-bottom: 1px solid #bbb;
border-radius: 3px;
color: #333;
font-size: 14px;
line-height: 1;
padding: 5px 4px;
text-align: center;
text-shadow: 0 1px 0 #eee;
vertical-align: middle;
}
.sp-container button:hover {
background-color: #dddddd;
background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb);
background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb);
background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb);
background-image: -o-linear-gradient(top, #dddddd, #bbbbbb);
background-image: linear-gradient(to bottom, #dddddd, #bbbbbb);
border: 1px solid #bbb;
border-bottom: 1px solid #999;
cursor: pointer;
text-shadow: 0 1px 0 #ddd;
}
.sp-container button:active {
border: 1px solid #aaa;
border-bottom: 1px solid #888;
-webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
-moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
-ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
-o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee;
}
.sp-cancel {
font-size: 11px;
color: #d93f3f !important;
margin:0;
padding:2px;
margin-right: 5px;
vertical-align: middle;
text-decoration:none;
}
.sp-cancel:hover {
color: #d93f3f !important;
text-decoration: underline;
}
.sp-palette span:hover, .sp-palette span.sp-thumb-active {
border-color: #000;
}
.sp-preview, .sp-alpha, .sp-thumb-el {
position:relative;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==);
}
.sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner {
display:block;
position:absolute;
top:0;left:0;bottom:0;right:0;
}
.sp-palette .sp-thumb-inner {
background-position: 50% 50%;
background-repeat: no-repeat;
}
.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=);
}
.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=);
}
.sp-clear-display {
background-repeat:no-repeat;
background-position: center;
background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==);
}

2323
files_reader/vendor/bgrins/spectrum.js vendored Normal file

File diff suppressed because it is too large Load diff

1
files_reader/vendor/bitjs vendored Submodule

@ -0,0 +1 @@
Subproject commit 1f76d7611598b88fe736ec77eb4626bcf1e9ee06

1478
files_reader/vendor/cbrjs/cbr.js vendored Normal file

File diff suppressed because it is too large Load diff

448
files_reader/vendor/cbrjs/css/cbr.css vendored Normal file
View file

@ -0,0 +1,448 @@
/* reader */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 100%;
vertical-align: baseline;
background: transparent;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
/* remember to define focus styles! */
:focus {
outline: 0;
}
/* remember to highlight inserts somehow! */
ins {
text-decoration: none;
}
del {
text-decoration: line-through;
}
/* tables still need 'cellspacing="0"' in the markup */
table {
border-collapse: collapse;
border-spacing: 0;
}
.cbr-control {
font-family: helvetica, arial, sans-serif;
font-size: 12px;
}
.cbr-control {
color: #fff;
background-color: #111;
padding: 10px;
position: fixed !important;
box-shadow: 0 0 4px #000;
}
.navigate {
top: 0;
margin: 0;
cursor: pointer;
width: 20%;
opacity: 0;
background: center no-repeat;
box-shadow: none;
padding: 0 3em;
}
.navigate > span {
color: #000;
font-size: 10em;
background-color: rgba(255, 255, 255, 0.8);
border-radius: 1em;
top: 45%;
position: relative;
}
body:not(.mobile) .navigate:hover {
opacity: 1;
}
.navigate-left {
left: 0;
}
.navigate-left > span {
float: left;
}
.navigate-right {
right: 0;
}
.navigate-right > span {
float: right;
}
.toggle-controls {
cursor: pointer;
width: 20%;
height: 20%;
left: 40%;
top: 40%;
border: none;
position: fixed;
}
#cbr-loading-overlay {
z-index: 100;
background: #000 url("img/loading.gif") no-repeat center;
}
.overlay {
opacity: 0.7;
box-shadow: none;
}
#cbr-status {
z-index: 101;
font-size: 12px;
right: 0;
bottom: 0;
margin: 8px;
border-radius: 4px;
}
#cbr-progress-bar {
width: 200px;
}
#cbr-progress-bar,
#cbr-progress-bar .progressbar-value {
height: 3px;
}
#cbr-progress-bar .progressbar-value {
width: 0;
background: #86C441;
border-color: #3E7600;
}
* {
-webkit-user-select: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color: rgba(0,0,0,0);
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 12px;
line-height: 20px;
color: #333;
}
button,
input,
label {
cursor: pointer;
}
.pull-left {
float: left;
}
.pull-right {
float: right;
}
.toolbar,
.panels {
position: absolute;
color: white;
/* overflow: visible; */
background: #4e4e4e;
/* left: 0; */
/* right: 0; */
width: 100%;
}
.toolbar {
/* position: fixed; */
z-index: 99;
/* margin-bottom: 0; */
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.4);
opacity: 0;
transition: opacity 0.1s ease-in-out;
text-align: center;
}
.toolbar .metainfo {
font-size: 1.2em;
top: 0.5em;
}
.metainfo span {
margin: 0 0.5em;
}
.mobile .metainfo .book-title,
.mobile .metainfo .title-separator {
display: none;
}
body:not(.mobile) .toolbar:hover,
.mobile .toolbar,
.toolbar.open {
opacity: 1;
}
.toolbar div {
display: inline-block;
position: relative;
}
.toolbar .separator {
/* border: solid 1px; */
height: 1em;
opacity: 0.5;
}
.toolbar button, .sidebar button {
color: white;
border: none;
background-color: transparent;
padding: 0;
}
.toolbar div > button,
.sidebar div > button {
font-size: 1.5em;
padding: 0.5em;
margin: 0;
}
.mobile .toolbar div > button,
.mobile .sidebar div > button {
padding: 0.5em;
margin: 0;
}
body:not(.mobile) .toolbar div > button:hover,
body:not(.mobile) .sidebar div > button:hover {
color: #8CC746;
}
body:not(.mobile) .toolbar button[data-action=close]:hover {
color: #FF6464;
}
.hide {
display: none !important;
}
/* sidebar */
.sidebar.open {
box-shadow: 3px 0px 3px 0px rgba(0, 0, 0, 0.4);
display: block;
}
.sidebar {
background: #6b6b6b;
position: fixed;
top: 0;
min-width: 25em;
height: 100%;
overflow: hidden;
display: none;
z-index: 100;
}
.sidebar.wide {
width: 20%;
}
.panels {
overflow: hidden;
}
.panels .open {
background-color: #6B6B6B;
}
.view.open {
display: block !important;
}
#toc-populate.open {
display: inline-block !important;
background-color: #4e4e4e;
}
.view {
overflow-y: scroll;
display: none !important;
width: 100%;
position: absolute;
top: 3em;
bottom: 0;
text-align: center;
}
.toc-view li {
margin: 1em;
font-family: Georgia, "Times New Roman", Times, serif;
}
.toc-view img, .placeholder {
width: 100%;
position: relative;
background-color: #999;
}
.toc-view span {
position: absolute;
transform: translate3d(-3em, 3em, 0);
font-size: 5em;
font-weight: bold;
color: #F8F8F8;
text-shadow: 0.05em 0.05em 0.02em rgba(70, 70, 70, 0.8);
-webkit-text-stroke: 2px black;
background-color: rgba(255,255,255,0.7);
border-radius: 1em;
box-shadow: 0 0 0.3em rgba(255,255,255,1);
padding: 0.5em;
}
.settings-container {
text-align: left;
display: inline-block;
width: 95%;
font-size: 1em;
background: #F8F8F8;
color: #111;
padding-top: 1em;
padding-bottom: 1em;
margin-top: 1em;
border-radius: 4px;
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.4);
}
.settings-container label {
margin-right: 1em;
}
.settings-container > label {
font-weight: bold;
width: 100%;
display: inline-block;
margin-bottom: 1em;
text-align: center;
}
.view .control-group input[type=range] {
width: 80%;
float: right;
margin: 0;
}
.view .control-group {
padding: 1em;
}
.view .sliders {
font-size: 1.5em;
}
.view .control-group span {
float: left;
margin: 0 2px;
clear: both;
}
.view .control-group input[type=reset] {
float: right;
}
.metadata {
padding: 1em;
margin: 1em;
}
.metadata table {
font-size: 1.2em;
color: #F8F8F8;
}
.metadata td:nth-child(1) {
font-weight: bold;
padding-right: 1em;
}
/* END sidebar */
/* progressbar (loading/unarchiving) */
.progress, .bar {
width: 100%;
height: 0.3em;
margin: 0;
padding: 0;
display: inline-block;
}
.progress {
border: none;
}
.bar {
width: 0;
background-color: red;
box-shadow: 0px 1px 3px rgba(0,0,0,.6);
}
.message {
margin: 3em;
}
.message-icons {
font-size: 3em;
color: lightgrey;
vertical-align: middle;
}
.message-text {
font-size: 1.5em;
color: black;
}
.active {
color:black;
}
.ok {
color:green;
}
.error {
color:red;
}
/* END progressbar */

View file

@ -0,0 +1,4 @@
.view {
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Before After
Before After

View file

@ -0,0 +1,14 @@
.notes,
.search-results,
.view {
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
.search-results {
height: calc(100% - 5em);
}
.notes {
height: calc(100% - 9em);
}

329
files_reader/vendor/epubjs/css/main.css vendored Normal file
View file

@ -0,0 +1,329 @@
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
fieldset {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 100%;
vertical-align: baseline;
background: transparent;
}
body {
background: #4e4e4e;
overflow: hidden;
font-style:
}
#main {
position: absolute;
width: 100%;
height: 100%;
right: 0;
border-radius: 5px;
background: #fff;
overflow: hidden;
-webkit-transition: -webkit-transform .4s, width .2s;
-moz-transition: -webkit-transform .4s, width .2s;
-moz-box-shadow: inset 0 0 50px rgba(0,0,0,.1);
-webkit-box-shadow: inset 0 0 50px rgba(0,0,0,.1);
box-shadow: inset 0 0 50px rgba(0,0,0,.1);
}
#titlebar {
padding: 0.5em;
color: #4f4f4f;
font-weight: 100;
font-family: Georgia, "Times New Roman", Times, serif;
opacity: .5;
text-align: center;
-webkit-transition: opacity .5s;
-moz-transition: opacity .5s;
z-index: 10;
position: fixed;
width: 100%;
}
#titlebar:hover {
opacity: 1;
}
#titlebar a {
width: 1em;
height: 1em;
overflow: hidden;
display: inline-block;
opacity: .5;
padding: 0.2em;
border-radius: 0.2em;
border: 1px rgba(0,0,0,0) solid;
}
#titlebar a::before {
visibility: visible;
}
#titlebar a:hover {
opacity: .8;
border: 1px rgba(0,0,0,.2) solid;
}
#titlebar a:active {
opacity: 1;
color: rgba(0,0,0,.6);
box-shadow: inset 0 0 6px rgba(155,155,155,.8);
}
#book-title {
font-weight: 600;
}
#title-seperator {
display: none;
}
#title-controls {
margin-left: 1em;
margin-right: 1em;
}
#viewer {
width: 80%;
height: 80%;
top: 10%;
margin: auto;
max-width: 72em;
z-index: 2;
position: relative;
overflow: hidden;
}
#viewer iframe {
border: none;
}
#prev, #next {
position: absolute;
top: 10%;
height: 80%;
margin: 0;
}
.touch_nav {
width: 35%;
}
.arrow div {
display: table-cell;
vertical-align: middle;
}
#prev {
left: 0;
padding-left: 2em;
}
#next {
right: 0;
padding-right: 2em;
text-align: right;
}
.arrow {
font-size: 64px;
/* color: #E2E2E2; */
font-family: arial, sans-serif;
font-weight: bold;
cursor: pointer;
display: table;
z-index: 3;
opacity: 0.2;
}
.arrow:hover {
/* color: #777; */
opacity: 0.5;
}
.arrow:active,
.arrow.active {
color: #000;
}
#main.closed {
transform: translate(25em, 0);
}
#main.single {
width: calc(100% - 25em);
}
#metainfo {
display: inline-block;
text-align: center;
max-width: 80%;
min-width: 20%;
}
#divider {
position: absolute;
width: 1px;
border-right: 1px #000 solid;
height: 80%;
z-index: 100;
left: 50%;
margin-left: -1px;
top: 10%;
opacity: .15;
box-shadow: -2px 0 15px rgba(0, 0, 0, 1);
display: none;
}
#divider.show {
display: block;
}
#loader {
position: absolute;
z-index: 10;
left: 50%;
top: 50%;
margin: -33px 0 0 -33px;
}
.pull-left {
float: left;
}
.pull-right {
float: right;
}
.highlight {
background-color: yellow;
}
.overlay {
position: fixed;
width: 100%;
height: 100%;
visibility: hidden;
top: 0;
left: 0;
z-index: 1000;
opacity: 0;
background: rgba(255,255,255,0.8);
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
transition: all 0.3s;
}
.hide {
display: none !important;
}
.translucent {
opacity: 0 !important;
}
@media only screen and (max-width: 1040px) {
/*
#viewer{
width: 50%;
margin-left: 25%;
}
*/
#divider,
#divider.show {
display: none;
}
}
@media only screen and (max-width: 900px) {
/*
#viewer{
width: 60%;
margin-left: 20%;
}
*/
#prev {
padding-left: 20px;
}
#next {
padding-right: 20px;
}
}
@media only screen and (max-width: 550px) {
/*
#viewer{
width: 80%;
margin-left: 10%;
}
*/
#viewer {
width: 95%;
}
#prev {
padding-left: 0;
}
#next {
padding-right: 0;
}
.arrow div {
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
}
/*
#main {
-webkit-transform: translate(0, 0);
-moz-transform: translate(0, 0);
-webkit-transition: -webkit-transform .3s;
-moz-transition: -moz-transform .3s;
}
#main.closed {
-webkit-transform: translate(260px, 0);
-moz-transform: translate(260px, 0);
}
*/
#titlebar {
/* font-size: 16px; */
/* margin: 0 50px 0 50px; */
}
#metainfo {
font-size: 10px;
}
/*
#tocView {
width: 260px;
}
#tocView li {
font-size: 12px;
}
#tocView > ul{
padding-left: 10px;
-webkit-padding-start:;
}
*/
}

View file

@ -93,4 +93,17 @@
.popup.show, .popup.on {
display: block;
}
}
.note-marker,
.EPUBJS-CFI-MARKER,
.EPUBJS-CFI-SPLIT {
vertical-align: super;
font-size: 0.75em;
line-height: 1em;
padding: 0.1em;
background-color: #fffa96;
border-radius: 5px;
cursor: pointer;
}

View file

@ -0,0 +1,492 @@
/* sidebar */
.sidebar.open {
box-shadow: 3px 0px 3px 0px rgba(0, 0, 0, 0.4);
display: block;
}
.sidebar {
background: #6b6b6b;
position: fixed;
top: 0;
min-width: 25em;
height: 100%;
overflow: hidden;
display: none;
z-index: 100;
}
.sidebar.wide {
width: 20%;
}
.toolbar,
.panels {
position: absolute;
width: 100%;
height: 2em;
background: #4e4e4e;
}
.toolbar {
text-align: center;
}
.toolbar .metainfo {
font-size: 1.2em;
top: 0.5em;
}
.toolbar div {
display: inline-block;
position: relative;
}
.toolbar .separator {
/* border: solid 1px; */
height: 1em;
opacity: 0.5;
}
.toolbar button, .sidebar button {
color: white;
border: none;
background-color: transparent;
padding: 0;
}
.sidebar div > button {
/* font-size: 1.5em; */
/* font-size: 1em; */
padding: 0.4em;
margin: 0;
}
.mobile .sidebar div > button {
padding: 0.5em;
margin: 0;
}
.sidebar div > button:hover {
color: #8CC746;
}
.panels .open {
background-color: #6B6B6B;
}
.view.open {
display: block !important;
}
.view {
overflow-x: hidden;
display: none !important;
width: 100%;
position: absolute;
top: 2em;
bottom: 0;
}
.list_item a {
color: #AAA;
text-decoration: none;
}
.list_item a.chapter {
font-size: 1em;
}
.list_item a.section {
font-size: .8em;
}
.list_item.currentChapter > a,
.list_item a:hover {
color: #f1f1f1
}
.list_item a:hover {
color: #E2E2E2;
}
.list_item ul {
display: none;
}
.list_item.currentChapter > ul,
.list_item.openChapter > ul {
display: block;
}
legend {
margin-left: 1em;
padding: 0.5em;
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.4);
}
.settings-container {
text-align: left;
margin: 1em;
background: #F8F8F8;
color: #111;
border-radius: 4px;
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.4);
}
.settings-container > legend {
position: relative;
top: 1em;
margin-bottom: 1em;
text-align: center;
font-weight: 600;
box-shadow: none;
}
.settings-container label {
margin-right: 1em;
}
.center-box {
text-align: center;
margin: 1em;
}
.font_example {
margin: 1em;
text-align: center;
box-shadow: inset 0 1px 10px rgba(0, 0, 0, 0.4);
}
.font_example div {
padding: 1em;
}
.view .control-group input[type=range] {
width: 90%;
float: right;
margin: 0;
}
.view .control-group {
padding: 1em;
}
.view .sliders {
font-size: 1.5em;
}
.view .control-group span {
float: left;
margin: 0 2px;
clear: both;
}
.view .control-group input[type=reset] {
float: right;
}
.metadata {
padding: 1em;
margin: 1em;
}
.metadata table {
font-size: 1.2em;
color: #F8F8F8;
}
.metadata td:nth-child(1) {
font-weight: bold;
padding-right: 1em;
}
/* panels */
.panels a {
visibility: hidden;
overflow: hidden;
display: inline-block;
color: #ccc;
}
.panels a::before {
visibility: visible;
}
.panels a:hover {
color: #AAA;
}
.panels a:active {
color: #AAA;
margin: 1px 0 -1px 6px;
}
.panels a.active,
.panels a.active:hover {
color: #AAA;
}
/* END panels */
/* TOC (and search, and bookmarks) */
.toc_toggle {
display: inline-block;
width: 14px;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.toc_toggle:before {
content: '▸';
color: #fff;
margin-right: -4px;
}
.currentChapter > .toc_toggle:before,
.openChapter > .toc_toggle:before {
content: '▾';
}
#toc-populate.open {
display: inline-block !important;
background-color: #4e4e4e;
}
.toc-view li,
.bookmarks-view li,
.search-view li {
margin: 1em;
font-family: Georgia, "Times New Roman", Times, serif;
list-style: none;
}
.toc-view li {
text-transform: capitalize;
}
.toc-vew.hidden {
display: none;
}
.bookmark_link_text {
float: right;
font-size: 75%;
margin: 1em;
color: #AAA;
}
/* END TOC */
/* search */
.search-view,
.notes-view {
overflow: hidden;
}
.search-results {
overflow-y: scroll;
height: 95%;
height: calc(100vh - 5em);
}
.search-input {
padding-top: 1em;
padding-bottom: 1em;
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.4);
}
.searchbox {
width: 80%;
float: left;
margin-left: 1em;
}
.searchbox + span {
position: relative;
left: -1em;
visibility: hidden;
font-weight: bold;
font-family: sans-serif;
cursor: pointer;
}
.searchbox + span:hover {
color: red;
}
#clear_search {
padding: 0;
padding-right: 0.5em;
}
/* END search */
/* notes */
.notes-input {
padding-top: 1em;
padding-bottom: 2em;
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.4);
}
.notes {
overflow-y: scroll;
height: 95%;
height: calc(100vh - 11em);
}
.notes li,
.bookmarks li {
margin: 1em 1em 1em 0.5em;
padding: 0.25em 0 0 0.5em;
font-family: Georgia, "Times New Roman", Times, serif;
/* border-top: 1px #eee dotted; */
color: #ccc;
padding-bottom: 0.5em;
border-left: 0.5em solid transparent;
}
.notes li:hover,
.bookmarks li:hover {
border-left: 0.5em solid #eee;
}
.notes li:hover span,
.notes li:hover a,
.bookmarks li:hover span,
.bookmarks li:hover a {
color: #fff;
}
.item-date {
text-align: right;
font-size: 0.8em;
padding-top: 0.5em;
color: #bbb;
}
.item-delete,
.item-edit,
.item-save,
.item-cancel,
.note-link {
color: #999;
display: inline-block;
text-decoration: none;
margin-right: 0.5em;
margin-top: 0.5em;
cursor: pointer;
}
.item-save,
.item-cancel {
background-color: #ccc;
padding: 0.2em 0.4em;
border: 1px solid #ccc;
border-radius: 0.2em;
}
.item-save:hover,
.item-cancel:hover {
background-color: #eee;
border: 1px solid white;
}
.item-save {
color: green !important;
}
.item-cancel {
color: red !important;
}
.note-link {
float: right;
margin-right: 0;
}
.note-delete,
.note-edit {
float: left;
}
div.editable {
background-color: #EEE;
color: #111;
/* border: 1px dotted white; */
border-radius: 0.2em;
padding: 0.25em;
box-shadow: inset 0 1px 10px rgba(0, 0, 0, 0.4);
}
.notes li a:hover,
.bookmarks li a:hover {
text-decoration: underline;
}
.notes li img {
}
.note-text {
text-align: left;
display: block;
width: calc(100% - 2em);
height: 6em;
margin-left: 1em;
margin-right: 1em;
margin-bottom: 1em;
border-radius: 4px;
}
.note-text[disabled], #note-text[disabled="disabled"]{
opacity: .5;
}
.note-anchor {
font-size: 1.5em;
padding: 0 !important;
margin-right: 0.5em !important;
}
.note-marker {
vertical-align: super;
font-size: 0.75em;
line-height: 1em;
padding: 0.1em;
background-color: #fffa96;
border-radius: 5px;
cursor: pointer;
}
/* END notes */
/* margins */
.margin-icon {
float: none !important;
font-size: 3em;
vertical-align: middle;
}
/* media-specific rules */
@media only screen and (max-width: 25em) {
.sidebar {
min-width: 10em;
width: 80%;
}
#main.single {
width: 100% !important;
}
}
/* END sidebar */

View file

@ -257,22 +257,18 @@ body {
color: #AAA;
}
#searchBox {
width: 165px;
float: left;
margin-left: 10px;
margin-top: -1px;
/*
border-radius: 5px;
background: #9b9b9b;
float: left;
margin-left: 5px;
margin-top: -5px;
padding: 3px 10px;
color: #000;
border: none;
outline: none; */
.searchbox {
position: inline-block;
width: 50%;
float: left;
margin-left: 1em;
}
.searchbox + span {
position: relative;
left: -1em;
visibility: hidden;
font-weight: bold;
}
input::-webkit-input-placeholder {

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
EPUBJS.Hooks.register("beforeChapterDisplay").endnotes=function(a,b){var c=b.contents.querySelectorAll("a[href]"),d=Array.prototype.slice.call(c),e="epub:type",f="noteref",g=EPUBJS.core.folder(location.pathname),h=(g+EPUBJS.cssPath||g,{});EPUBJS.core.addCss(EPUBJS.cssPath+"popup.css",!1,b.render.document.head),d.forEach(function(a){function c(){var c,e,f=b.height,j=b.width,p=225;o||(c=l.cloneNode(!0),o=c.querySelector("p")),h[k]||(h[k]=document.createElement("div"),h[k].setAttribute("class","popup"),pop_content=document.createElement("div"),h[k].appendChild(pop_content),pop_content.appendChild(o),pop_content.setAttribute("class","pop_content"),b.render.document.body.appendChild(h[k]),h[k].addEventListener("mouseover",d,!1),h[k].addEventListener("mouseout",g,!1),b.on("renderer:pageChanged",i,this),b.on("renderer:pageChanged",g,this)),c=h[k],e=a.getBoundingClientRect(),m=e.left,n=e.top,c.classList.add("show"),popRect=c.getBoundingClientRect(),c.style.left=m-popRect.width/2+"px",c.style.top=n+"px",p>f/2.5&&(p=f/2.5,pop_content.style.maxHeight=p+"px"),popRect.height+n>=f-25?(c.style.top=n-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),m-popRect.width<=0?(c.style.left=m+"px",c.classList.add("left")):c.classList.remove("left"),m+popRect.width/2>=j?(c.style.left=m-300+"px",popRect=c.getBoundingClientRect(),c.style.left=m-popRect.width+"px",popRect.height+n>=f-25?(c.style.top=n-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),c.classList.add("right")):c.classList.remove("right")}function d(){h[k].classList.add("on")}function g(){h[k].classList.remove("on")}function i(){setTimeout(function(){h[k].classList.remove("show")},100)}var j,k,l,m,n,o,p=a.getAttribute(e);p==f&&(j=a.getAttribute("href"),k=j.replace("#",""),l=b.render.document.getElementById(k),a.addEventListener("mouseover",c,!1),a.addEventListener("mouseout",i,!1))}),a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").mathml=function(a,b){if(b.currentChapter.manifestProperties.indexOf("mathml")!==-1){b.render.iframe.contentWindow.mathmlCallback=a;var c=document.createElement("script");c.type="text/x-mathjax-config",c.innerHTML=' MathJax.Hub.Register.StartupHook("End",function () { window.mathmlCallback(); }); MathJax.Hub.Config({jax: ["input/TeX","input/MathML","output/SVG"],extensions: ["tex2jax.js","mml2jax.js","MathEvents.js"],TeX: {extensions: ["noErrors.js","noUndefined.js","autoload-all.js"]},MathMenu: {showRenderer: false},menuSettings: {zoom: "Click"},messageStyle: "none"}); ',b.doc.body.appendChild(c),EPUBJS.core.addScript("http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML",null,b.doc.head)}else a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").smartimages=function(a,b){var c=b.contents.querySelectorAll("img"),d=Array.prototype.slice.call(c),e=b.height;return"reflowable"!=b.layoutSettings.layout?void a():(d.forEach(function(a){var c=function(){var c,d=a.getBoundingClientRect(),f=d.height,g=d.top,h=a.getAttribute("data-height"),i=h||f,j=Number(getComputedStyle(a,"").fontSize.match(/(\d*(\.\d*)?)px/)[1]),k=j?j/2:0;e=b.contents.clientHeight,g<0&&(g=0),i+g>=e?(g<e/2?(c=e-g-k,a.style.maxHeight=c+"px",a.style.width="auto"):(i>e&&(a.style.maxHeight=e+"px",a.style.width="auto",d=a.getBoundingClientRect(),i=d.height),a.style.display="block",a.style.WebkitColumnBreakBefore="always",a.style.breakBefore="column"),a.setAttribute("data-height",c)):(a.style.removeProperty("max-height"),a.style.removeProperty("margin-top"))},d=function(){b.off("renderer:resized",c),b.off("renderer:chapterUnload",this)};a.addEventListener("load",c,!1),b.on("renderer:resized",c),b.on("renderer:chapterUnload",d),c()}),void(a&&a()))},EPUBJS.Hooks.register("beforeChapterDisplay").transculsions=function(a,b){var c=b.contents.querySelectorAll("[transclusion]"),d=Array.prototype.slice.call(c);d.forEach(function(a){function c(){j=g,k=h,j>chapter.colWidth&&(d=chapter.colWidth/j,j=chapter.colWidth,k*=d),f.width=j,f.height=k}var d,e=a.getAttribute("ref"),f=document.createElement("iframe"),g=a.getAttribute("width"),h=a.getAttribute("height"),i=a.parentNode,j=g,k=h;c(),b.listenUntil("renderer:resized","renderer:chapterUnloaded",c),f.src=e,i.replaceChild(f,a)}),a&&a()};
EPUBJS.Hooks.register("beforeChapterDisplay").endnotes=function(a,b){var c=b.contents.querySelectorAll("a[href]"),d=Array.prototype.slice.call(c),e="epub:type",f="noteref",g=(parent.location.origin+parent.location.pathname,EPUBJS.basePath+EPUBJS.cssPath||folder),h={};EPUBJS.core.addCss(g+"popup.css",!1,b.render.document.head),d.forEach(function(a){function c(){var c,e,f=b.height,j=b.width,o=225;n||(c=k.cloneNode(!0),n=c.querySelector("p")),h[id]||(h[id]=document.createElement("div"),h[id].setAttribute("class","popup"),pop_content=document.createElement("div"),h[id].appendChild(pop_content),pop_content.appendChild(n),pop_content.setAttribute("class","pop_content"),b.render.document.body.appendChild(h[id]),h[id].addEventListener("mouseover",d,!1),h[id].addEventListener("mouseout",g,!1),b.on("renderer:pageChanged",i,this),b.on("renderer:pageChanged",g,this)),c=h[id],e=a.getBoundingClientRect(),l=e.left,m=e.top,c.classList.add("show"),popRect=c.getBoundingClientRect(),c.style.left=l-popRect.width/2+"px",c.style.top=m+"px",o>f/2.5&&(o=f/2.5,pop_content.style.maxHeight=o+"px"),popRect.height+m>=f-25?(c.style.top=m-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),l-popRect.width<=0?(c.style.left=l+"px",c.classList.add("left")):c.classList.remove("left"),l+popRect.width/2>=j?(c.style.left=l-300+"px",popRect=c.getBoundingClientRect(),c.style.left=l-popRect.width+"px",popRect.height+m>=f-25?(c.style.top=m-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),c.classList.add("right")):c.classList.remove("right")}function d(){h[id].classList.add("on")}function g(){h[id].classList.remove("on")}function i(){setTimeout(function(){h[id].classList.remove("show")},100)}var j,k,l,m,n,o=a.getAttribute(e);o==f&&(j=a.getAttribute("href"),id=j.replace("#",""),k=b.render.document.getElementById(id),a.addEventListener("mouseover",c,!1),a.addEventListener("mouseout",i,!1))}),a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").mathml=function(a,b){if(b.currentChapter.manifestProperties.indexOf("mathml")!==-1){b.render.iframe.contentWindow.mathmlCallback=a;var c=document.createElement("script");c.type="text/x-mathjax-config",c.innerHTML=' MathJax.Hub.Register.StartupHook("End",function () { window.mathmlCallback(); }); MathJax.Hub.Config({jax: ["input/TeX","input/MathML","output/SVG"],extensions: ["tex2jax.js","mml2jax.js","MathEvents.js"],TeX: {extensions: ["noErrors.js","noUndefined.js","autoload-all.js"]},MathMenu: {showRenderer: false},menuSettings: {zoom: "Click"},messageStyle: "none"}); ',b.doc.body.appendChild(c),EPUBJS.core.addScript("http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML",null,b.doc.head)}else a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").smartimages=function(a,b){var c=b.contents.querySelectorAll("img"),d=Array.prototype.slice.call(c),e=b.height;return"reflowable"!=b.layoutSettings.layout?void a():(d.forEach(function(a){var c=function(){var c,d=a.getBoundingClientRect(),f=d.height,g=d.top,h=a.getAttribute("data-height"),i=h||f,j=Number(getComputedStyle(a,"").fontSize.match(/(\d*(\.\d*)?)px/)[1]),k=j?j/2:0;e=b.contents.clientHeight,g<0&&(g=0),i+g>=e?(g<e/2?(c=e-g-k,a.style.maxHeight=c+"px",a.style.width="auto"):(i>e&&(a.style.maxHeight=e+"px",a.style.width="auto",d=a.getBoundingClientRect(),i=d.height),a.style.display="block",a.style.WebkitColumnBreakBefore="always",a.style.breakBefore="column"),a.setAttribute("data-height",c)):(a.style.removeProperty("max-height"),a.style.removeProperty("margin-top"))},d=function(){b.off("renderer:resized",c),b.off("renderer:chapterUnload",this)};a.addEventListener("load",c,!1),b.on("renderer:resized",c),b.on("renderer:chapterUnload",d),c()}),void(a&&a()))},EPUBJS.Hooks.register("beforeChapterDisplay").transculsions=function(a,b){var c=b.contents.querySelectorAll("[transclusion]"),d=Array.prototype.slice.call(c);d.forEach(function(a){function c(){j=g,k=h,j>chapter.colWidth&&(d=chapter.colWidth/j,j=chapter.colWidth,k*=d),f.width=j,f.height=k}var d,e=a.getAttribute("ref"),f=document.createElement("iframe"),g=a.getAttribute("width"),h=a.getAttribute("height"),i=a.parentNode,j=g,k=h;c(),b.listenUntil("renderer:resized","renderer:chapterUnloaded",c),f.src=e,i.replaceChild(f,a)}),a&&a()};

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -0,0 +1,121 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="icomoon" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe06d;" glyph-name="featured_play_list" d="M512 640.667v84h-384v-84h384zM512 468.667v86h-384v-86h384zM896 810.667c46 0 86-40 86-86v-596c0-46-40-86-86-86h-768c-46 0-86 40-86 86v596c0 46 40 86 86 86h768z" />
<glyph unicode="&#xe0b7;" glyph-name="chat" d="M768 596.667v86h-512v-86h512zM598 340.667v86h-342v-86h342zM256 554.667v-86h512v86h-512zM854 852.667c46 0 84-38 84-84v-512c0-46-38-86-84-86h-598l-170-170v768c0 46 38 84 84 84h684z" />
<glyph unicode="&#xe0b9;" glyph-name="comment" d="M768 596.667v86h-512v-86h512zM768 468.667v86h-512v-86h512zM768 340.667v86h-512v-86h512zM938 768.667v-768l-170 170h-598c-46 0-84 40-84 86v512c0 46 38 84 84 84h684c46 0 84-38 84-84z" />
<glyph unicode="&#xe0c7;" glyph-name="location_off" d="M500 448.667c118.353-116.98 236.568-234.098 354-352l-54-54-144 142c-72-106-144-184-144-184s-298 330-298 554c0 22 4 44 8 66l-136 136 54 54 356-356zM512 660.667c-32 0-58-14-78-36l-138 136c54 56 132 92 216 92 166 0 298-132 298-298 0-72-30-154-72-234l-154 156c22 20 34 46 34 78 0 58-48 106-106 106z" />
<glyph unicode="&#xe0c9;" glyph-name="message" d="M768 596.667v86h-512v-86h512zM768 468.667v86h-512v-86h512zM768 340.667v86h-512v-86h512zM854 852.667c46 0 84-38 84-84v-512c0-46-38-86-84-86h-598l-170-170v768c0 46 38 84 84 84h684z" />
<glyph unicode="&#xe0ca;" glyph-name="chat_bubble" d="M854 852.667c46 0 84-38 84-84v-512c0-46-38-86-84-86h-598l-170-170v768c0 46 38 84 84 84h684z" />
<glyph unicode="&#xe0cb;" glyph-name="chat_bubble_outline" d="M854 256.667v512h-684v-598l86 86h598zM854 852.667c46 0 84-38 84-84v-512c0-46-38-86-84-86h-598l-170-170v768c0 46 38 84 84 84h684z" />
<glyph unicode="&#xe14d;" glyph-name="content_copy" d="M810 42.667v598h-468v-598h468zM810 724.667c46 0 86-38 86-84v-598c0-46-40-86-86-86h-468c-46 0-86 40-86 86v598c0 46 40 84 86 84h468zM682 896.667v-86h-512v-598h-84v598c0 46 38 86 84 86h512z" />
<glyph unicode="&#xe153;" glyph-name="flag" d="M614 682.667h240v-426h-300l-16 84h-240v-298h-84v726h384z" />
<glyph unicode="&#xe157;" glyph-name="link2" d="M726 640.667c118 0 212-96 212-214s-94-214-212-214h-172v82h172c72 0 132 60 132 132s-60 132-132 132h-172v82h172zM342 384.667v84h340v-84h-340zM166 426.667c0-72 60-132 132-132h172v-82h-172c-118 0-212 96-212 214s94 214 212 214h172v-82h-172c-72 0-132-60-132-132z" />
<glyph unicode="&#xe161;" glyph-name="save" d="M640 554.667v170h-426v-170h426zM512 128.667c70 0 128 58 128 128s-58 128-128 128-128-58-128-128 58-128 128-128zM726 810.667l170-170v-512c0-46-40-86-86-86h-596c-48 0-86 40-86 86v596c0 46 38 86 86 86h512z" />
<glyph unicode="&#xe169;" glyph-name="unarchive" d="M218 724.667h588l-40 44h-512zM512 532.667l-234-234h148v-86h172v86h148zM876 716.667c12-14 20-36 20-56v-532c0-46-40-86-86-86h-596c-48 0-86 40-86 86v532c0 20 8 42 20 56l58 70c12 14 30 24 50 24h512c20 0 38-10 50-24z" />
<glyph unicode="&#xe1ac;" glyph-name="brightness_high" d="M512 596.667c94 0 170-76 170-170s-76-170-170-170-170 76-170 170 76 170 170 170zM512 170.667c142 0 256 114 256 256s-114 256-256 256-256-114-256-256 114-256 256-256zM854 568.667l140-142-140-142v-200h-200l-142-140-142 140h-200v200l-140 142 140 142v200h200l142 140 142-140h200v-200z" />
<glyph unicode="&#xe1ad;" glyph-name="brightness_low" d="M512 170.667c142 0 256 114 256 256s-114 256-256 256-256-114-256-256 114-256 256-256zM854 284.667v-200h-200l-142-140-142 140h-200v200l-140 142 140 142v200h200l142 140 142-140h200v-200l140-142z" />
<glyph unicode="&#xe1ae;" glyph-name="brightness_low2" d="M512 170.667c142 0 256 114 256 256s-114 256-256 256-256-114-256-256 114-256 256-256zM854 284.667v-200h-200l-142-140-142 140h-200v200l-140 142 140 142v200h200l142 140 142-140h200v-200l140-142z" />
<glyph unicode="&#xe1af;" glyph-name="brightness_medium" d="M512 170.667c142 0 256 114 256 256s-114 256-256 256v-512zM854 284.667v-200h-200l-142-140-142 140h-200v200l-140 142 140 142v200h200l142 140 142-140h200v-200l140-142z" />
<glyph unicode="&#xe226;" glyph-name="attach_file" d="M704 682.667h64v-490c0-130-104-236-234-236s-236 106-236 236v532c0 94 78 172 172 172s170-78 170-172v-448c0-58-48-106-106-106s-108 48-108 106v406h64v-406c0-24 20-42 44-42s42 18 42 42v448c0 58-48 108-106 108s-108-50-108-108v-532c0-94 78-172 172-172s170 78 170 172v490z" />
<glyph unicode="&#xe241;" glyph-name="format_list_bulleted" d="M298 724.667h598v-84h-598v84zM298 384.667v84h598v-84h-598zM298 128.667v84h598v-84h-598zM170 234.667c36 0 64-30 64-64s-30-64-64-64-64 30-64 64 28 64 64 64zM170 746.667c36 0 64-28 64-64s-28-64-64-64-64 28-64 64 28 64 64 64zM170 490.667c36 0 64-28 64-64s-28-64-64-64-64 28-64 64 28 64 64 64z" />
<glyph unicode="&#xe242;" glyph-name="format_list_numbered" d="M298 384.667v84h598v-84h-598zM298 128.667v84h598v-84h-598zM298 724.667h598v-84h-598v84zM86 468.667v44h128v-40l-78-88h78v-44h-128v40l76 88h-76zM128 596.667v128h-42v44h84v-172h-42zM86 212.667v44h128v-172h-128v44h84v20h-42v44h42v20h-84z" />
<glyph unicode="&#xe245;" glyph-name="format_size" d="M128 426.667v128h384v-128h-128v-298h-128v298h-128zM384 768.667h554v-128h-212v-512h-128v512h-214v128z" />
<glyph unicode="&#xe247;" glyph-name="format_textdirection_l_to_r" d="M896 170.667l-170-170v128h-512v84h512v128zM384 512.667c-94 0-170 76-170 170s76 170 170 170h342v-84h-86v-470h-86v470h-84v-470h-86v214z" />
<glyph unicode="&#xe248;" glyph-name="format_textdirection_r_to_l" d="M342 212.667h512v-84h-512v-128l-172 170 172 170v-128zM426 512.667c-94 0-170 76-170 170s76 170 170 170h342v-84h-86v-470h-84v470h-86v-470h-86v214z" />
<glyph unicode="&#xe254;" glyph-name="mode_edit" d="M884 638.667l-78-78-160 160 78 78c16 16 44 16 60 0l100-100c16-16 16-44 0-60zM128 202.667l472 472 160-160-472-472h-160v160z" />
<glyph unicode="&#xe2bc;" glyph-name="attachment" d="M86 404.667c0 130 104 236 234 236h448c94 0 170-78 170-172s-76-170-170-170h-362c-58 0-108 48-108 106s50 108 108 108h320v-86h-324c-24 0-24-42 0-42h366c46 0 86 38 86 84s-40 86-86 86h-448c-82 0-150-68-150-150s68-148 150-148h406v-86h-406c-130 0-234 104-234 234z" />
<glyph unicode="&#xe2c0;" glyph-name="cloud_download" d="M726 384.667h-128v170h-172v-170h-128l214-214zM826 510.667c110-8 198-100 198-212 0-118-96-214-214-214h-554c-142 0-256 114-256 256 0 132 100 240 228 254 54 102 160 174 284 174 156 0 284-110 314-258z" />
<glyph unicode="&#xe314;" glyph-name="keyboard_arrow_left" d="M658 252.667l-60-60-256 256 256 256 60-60-196-196z" />
<glyph unicode="&#xe315;" glyph-name="keyboard_arrow_right" d="M366 240.667l196 196-196 196 60 60 256-256-256-256z" />
<glyph unicode="&#xe316;" glyph-name="keyboard_arrow_left2" d="M658 252.667l-60-60-256 256 256 256 60-60-196-196z" />
<glyph unicode="&#xe3a6;" glyph-name="brightness_1" d="M86 426.667c0 236 190 426 426 426s426-190 426-426-190-426-426-426-426 190-426 426z" />
<glyph unicode="&#xe3a7;" glyph-name="brightness_2" d="M426 852.667c236 0 428-190 428-426s-192-426-428-426c-78 0-150 20-212 56 128 74 212 212 212 370s-84 296-212 370c62 36 134 56 212 56z" />
<glyph unicode="&#xe3a8;" glyph-name="brightness_3" d="M384 852.667c236 0 426-190 426-426s-190-426-426-426c-44 0-88 6-128 18 174 54 298 216 298 408s-124 354-298 408c40 12 84 18 128 18z" />
<glyph unicode="&#xe3a9;" glyph-name="brightness_4" d="M512 170.667c142 0 256 114 256 256s-114 256-256 256c-38 0-74-10-106-24 88-40 148-128 148-232s-60-192-148-232c32-14 68-24 106-24zM854 568.667l140-142-140-142v-200h-200l-142-140-142 140h-200v200l-140 142 140 142v200h200l142 140 142-140h200v-200z" />
<glyph unicode="&#xe3c2;" glyph-name="crop_free" d="M810 810.667c46 0 86-40 86-86v-170h-86v170h-170v86h170zM810 128.667v170h86v-170c0-46-40-86-86-86h-170v86h170zM214 298.667v-170h170v-86h-170c-46 0-86 40-86 86v170h86zM128 724.667c0 46 40 86 86 86h170v-86h-170v-170h-86v170z" />
<glyph unicode="&#xe3c5;" glyph-name="crop_portrait" d="M726 128.667v596h-428v-596h428zM726 810.667c46 0 84-40 84-86v-596c0-46-38-86-84-86h-428c-46 0-84 40-84 86v596c0 46 38 86 84 86h428z" />
<glyph unicode="&#xe3c7;" glyph-name="dehaze" d="M86 704.667h852v-86h-852v86zM86 490.667h852v-86h-852v86zM86 276.667h852v-84h-852v84z" />
<glyph unicode="&#xe408;" glyph-name="navigate_before" d="M658 622.667l-196-196 196-196-60-60-256 256 256 256z" />
<glyph unicode="&#xe409;" glyph-name="navigate_next" d="M426 682.667l256-256-256-256-60 60 196 196-196 196z" />
<glyph unicode="&#xe429;" glyph-name="tune" d="M640 554.667v256h86v-86h170v-84h-170v-86h-86zM896 384.667h-426v84h426v-84zM298 554.667h86v-256h-86v86h-170v84h170v86zM554 42.667h-84v256h84v-86h342v-84h-342v-86zM128 724.667h426v-84h-426v84zM128 212.667h256v-84h-256v84z" />
<glyph unicode="&#xe430;" glyph-name="wb_sunny" d="M152 146.667l76 78 60-60-76-78zM470-19.333v126h84v-126h-84zM512 704.667c142 0 256-114 256-256s-114-256-256-256-256 114-256 256 114 256 256 256zM854 490.667h128v-86h-128v86zM736 164.667l60 58 76-76-60-60zM872 748.667l-76-76-60 60 76 76zM554 914.667v-126h-84v126h84zM170 490.667v-86h-128v86h128zM288 732.667l-60-60-76 76 60 60z" />
<glyph unicode="&#xe54b;" glyph-name="local_library" d="M512 596.667c-70 0-128 58-128 128s58 128 128 128 128-58 128-128-58-128-128-128zM512 446.667c100 94 236 150 384 150v-468c-148 0-284-58-384-152-100 94-236 152-384 152v468c148 0 284-56 384-150z" />
<glyph unicode="&#xe560;" glyph-name="rate_review" d="M768 340.667v86h-234l-86-86h320zM256 340.667h106l294 294c8 8 8 22 0 30l-76 76c-8 8-22 8-30 0l-294-294v-106zM854 852.667c46 0 84-38 84-84v-512c0-46-38-86-84-86h-598l-170-170v768c0 46 38 84 84 84h684z" />
<glyph unicode="&#xe56b;" glyph-name="zoom_out_map" d="M896 298.667v-256h-256l98 98-124 122 62 62 122-124zM384 42.667h-256v256l98-98 122 124 62-62-124-122zM128 554.667v256h256l-98-98 124-122-62-62-122 124zM640 810.667h256v-256l-98 98-122-124-62 62 124 122z" />
<glyph unicode="&#xe5c4;" glyph-name="arrow_back" d="M854 468.667v-84h-520l238-240-60-60-342 342 342 342 60-60-238-240h520z" />
<glyph unicode="&#xe5c5;" glyph-name="arrow_back2" d="M854 468.667v-84h-520l238-240-60-60-342 342 342 342 60-60-238-240h520z" />
<glyph unicode="&#xe5c8;" glyph-name="arrow_forward" d="M512 768.667l342-342-342-342-60 60 238 240h-520v84h520l-238 240z" />
<glyph unicode="&#xe5c9;" glyph-name="cancel" d="M726 272.667l-154 154 154 154-60 60-154-154-154 154-60-60 154-154-154-154 60-60 154 154 154-154zM512 852.667c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
<glyph unicode="&#xe5ca;" glyph-name="check" d="M384 248.667l452 452 60-60-512-512-238 238 60 60z" />
<glyph unicode="&#xe5cd;" glyph-name="close" d="M810 664.667l-238-238 238-238-60-60-238 238-238-238-60 60 238 238-238 238 60 60 238-238 238 238z" />
<glyph unicode="&#xe5d0;" glyph-name="fullscreen" d="M598 724.667h212v-212h-84v128h-128v84zM726 212.667v128h84v-212h-212v84h128zM214 512.667v212h212v-84h-128v-128h-84zM298 340.667v-128h128v-84h-212v212h84z" />
<glyph unicode="&#xe5d1;" glyph-name="fullscreen_exit" d="M682 596.667h128v-84h-212v212h84v-128zM598 128.667v212h212v-84h-128v-128h-84zM342 596.667v128h84v-212h-212v84h128zM214 256.667v84h212v-212h-84v128h-128z" />
<glyph unicode="&#xe5d2;" glyph-name="menu" d="M128 682.667h768v-86h-768v86zM128 384.667v84h768v-84h-768zM128 170.667v86h768v-86h-768z" />
<glyph unicode="&#xe5d3;" glyph-name="fullscreen2" d="M598 724.667h212v-212h-84v128h-128v84zM726 212.667v128h84v-212h-212v84h128zM214 512.667v212h212v-84h-128v-128h-84zM298 340.667v-128h128v-84h-212v212h84z" />
<glyph unicode="&#xe5d4;" glyph-name="fullscreen_exit2" d="M682 596.667h128v-84h-212v212h84v-128zM598 128.667v212h212v-84h-128v-128h-84zM342 596.667v128h84v-212h-212v84h128zM214 256.667v84h212v-212h-84v128h-128z" />
<glyph unicode="&#xe5d5;" glyph-name="menu3" d="M128 682.667h768v-86h-768v86zM128 384.667v84h768v-84h-768zM128 170.667v86h768v-86h-768z" />
<glyph unicode="&#xe627;" glyph-name="sync" d="M512 170.667v128l170-170-170-172v128c-188 0-342 154-342 342 0 66 20 130 54 182l62-62c-20-36-30-76-30-120 0-142 114-256 256-256zM512 768.667c188 0 342-154 342-342 0-66-20-130-54-182l-62 62c20 36 30 76 30 120 0 142-114 256-256 256v-128l-170 170 170 172v-128z" />
<glyph unicode="&#xe7f9;" glyph-name="pages" d="M810 810.667c46 0 86-40 86-86v-256h-214l44 172-172-44v214h256zM726 212.667l-44 172h214v-256c0-46-40-86-86-86h-256v214zM342 384.667l-44-172 172 44v-214h-256c-46 0-86 40-86 86v256h214zM128 724.667c0 46 40 86 86 86h256v-214l-172 44 44-172h-214v256z" />
<glyph unicode="&#xe834;" glyph-name="check_box" d="M426 212.667l384 384-60 62-324-324-152 152-60-60zM810 810.667c48 0 86-40 86-86v-596c0-46-38-86-86-86h-596c-48 0-86 40-86 86v596c0 46 38 86 86 86h596z" />
<glyph unicode="&#xe838;" glyph-name="star" d="M512 202.667l-264-160 70 300-232 202 306 26 120 282 120-282 306-26-232-202 70-300z" />
<glyph unicode="&#xe839;" glyph-name="star_half" d="M512 280.667l160-96-42 182 142 124-188 16-72 172v-398zM938 544.667l-232-202 70-300-264 160-264-160 70 300-232 202 306 26 120 282 120-282z" />
<glyph unicode="&#xe83a;" glyph-name="star_border" d="M512 280.667l160-96-42 182 142 124-188 16-72 172-72-172-188-16 142-124-42-182zM938 544.667l-232-202 70-300-264 160-264-160 70 300-232 202 306 26 120 282 120-282z" />
<glyph unicode="&#xe85b;" glyph-name="icon-fit-window" d="M514.011 433.334v-13.333h13.333v13.333zM515.345 432h10.667v-10.667h-10.667zM512.678 429.334l-2.667-2.667 2.667-2.667zM528.678 429.334v-5.333l2.667 2.667zM215.333 727.797v-596.384h596.384v596.384zM274.972 668.159h477.107v-477.107h-477.107zM155.695 548.882l-119.277-119.277 119.277-119.277zM871.356 548.882v-238.554l119.277 119.277zM811.717 727.797h-596.384v-596.384h596.384zM752.079 668.159v-477.107h-477.107v477.107zM632.802 787.435l-119.277 119.277-119.277-119.277zM632.802 71.774h-238.554l119.277-119.277z" />
<glyph unicode="&#xe85c;" glyph-name="icon-fit-width" d="M514.011 433.334v-13.333h13.333v13.333zM515.345 432h10.667v-10.667h-10.667zM512.678 429.334l-2.667-2.667 2.667-2.667zM528.678 429.334v-5.333l2.667 2.667zM215.333 727.797v-596.384h596.384v596.384zM274.972 668.159h477.107v-477.107h-477.107zM155.695 548.882l-119.277-119.277 119.277-119.277zM871.356 548.882v-238.554l119.277 119.277z" />
<glyph unicode="&#xe869;" glyph-name="build" d="M968 128.667c18-12 18-42-4-60l-98-98c-18-18-42-18-60 0l-388 388c-98-38-212-18-294 64-86 86-108 214-56 316l188-184 128 128-184 184c102 46 230 30 316-56 82-82 102-196 64-294z" />
<glyph unicode="&#xe86d;" glyph-name="double_page_mode" d="M125.831 770.49c-46 0-86-40-86-86v-554c0-46 40-86 86-86h768c46 0 86 40 86 86v554c0 46-40 86-86 86h-768zM112.497 684.49h384v-554h-384v554zM523.164 684.49h384v-554h-384v554zM154.497 534.49v-64h300v64h-300zM565.164 534.49v-64h300v64h-300zM154.497 428.49v-64h300v64h-300zM565.164 428.49v-64h300v64h-300zM154.497 322.49v-64h300v64h-300zM565.164 322.49v-64h300v64h-300z" />
<glyph unicode="&#xe86e;" glyph-name="single_page_mode" d="M704 128.667v554h-384v-554zM896 768.667c46 0 86-40 86-86v-554c0-46-40-86-86-86h-768c-46 0-86 40-86 86v554c0 46 40 86 86 86zM362 320.667h300v-64h-300zM362 532.667h300v-64h-300zM362 426.667h300v-64h-300z" />
<glyph unicode="&#xe86f;" glyph-name="class" d="M256 768.667v-342l106 64 108-64v342h-214zM768 852.667c46 0 86-38 86-84v-684c0-46-40-84-86-84h-512c-46 0-86 38-86 84v684c0 46 40 84 86 84h512z" />
<glyph unicode="&#xe872;" glyph-name="delete" d="M810 768.667v-86h-596v86h148l44 42h212l44-42h148zM256 128.667v512h512v-512c0-46-40-86-86-86h-340c-46 0-86 40-86 86z" />
<glyph unicode="&#xe875;" glyph-name="dns" d="M298 554.667c46 0 86 40 86 86s-40 84-86 84-84-38-84-84 38-86 84-86zM854 810.667c24 0 42-18 42-42v-256c0-24-18-44-42-44h-684c-24 0-42 20-42 44v256c0 24 18 42 42 42h684zM298 128.667c46 0 86 38 86 84s-40 86-86 86-84-40-84-86 38-84 84-84zM854 384.667c24 0 42-20 42-44v-256c0-24-18-42-42-42h-684c-24 0-42 18-42 42v256c0 24 18 44 42 44h684z" />
<glyph unicode="&#xe879;" glyph-name="exit_to_app" d="M810 810.667c46 0 86-40 86-86v-596c0-46-40-86-86-86h-596c-48 0-86 40-86 86v170h86v-170h596v596h-596v-170h-86v170c0 46 38 86 86 86h596zM430 272.667l110 112h-412v84h412l-110 112 60 60 214-214-214-214z" />
<glyph unicode="&#xe880;" glyph-name="find_in_page" d="M384 384.667c0 70 58 128 128 128s128-58 128-128-58-128-128-128-128 58-128 128zM854 102.667l-164 164c22 34 36 74 36 118 0 118-96 212-214 212s-214-94-214-212 96-214 214-214c44 0 84 14 118 36l188-190c-14-10-30-16-50-16h-512c-46 0-86 38-86 84l2 684c0 46 38 84 84 84h342l256-256v-494z" />
<glyph unicode="&#xe893;" glyph-name="label_outline" d="M682 212.667l152 214-152 214h-468v-428h468zM752 688.667l186-262-186-262c-16-22-42-36-70-36h-468c-46 0-86 38-86 84v428c0 46 40 84 86 84h468c28 0 54-14 70-36z" />
<glyph unicode="&#xe896;" glyph-name="list" d="M298 640.667h598v-86h-598v86zM298 212.667v86h598v-86h-598zM298 384.667v84h598v-84h-598zM128 554.667v86h86v-86h-86zM128 212.667v86h86v-86h-86zM128 384.667v84h86v-84h-86z" />
<glyph unicode="&#xe89f;" glyph-name="open_with" d="M598 298.667v-128h128l-214-214-214 214h128v128h172zM982 426.667l-214-214v128h-128v172h128v128zM384 512.667v-172h-128v-128l-214 214 214 214v-128h128zM426 554.667v128h-128l214 214 214-214h-128v-128h-172z" />
<glyph unicode="&#xe8b4;" glyph-name="room" d="M512 448.667c58 0 106 48 106 106s-48 106-106 106-106-48-106-106 48-106 106-106zM512 852.667c166 0 298-132 298-298 0-224-298-554-298-554s-298 330-298 554c0 166 132 298 298 298z" />
<glyph unicode="&#xe8b6;" glyph-name="search" d="M406 340.667c106 0 192 86 192 192s-86 192-192 192-192-86-192-192 86-192 192-192zM662 340.667l212-212-64-64-212 212v34l-12 12c-48-42-112-66-180-66-154 0-278 122-278 276s124 278 278 278 276-124 276-278c0-68-24-132-66-180l12-12h34z" />
<glyph unicode="&#xe8b7;" glyph-name="search3" d="M406 340.667c106 0 192 86 192 192s-86 192-192 192-192-86-192-192 86-192 192-192zM662 340.667l212-212-64-64-212 212v34l-12 12c-48-42-112-66-180-66-154 0-278 122-278 276s124 278 278 278 276-124 276-278c0-68-24-132-66-180l12-12h34z" />
<glyph unicode="&#xe8b8;" glyph-name="settings" d="M512 276.667c82 0 150 68 150 150s-68 150-150 150-150-68-150-150 68-150 150-150zM830 384.667l90-70c8-6 10-18 4-28l-86-148c-6-10-16-12-26-8l-106 42c-22-16-46-32-72-42l-16-112c-2-10-10-18-20-18h-172c-10 0-18 8-20 18l-16 112c-26 10-50 24-72 42l-106-42c-10-4-20-2-26 8l-86 148c-6 10-4 22 4 28l90 70c-2 14-2 28-2 42s0 28 2 42l-90 70c-8 6-10 18-4 28l86 148c6 10 16 12 26 8l106-42c22 16 46 32 72 42l16 112c2 10 10 18 20 18h172c10 0 18-8 20-18l16-112c26-10 50-24 72-42l106 42c10 4 20 2 26-8l86-148c6-10 4-22-4-28l-90-70c2-14 2-28 2-42s0-28-2-42z" />
<glyph unicode="&#xe8c4;" glyph-name="settings_overscan" d="M896 126.667v600h-768v-600h768zM896 810.667c46 0 86-40 86-86v-596c0-46-40-86-86-86h-768c-46 0-86 40-86 86v596c0 46 40 86 86 86h768zM598 256.667l-86-108-86 108h172zM256 512.667v-172l-106 86zM768 512.667l106-86-106-86v172zM512 704.667l86-108h-172z" />
<glyph unicode="&#xe8d0;" glyph-name="stars" d="M692 170.667l-48 206 160 138-210 18-82 192-82-194-210-16 160-138-48-206 180 108zM512 852.667c236 0 426-190 426-426s-190-426-426-426-426 190-426 426 190 426 426 426z" />
<glyph unicode="&#xe8e6;" glyph-name="turned_in" d="M726 810.667c46 0 84-40 84-86v-682l-298 128-298-128v682c0 46 38 86 84 86h428z" />
<glyph unicode="&#xe8e7;" glyph-name="turned_in_not" d="M726 170.667v554h-428v-554l214 94zM726 810.667c46 0 84-40 84-86v-682l-298 128-298-128v682c0 46 38 86 84 86h428z" />
<glyph unicode="&#xe8e8;" glyph-name="turned_in2" d="M726 810.667c46 0 84-40 84-86v-682l-298 128-298-128v682c0 46 38 86 84 86h428z" />
<glyph unicode="&#xe8e9;" glyph-name="turned_in_not2" d="M726 170.667v554h-428v-554l214 94zM726 810.667c46 0 84-40 84-86v-682l-298 128-298-128v682c0 46 38 86 84 86h428z" />
<glyph unicode="&#xe8ff;" glyph-name="zoom_in" d="M512 512.667h-86v-86h-42v86h-86v42h86v86h42v-86h86v-42zM406 340.667c106 0 192 86 192 192s-86 192-192 192-192-86-192-192 86-192 192-192zM662 340.667l212-212-64-64-212 212v34l-12 12c-48-42-112-66-180-66-154 0-278 122-278 276s124 278 278 278 276-124 276-278c0-68-24-132-66-180l12-12h34z" />
<glyph unicode="&#xe900;" glyph-name="zoom_out" d="M298 554.667h214v-42h-214v42zM406 340.667c106 0 192 86 192 192s-86 192-192 192-192-86-192-192 86-192 192-192zM662 340.667l212-212-64-64-212 212v34l-12 12c-48-42-112-66-180-66-154 0-278 122-278 276s124 278 278 278 276-124 276-278c0-68-24-132-66-180l12-12h34z" />
<glyph unicode="&#xe901;" glyph-name="anchor, link, reference" d="M927.968 348.96l-36.352-247.328-73.568 71.36c-58.272-49.248-166.336-116.256-323.328-116.256-157.92 0-267.136 65.376-325.248 112.224l-67.136-65.12-38.336 245.088 252.576-37.184-69.6-67.552c48.832-36.256 125.44-79.968 201.728-79.968l-0.224 403.488c-55.712 19.392-95.808 70.624-95.808 131.36 0 77.376 64.608 140.096 144.32 140.096 79.68 0 144.32-62.72 144.32-140.096 0-61.664-41.344-113.44-98.368-132.128 0.352-78.72 1.632-404.224-0.128-404.224 72.96 0 148.288 47.488 197.344 85.888l-65.024 63.136 252.832 37.216zM571.392 701.344c0 39.872-33.312 72.224-74.4 72.224s-74.432-32.352-74.432-72.224c0-39.904 33.344-72.256 74.432-72.256s74.4 32.352 74.4 72.256z" />
<glyph unicode="&#xe902;" glyph-name="zoom_in2" d="M512 512.667h-86v-86h-42v86h-86v42h86v86h42v-86h86v-42zM406 340.667c106 0 192 86 192 192s-86 192-192 192-192-86-192-192 86-192 192-192zM662 340.667l212-212-64-64-212 212v34l-12 12c-48-42-112-66-180-66-154 0-278 122-278 276s124 278 278 278 276-124 276-278c0-68-24-132-66-180l12-12h34z" />
<glyph unicode="&#xe903;" glyph-name="zoom_out2" d="M298 554.667h214v-42h-214v42zM406 340.667c106 0 192 86 192 192s-86 192-192 192-192-86-192-192 86-192 192-192zM662 340.667l212-212-64-64-212 212v34l-12 12c-48-42-112-66-180-66-154 0-278 122-278 276s124 278 278 278 276-124 276-278c0-68-24-132-66-180l12-12h34z" />
<glyph unicode="&#xe90b;" glyph-name="droplet" d="M864.626 486.838c-65.754 183.44-205.11 348.15-352.626 473.162-147.516-125.012-286.87-289.722-352.626-473.162-40.664-113.436-44.682-236.562 12.584-345.4 65.846-125.14 198.632-205.438 340.042-205.438s274.196 80.298 340.040 205.44c57.27 108.838 53.25 231.962 12.586 345.398zM738.764 201.044c-43.802-83.252-132.812-137.044-226.764-137.044-55.12 0-108.524 18.536-152.112 50.652 13.242-1.724 26.632-2.652 40.112-2.652 117.426 0 228.668 67.214 283.402 171.242 44.878 85.292 40.978 173.848 23.882 244.338 14.558-28.15 26.906-56.198 36.848-83.932 22.606-63.062 40.024-156.34-5.368-242.604z" />
<glyph unicode="&#xe95f;" glyph-name="box-remove" d="M832 896h-640l-192-192v-672c0-17.674 14.326-32 32-32h960c17.672 0 32 14.326 32 32v672l-192 192zM640 320v-192h-256v192h-192l320 256 320-256h-192zM154.51 768l64 64h586.976l64-64h-714.976z" />
<glyph unicode="&#xe960;" glyph-name="download" d="M512 384l256 256h-192v256h-128v-256h-192zM744.726 488.728l-71.74-71.742 260.080-96.986-421.066-157.018-421.066 157.018 260.080 96.986-71.742 71.742-279.272-104.728v-256l512-192 512 192v256z" />
<glyph unicode="&#xe97a;" glyph-name="spinner" d="M384 832c0 70.692 57.308 128 128 128s128-57.308 128-128c0-70.692-57.308-128-128-128s-128 57.308-128 128zM655.53 719.53c0 70.692 57.308 128 128 128s128-57.308 128-128c0-70.692-57.308-128-128-128s-128 57.308-128 128zM832 448c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64s-64 28.654-64 64zM719.53 176.47c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64s-64 28.654-64 64zM448.002 64c0 0 0 0 0 0 0 35.346 28.654 64 64 64s64-28.654 64-64c0 0 0 0 0 0 0-35.346-28.654-64-64-64s-64 28.654-64 64zM176.472 176.47c0 0 0 0 0 0 0 35.346 28.654 64 64 64s64-28.654 64-64c0 0 0 0 0 0 0-35.346-28.654-64-64-64s-64 28.654-64 64zM144.472 719.53c0 0 0 0 0 0 0 53.019 42.981 96 96 96s96-42.981 96-96c0 0 0 0 0 0 0-53.019-42.981-96-96-96s-96 42.981-96 96zM56 448c0 39.765 32.235 72 72 72s72-32.235 72-72c0-39.765-32.235-72-72-72s-72 32.235-72 72z" />
<glyph unicode="&#xe97c;" glyph-name="spinner3" d="M512 656.904c-32.964 0-59.686 26.724-59.686 59.686v179.060c0 32.964 26.722 59.686 59.686 59.686 32.962 0 59.688-26.722 59.688-59.686v-179.060c0-32.964-26.726-59.686-59.688-59.686zM512-36.956c-20.602 0-37.304 16.702-37.304 37.304v179.060c0 20.602 16.702 37.304 37.304 37.304 20.604 0 37.304-16.704 37.304-37.304v-179.060c0-20.602-16.7-37.304-37.304-37.304zM377.756 624.64c-19.34 0-38.146 10.034-48.512 27.988l-89.53 155.070c-15.452 26.764-6.282 60.986 20.482 76.438 26.762 15.45 60.986 6.284 76.438-20.482l89.53-155.072c15.452-26.764 6.282-60.986-20.482-76.438-8.81-5.084-18.432-7.504-27.926-7.504zM735.856 26.744c-11.602 0-22.886 6.022-29.108 16.792l-89.53 155.070c-9.27 16.056-3.77 36.592 12.29 45.864 16.056 9.264 36.59 3.77 45.864-12.292l89.532-155.068c9.27-16.058 3.768-36.592-12.292-45.864-5.286-3.048-11.060-4.502-16.756-4.502zM279.344 530.060c-8.86 0-17.838 2.256-26.064 7.006l-155.072 89.53c-24.978 14.422-33.538 46.362-19.116 71.342 14.42 24.978 46.364 33.538 71.342 19.116l155.070-89.53c24.98-14.422 33.538-46.362 19.116-71.34-9.668-16.756-27.226-26.124-45.276-26.124zM899.648 194.326c-5.064 0-10.196 1.29-14.894 4.004l-155.068 89.53c-14.274 8.24-19.164 26.494-10.924 40.768 8.242 14.276 26.496 19.166 40.766 10.924l155.070-89.532c14.274-8.24 19.164-26.492 10.924-40.766-5.53-9.574-15.562-14.928-25.874-14.928zM243.41 399.504h-179.060c-26.784 0-48.496 21.712-48.496 48.496s21.712 48.496 48.496 48.496h179.060c26.784 0 48.496-21.712 48.496-48.496s-21.712-48.496-48.496-48.496zM959.65 418.156c-0.002 0 0 0 0 0h-179.060c-16.482 0.002-29.844 13.364-29.844 29.844s13.364 29.844 29.844 29.844c0.002 0 0 0 0 0h179.060c16.482 0 29.844-13.362 29.844-29.844 0-16.48-13.364-29.844-29.844-29.844zM124.366 179.402c-15.472 0-30.518 8.028-38.81 22.39-12.362 21.41-5.026 48.79 16.384 61.148l155.072 89.532c21.41 12.368 48.79 5.028 61.15-16.384 12.362-21.412 5.026-48.79-16.384-61.15l-155.072-89.53c-7.050-4.070-14.748-6.006-22.34-6.006zM744.632 552.448c-10.314 0-20.346 5.352-25.874 14.926-8.24 14.274-3.35 32.526 10.924 40.768l155.070 89.528c14.272 8.236 32.526 3.352 40.768-10.922 8.24-14.274 3.35-32.526-10.924-40.768l-155.070-89.528c-4.7-2.714-9.83-4.004-14.894-4.004zM288.136 19.284c-6.962 0-14.016 1.774-20.48 5.504-19.626 11.332-26.35 36.428-15.020 56.054l89.53 155.070c11.33 19.628 36.426 26.352 56.054 15.022 19.626-11.332 26.35-36.43 15.020-56.054l-89.53-155.072c-7.598-13.166-21.392-20.524-35.574-20.524zM646.266 650.758c-5.062 0-10.196 1.29-14.894 4.002-14.274 8.242-19.164 26.494-10.924 40.766l89.534 155.070c8.24 14.274 26.492 19.166 40.766 10.922 14.274-8.242 19.164-26.494 10.924-40.766l-89.532-155.070c-5.53-9.57-15.56-14.924-25.874-14.924z" />
<glyph unicode="&#xe97f;" glyph-name="spinner6" d="M384 832c0 70.692 57.308 128 128 128s128-57.308 128-128c0-70.692-57.308-128-128-128s-128 57.308-128 128zM790.994 448c0 0 0 0 0 0 0 57.993 47.013 105.006 105.006 105.006s105.006-47.013 105.006-105.006c0 0 0 0 0 0 0-57.993-47.013-105.006-105.006-105.006s-105.006 47.013-105.006 105.006zM688.424 176.47c0 52.526 42.58 95.106 95.106 95.106s95.106-42.58 95.106-95.106c0-52.526-42.58-95.106-95.106-95.106s-95.106 42.58-95.106 95.106zM425.862 64c0 47.573 38.565 86.138 86.138 86.138s86.138-38.565 86.138-86.138c0-47.573-38.565-86.138-86.138-86.138s-86.138 38.565-86.138 86.138zM162.454 176.47c0 43.088 34.93 78.018 78.018 78.018s78.018-34.93 78.018-78.018c0-43.088-34.93-78.018-78.018-78.018s-78.018 34.93-78.018 78.018zM57.338 448c0 39.026 31.636 70.662 70.662 70.662s70.662-31.636 70.662-70.662c0-39.026-31.636-70.662-70.662-70.662s-70.662 31.636-70.662 70.662zM176.472 719.528c0 0 0 0 0 0 0 35.346 28.654 64 64 64s64-28.654 64-64c0 0 0 0 0 0 0-35.346-28.654-64-64-64s-64 28.654-64 64zM899.464 719.528c0-64.024-51.906-115.934-115.936-115.934-64.024 0-115.936 51.91-115.936 115.934 0 64.032 51.912 115.934 115.936 115.934 64.030 0 115.936-51.902 115.936-115.934z" />
<glyph unicode="&#xe982;" glyph-name="spinner9" d="M512 960c-278.748 0-505.458-222.762-511.848-499.974 5.92 241.864 189.832 435.974 415.848 435.974 229.75 0 416-200.576 416-448 0-53.020 42.98-96 96-96s96 42.98 96 96c0 282.77-229.23 512-512 512zM512-64c278.748 0 505.458 222.762 511.848 499.974-5.92-241.864-189.832-435.974-415.848-435.974-229.75 0-416 200.576-416 448 0 53.020-42.98 96-96 96s-96-42.98-96-96c0-282.77 229.23-512 512-512z" />
<glyph unicode="&#xe984;" glyph-name="spinner11" d="M1024 576h-384l143.53 143.53c-72.53 72.526-168.96 112.47-271.53 112.47s-199-39.944-271.53-112.47c-72.526-72.53-112.47-168.96-112.47-271.53s39.944-199 112.47-271.53c72.53-72.526 168.96-112.47 271.53-112.47s199 39.944 271.528 112.472c6.056 6.054 11.86 12.292 17.456 18.668l96.32-84.282c-93.846-107.166-231.664-174.858-385.304-174.858-282.77 0-512 229.23-512 512s229.23 512 512 512c141.386 0 269.368-57.326 362.016-149.984l149.984 149.984v-384z" />
<glyph unicode="&#xe986;" glyph-name="search2" d="M992.262 88.604l-242.552 206.294c-25.074 22.566-51.89 32.926-73.552 31.926 57.256 67.068 91.842 154.078 91.842 249.176 0 212.078-171.922 384-384 384-212.076 0-384-171.922-384-384s171.922-384 384-384c95.098 0 182.108 34.586 249.176 91.844-1-21.662 9.36-48.478 31.926-73.552l206.294-242.552c35.322-39.246 93.022-42.554 128.22-7.356s31.892 92.898-7.354 128.22zM384 320c-141.384 0-256 114.616-256 256s114.616 256 256 256 256-114.616 256-256-114.614-256-256-256z" />
<glyph unicode="&#xe989;" glyph-name="enlarge" d="M1024 960h-416l160-160-192-192 96-96 192 192 160-160zM1024-64v416l-160-160-192 192-96-96 192-192-160-160zM0-64h416l-160 160 192 192-96 96-192-192-160 160zM0 960v-416l160 160 192-192 96 96-192 192 160 160z" />
<glyph unicode="&#xe98b;" glyph-name="enlarge2" d="M1024 960v-416l-160 160-192-192-96 96 192 192-160 160zM448 288l-192-192 160-160h-416v416l160-160 192 192z" />
<glyph unicode="&#xe992;" glyph-name="equalizer" d="M448 832v16c0 26.4-21.6 48-48 48h-160c-26.4 0-48-21.6-48-48v-16h-192v-128h192v-16c0-26.4 21.6-48 48-48h160c26.4 0 48 21.6 48 48v16h576v128h-576zM256 704v128h128v-128h-128zM832 528c0 26.4-21.6 48-48 48h-160c-26.4 0-48-21.6-48-48v-16h-576v-128h576v-16c0-26.4 21.6-48 48-48h160c26.4 0 48 21.6 48 48v16h192v128h-192v16zM640 384v128h128v-128h-128zM448 208c0 26.4-21.6 48-48 48h-160c-26.4 0-48-21.6-48-48v-16h-192v-128h192v-16c0-26.4 21.6-48 48-48h160c26.4 0 48 21.6 48 48v16h576v128h-576v16zM256 64v128h128v-128h-128z" />
<glyph unicode="&#xe994;" glyph-name="cog" d="M933.79 349.75c-53.726 93.054-21.416 212.304 72.152 266.488l-100.626 174.292c-28.75-16.854-62.176-26.518-97.846-26.518-107.536 0-194.708 87.746-194.708 195.99h-201.258c0.266-33.41-8.074-67.282-25.958-98.252-53.724-93.056-173.156-124.702-266.862-70.758l-100.624-174.292c28.97-16.472 54.050-40.588 71.886-71.478 53.638-92.908 21.512-211.92-71.708-266.224l100.626-174.292c28.65 16.696 61.916 26.254 97.4 26.254 107.196 0 194.144-87.192 194.7-194.958h201.254c-0.086 33.074 8.272 66.57 25.966 97.218 53.636 92.906 172.776 124.594 266.414 71.012l100.626 174.29c-28.78 16.466-53.692 40.498-71.434 71.228zM512 240.668c-114.508 0-207.336 92.824-207.336 207.334 0 114.508 92.826 207.334 207.336 207.334 114.508 0 207.332-92.826 207.332-207.334-0.002-114.51-92.824-207.334-207.332-207.334z" />
<glyph unicode="&#xe9bd;" glyph-name="menu2" d="M64 768h896v-192h-896zM64 512h896v-192h-896zM64 256h896v-192h-896z" />
<glyph unicode="&#xe9d5;" glyph-name="contrast" d="M512 960c-282.77 0-512-229.23-512-512s229.23-512 512-512 512 229.23 512 512-229.23 512-512 512zM128 448c0 212.078 171.922 384 384 384v-768c-212.078 0-384 171.922-384 384z" />
<glyph unicode="&#xea0d;" glyph-name="cancel-circle" d="M512 960c-282.77 0-512-229.23-512-512s229.23-512 512-512 512 229.23 512 512-229.23 512-512 512zM512 32c-229.75 0-416 186.25-416 416s186.25 416 416 416 416-186.25 416-416-186.25-416-416-416zM672 704l-160-160-160 160-96-96 160-160-160-160 96-96 160 160 160-160 96 96-160 160 160 160z" />
<glyph unicode="&#xea14;" glyph-name="exit" d="M768 320v128h-320v128h320v128l192-192zM704 384v-256h-320v-192l-384 192v832h704v-320h-64v256h-512l256-128v-576h256v192z" />
<glyph unicode="&#xea34;" glyph-name="arrow-right" d="M992 448l-480 480v-288h-512v-384h512v-288z" />
<glyph unicode="&#xea38;" glyph-name="arrow-left" d="M32 448l480-480v288h512v384h-512v288z" />
<glyph unicode="&#xea3c;" glyph-name="arrow-right2" d="M621.254 82.746l320 320c24.994 24.992 24.994 65.516 0 90.51l-320 320c-24.994 24.992-65.516 24.992-90.51 0-24.994-24.994-24.994-65.516 0-90.51l210.746-210.746h-613.49c-35.346 0-64-28.654-64-64s28.654-64 64-64h613.49l-210.746-210.746c-12.496-12.496-18.744-28.876-18.744-45.254s6.248-32.758 18.744-45.254c24.994-24.994 65.516-24.994 90.51 0z" />
<glyph unicode="&#xea40;" glyph-name="arrow-left2" d="M402.746 82.746l-320 320c-24.994 24.992-24.994 65.516 0 90.51l320 320c24.994 24.992 65.516 24.992 90.51 0 24.994-24.994 24.994-65.516 0-90.51l-210.746-210.746h613.49c35.346 0 64-28.654 64-64s-28.654-64-64-64h-613.49l210.746-210.746c12.496-12.496 18.744-28.876 18.744-45.254s-6.248-32.758-18.744-45.254c-24.994-24.994-65.516-24.994-90.51 0z" />
<glyph unicode="&#xea42;" glyph-name="circle-right" d="M512 960c-282.77 0-512-229.23-512-512s229.23-512 512-512 512 229.23 512 512-229.23 512-512 512zM512 32c-229.75 0-416 186.25-416 416s186.25 416 416 416 416-186.25 416-416-186.25-416-416-416zM354.744 253.256l90.512-90.512 285.254 285.256-285.256 285.254-90.508-90.508 194.744-194.746z" />
<glyph unicode="&#xea44;" glyph-name="circle-left" d="M512-64c282.77 0 512 229.23 512 512s-229.23 512-512 512-512-229.23-512-512 229.23-512 512-512zM512 864c229.75 0 416-186.25 416-416s-186.25-416-416-416-416 186.25-416 416 186.25 416 416 416zM669.256 642.744l-90.512 90.512-285.254-285.256 285.256-285.254 90.508 90.508-194.744 194.746z" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Binary file not shown.

369
files_reader/vendor/icomoon/style.css vendored Normal file
View file

@ -0,0 +1,369 @@
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?jhgf4g');
src: url('fonts/icomoon.eot?jhgf4g#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?jhgf4g') format('truetype'),
url('fonts/icomoon.woff?jhgf4g') format('woff'),
url('fonts/icomoon.svg?jhgf4g#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
[class^="icon-"], [class*=" icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'icomoon' !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/* slightly bigger icons */
font-size: 1.2em;
}
.icon-anchor:before {
content: "\e901";
}
.icon-link:before {
content: "\e901";
}
.icon-reference:before {
content: "\e901";
}
.icon-arrow_back2:before {
content: "\e5c5";
}
.icon-flag:before {
content: "\e153";
}
.icon-attach_file:before {
content: "\e226";
}
.icon-attachment:before {
content: "\e2bc";
}
.icon-class:before {
content: "\e86f";
}
.icon-turned_in2:before {
content: "\e8e8";
}
.icon-turned_in_not2:before {
content: "\e8e9";
}
.icon-brightness_1:before {
content: "\e3a6";
}
.icon-brightness_2:before {
content: "\e3a7";
}
.icon-brightness_3:before {
content: "\e3a8";
}
.icon-brightness_4:before {
content: "\e3a9";
}
.icon-brightness_low2:before {
content: "\e1ae";
}
.icon-brightness_medium:before {
content: "\e1af";
}
.icon-brightness_high:before {
content: "\e1ac";
}
.icon-chat:before {
content: "\e0b7";
}
.icon-chat_bubble:before {
content: "\e0ca";
}
.icon-chat_bubble_outline:before {
content: "\e0cb";
}
.icon-check:before {
content: "\e5ca";
}
.icon-check_box:before {
content: "\e834";
}
.icon-double_page_mode:before {
content: "\e86d";
}
.icon-single_page_mode:before {
content: "\e86e";
}
.icon-comment:before {
content: "\e0b9";
}
.icon-delete:before {
content: "\e872";
}
.icon-find_in_page:before {
content: "\e880";
}
.icon-format_size:before {
content: "\e245";
}
.icon-fullscreen2:before {
content: "\e5d3";
}
.icon-fullscreen_exit2:before {
content: "\e5d4";
}
.icon-star:before {
content: "\e838";
}
.icon-link2:before {
content: "\e157";
}
.icon-keyboard_arrow_left2:before {
content: "\e316";
}
.icon-label_outline:before {
content: "\e893";
}
.icon-local_library:before {
content: "\e54b";
}
.icon-location_off:before {
content: "\e0c7";
}
.icon-room:before {
content: "\e8b4";
}
.icon-menu3:before {
content: "\e5d5";
}
.icon-message:before {
content: "\e0c9";
}
.icon-rate_review:before {
content: "\e560";
}
.icon-save:before {
content: "\e161";
}
.icon-search3:before {
content: "\e8b7";
}
.icon-star_border:before {
content: "\e83a";
}
.icon-star_half:before {
content: "\e839";
}
.icon-stars:before {
content: "\e8d0";
}
.icon-zoom_in2:before {
content: "\e902";
}
.icon-zoom_out2:before {
content: "\e903";
}
.icon-arrow_back:before {
content: "\e5c4";
}
.icon-arrow_forward:before {
content: "\e5c8";
}
.icon-icon-fit-window:before {
content: "\e85b";
}
.icon-icon-fit-width:before {
content: "\e85c";
}
.icon-turned_in:before {
content: "\e8e6";
}
.icon-turned_in_not:before {
content: "\e8e7";
}
.icon-brightness_low:before {
content: "\e1ad";
}
.icon-build:before {
content: "\e869";
}
.icon-cancel:before {
content: "\e5c9";
}
.icon-navigate_before:before {
content: "\e408";
}
.icon-navigate_next:before {
content: "\e409";
}
.icon-close:before {
content: "\e5cd";
}
.icon-cloud_download:before {
content: "\e2c0";
}
.icon-content_copy:before {
content: "\e14d";
}
.icon-mode_edit:before {
content: "\e254";
}
.icon-crop_free:before {
content: "\e3c2";
}
.icon-crop_portrait:before {
content: "\e3c5";
}
.icon-dehaze:before {
content: "\e3c7";
}
.icon-dns:before {
content: "\e875";
}
.icon-exit_to_app:before {
content: "\e879";
}
.icon-featured_play_list:before {
content: "\e06d";
}
.icon-format_list_bulleted:before {
content: "\e241";
}
.icon-format_list_numbered:before {
content: "\e242";
}
.icon-format_textdirection_l_to_r:before {
content: "\e247";
}
.icon-format_textdirection_r_to_l:before {
content: "\e248";
}
.icon-fullscreen:before {
content: "\e5d0";
}
.icon-fullscreen_exit:before {
content: "\e5d1";
}
.icon-keyboard_arrow_left:before {
content: "\e314";
}
.icon-keyboard_arrow_right:before {
content: "\e315";
}
.icon-list:before {
content: "\e896";
}
.icon-sync:before {
content: "\e627";
}
.icon-menu:before {
content: "\e5d2";
}
.icon-open_with:before {
content: "\e89f";
}
.icon-pages:before {
content: "\e7f9";
}
.icon-search:before {
content: "\e8b6";
}
.icon-settings:before {
content: "\e8b8";
}
.icon-settings_overscan:before {
content: "\e8c4";
}
.icon-tune:before {
content: "\e429";
}
.icon-unarchive:before {
content: "\e169";
}
.icon-wb_sunny:before {
content: "\e430";
}
.icon-zoom_in:before {
content: "\e8ff";
}
.icon-zoom_out:before {
content: "\e900";
}
.icon-zoom_out_map:before {
content: "\e56b";
}
.icon-droplet:before {
content: "\e90b";
}
.icon-box-remove:before {
content: "\e95f";
}
.icon-download:before {
content: "\e960";
}
.icon-spinner:before {
content: "\e97a";
}
.icon-spinner3:before {
content: "\e97c";
}
.icon-spinner6:before {
content: "\e97f";
}
.icon-spinner9:before {
content: "\e982";
}
.icon-spinner11:before {
content: "\e984";
}
.icon-search2:before {
content: "\e986";
}
.icon-enlarge:before {
content: "\e989";
}
.icon-enlarge2:before {
content: "\e98b";
}
.icon-equalizer:before {
content: "\e992";
}
.icon-cog:before {
content: "\e994";
}
.icon-menu2:before {
content: "\e9bd";
}
.icon-contrast:before {
content: "\e9d5";
}
.icon-cancel-circle:before {
content: "\ea0d";
}
.icon-exit:before {
content: "\ea14";
}
.icon-arrow-right:before {
content: "\ea34";
}
.icon-arrow-left:before {
content: "\ea38";
}
.icon-arrow-right2:before {
content: "\ea3c";
}
.icon-arrow-left2:before {
content: "\ea40";
}
.icon-circle-right:before {
content: "\ea42";
}
.icon-circle-left:before {
content: "\ea44";
}

View file

@ -0,0 +1,18 @@
jQuery.each( [ "put", "delete" ], function( i, method ) {
jQuery[ method ] = function( url, data, callback, type ) {
if ( jQuery.isFunction( data ) ) {
type = type || callback;
callback = data;
data = undefined;
}
return jQuery.ajax({
url: url,
type: method,
dataType: type,
data: data,
success: callback
});
};
});

File diff suppressed because it is too large Load diff

286
files_reader/vendor/pixastic/pixastic.js vendored Normal file
View file

@ -0,0 +1,286 @@
/*!
* Pixastic - JavaScript Image Processing
* http://pixastic.com/
* Copyright 2012, Jacob Seidelin
*
* Dual licensed under the MPL 1.1 or GPLv3 licenses.
* http://pixastic.com/license-mpl.txt
* http://pixastic.com/license-gpl-3.0.txt
*
*/
var Pixastic = (function() {
var worker;
function createImageData(ctx, width, height) {
if (ctx.createImageData) {
return ctx.createImageData(width, height);
} else {
return ctx.getImageData(0, 0, width, height);
}
}
function Pixastic(ctx, workerControlPath) {
var P = {},
width = ctx.canvas.width,
height = ctx.canvas.height,
queue = [],
workerControlPath = workerControlPath || "";
if (!worker) {
if (typeof window.Worker != "undefined") {
try {
worker = new window.Worker(workerControlPath + "pixastic.worker.control.js");
} catch(e) {
if (location.protocol == "file:") {
Pixastic.log("Could not create native worker, running from file://")
} else {
Pixastic.log("Could not create native worker.")
}
}
}
if (!worker) {
worker = new Pixastic.Worker();
}
}
for (var e in Pixastic.Effects) {
if (Pixastic.Effects.hasOwnProperty(e)) {
(function(e) {
P[e] = function(options) {
queue.push({
effect : e,
options : options
});
return P;
}
P.done = function(callback, progress) {
var inData, outData;
try {
inData = ctx.getImageData(0, 0, width, height);
} catch(e) {
if (location.protocol == "file:") {
throw new Error("Could not access image data, running from file://");
} else {
throw new Error("Could not access image data, is canvas tainted by cross-origin data?");
}
}
outData = createImageData(ctx, width, height);
worker.postMessage({
queue : queue,
inData : inData,
outData : outData,
width : width,
height : height
});
worker.onmessage = function(message) {
var d = message.data;
switch (d.event) {
case "done" :
ctx.putImageData(d.data, 0, 0);
if (callback) {
callback();
}
if (progress) {
progress(1);
}
break;
case "progress" :
if (progress) {
progress(d.data);
}
break;
case "error" :
break;
}
}
if (progress) {
progress(0);
}
}
})(e);
}
}
return P;
}
Pixastic.Worker = function() {
var me = this;
function processMessage(data) {
var queue = data.queue,
inData = data.inData,
outData = data.outData,
width = data.width,
height = data.height,
tmpData;
for (var i=0;i<queue.length;i++) {
var e = queue[i].effect,
options = queue[i].options,
progressCallback;
if (i > 0) {
tmpData = inData;
inData = outData;
outData = tmpData;
}
if (typeof importScripts == "function") {
progressCallback = function(p) {
me.onmessage({
data : {
event : "progress",
data : (i + p) / queue.length
}
});
return p;
}
}
Pixastic.Effects[e](inData.data, outData.data, width, height, options, progressCallback);
me.onmessage({
data : {
event : "progress",
data : (i+1) / queue.length
}
});
}
me.onmessage({
data : {
event : "done",
data : outData
}
});
}
this.postMessage = function(data) {
setTimeout(function() {
processMessage(data)
}, 0);
};
this.onmessage = function() {};
}
Pixastic.log = function(str) {
if (typeof console != "undefined" && console.log) {
console.log("Pixastic: " + str);
}
};
function toCanvas(o) {
var canvas;
if (typeof o == "object") {
if (typeof o.tagName == "string") {
if (o.tagName.toLowerCase() == "canvas" || o.tagName.toLowerCase() == "img") {
canvas = document.createElement("canvas");
canvas.width = o.width;
canvas.height = o.height;
canvas.getContext("2d").drawImage(o, 0,0);
}
} else if ((window.ImageData && o instanceof window.ImageData)
|| (typeof o.width == "number" && typeof o.height == "number" && typeof o.data == "object")) {
canvas = document.createElement("canvas");
canvas.width = o.width;
canvas.height = o.height;
canvas.getContext("2d").putImageData(o, 0, 0);
}
}
return canvas;
};
function toImage(o) {
var canvas = toCanvas(o),
image = new Image();
image.width = canvas.width;
image.height = canvas.height;
image.src = canvas.toDataURL();
return image;
};
function toImageData(o) {
var canvas = toCanvas(o),
ctx = canvas.getContext("2d");
return ctx.getImageData(0, 0, canvas.width, canvas.height);
};
function histogram(imageData) {
var values = [],
i, p,
data = imageData.data,
round = Math.round,
maxValue,
n = imageData.width * imageData.height;
for (i=0;i<256;i++) {
values[i] = 0;
}
for (i=0;i<n;i++) {
p = i * 4;
values[ round((data[p]+data[p+1]+data[p+2])/3) ]++;
}
maxValue = 0;
for (i=0;i<256;i++) {
if (values[i] > maxValue) {
maxValue = values[i];
}
}
return {
maxValue : maxValue,
values : values
};
}
Pixastic.toCanvas = toCanvas;
Pixastic.toImage = toImage;
Pixastic.toImageData = toImageData;
Pixastic.histogram = histogram;
Pixastic.Color = {
rgb2hsl : function(r, g, b) {
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
if (r > 255) r = 0;
if (g > 255) g = 0;
if (b > 255) b = 0;
},
rgb2hsv : function(r, g, b) {
},
rgb2hex : function(r, g, b) {
},
hsl2rgb : function(h, s, l) {
},
hsv2rgb : function(h, s, v) {
}
}
return Pixastic;
})();

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,47 @@
Pixastic.Worker = function() {
var me = this;
function processMessage(data) {
var queue = data.queue,
inData = data.inData,
outData = data.outData,
width = data.width,
height = data.height,
tmpData;
for (var i=0;i<queue.length;i++) {
var e = queue[i].effect,
options = queue[i].options;
if (i > 0) {
tmpData = inData;
inData = outData;
outData = tmpData;
}
Pixastic.Effects[e](inData.data, outData.data, width, height, options);
me.onmessage({
data : {
event : "progress",
data : (i+1) / queue.length
}
});
}
me.onmessage({
data : {
event : "done",
data : outData
}
});
}
this.postMessage = function(data) {
setTimeout(function() {
processMessage(data)
}, 0);
}
this.onmessage = function() {};
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,145 @@
/*!
* screenfull
* v3.0.0 - 2015-11-24
* (c) Sindre Sorhus; MIT License
*/
(function () {
'use strict';
var isCommonjs = typeof module !== 'undefined' && module.exports;
var keyboardAllowed = typeof Element !== 'undefined' && 'ALLOW_KEYBOARD_INPUT' in Element;
var fn = (function () {
var val;
var valLength;
var fnMap = [
[
'requestFullscreen',
'exitFullscreen',
'fullscreenElement',
'fullscreenEnabled',
'fullscreenchange',
'fullscreenerror'
],
// new WebKit
[
'webkitRequestFullscreen',
'webkitExitFullscreen',
'webkitFullscreenElement',
'webkitFullscreenEnabled',
'webkitfullscreenchange',
'webkitfullscreenerror'
],
// old WebKit (Safari 5.1)
[
'webkitRequestFullScreen',
'webkitCancelFullScreen',
'webkitCurrentFullScreenElement',
'webkitCancelFullScreen',
'webkitfullscreenchange',
'webkitfullscreenerror'
],
[
'mozRequestFullScreen',
'mozCancelFullScreen',
'mozFullScreenElement',
'mozFullScreenEnabled',
'mozfullscreenchange',
'mozfullscreenerror'
],
[
'msRequestFullscreen',
'msExitFullscreen',
'msFullscreenElement',
'msFullscreenEnabled',
'MSFullscreenChange',
'MSFullscreenError'
]
];
var i = 0;
var l = fnMap.length;
var ret = {};
for (; i < l; i++) {
val = fnMap[i];
if (val && val[1] in document) {
for (i = 0, valLength = val.length; i < valLength; i++) {
ret[fnMap[0][i]] = val[i];
}
return ret;
}
}
return false;
})();
var screenfull = {
request: function (elem) {
var request = fn.requestFullscreen;
elem = elem || document.documentElement;
// Work around Safari 5.1 bug: reports support for
// keyboard in fullscreen even though it doesn't.
// Browser sniffing, since the alternative with
// setTimeout is even worse.
if (/5\.1[\.\d]* Safari/.test(navigator.userAgent)) {
elem[request]();
} else {
elem[request](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);
}
},
exit: function () {
document[fn.exitFullscreen]();
},
toggle: function (elem) {
if (this.isFullscreen) {
this.exit();
} else {
this.request(elem);
}
},
raw: fn
};
if (!fn) {
if (isCommonjs) {
module.exports = false;
} else {
window.screenfull = false;
}
return;
}
Object.defineProperties(screenfull, {
isFullscreen: {
get: function () {
return Boolean(document[fn.fullscreenElement]);
}
},
element: {
enumerable: true,
get: function () {
return document[fn.fullscreenElement];
}
},
enabled: {
enumerable: true,
get: function () {
// Coerce to boolean in case of old WebKit
return Boolean(document[fn.fullscreenEnabled]);
}
}
});
if (isCommonjs) {
module.exports = screenfull;
} else {
window.screenfull = screenfull;
}
})();