diff --git a/reader/CHANGELOG.md b/reader/CHANGELOG.md new file mode 100644 index 0000000..ec1893c --- /dev/null +++ b/reader/CHANGELOG.md @@ -0,0 +1,29 @@ +## Unreleased +### Added + - Reader now supports CBR/CBZ ('comics') files + - Book position is saved on server and restored on next invocation + - Framework to support more file format renderers + +## 0.8.3 - 2017-02-02 +### Fixed + . #31: ReferenceError: cleanStartTextContent is not defined, caused by failure to declare local var in epub.js + +## 0.8.3 - 2017-02-01 +### Fixed + - missing $title parameter in template/reader.php caused warnings in log, fixed + +## 0.8.2 - 2017-01-10 +### Fixed + - Nextcloud-port broke compatibility with Owncloud due to OC not supporting CSPv3, workaround implemented + +## 0.8.1 - 2017-01-09 +### Added + - Modified info.xml, added screenshots + +## 0.8.0 - 2017-01-09 +### Added + - new version 0.2.15 of Futurepress epub.js renderer + +### Changed + - New logo + - First release to be compatible with Nextcloud diff --git a/reader/README.md b/reader/README.md new file mode 100644 index 0000000..4c1f536 --- /dev/null +++ b/reader/README.md @@ -0,0 +1,11 @@ +files_reader +------------ + +Reader is an ebook reader based on a pure javascript epub renderer. It only works for books formatted according to the epub standard. + +Using the futurepress epub.js renderer 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. + +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. + +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. + diff --git a/reader/appinfo/app.php b/reader/appinfo/app.php new file mode 100644 index 0000000..4d35577 --- /dev/null +++ b/reader/appinfo/app.php @@ -0,0 +1,30 @@ +getContentSecurityPolicyManager(); + $csp = new \OCP\AppFramework\Http\EmptyContentSecurityPolicy(); + $csp->addAllowedStyleDomain('\'self\''); + $csp->addAllowedStyleDomain('blob:'); + $csp->addAllowedScriptDomain('\'self\''); + $csp->addAllowedFrameDomain('\'self\''); + $csp->addAllowedChildSrcDomain('\'self\''); + $csp->addAllowedFontDomain('\'self\''); + $csp->addAllowedImageDomain('blob:'); + $manager->addDefaultPolicy($csp); +} diff --git a/reader/appinfo/application.php.org b/reader/appinfo/application.php.org new file mode 100644 index 0000000..e8894d3 --- /dev/null +++ b/reader/appinfo/application.php.org @@ -0,0 +1,118 @@ +getContainer(); + + $container->registerService('PageController', function($c){ + return new PageController( + $c->query('AppName'), + $c->query('Request'), + $c->query('OCP\IURLGenerator') + ); + }); + + $container->registerService('BookmarkController', function($c){ + return new BookmarkController( + $c->query('AppName'), + $c->query('Request'), + $c->query('BookmarkService') + ); + }); + + $container->registerService('MetadataController', function($c){ + return new MetadataController( + $c->query('AppName'), + $c->query('Request'), + $c->query('MetadataService') + ); + }); + + $container->registerService('PreferenceController', function($c){ + $UserId = ($user = $c->query('ServerContainer')->getUserSession()->getUser()) + ? $user->getUID() : null; + + return new PreferenceController( + $c->query('AppName'), + $c->query('Request'), + $c->query('OCP\IURLGenerator'), + $c->query('PreferenceService') + ); + }); + + $container->registerService('BookmarkService', function($c){ + $UserId = ($user = $c->query('ServerContainer')->getUserSession()->getUser()) + ? $user->getUID() + : null; + + return new BookmarkService( + $c->query('BookmarkMapper'), + $UserId + ); + }); + + $container->registerService('MetadataService', function($c){ + return new MetadataService(); + }); + + $container->registerService('PreferenceService', function($c){ + return new PreferenceService( + $c->query('PreferenceMapper') + ); + }); + + $container->registerService('BookmarkMapper', function($c){ + $UserId = ($user = $c->query('ServerContainer')->getUserSession()->getUser()) + ? $user->getUID() + : null; + + return new BookmarkMapper( + $c->query('ServerContainer')->getDb(), + $UserId, + $c->query('Time') + ); + }); + + $container->registerService('PreferenceMapper', function($c){ + $UserId = ($user = $c->query('ServerContainer')->getUserSession()->getUser()) + ? $user->getUID() + : null; + + return new PreferenceMapper( + $c->query('ServerContainer')->getDb(), + $UserId, + $c->query('Time') + ); + }); + } +} + diff --git a/reader/appinfo/database.xml b/reader/appinfo/database.xml new file mode 100644 index 0000000..0445527 --- /dev/null +++ b/reader/appinfo/database.xml @@ -0,0 +1,185 @@ + + + *dbname* + true + false + utf8 + + + *dbprefix*reader_bookmarks + + + + id + integer + true + true + true + true + 8 + + + + + user_id + text + + true + 64 + + + + + file_id + integer + true + true + 11 + + + + + name + text + + true + 64 + + + + + value + text + + true + 64 + + + + + last_modified + integer + 0 + 8 + false + true + + + + reader_bookmarks_file_id_index + + file_id + + + + + reader_bookmarks_user_id_index + + user_id + + + + + reader_bookmarks_name_index + + name + + + + +
+ + + *dbprefix*reader_preferences + + + + id + integer + true + true + true + true + 8 + + + + + user_id + text + + true + 64 + + + + + file_id + integer + true + true + 11 + + + + + scope + text + + true + 32 + + + + + name + text + + true + 128 + + + + + value + text + + true + 128 + + + + + last_modified + integer + 0 + 8 + false + true + + + + reader_preferences_file_id_index + + file_id + + + + + reader_preferences_user_id_index + + user_id + + + + + reader_preferences_scope_index + + scope + + + + +
+ +
diff --git a/reader/appinfo/info.xml b/reader/appinfo/info.xml new file mode 100644 index 0000000..991bb7b --- /dev/null +++ b/reader/appinfo/info.xml @@ -0,0 +1,42 @@ + + + files_reader + Reader (ebook reader) + Files_Reader + An epub-compatible ebook reader based on a pure javascript epub renderer + + Reader is an ebook reader based on pure javascript renderers. It works for books formatted according to the epub standard as well as those conforming to the (informal) CBR and CBZ ('comics') scheme. + + For Epub Reader uses the futurepress epub.js renderer (https://github.com/futurepress/epub.js) 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. + + CBR and CBZ are supported using a custom renderer based in part on balaclark's work (https://github.com/balaclark/HTML5-Comic-Book-Reader). As with Epub, books can be navigated using the keyboard as well as mouse or touch navigation. + + For text-based formats 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. + + 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. + + Current reading position and settings are saved to the server which makes it possible to start reading on one device and continue on another without losing track of where you were. + + 0.8.4 + AGPL + Frank de Lange + + https://github.com/Yetangitu/owncloud-apps/blob/master/files_reader/README.md + + https://github.com/Yetangitu/owncloud-apps/issues + https://github.com/Yetangitu/owncloud-apps/files_reader + https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/files_reader-1.png + https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/files_reader-2.png + https://raw.githubusercontent.com/Yetangitu/owncloud-apps/master/screenshots/files_reader-3.png + files + multimedia + office + + + + pgsql + sqlite + mysql + + 167127 + diff --git a/reader/appinfo/routes.php b/reader/appinfo/routes.php new file mode 100644 index 0000000..e117ff0 --- /dev/null +++ b/reader/appinfo/routes.php @@ -0,0 +1,33 @@ + [ + // Page + ['name' => 'page#showReader', 'url' => '/', 'verb' => 'GET'], + + // Bookmarks + ['name' => 'bookmark#get_cursor', 'url' => '/position/cursor/{fileId}', 'verb' => 'GET'], + ['name' => 'bookmark#set_cursor', 'url' => '/position/cursor/{fileId}/{value}', 'verb' => 'POST'], + ['name' => 'bookmark#get', 'url' => '/position/{fileId}/{name}', 'verb' => 'GET', 'defaults' => ['name' => '']], + ['name' => 'bookmark#set', 'url' => '/position/{fileId}/{name}/{value}', 'verb' => 'POST'], + + // 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/{scope}/{name}/{value}', 'verb' => 'POST'], + ['name' => 'preference#get', 'url' => '/preference/{fileId}/{scope}/{name}', 'verb' => 'GET', 'defaults' => ['name' => '']], + ['name' => 'preference#set', 'url' => '/preference/{fileId}/{scope}/{name}/{value}', 'verb' => 'POST'], +]]; + diff --git a/reader/css/annotations.css b/reader/css/annotations.css new file mode 100644 index 0000000..ae74f91 --- /dev/null +++ b/reader/css/annotations.css @@ -0,0 +1,8 @@ +.ui-loader { + display: none; +} + +.annotator-hl { + box-shadow: none !important; + cursor: pointer !important; +} \ No newline at end of file diff --git a/reader/css/font/fontello.eot b/reader/css/font/fontello.eot new file mode 100644 index 0000000..f63ffa0 Binary files /dev/null and b/reader/css/font/fontello.eot differ diff --git a/reader/css/font/fontello.svg b/reader/css/font/fontello.svg new file mode 100644 index 0000000..2db1398 --- /dev/null +++ b/reader/css/font/fontello.svg @@ -0,0 +1,33 @@ + + + +Copyright (C) 2013 by original authors @ fontello.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/reader/css/font/fontello.ttf b/reader/css/font/fontello.ttf new file mode 100644 index 0000000..95715f8 Binary files /dev/null and b/reader/css/font/fontello.ttf differ diff --git a/reader/css/font/fontello.woff b/reader/css/font/fontello.woff new file mode 100644 index 0000000..084f0c5 Binary files /dev/null and b/reader/css/font/fontello.woff differ diff --git a/reader/css/idevice.css b/reader/css/idevice.css new file mode 100644 index 0000000..888c060 --- /dev/null +++ b/reader/css/idevice.css @@ -0,0 +1,33 @@ +/* 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; + } +} + diff --git a/reader/css/main.css b/reader/css/main.css new file mode 100644 index 0000000..436966e --- /dev/null +++ b/reader/css/main.css @@ -0,0 +1,782 @@ +@font-face { + font-family: 'fontello'; + src: url('font/fontello.eot?60518104'); + src: url('font/fontello.eot?60518104#iefix') format('embedded-opentype'), + url('font/fontello.woff?60518104') format('woff'), + url('font/fontello.ttf?60518104') format('truetype'), + url('font/fontello.svg?60518104#fontello') format('svg'); + font-weight: normal; + font-style: normal; +} + +body { + background: #4e4e4e; + overflow: hidden; +} + +#main { + /* height: 500px; */ + position: absolute; + width: 100%; + height: 100%; + right: 0; + /* left: 40px; */ +/* -webkit-transform: translate(40px, 0); + -moz-transform: translate(40px, 0); */ + + /* border-radius: 5px 0px 0px 5px; */ + 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 { + height: 8%; + min-height: 20px; + padding: 10px; + /* margin: 0 50px 0 50px; */ + position: relative; + 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; +} + +#titlebar:hover { + opacity: 1; +} + +#titlebar a { + width: 18px; + height: 19px; + line-height: 20px; + overflow: hidden; + display: inline-block; + opacity: .5; + padding: 4px; + border-radius: 4px; +} + +#titlebar a::before { + visibility: visible; +} + +#titlebar a:hover { + opacity: .8; + border: 1px rgba(0,0,0,.2) solid; + padding: 3px; +} + +#titlebar a:active { + opacity: 1; + color: rgba(0,0,0,.6); + /* margin: 1px -1px -1px 1px; */ + -moz-box-shadow: inset 0 0 6px rgba(155,155,155,.8); + -webkit-box-shadow: inset 0 0 6px rgba(155,155,155,.8); + box-shadow: inset 0 0 6px rgba(155,155,155,.8); +} + +#book-title { + font-weight: 600; +} + +#title-seperator { + display: none; +} + +#viewer { + width: 80%; + height: 80%; + /* margin-left: 10%; */ + margin: 0 auto; + max-width: 1250px; + z-index: 2; + position: relative; + overflow: hidden; +} + +#viewer iframe { + border: none; +} + +#prev, #next { + position: absolute; + top: 10%; + height: 85%; + margin: 0; +} + +.touch_nav { + width: 35%; +} + +.arrow div { + display: table-cell; + vertical-align: middle; +} + + +#prev { + left: 0; + padding-left: 40px; +} + +#next { + right: 0; + padding-right: 40px; + text-align: right; +} + +.arrow { + /* position: relative; + top: 50%; + margin-top: -32px; */ + font-size: 64px; + color: #E2E2E2; + font-family: arial, sans-serif; + font-weight: bold; + cursor: pointer; + display: table; + z-index: 3; +} + +.arrow:hover { + color: #777; +} + +.arrow:active, +.arrow.active { + color: #000; +} + +#sidebar { + background: #6b6b6b; + position: absolute; + /* left: -260px; */ + /* -webkit-transform: translate(-260px, 0); + -moz-transform: translate(-260px, 0); */ + top: 0; + min-width: 300px; + width: 25%; + height: 100%; + -webkit-transition: -webkit-transform .5s; + -moz-transition: -moz-transform .5s; + + overflow: hidden; +} + +#sidebar.open { + /* left: 0; */ + /* -webkit-transform: translate(0, 0); + -moz-transform: translate(0, 0); */ +} + +#main.closed { + /* left: 300px; */ + -webkit-transform: translate(300px, 0); + -moz-transform: translate(300px, 0); +} + +#main.single { + width: 75%; +} + +#main.single #viewer { + /* width: 60%; + margin-left: 20%; */ +} + +#panels { + background: #4e4e4e; + position: absolute; + left: 0; + top: 0; + width: 100%; + padding: 13px 0; + height: 14px; + -moz-box-shadow: 0px 1px 3px rgba(0,0,0,.6); + -webkit-box-shadow: 0px 1px 3px rgba(0,0,0,.6); + box-shadow: 0px 1px 3px rgba(0,0,0,.6); +} + +#opener { + /* padding: 10px 10px; */ + float: left; +} + +/* #opener #slider { + width: 25px; +} */ + +#metainfo { + display: inline-block; + text-align: center; + max-width: 80%; +} + +#title-controls { + float: right; +} + +#panels a { + visibility: hidden; + width: 18px; + height: 20px; + overflow: hidden; + display: inline-block; + color: #ccc; + margin-left: 6px; +} + +#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; +} + +#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; */ + +} + +input::-webkit-input-placeholder { + color: #454545; +} +input:-moz-placeholder { + color: #454545; +} + +#divider { + position: absolute; + width: 1px; + border-right: 1px #000 solid; + height: 80%; + z-index: 1; + 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; +} + +#tocView, +#bookmarksView { + overflow-x: hidden; + overflow-y: hidden; + min-width: 300px; + width: 25%; + height: 100%; + visibility: hidden; + -webkit-transition: visibility 0 ease .5s; + -moz-transition: visibility 0 ease .5s; +} + + + +#sidebar.open #tocView, +#sidebar.open #bookmarksView { + overflow-y: auto; + visibility: visible; + -webkit-transition: visibility 0 ease 0; + -moz-transition: visibility 0 ease 0; +} + +#sidebar.open #tocView { + display: block; +} + +#tocView > ul, +#bookmarksView > ul { + margin-top: 15px; + margin-bottom: 50px; + padding-left: 20px; + display: block; +} + +#tocView li, +#bookmarksView li { + margin-bottom:10px; + width: 225px; + font-family: Georgia, "Times New Roman", Times, serif; + list-style: none; + text-transform: capitalize; +} + +#tocView li:active, +#tocView li.currentChapter +{ + list-style: none; +} + +.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 +} + +/* #tocView li.openChapter > a, */ +.list_item a:hover { + color: #E2E2E2; +} + +.list_item ul { + padding-left:10px; + margin-top: 8px; + display: none; +} + +.list_item.currentChapter > ul, +.list_item.openChapter > ul { + display: block; +} + +#tocView.hidden { + display: none; +} + +.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: '▾'; +} + +.view { + width: 300px; + height: 100%; + display: none; + padding-top: 50px; + overflow-y: auto; +} + +#searchResults { + margin-bottom: 50px; + padding-left: 20px; + display: block; +} + +#searchResults li { + margin-bottom:10px; + width: 225px; + font-family: Georgia, "Times New Roman", Times, serif; + list-style: none; +} + +#searchResults a { + color: #AAA; + text-decoration: none; +} + +#searchResults p { + text-decoration: none; + font-size: 12px; + line-height: 16px; +} + +#searchResults p .match { + background: #ccc; + color: #000; +} + +#searchResults li > p { + color: #AAA; +} + +#searchResults li a:hover { + color: #E2E2E2; +} + +#searchView.shown { + display: block; + overflow-y: scroll; +} + +#notes { + padding: 0 0 0 34px; +} + +#notes li { + color: #eee; + font-size: 12px; + width: 240px; + border-top: 1px #fff solid; + padding-top: 6px; + margin-bottom: 6px; +} + +#notes li a { + color: #fff; + display: inline-block; + margin-left: 6px; +} + +#notes li a:hover { + text-decoration: underline; +} + +#notes li img { + max-width: 240px; +} + +#note-text { + display: block; + width: 260px; + height: 80px; + margin: 0 auto; + padding: 5px; + border-radius: 5px; +} + +#note-text[disabled], #note-text[disabled="disabled"]{ + opacity: .5; +} + +#note-anchor { + margin-left: 218px; + margin-top: 5px; +} + +#settingsPanel { + display:none; +} + +#settingsPanel h3 { + color:#f1f1f1; + font-family:Georgia, "Times New Roman", Times, serif; + margin-bottom:10px; +} + +#settingsPanel ul { + margin-top:60px; + list-style-type:none; +} + +#settingsPanel li { + font-size:1em; + color:#f1f1f1; +} + +#settingsPanel .xsmall { font-size:x-small; } +#settingsPanel .small { font-size:small; } +#settingsPanel .medium { font-size:medium; } +#settingsPanel .large { font-size:large; } +#settingsPanel .xlarge { font-size:x-large; } + +.highlight { background-color: yellow } + +.modal { + position: fixed; + top: 50%; + left: 50%; + width: 50%; + width: 630px; + + height: auto; + z-index: 2000; + visibility: hidden; + margin-left: -320px; + margin-top: -160px; + +} + +.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; +} + +.md-show { + visibility: visible; +} + +.md-show ~ .overlay { + opacity: 1; + visibility: visible; +} + +/* Content styles */ +.md-content { + color: #fff; + background: #6b6b6b; + position: relative; + border-radius: 3px; + margin: 0 auto; + height: 320px; +} + +.md-content h3 { + margin: 0; + padding: 6px; + text-align: center; + font-size: 22px; + font-weight: 300; + opacity: 0.8; + background: rgba(0,0,0,0.1); + border-radius: 3px 3px 0 0; +} + +.md-content > div { + padding: 15px 40px 30px; + margin: 0; + font-weight: 300; + font-size: 14px; +} + +.md-content > div p { + margin: 0; + padding: 10px 0; +} + +.md-content > div ul { + margin: 0; + padding: 0 0 30px 20px; +} + +.md-content > div ul li { + padding: 5px 0; +} + +.md-content button { + display: block; + margin: 0 auto; + font-size: 0.8em; +} + +/* Effect 1: Fade in and scale up */ +.md-effect-1 .md-content { + -webkit-transform: scale(0.7); + -moz-transform: scale(0.7); + -ms-transform: scale(0.7); + transform: scale(0.7); + opacity: 0; + -webkit-transition: all 0.3s; + -moz-transition: all 0.3s; + transition: all 0.3s; +} + +.md-show.md-effect-1 .md-content { + -webkit-transform: scale(1); + -moz-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + opacity: 1; +} + +.md-content > .closer { + font-size: 18px; + position: absolute; + right: 0; + top: 0; + font-size: 24px; + padding: 4px; +} + +@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%; + } + + #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:; + } +} + +[class^="icon-"]:before, [class*=" icon-"]:before { + font-family: "fontello"; + font-style: normal; + font-weight: normal; + speak: none; + + display: inline-block; + text-decoration: inherit; + width: 1em; + margin-right: .2em; + text-align: center; + /* opacity: .8; */ + + /* For safety - reset parent styles, that can break glyph codes*/ + font-variant: normal; + text-transform: none; + + /* you can be more comfortable with increased icons size */ + font-size: 112%; +} + + +.icon-search:before { content: '\e807'; } /* '' */ +.icon-resize-full-1:before { content: '\e804'; } /* '' */ +.icon-cancel-circled2:before { content: '\e80f'; } /* '' */ +.icon-link:before { content: '\e80d'; } /* '' */ +.icon-bookmark:before { content: '\e805'; } /* '' */ +.icon-bookmark-empty:before { content: '\e806'; } /* '' */ +.icon-download-cloud:before { content: '\e811'; } /* '' */ +.icon-edit:before { content: '\e814'; } /* '' */ +.icon-menu:before { content: '\e802'; } /* '' */ +.icon-cog:before { content: '\e813'; } /* '' */ +.icon-resize-full:before { content: '\e812'; } /* '' */ +.icon-cancel-circled:before { content: '\e80e'; } /* '' */ +.icon-up-dir:before { content: '\e80c'; } /* '' */ +.icon-right-dir:before { content: '\e80b'; } /* '' */ +.icon-angle-right:before { content: '\e809'; } /* '' */ +.icon-angle-down:before { content: '\e80a'; } /* '' */ +.icon-right:before { content: '\e815'; } /* '' */ +.icon-list-1:before { content: '\e803'; } /* '' */ +.icon-list-numbered:before { content: '\e801'; } /* '' */ +.icon-columns:before { content: '\e810'; } /* '' */ +.icon-list:before { content: '\e800'; } /* '' */ +.icon-resize-small:before { content: '\e808'; } /* '' */ diff --git a/reader/css/normalize.css b/reader/css/normalize.css new file mode 100644 index 0000000..c3e014d --- /dev/null +++ b/reader/css/normalize.css @@ -0,0 +1,505 @@ +/*! normalize.css v1.0.1 | MIT License | git.io/normalize */ + +/* ========================================================================== + HTML5 display definitions + ========================================================================== */ + +/* + * Corrects `block` display not defined in IE 6/7/8/9 and Firefox 3. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section, +summary { + display: block; +} + +/* + * Corrects `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + */ + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +/* + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/* + * Addresses styling for `hidden` attribute not present in IE 7/8/9, Firefox 3, + * and Safari 4. + * Known issue: no IE 6 support. + */ + +[hidden] { + display: none; +} + +/* ========================================================================== + Base + ========================================================================== */ + +/* + * 1. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + * 2. Prevents iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-size: 100%; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ + -ms-text-size-adjust: 100%; /* 2 */ +} + +/* + * Addresses `font-family` inconsistency between `textarea` and other form + * elements. + */ + +html, +button, +input, +select, +textarea { + font-family: sans-serif; +} + +/* + * Addresses margins handled incorrectly in IE 6/7. + */ + +body { + margin: 0; +} + +/* ========================================================================== + Links + ========================================================================== */ + +/* + * Addresses `outline` inconsistency between Chrome and other browsers. + */ + +a:focus { + outline: thin dotted; +} + +/* + * Improves readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* ========================================================================== + Typography + ========================================================================== */ + +/* + * Addresses font sizes and margins set differently in IE 6/7. + * Addresses font sizes within `section` and `article` in Firefox 4+, Safari 5, + * and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +h2 { + font-size: 1.5em; + margin: 0.83em 0; +} + +h3 { + font-size: 1.17em; + margin: 1em 0; +} + +h4 { + font-size: 1em; + margin: 1.33em 0; +} + +h5 { + font-size: 0.83em; + margin: 1.67em 0; +} + +h6 { + font-size: 0.75em; + margin: 2.33em 0; +} + +/* + * Addresses styling not present in IE 7/8/9, Safari 5, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/* + * Addresses style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +blockquote { + margin: 1em 40px; +} + +/* + * Addresses styling not present in Safari 5 and Chrome. + */ + +dfn { + font-style: italic; +} + +/* + * Addresses styling not present in IE 6/7/8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +/* + * Addresses margins set differently in IE 6/7. + */ + +p, +pre { + margin: 1em 0; +} + +/* + * Corrects font family set oddly in IE 6, Safari 4/5, and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + _font-family: 'courier new', monospace; + font-size: 1em; +} + +/* + * Improves readability of pre-formatted text in all browsers. + */ + +pre { + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} + +/* + * Addresses CSS quotes not supported in IE 6/7. + */ + +q { + quotes: none; +} + +/* + * Addresses `quotes` property not supported in Safari 4. + */ + +q:before, +q:after { + content: ''; + content: none; +} + +/* + * Addresses inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/* + * Prevents `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* ========================================================================== + Lists + ========================================================================== */ + +/* + * Addresses margins set differently in IE 6/7. + */ + +dl, +menu, +ol, +ul { + margin: 1em 0; +} + +dd { + margin: 0 0 0 40px; +} + +/* + * Addresses paddings set differently in IE 6/7. + */ + +menu, +ol, +ul { + padding: 0 0 0 40px; +} + +/* + * Corrects list images handled incorrectly in IE 7. + */ + +nav ul, +nav ol { + list-style: none; + list-style-image: none; +} + +/* ========================================================================== + Embedded content + ========================================================================== */ + +/* + * 1. Removes border when inside `a` element in IE 6/7/8/9 and Firefox 3. + * 2. Improves image quality when scaled in IE 7. + */ + +img { + border: 0; /* 1 */ + -ms-interpolation-mode: bicubic; /* 2 */ +} + +/* + * Corrects overflow displayed oddly in IE 9. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* ========================================================================== + Figures + ========================================================================== */ + +/* + * Addresses margin not present in IE 6/7/8/9, Safari 5, and Opera 11. + */ + +figure { + margin: 0; +} + +/* ========================================================================== + Forms + ========================================================================== */ + +/* + * Corrects margin displayed oddly in IE 6/7. + */ + +form { + margin: 0; +} + +/* + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/* + * 1. Corrects color not being inherited in IE 6/7/8/9. + * 2. Corrects text not wrapping in Firefox 3. + * 3. Corrects alignment displayed oddly in IE 6/7. + */ + +legend { + border: 0; /* 1 */ + padding: 0; + white-space: normal; /* 2 */ + *margin-left: -7px; /* 3 */ +} + +/* + * 1. Corrects font size not being inherited in all browsers. + * 2. Addresses margins set differently in IE 6/7, Firefox 3+, Safari 5, + * and Chrome. + * 3. Improves appearance and consistency in all browsers. + */ + +button, +input, +select, +textarea { + font-size: 100%; /* 1 */ + margin: 0; /* 2 */ + vertical-align: baseline; /* 3 */ + *vertical-align: middle; /* 3 */ +} + +/* + * Addresses Firefox 3+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +button, +input { + line-height: normal; +} + +/* + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Corrects inability to style clickable `input` types in iOS. + * 3. Improves usability and consistency of cursor style between image-type + * `input` and others. + * 4. Removes inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + *overflow: visible; /* 4 */ +} + +/* + * Re-set default cursor for disabled elements. + */ + +button[disabled], +input[disabled] { + cursor: default; +} + +/* + * 1. Addresses box sizing set to content-box in IE 8/9. + * 2. Removes excess padding in IE 8/9. + * 3. Removes excess padding in IE 7. + * Known issue: excess padding remains in IE 6. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + *height: 13px; /* 3 */ + *width: 13px; /* 3 */ +} + +/* + * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome. + * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome + * (include `-moz` to future-proof). + */ +/* +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} +*/ + +/* + * Removes inner padding and search cancel button in Safari 5 and Chrome + * on OS X. + */ + +/* input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} */ + +/* + * Removes inner padding and border in Firefox 3+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* + * 1. Removes default vertical scrollbar in IE 6/7/8/9. + * 2. Improves readability and alignment in all browsers. + */ + +textarea { + overflow: auto; /* 1 */ + vertical-align: top; /* 2 */ +} + +/* ========================================================================== + Tables + ========================================================================== */ + +/* + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/reader/css/popup.css b/reader/css/popup.css new file mode 100644 index 0000000..c41aac7 --- /dev/null +++ b/reader/css/popup.css @@ -0,0 +1,96 @@ +/* http://davidwalsh.name/css-tooltips */ +/* base CSS element */ +.popup { + background: #eee; + border: 1px solid #ccc; + padding: 10px; + border-radius: 8px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + position: fixed; + max-width: 300px; + font-size: 12px; + + display: none; + margin-left: 2px; + + margin-top: 30px; +} + +.popup.above { + margin-top: -10px; +} + +.popup.left { + margin-left: -20px; +} + +.popup.right { + margin-left: 40px; +} + +.pop_content { + max-height: 225px; + overflow-y: auto; +} + +.pop_content > p { + margin-top: 0; +} + +/* below */ +.popup:before { + position: absolute; + display: inline-block; + border-bottom: 10px solid #eee; + border-right: 10px solid transparent; + border-left: 10px solid transparent; + border-bottom-color: rgba(0, 0, 0, 0.2); + left: 50%; + top: -10px; + margin-left: -6px; + content: ''; +} + +.popup:after { + position: absolute; + display: inline-block; + border-bottom: 9px solid #eee; + border-right: 9px solid transparent; + border-left: 9px solid transparent; + left: 50%; + top: -9px; + margin-left: -5px; + content: ''; +} + +/* above */ +.popup.above:before { + border-bottom: none; + border-top: 10px solid #eee; + border-top-color: rgba(0, 0, 0, 0.2); + top: 100%; +} + +.popup.above:after { + border-bottom: none; + border-top: 9px solid #eee; + top: 100%; +} + +.popup.left:before, +.popup.left:after +{ + left: 20px; +} + +.popup.right:before, +.popup.right:after +{ + left: auto; + right: 20px; +} + + +.popup.show, .popup.on { + display: block; +} \ No newline at end of file diff --git a/reader/css/tooltip.css b/reader/css/tooltip.css new file mode 100644 index 0000000..cd538ab --- /dev/null +++ b/reader/css/tooltip.css @@ -0,0 +1,31 @@ +.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; +} diff --git a/reader/img/app.svg b/reader/img/app.svg new file mode 100644 index 0000000..b8b4fb8 --- /dev/null +++ b/reader/img/app.svg @@ -0,0 +1,76 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/reader/img/book.png b/reader/img/book.png new file mode 100644 index 0000000..a7b8079 Binary files /dev/null and b/reader/img/book.png differ diff --git a/reader/img/loading.gif b/reader/img/loading.gif new file mode 100644 index 0000000..f8f3dff Binary files /dev/null and b/reader/img/loading.gif differ diff --git a/reader/js/lib/Blob.js b/reader/js/lib/Blob.js new file mode 100644 index 0000000..3b44c65 --- /dev/null +++ b/reader/js/lib/Blob.js @@ -0,0 +1,197 @@ +/* Blob.js + * A Blob implementation. + * 2014-07-24 + * + * By Eli Grey, http://eligrey.com + * By Devin Samarin, https://github.com/dsamarin + * License: X11/MIT + * See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md + */ + +/*global self, unescape */ +/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, + plusplus: true */ + +/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */ + +(function (view) { + "use strict"; + + view.URL = view.URL || view.webkitURL; + + if (view.Blob && view.URL) { + try { + new Blob; + return; + } catch (e) {} + } + + // Internally we use a BlobBuilder implementation to base Blob off of + // in order to support older browsers that only have BlobBuilder + var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) { + var + get_class = function(object) { + return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; + } + , FakeBlobBuilder = function BlobBuilder() { + this.data = []; + } + , FakeBlob = function Blob(data, type, encoding) { + this.data = data; + this.size = data.length; + this.type = type; + this.encoding = encoding; + } + , FBB_proto = FakeBlobBuilder.prototype + , FB_proto = FakeBlob.prototype + , FileReaderSync = view.FileReaderSync + , FileException = function(type) { + this.code = this[this.name = type]; + } + , file_ex_codes = ( + "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " + + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" + ).split(" ") + , file_ex_code = file_ex_codes.length + , real_URL = view.URL || view.webkitURL || view + , real_create_object_URL = real_URL.createObjectURL + , real_revoke_object_URL = real_URL.revokeObjectURL + , URL = real_URL + , btoa = view.btoa + , atob = view.atob + + , ArrayBuffer = view.ArrayBuffer + , Uint8Array = view.Uint8Array + + , origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/ + ; + FakeBlob.fake = FB_proto.fake = true; + while (file_ex_code--) { + FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; + } + // Polyfill URL + if (!real_URL.createObjectURL) { + URL = view.URL = function(uri) { + var + uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a") + , uri_origin + ; + uri_info.href = uri; + if (!("origin" in uri_info)) { + if (uri_info.protocol.toLowerCase() === "data:") { + uri_info.origin = null; + } else { + uri_origin = uri.match(origin); + uri_info.origin = uri_origin && uri_origin[1]; + } + } + return uri_info; + }; + } + URL.createObjectURL = function(blob) { + var + type = blob.type + , data_URI_header + ; + if (type === null) { + type = "application/octet-stream"; + } + if (blob instanceof FakeBlob) { + data_URI_header = "data:" + type; + if (blob.encoding === "base64") { + return data_URI_header + ";base64," + blob.data; + } else if (blob.encoding === "URI") { + return data_URI_header + "," + decodeURIComponent(blob.data); + } if (btoa) { + return data_URI_header + ";base64," + btoa(blob.data); + } else { + return data_URI_header + "," + encodeURIComponent(blob.data); + } + } else if (real_create_object_URL) { + return real_create_object_URL.call(real_URL, blob); + } + }; + URL.revokeObjectURL = function(object_URL) { + if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) { + real_revoke_object_URL.call(real_URL, object_URL); + } + }; + FBB_proto.append = function(data/*, endings*/) { + var bb = this.data; + // decode data to a binary string + if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { + var + str = "" + , buf = new Uint8Array(data) + , i = 0 + , buf_len = buf.length + ; + for (; i < buf_len; i++) { + str += String.fromCharCode(buf[i]); + } + bb.push(str); + } else if (get_class(data) === "Blob" || get_class(data) === "File") { + if (FileReaderSync) { + var fr = new FileReaderSync; + bb.push(fr.readAsBinaryString(data)); + } else { + // async FileReader won't work as BlobBuilder is sync + throw new FileException("NOT_READABLE_ERR"); + } + } else if (data instanceof FakeBlob) { + if (data.encoding === "base64" && atob) { + bb.push(atob(data.data)); + } else if (data.encoding === "URI") { + bb.push(decodeURIComponent(data.data)); + } else if (data.encoding === "raw") { + bb.push(data.data); + } + } else { + if (typeof data !== "string") { + data += ""; // convert unsupported types to strings + } + // decode UTF-16 to binary string + bb.push(unescape(encodeURIComponent(data))); + } + }; + FBB_proto.getBlob = function(type) { + if (!arguments.length) { + type = null; + } + return new FakeBlob(this.data.join(""), type, "raw"); + }; + FBB_proto.toString = function() { + return "[object BlobBuilder]"; + }; + FB_proto.slice = function(start, end, type) { + var args = arguments.length; + if (args < 3) { + type = null; + } + return new FakeBlob( + this.data.slice(start, args > 1 ? end : this.data.length) + , type + , this.encoding + ); + }; + FB_proto.toString = function() { + return "[object Blob]"; + }; + FB_proto.close = function() { + this.size = 0; + delete this.data; + }; + return FakeBlobBuilder; + }(view)); + + view.Blob = function(blobParts, options) { + var type = options ? (options.type || "") : ""; + var builder = new BlobBuilder(); + if (blobParts) { + for (var i = 0, len = blobParts.length; i < len; i++) { + builder.append(blobParts[i]); + } + } + return builder.getBlob(type); + }; +}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this)); diff --git a/reader/js/lib/blob.js b/reader/js/lib/blob.js new file mode 100644 index 0000000..b20ed0b --- /dev/null +++ b/reader/js/lib/blob.js @@ -0,0 +1,31 @@ +Blob = (function() { + var nativeBlob = Blob; + + // Add unprefixed slice() method. + if (Blob.prototype.webkitSlice) { + Blob.prototype.slice = Blob.prototype.webkitSlice; + } + else if (Blob.prototype.mozSlice) { + Blob.prototype.slice = Blob.prototype.mozSlice; + } + + // Temporarily replace Blob() constructor with one that checks support. + return function(parts, properties) { + try { + // Restore native Blob() constructor, so this check is only evaluated once. + Blob = nativeBlob; + return new Blob(parts || [], properties || {}); + } + catch (e) { + // If construction fails provide one that uses BlobBuilder. + Blob = function (parts, properties) { + var bb = new (WebKitBlobBuilder || MozBlobBuilder), i; + for (i in parts) { + bb.append(parts[i]); + } + + return bb.getBlob(properties && properties.type ? properties.type : undefined); + }; + } + }; +}()); diff --git a/reader/js/lib/typedarray.js b/reader/js/lib/typedarray.js new file mode 100644 index 0000000..9c02368 --- /dev/null +++ b/reader/js/lib/typedarray.js @@ -0,0 +1,629 @@ +/* +$LicenseInfo:firstyear=2010&license=mit$ + +Copyright (c) 2010, Linden Research, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +$/LicenseInfo$ +*/ +/*global document*/ + +// +// ES3/ES5 implementation of the Krhonos TypedArray Working Draft (work in progress): +// Ref: https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/doc/spec/TypedArray-spec.html +// Date: 2011-02-01 +// +// Variations: +// * Float/Double -> Float32/Float64, per WebGL-Public mailing list conversations (post 5/17) +// * Allows typed_array.get/set() as alias for subscripts (typed_array[]) + +var ArrayBuffer, ArrayBufferView, + Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array, + DataView; + +(function () { + "use strict"; + /*jslint bitwise: false, nomen: false */ + + // Approximations of internal ECMAScript conversion functions + var ECMAScript = { + ToInt32: function (v) { return v >> 0; }, + ToUint32: function (v) { return v >>> 0; } + }; + + // Raise an INDEX_SIZE_ERR event - intentionally induces a DOM error + function raise_INDEX_SIZE_ERR() { + if (document) { + // raises DOMException(INDEX_SIZE_ERR) + document.createTextNode("").splitText(1); + } + throw new RangeError("INDEX_SIZE_ERR"); + } + + // ES5: lock down object properties + function configureProperties(obj) { + if (Object.getOwnPropertyNames && Object.defineProperty) { + var props = Object.getOwnPropertyNames(obj), i; + for (i = 0; i < props.length; i += 1) { + Object.defineProperty(obj, props[i], { + value: obj[props[i]], + writable: false, + enumerable: false, + configurable: false + }); + } + } + } + + // emulate ES5 getter/setter API using legacy APIs + // http://blogs.msdn.com/b/ie/archive/2010/09/07/transitioning-existing-code-to-the-es5-getter-setter-apis.aspx + if (Object.prototype.__defineGetter__ && !Object.defineProperty) { + Object.defineProperty = function (obj, prop, desc) { + if (desc.hasOwnProperty('get')) { obj.__defineGetter__(prop, desc.get); } + if (desc.hasOwnProperty('set')) { obj.__defineSetter__(prop, desc.set); } + }; + } + + // ES5: Make obj[index] an alias for obj._getter(index)/obj._setter(index, value) + // for index in 0 ... obj.length + function makeArrayAccessors(obj) { + if (!Object.defineProperty) { return; } + + function makeArrayAccessor(index) { + Object.defineProperty(obj, index, { + 'get': function () { return obj._getter(index); }, + 'set': function (v) { obj._setter(index, v); }, + enumerable: true, + configurable: false + }); + } + + var i; + for (i = 0; i < obj.length; i += 1) { + makeArrayAccessor(i); + } + } + + // Internal conversion functions: + // pack() - take a number (interpreted as Type), output a byte array + // unpack() - take a byte array, output a Type-like number + + function as_signed(value, bits) { var s = 32 - bits; return (value << s) >> s; } + function as_unsigned(value, bits) { var s = 32 - bits; return (value << s) >>> s; } + + function packInt8(n) { return [n & 0xff]; } + function unpackInt8(bytes) { return as_signed(bytes[0], 8); } + + function packUint8(n) { return [n & 0xff]; } + function unpackUint8(bytes) { return as_unsigned(bytes[0], 8); } + + function packInt16(n) { return [(n >> 8) & 0xff, n & 0xff]; } + function unpackInt16(bytes) { return as_signed(bytes[0] << 8 | bytes[1], 16); } + + function packUint16(n) { return [(n >> 8) & 0xff, n & 0xff]; } + function unpackUint16(bytes) { return as_unsigned(bytes[0] << 8 | bytes[1], 16); } + + function packInt32(n) { return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; } + function unpackInt32(bytes) { return as_signed(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32); } + + function packUint32(n) { return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; } + function unpackUint32(bytes) { return as_unsigned(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32); } + + function packIEEE754(v, ebits, fbits) { + + var bias = (1 << (ebits - 1)) - 1, + s, e, f, ln, + i, bits, str, bytes; + + // Compute sign, exponent, fraction + if (isNaN(v)) { + // http://dev.w3.org/2006/webapi/WebIDL/#es-type-mapping + e = (1 << bias) - 1; f = Math.pow(2, fbits - 1); s = 0; + } + else if (v === Infinity || v === -Infinity) { + e = (1 << bias) - 1; f = 0; s = (v < 0) ? 1 : 0; + } + else if (v === 0) { + e = 0; f = 0; s = (1 / v === -Infinity) ? 1 : 0; + } + else { + s = v < 0; + v = Math.abs(v); + + if (v >= Math.pow(2, 1 - bias)) { + // Normalized + ln = Math.min(Math.floor(Math.log(v) / Math.LN2), bias); + e = ln + bias; + f = Math.round(v * Math.pow(2, fbits - ln) - Math.pow(2, fbits)); + } + else { + // Denormalized + e = 0; + f = Math.round(v / Math.pow(2, 1 - bias - fbits)); + } + } + + // Pack sign, exponent, fraction + bits = []; + for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = Math.floor(f / 2); } + for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = Math.floor(e / 2); } + bits.push(s ? 1 : 0); + bits.reverse(); + str = bits.join(''); + + // Bits to bytes + bytes = []; + while (str.length) { + bytes.push(parseInt(str.substring(0, 8), 2)); + str = str.substring(8); + } + return bytes; + } + + function unpackIEEE754(bytes, ebits, fbits) { + + // Bytes to bits + var bits = [], i, j, b, str, + bias, s, e, f; + + for (i = bytes.length; i; i -= 1) { + b = bytes[i - 1]; + for (j = 8; j; j -= 1) { + bits.push(b % 2 ? 1 : 0); b = b >> 1; + } + } + bits.reverse(); + str = bits.join(''); + + // Unpack sign, exponent, fraction + bias = (1 << (ebits - 1)) - 1; + s = parseInt(str.substring(0, 1), 2) ? -1 : 1; + e = parseInt(str.substring(1, 1 + ebits), 2); + f = parseInt(str.substring(1 + ebits), 2); + + // Produce number + if (e === (1 << ebits) - 1) { + return f !== 0 ? NaN : s * Infinity; + } + else if (e > 0) { + // Normalized + return s * Math.pow(2, e - bias) * (1 + f / Math.pow(2, fbits)); + } + else if (f !== 0) { + // Denormalized + return s * Math.pow(2, -(bias - 1)) * (f / Math.pow(2, fbits)); + } + else { + return s < 0 ? -0 : 0; + } + } + + function unpackFloat64(b) { return unpackIEEE754(b, 11, 52); } + function packFloat64(v) { return packIEEE754(v, 11, 52); } + function unpackFloat32(b) { return unpackIEEE754(b, 8, 23); } + function packFloat32(v) { return packIEEE754(v, 8, 23); } + + + if (!ArrayBuffer) { + (function () { + + // + // 3 The ArrayBuffer Type + // + + ArrayBuffer = function (length) { + length = ECMAScript.ToInt32(length); + if (length < 0) { throw new RangeError('ArrayBuffer size is not a small enough positive integer.'); } + + this.byteLength = length; + this._bytes = []; + this._bytes.length = length; + + var i; + for (i = 0; i < this.byteLength; i += 1) { + this._bytes[i] = 0; + } + + configureProperties(this); + }; + + + // + // 4 The ArrayBufferView Type + // + + // NOTE: this constructor is not exported + ArrayBufferView = function () { + //this.buffer = null; + //this.byteOffset = 0; + //this.byteLength = 0; + }; + + // + // 5 The Typed Array View Types + // + + function makeTypedArrayConstructor(bytesPerElement, pack, unpack) { + // Each TypedArray type requires a distinct constructor instance with + // identical logic, which this produces. + + var ctor; + ctor = function (buffer, byteOffset, length) { + var array, sequence, i, s; + + // Constructor(unsigned long length) + if (!arguments.length || typeof arguments[0] === 'number') { + this.length = ECMAScript.ToInt32(arguments[0]); + if (length < 0) { throw new RangeError('ArrayBufferView size is not a small enough positive integer.'); } + + this.byteLength = this.length * this.BYTES_PER_ELEMENT; + this.buffer = new ArrayBuffer(this.byteLength); + this.byteOffset = 0; + } + + // Constructor(TypedArray array) + else if (typeof arguments[0] === 'object' && arguments[0].constructor === ctor) { + array = arguments[0]; + + this.length = array.length; + this.byteLength = this.length * this.BYTES_PER_ELEMENT; + this.buffer = new ArrayBuffer(this.byteLength); + this.byteOffset = 0; + + for (i = 0; i < this.length; i += 1) { + this._setter(i, array._getter(i)); + } + } + + // Constructor(sequence array) + else if (typeof arguments[0] === 'object' && !(arguments[0] instanceof ArrayBuffer)) { + sequence = arguments[0]; + + this.length = ECMAScript.ToUint32(sequence.length); + this.byteLength = this.length * this.BYTES_PER_ELEMENT; + this.buffer = new ArrayBuffer(this.byteLength); + this.byteOffset = 0; + + for (i = 0; i < this.length; i += 1) { + s = sequence[i]; + this._setter(i, Number(s)); + } + } + + // Constructor(ArrayBuffer buffer, + // optional unsigned long byteOffset, optional unsigned long length) + else if (typeof arguments[0] === 'object' && arguments[0] instanceof ArrayBuffer) { + this.buffer = buffer; + + this.byteOffset = ECMAScript.ToUint32(byteOffset); + if (this.byteOffset > this.buffer.byteLength) { + raise_INDEX_SIZE_ERR(); // byteOffset out of range + } + + if (this.byteOffset % this.BYTES_PER_ELEMENT) { + // The given byteOffset must be a multiple of the element + // size of the specific type, otherwise an exception is raised. + //raise_INDEX_SIZE_ERR(); + throw new RangeError("ArrayBuffer length minus the byteOffset is not a multiple of the element size."); + } + + if (arguments.length < 3) { + this.byteLength = this.buffer.byteLength - this.byteOffset; + + if (this.byteLength % this.BYTES_PER_ELEMENT) { + raise_INDEX_SIZE_ERR(); // length of buffer minus byteOffset not a multiple of the element size + } + this.length = this.byteLength / this.BYTES_PER_ELEMENT; + } + else { + this.length = ECMAScript.ToUint32(length); + this.byteLength = this.length * this.BYTES_PER_ELEMENT; + } + + if ((this.byteOffset + this.byteLength) > this.buffer.byteLength) { + raise_INDEX_SIZE_ERR(); // byteOffset and length reference an area beyond the end of the buffer + } + } + else { + throw new TypeError("Unexpected argument type(s)"); + } + + this.constructor = ctor; + + // ES5-only magic + configureProperties(this); + makeArrayAccessors(this); + }; + + ctor.prototype = new ArrayBufferView(); + ctor.prototype.BYTES_PER_ELEMENT = bytesPerElement; + ctor.prototype._pack = pack; + ctor.prototype._unpack = unpack; + ctor.BYTES_PER_ELEMENT = bytesPerElement; + + // getter type (unsigned long index); + ctor.prototype._getter = function (index) { + if (arguments.length < 1) { throw new SyntaxError("Not enough arguments"); } + + index = ECMAScript.ToUint32(index); + if (index >= this.length) { + //raise_INDEX_SIZE_ERR(); // Array index out of range + return; // undefined + } + + var bytes = [], i, o; + for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT; + i < this.BYTES_PER_ELEMENT; + i += 1, o += 1) { + bytes.push(this.buffer._bytes[o]); + } + return this._unpack(bytes); + }; + + // NONSTANDARD: convenience alias for getter: type get(unsigned long index); + ctor.prototype.get = ctor.prototype._getter; + + // setter void (unsigned long index, type value); + ctor.prototype._setter = function (index, value) { + if (arguments.length < 2) { throw new SyntaxError("Not enough arguments"); } + + index = ECMAScript.ToUint32(index); + if (index >= this.length) { + //raise_INDEX_SIZE_ERR(); // Array index out of range + return; + } + + var bytes = this._pack(value), i, o; + for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT; + i < this.BYTES_PER_ELEMENT; + i += 1, o += 1) { + this.buffer._bytes[o] = bytes[i]; + } + }; + + // void set(TypedArray array, optional unsigned long offset); + // void set(sequence array, optional unsigned long offset); + ctor.prototype.set = function (index, value) { + if (arguments.length < 1) { throw new SyntaxError("Not enough arguments"); } + var array, sequence, offset, len, + i, s, d, + byteOffset, byteLength, tmp; + + // void set(TypedArray array, optional unsigned long offset); + if (typeof arguments[0] === 'object' && arguments[0].constructor === this.constructor) { + array = arguments[0]; + offset = ECMAScript.ToUint32(arguments[1]); + + if (offset + array.length > this.length) { + raise_INDEX_SIZE_ERR(); // Offset plus length of array is out of range + } + + byteOffset = this.byteOffset + offset * this.BYTES_PER_ELEMENT; + byteLength = array.length * this.BYTES_PER_ELEMENT; + + if (array.buffer === this.buffer) { + tmp = []; + for (i = 0, s = array.byteOffset; i < byteLength; i += 1, s += 1) { + tmp[i] = array.buffer._bytes[s]; + } + for (i = 0, d = byteOffset; i < byteLength; i += 1, d += 1) { + this.buffer._bytes[d] = tmp[i]; + } + } + else { + for (i = 0, s = array.byteOffset, d = byteOffset; + i < byteLength; i += 1, s += 1, d += 1) { + this.buffer._bytes[d] = array.buffer._bytes[s]; + } + } + } + + // void set(sequence array, optional unsigned long offset); + else if (typeof arguments[0] === 'object' && typeof arguments[0].length !== 'undefined') { + sequence = arguments[0]; + len = ECMAScript.ToUint32(sequence.length); + offset = ECMAScript.ToUint32(arguments[1]); + + if (offset + len > this.length) { + raise_INDEX_SIZE_ERR(); // Offset plus length of array is out of range + } + + for (i = 0; i < len; i += 1) { + s = sequence[i]; + this._setter(offset + i, Number(s)); + } + } + + else { + throw new TypeError("Unexpected argument type(s)"); + } + }; + + // TypedArray subarray(long begin, optional long end); + ctor.prototype.subarray = function (start, end) { + function clamp(v, min, max) { return v < min ? min : v > max ? max : v; } + + start = ECMAScript.ToInt32(start); + end = ECMAScript.ToInt32(end); + + if (arguments.length < 1) { start = 0; } + if (arguments.length < 2) { end = this.length; } + + if (start < 0) { start = this.length + start; } + if (end < 0) { end = this.length + end; } + + start = clamp(start, 0, this.length); + end = clamp(end, 0, this.length); + + var len = end - start; + if (len < 0) { + len = 0; + } + + return new this.constructor(this.buffer, start * this.BYTES_PER_ELEMENT, len); + }; + + return ctor; + } + + Int8Array = Int8Array || makeTypedArrayConstructor(1, packInt8, unpackInt8); + Uint8Array = Uint8Array || makeTypedArrayConstructor(1, packUint8, unpackUint8); + Int16Array = Int16Array || makeTypedArrayConstructor(2, packInt16, unpackInt16); + Uint16Array = Uint16Array || makeTypedArrayConstructor(2, packUint16, unpackUint16); + Int32Array = Int32Array || makeTypedArrayConstructor(4, packInt32, unpackInt32); + Uint32Array = Uint32Array || makeTypedArrayConstructor(4, packUint32, unpackUint32); + Float32Array = Float32Array || makeTypedArrayConstructor(4, packFloat32, unpackFloat32); + Float64Array = Float64Array || makeTypedArrayConstructor(8, packFloat64, unpackFloat64); + + } ()); + } + + + if (!DataView) { + (function () { + + // + // 6 The DataView View Type + // + + function r(array, index) { + if (typeof array.get === 'function') { + return array.get(index); + } + else { + return array[index]; + } + } + + + var IS_BIG_ENDIAN = (function () { + var u16array = new Uint16Array([0x1234]), + u8array = new Uint8Array(u16array.buffer); + return r(u8array, 0) === 0x12; + } ()); + + // Constructor(ArrayBuffer buffer, + // optional unsigned long byteOffset, + // optional unsigned long byteLength) + DataView = function (buffer, byteOffset, byteLength) { + if (!(typeof buffer === 'object' && buffer instanceof ArrayBuffer)) { + throw new TypeError("TypeError"); + } + + this.buffer = buffer; + + this.byteOffset = ECMAScript.ToUint32(byteOffset); + if (this.byteOffset > this.buffer.byteLength) { + raise_INDEX_SIZE_ERR(); // byteOffset out of range + } + + if (arguments.length < 3) { + this.byteLength = this.buffer.byteLength - this.byteOffset; + } + else { + this.byteLength = ECMAScript.ToUint32(byteLength); + } + + if ((this.byteOffset + this.byteLength) > this.buffer.byteLength) { + raise_INDEX_SIZE_ERR(); // byteOffset and length reference an area beyond the end of the buffer + } + + // ES5-only magic + configureProperties(this); + }; + + if (ArrayBufferView) { + DataView.prototype = new ArrayBufferView(); + } + + function makeDataView_getter(arrayType) { + return function (byteOffset, littleEndian) { + /*jslint newcap: false*/ + byteOffset = ECMAScript.ToUint32(byteOffset); + + if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength) { + raise_INDEX_SIZE_ERR(); // Array index out of range + } + byteOffset += this.byteOffset; + + var uint8Array = new Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT), + bytes = [], i; + for (i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1) { + bytes.push(r(uint8Array, i)); + } + + if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN)) { + bytes.reverse(); + } + + return r(new arrayType(new Uint8Array(bytes).buffer), 0); + }; + } + + DataView.prototype.getUint8 = makeDataView_getter(Uint8Array); + DataView.prototype.getInt8 = makeDataView_getter(Int8Array); + DataView.prototype.getUint16 = makeDataView_getter(Uint16Array); + DataView.prototype.getInt16 = makeDataView_getter(Int16Array); + DataView.prototype.getUint32 = makeDataView_getter(Uint32Array); + DataView.prototype.getInt32 = makeDataView_getter(Int32Array); + DataView.prototype.getFloat32 = makeDataView_getter(Float32Array); + DataView.prototype.getFloat64 = makeDataView_getter(Float64Array); + + function makeDataView_setter(arrayType) { + return function (byteOffset, value, littleEndian) { + /*jslint newcap: false*/ + byteOffset = ECMAScript.ToUint32(byteOffset); + if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength) { + raise_INDEX_SIZE_ERR(); // Array index out of range + } + + // Get bytes + var typeArray = new arrayType([value]), + byteArray = new Uint8Array(typeArray.buffer), + bytes = [], i, byteView; + + for (i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1) { + bytes.push(r(byteArray, i)); + } + + // Flip if necessary + if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN)) { + bytes.reverse(); + } + + // Write them + byteView = new Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT); + byteView.set(bytes); + }; + } + + DataView.prototype.setUint8 = makeDataView_setter(Uint8Array); + DataView.prototype.setInt8 = makeDataView_setter(Int8Array); + DataView.prototype.setUint16 = makeDataView_setter(Uint16Array); + DataView.prototype.setInt16 = makeDataView_setter(Int16Array); + DataView.prototype.setUint32 = makeDataView_setter(Uint32Array); + DataView.prototype.setInt32 = makeDataView_setter(Int32Array); + DataView.prototype.setFloat32 = makeDataView_setter(Float32Array); + DataView.prototype.setFloat64 = makeDataView_setter(Float64Array); + + } ()); + } + +} ()); + diff --git a/reader/js/lib/typedarray.min.js b/reader/js/lib/typedarray.min.js new file mode 100644 index 0000000..d47ad9e --- /dev/null +++ b/reader/js/lib/typedarray.min.js @@ -0,0 +1 @@ +var ArrayBuffer,ArrayBufferView,Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array,DataView;(function(){"use strict";function t(){if(document){document.createTextNode("").splitText(1)}throw new RangeError("INDEX_SIZE_ERR")}function n(e){if(Object.getOwnPropertyNames&&Object.defineProperty){var t=Object.getOwnPropertyNames(e),n;for(n=0;n>n}function s(e,t){var n=32-t;return e<>>n}function o(e){return[e&255]}function u(e){return i(e[0],8)}function a(e){return[e&255]}function f(e){return s(e[0],8)}function l(e){return[e>>8&255,e&255]}function c(e){return i(e[0]<<8|e[1],16)}function h(e){return[e>>8&255,e&255]}function p(e){return s(e[0]<<8|e[1],16)}function d(e){return[e>>24&255,e>>16&255,e>>8&255,e&255]}function v(e){return i(e[0]<<24|e[1]<<16|e[2]<<8|e[3],32)}function m(e){return[e>>24&255,e>>16&255,e>>8&255,e&255]}function g(e){return s(e[0]<<24|e[1]<<16|e[2]<<8|e[3],32)}function y(e,t,n){var r=(1<=Math.pow(2,1-r)){u=Math.min(Math.floor(Math.log(e)/Math.LN2),r);s=u+r;o=Math.round(e*Math.pow(2,n-u)-Math.pow(2,n))}else{s=0;o=Math.round(e/Math.pow(2,1-r-n))}}f=[];for(a=n;a;a-=1){f.push(o%2?1:0);o=Math.floor(o/2)}for(a=t;a;a-=1){f.push(s%2?1:0);s=Math.floor(s/2)}f.push(i?1:0);f.reverse();l=f.join("");c=[];while(l.length){c.push(parseInt(l.substring(0,8),2));l=l.substring(8)}return c}function b(e,t,n){var r=[],i,s,o,u,a,f,l,c;for(i=e.length;i;i-=1){o=e[i-1];for(s=8;s;s-=1){r.push(o%2?1:0);o=o>>1}}r.reverse();u=r.join("");a=(1<0){return f*Math.pow(2,l-a)*(1+c/Math.pow(2,n))}else if(c!==0){return f*Math.pow(2,-(a-1))*(c/Math.pow(2,n))}else{return f<0?-0:0}}function w(e){return b(e,11,52)}function E(e){return y(e,11,52)}function S(e){return b(e,8,23)}function x(e){return y(e,8,23)}var e={ToInt32:function(e){return e>>0},ToUint32:function(e){return e>>>0}};if(Object.prototype.__defineGetter__&&!Object.defineProperty){Object.defineProperty=function(e,t,n){if(n.hasOwnProperty("get")){e.__defineGetter__(t,n.get)}if(n.hasOwnProperty("set")){e.__defineSetter__(t,n.set)}}}if(!ArrayBuffer){(function(){function i(i,s,o){var u;u=function(i,s,o){var a,f,l,c;if(!arguments.length||typeof arguments[0]==="number"){this.length=e.ToInt32(arguments[0]);if(o<0){throw new RangeError("ArrayBufferView size is not a small enough positive integer.")}this.byteLength=this.length*this.BYTES_PER_ELEMENT;this.buffer=new ArrayBuffer(this.byteLength);this.byteOffset=0}else if(typeof arguments[0]==="object"&&arguments[0].constructor===u){a=arguments[0];this.length=a.length;this.byteLength=this.length*this.BYTES_PER_ELEMENT;this.buffer=new ArrayBuffer(this.byteLength);this.byteOffset=0;for(l=0;lthis.buffer.byteLength){t()}if(this.byteOffset%this.BYTES_PER_ELEMENT){throw new RangeError("ArrayBuffer length minus the byteOffset is not a multiple of the element size.")}if(arguments.length<3){this.byteLength=this.buffer.byteLength-this.byteOffset;if(this.byteLength%this.BYTES_PER_ELEMENT){t()}this.length=this.byteLength/this.BYTES_PER_ELEMENT}else{this.length=e.ToUint32(o);this.byteLength=this.length*this.BYTES_PER_ELEMENT}if(this.byteOffset+this.byteLength>this.buffer.byteLength){t()}}else{throw new TypeError("Unexpected argument type(s)")}this.constructor=u;n(this);r(this)};u.prototype=new ArrayBufferView;u.prototype.BYTES_PER_ELEMENT=i;u.prototype._pack=s;u.prototype._unpack=o;u.BYTES_PER_ELEMENT=i;u.prototype._getter=function(t){if(arguments.length<1){throw new SyntaxError("Not enough arguments")}t=e.ToUint32(t);if(t>=this.length){return}var n=[],r,i;for(r=0,i=this.byteOffset+t*this.BYTES_PER_ELEMENT;r=this.length){return}var r=this._pack(n),i,s;for(i=0,s=this.byteOffset+t*this.BYTES_PER_ELEMENT;ithis.length){t()}c=this.byteOffset+o*this.BYTES_PER_ELEMENT;h=i.length*this.BYTES_PER_ELEMENT;if(i.buffer===this.buffer){p=[];for(a=0,f=i.byteOffset;athis.length){t()}for(a=0;an?n:e}t=e.ToInt32(t);n=e.ToInt32(n);if(arguments.length<1){t=0}if(arguments.length<2){n=this.length}if(t<0){t=this.length+t}if(n<0){n=this.length+n}t=r(t,0,this.length);n=r(n,0,this.length);var i=n-t;if(i<0){i=0}return new this.constructor(this.buffer,t*this.BYTES_PER_ELEMENT,i)};return u}ArrayBuffer=function(t){t=e.ToInt32(t);if(t<0){throw new RangeError("ArrayBuffer size is not a small enough positive integer.")}this.byteLength=t;this._bytes=[];this._bytes.length=t;var r;for(r=0;rthis.byteLength){t()}s+=this.byteOffset;var u=new Uint8Array(this.buffer,s,n.BYTES_PER_ELEMENT),a=[],f;for(f=0;fthis.byteLength){t()}var a=new n([o]),f=new Uint8Array(a.buffer),l=[],c,h;for(c=0;cthis.buffer.byteLength){t()}if(arguments.length<3){this.byteLength=this.buffer.byteLength-this.byteOffset}else{this.byteLength=e.ToUint32(s)}if(this.byteOffset+this.byteLength>this.buffer.byteLength){t()}n(this)};if(ArrayBufferView){DataView.prototype=new ArrayBufferView}DataView.prototype.getUint8=s(Uint8Array);DataView.prototype.getInt8=s(Int8Array);DataView.prototype.getUint16=s(Uint16Array);DataView.prototype.getInt16=s(Int16Array);DataView.prototype.getUint32=s(Uint32Array);DataView.prototype.getInt32=s(Int32Array);DataView.prototype.getFloat32=s(Float32Array);DataView.prototype.getFloat64=s(Float64Array);DataView.prototype.setUint8=o(Uint8Array);DataView.prototype.setInt8=o(Int8Array);DataView.prototype.setUint16=o(Uint16Array);DataView.prototype.setInt16=o(Int16Array);DataView.prototype.setUint32=o(Uint32Array);DataView.prototype.setInt32=o(Int32Array);DataView.prototype.setFloat32=o(Float32Array);DataView.prototype.setFloat64=o(Float64Array)})()}})() diff --git a/reader/js/lib/wgxpath.install.js b/reader/js/lib/wgxpath.install.js new file mode 100644 index 0000000..f070e5f --- /dev/null +++ b/reader/js/lib/wgxpath.install.js @@ -0,0 +1,75 @@ +(function(){function h(a){return function(){return this[a]}}function l(a){return function(){return a}}var m=this; +function ba(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null"; +else if("function"==b&&"undefined"==typeof a.call)return"object";return b}function n(a){return"string"==typeof a}function ca(a,b,c){return a.call.apply(a.bind,arguments)}function da(a,b,c){if(!a)throw Error();if(2b?1:0};var v=Array.prototype,ia=v.indexOf?function(a,b,c){return v.indexOf.call(a,b,c)}:function(a,b,c){c=null==c?0:0>c?Math.max(0,a.length+c):c;if(n(a))return n(b)&&1==b.length?a.indexOf(b,c):-1;for(;cc?null:n(a)?a.charAt(c):a[c]}function ma(a){return v.concat.apply(v,arguments)}function na(a,b,c){return 2>=arguments.length?v.slice.call(a,b):v.slice.call(a,b,c)};var y;a:{var oa=m.navigator;if(oa){var pa=oa.userAgent;if(pa){y=pa;break a}}y=""};var qa=u(y,"Opera")||u(y,"OPR"),A=u(y,"Trident")||u(y,"MSIE"),ra=u(y,"Edge"),sa=u(y,"Gecko")&&!(u(y.toLowerCase(),"webkit")&&!u(y,"Edge"))&&!(u(y,"Trident")||u(y,"MSIE"))&&!u(y,"Edge"),ta=u(y.toLowerCase(),"webkit")&&!u(y,"Edge");function ua(){var a=y;if(sa)return/rv\:([^\);]+)(\)|;)/.exec(a);if(ra)return/Edge\/([\d\.]+)/.exec(a);if(A)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(ta)return/WebKit\/(\S+)/.exec(a)}function va(){var a=m.document;return a?a.documentMode:void 0} +var wa=function(){if(qa&&m.opera){var a=m.opera.version;return"function"==ba(a)?a():a}var a="",b=ua();b&&(a=b?b[1]:"");return A&&(b=va(),b>parseFloat(a))?String(b):a}(),xa={}; +function ya(a){if(!xa[a]){for(var b=0,c=ga(String(wa)).split("."),d=ga(String(a)).split("."),e=Math.max(c.length,d.length),f=0;0==b&&f]=|\\s+|.","g"),Ga=/^\s/;function D(a,b){return a.b[a.a+(b||0)]}function F(a){return a.b[a.a++]}function Ha(a){return a.b.length<=a.a};!sa&&!A||A&&9<=Aa||sa&&ya("1.9.1");A&&ya("9");function Ia(a,b){if(a.contains&&1==b.nodeType)return a==b||a.contains(b);if("undefined"!=typeof a.compareDocumentPosition)return a==b||Boolean(a.compareDocumentPosition(b)&16);for(;b&&a!=b;)b=b.parentNode;return b==a} +function Ja(a,b){if(a==b)return 0;if(a.compareDocumentPosition)return a.compareDocumentPosition(b)&2?1:-1;if(A&&!(9<=Aa)){if(9==a.nodeType)return-1;if(9==b.nodeType)return 1}if("sourceIndex"in a||a.parentNode&&"sourceIndex"in a.parentNode){var c=1==a.nodeType,d=1==b.nodeType;if(c&&d)return a.sourceIndex-b.sourceIndex;var e=a.parentNode,f=b.parentNode;return e==f?Ka(a,b):!c&&Ia(e,b)?-1*La(a,b):!d&&Ia(f,a)?La(b,a):(c?a.sourceIndex:e.sourceIndex)-(d?b.sourceIndex:f.sourceIndex)}d=9==a.nodeType?a:a.ownerDocument|| +a.document;c=d.createRange();c.selectNode(a);c.collapse(!0);d=d.createRange();d.selectNode(b);d.collapse(!0);return c.compareBoundaryPoints(m.Range.START_TO_END,d)}function La(a,b){var c=a.parentNode;if(c==b)return-1;for(var d=b;d.parentNode!=c;)d=d.parentNode;return Ka(d,a)}function Ka(a,b){for(var c=b;c=c.previousSibling;)if(c==a)return-1;return 1};function G(a){var b=null,c=a.nodeType;1==c&&(b=a.textContent,b=void 0==b||null==b?a.innerText:b,b=void 0==b||null==b?"":b);if("string"!=typeof b)if(B&&"title"==a.nodeName.toLowerCase()&&1==c)b=a.text;else if(9==c||1==c){a=9==c?a.documentElement:a.firstChild;for(var c=0,d=[],b="";a;){do 1!=a.nodeType&&(b+=a.nodeValue),B&&"title"==a.nodeName.toLowerCase()&&(b+=a.text),d[c++]=a;while(a=a.firstChild);for(;c&&!(a=d[--c].nextSibling););}}else b=a.nodeValue;return""+b} +function H(a,b,c){if(null===b)return!0;try{if(!a.getAttribute)return!1}catch(d){return!1}Ba&&"class"==b&&(b="className");return null==c?!!a.getAttribute(b):a.getAttribute(b,2)==c}function Ma(a,b,c,d,e){return(B?Na:Oa).call(null,a,b,n(c)?c:null,n(d)?d:null,e||new I)} +function Na(a,b,c,d,e){if(a instanceof J||8==a.b||c&&null===a.b){var f=b.all;if(!f)return e;a=Pa(a);if("*"!=a&&(f=b.getElementsByTagName(a),!f))return e;if(c){for(var g=[],k=0;b=f[k++];)H(b,c,d)&&g.push(b);f=g}for(k=0;b=f[k++];)"*"==a&&"!"==b.tagName||K(e,b);return e}Qa(a,b,c,d,e);return e} +function Oa(a,b,c,d,e){b.getElementsByName&&d&&"name"==c&&!A?(b=b.getElementsByName(d),w(b,function(b){a.a(b)&&K(e,b)})):b.getElementsByClassName&&d&&"class"==c?(b=b.getElementsByClassName(d),w(b,function(b){b.className==d&&a.a(b)&&K(e,b)})):a instanceof L?Qa(a,b,c,d,e):b.getElementsByTagName&&(b=b.getElementsByTagName(a.f()),w(b,function(a){H(a,c,d)&&K(e,a)}));return e} +function Ra(a,b,c,d,e){var f;if((a instanceof J||8==a.b||c&&null===a.b)&&(f=b.childNodes)){var g=Pa(a);if("*"!=g&&(f=ja(f,function(a){return a.tagName&&a.tagName.toLowerCase()==g}),!f))return e;c&&(f=ja(f,function(a){return H(a,c,d)}));w(f,function(a){"*"==g&&("!"==a.tagName||"*"==g&&1!=a.nodeType)||K(e,a)});return e}return Sa(a,b,c,d,e)}function Sa(a,b,c,d,e){for(b=b.firstChild;b;b=b.nextSibling)H(b,c,d)&&a.a(b)&&K(e,b);return e} +function Qa(a,b,c,d,e){for(b=b.firstChild;b;b=b.nextSibling)H(b,c,d)&&a.a(b)&&K(e,b),Qa(a,b,c,d,e)}function Pa(a){if(a instanceof L){if(8==a.b)return"!";if(null===a.b)return"*"}return a.f()};function I(){this.b=this.a=null;this.l=0}function Ta(a){this.node=a;this.a=this.b=null}function Ua(a,b){if(!a.a)return b;if(!b.a)return a;for(var c=a.a,d=b.a,e=null,f=null,g=0;c&&d;){var f=c.node,k=d.node;f==k||f instanceof C&&k instanceof C&&f.a==k.a?(f=c,c=c.a,d=d.a):0",4,2,function(a,b,c){return S(function(a,b){return a>b},a,b,c)});T("<=",4,2,function(a,b,c){return S(function(a,b){return a<=b},a,b,c)}); +T(">=",4,2,function(a,b,c){return S(function(a,b){return a>=b},a,b,c)});var eb=T("=",3,2,function(a,b,c){return S(function(a,b){return a==b},a,b,c,!0)});T("!=",3,2,function(a,b,c){return S(function(a,b){return a!=b},a,b,c,!0)});T("and",2,2,function(a,b,c){return R(a,c)&&R(b,c)});T("or",1,2,function(a,b,c){return R(a,c)||R(b,c)});function hb(a,b){if(b.a.length&&4!=a.i)throw Error("Primary expression must evaluate to nodeset if filter has predicate(s).");r.call(this,a.i);this.c=a;this.h=b;this.g=a.g;this.b=a.b}q(hb);hb.prototype.a=function(a){a=this.c.a(a);return ib(this.h,a)};hb.prototype.toString=function(){var a;a="Filter:"+O(this.c);return a+=O(this.h)};function jb(a,b){if(b.lengtha.v)throw Error("Function "+a.j+" expects at most "+a.v+" arguments, "+b.length+" given");a.B&&w(b,function(b,d){if(4!=b.i)throw Error("Argument "+d+" to function "+a.j+" is not of type Nodeset: "+b);});r.call(this,a.i);this.h=a;this.c=b;bb(this,a.g||ka(b,function(a){return a.g}));cb(this,a.D&&!b.length||a.C&&!!b.length||ka(b,function(a){return a.b}))}q(jb); +jb.prototype.a=function(a){return this.h.m.apply(null,ma(a,this.c))};jb.prototype.toString=function(){var a="Function: "+this.h;if(this.c.length)var b=x(this.c,function(a,b){return a+O(b)},"Arguments:"),a=a+O(b);return a};function kb(a,b,c,d,e,f,g,k,p){this.j=a;this.i=b;this.g=c;this.D=d;this.C=e;this.m=f;this.A=g;this.v=void 0!==k?k:g;this.B=!!p}kb.prototype.toString=h("j");var lb={}; +function U(a,b,c,d,e,f,g,k){if(lb.hasOwnProperty(a))throw Error("Function already created: "+a+".");lb[a]=new kb(a,b,c,d,!1,e,f,g,k)}U("boolean",2,!1,!1,function(a,b){return R(b,a)},1);U("ceiling",1,!1,!1,function(a,b){return Math.ceil(P(b,a))},1);U("concat",3,!1,!1,function(a,b){var c=na(arguments,1);return x(c,function(b,c){return b+Q(c,a)},"")},2,null);U("contains",2,!1,!1,function(a,b,c){return u(Q(b,a),Q(c,a))},2);U("count",1,!1,!1,function(a,b){return b.a(a).l},1,1,!0); +U("false",2,!1,!1,l(!1),0);U("floor",1,!1,!1,function(a,b){return Math.floor(P(b,a))},1);U("id",4,!1,!1,function(a,b){function c(a){if(B){var b=e.all[a];if(b){if(b.nodeType&&a==b.id)return b;if(b.length)return la(b,function(b){return a==b.id})}return null}return e.getElementById(a)}var d=a.a,e=9==d.nodeType?d:d.ownerDocument,d=Q(b,a).split(/\s+/),f=[];w(d,function(a){a=c(a);!a||0<=ia(f,a)||f.push(a)});f.sort(Ja);var g=new I;w(f,function(a){K(g,a)});return g},1);U("lang",2,!1,!1,l(!1),1); +U("last",1,!0,!1,function(a){if(1!=arguments.length)throw Error("Function last expects ()");return a.f},0);U("local-name",3,!1,!0,function(a,b){var c=b?Wa(b.a(a)):a.a;return c?c.localName||c.nodeName.toLowerCase():""},0,1,!0);U("name",3,!1,!0,function(a,b){var c=b?Wa(b.a(a)):a.a;return c?c.nodeName.toLowerCase():""},0,1,!0);U("namespace-uri",3,!0,!1,l(""),0,1,!0);U("normalize-space",3,!1,!0,function(a,b){return(b?Q(b,a):G(a.a)).replace(/[\s\xa0]+/g," ").replace(/^\s+|\s+$/g,"")},0,1); +U("not",2,!1,!1,function(a,b){return!R(b,a)},1);U("number",1,!1,!0,function(a,b){return b?P(b,a):+G(a.a)},0,1);U("position",1,!0,!1,function(a){return a.b},0);U("round",1,!1,!1,function(a,b){return Math.round(P(b,a))},1);U("starts-with",2,!1,!1,function(a,b,c){b=Q(b,a);a=Q(c,a);return 0==b.lastIndexOf(a,0)},2);U("string",3,!1,!0,function(a,b){return b?Q(b,a):G(a.a)},0,1);U("string-length",1,!1,!0,function(a,b){return(b?Q(b,a):G(a.a)).length},0,1); +U("substring",3,!1,!1,function(a,b,c,d){c=P(c,a);if(isNaN(c)||Infinity==c||-Infinity==c)return"";d=d?P(d,a):Infinity;if(isNaN(d)||-Infinity===d)return"";c=Math.round(c)-1;var e=Math.max(c,0);a=Q(b,a);if(Infinity==d)return a.substring(e);b=Math.round(d);return a.substring(e,c+b)},2,3);U("substring-after",3,!1,!1,function(a,b,c){b=Q(b,a);a=Q(c,a);c=b.indexOf(a);return-1==c?"":b.substring(c+a.length)},2); +U("substring-before",3,!1,!1,function(a,b,c){b=Q(b,a);a=Q(c,a);a=b.indexOf(a);return-1==a?"":b.substring(0,a)},2);U("sum",1,!1,!1,function(a,b){for(var c=M(b.a(a)),d=0,e=N(c);e;e=N(c))d+=+G(e);return d},1,1,!0);U("translate",3,!1,!1,function(a,b,c,d){b=Q(b,a);c=Q(c,a);var e=Q(d,a);a=[];for(d=0;da.length)throw Error("Unclosed literal string");return new nb(a)}function Lb(a){var b=F(a.a),c=b.indexOf(":");if(-1==c)return new J(b);var d=b.substring(0,c);a=a.b(d);if(!a)throw Error("Namespace prefix not declared: "+d);b=b.substr(c+1);return new J(b,a)} +function Mb(a){var b,c=[],d;if(tb(D(a.a))){b=F(a.a);d=D(a.a);if("/"==b&&(Ha(a.a)||"."!=d&&".."!=d&&"@"!=d&&"*"!=d&&!/(?![0-9])[\w]/.test(d)))return new rb;d=new rb;X(a,"Missing next location step.");b=Nb(a,b);c.push(b)}else{a:{b=D(a.a);d=b.charAt(0);switch(d){case "$":throw Error("Variable reference not allowed in HTML XPath");case "(":F(a.a);b=Gb(a);X(a,'unclosed "("');Ib(a,")");break;case '"':case "'":b=Kb(a);break;default:if(isNaN(+b))if(!mb(b)&&/(?![0-9])[\w]/.test(d)&&"("==D(a.a,1)){b=F(a.a); +b=lb[b]||null;F(a.a);for(d=[];")"!=D(a.a);){X(a,"Missing function argument list.");d.push(Gb(a));if(","!=D(a.a))break;F(a.a)}X(a,"Unclosed function argument list.");Jb(a);b=new jb(b,d)}else{b=null;break a}else b=new ob(+F(a.a))}"["==D(a.a)&&(d=new wb(Ob(a)),b=new hb(b,d))}if(b)if(tb(D(a.a)))d=b;else return b;else b=Nb(a,"/"),d=new sb,c.push(b)}for(;tb(D(a.a));)b=F(a.a),X(a,"Missing next location step."),b=Nb(a,b),c.push(b);return new pb(d,c)} +function Nb(a,b){var c,d,e;if("/"!=b&&"//"!=b)throw Error('Step op should be "/" or "//"');if("."==D(a.a))return d=new V(Cb,new L("node")),F(a.a),d;if(".."==D(a.a))return d=new V(Bb,new L("node")),F(a.a),d;var f;if("@"==D(a.a))f=qb,F(a.a),X(a,"Missing attribute name");else if("::"==D(a.a,1)){if(!/(?![0-9])[\w]/.test(D(a.a).charAt(0)))throw Error("Bad token: "+F(a.a));c=F(a.a);f=Ab[c]||null;if(!f)throw Error("No axis with name: "+c);F(a.a);X(a,"Missing node name")}else f=xb;c=D(a.a);if(/(?![0-9])[\w]/.test(c.charAt(0)))if("("== +D(a.a,1)){if(!mb(c))throw Error("Invalid node type: "+c);c=F(a.a);if(!mb(c))throw Error("Invalid type name: "+c);Ib(a,"(");X(a,"Bad nodetype");e=D(a.a).charAt(0);var g=null;if('"'==e||"'"==e)g=Kb(a);X(a,"Bad nodetype");Jb(a);c=new L(c,g)}else c=Lb(a);else if("*"==c)c=Lb(a);else throw Error("Bad token: "+F(a.a));e=new wb(Ob(a),f.a);return d||new V(f,c,e,"//"==b)} +function Ob(a){for(var b=[];"["==D(a.a);){F(a.a);X(a,"Missing predicate expression.");var c=Gb(a);b.push(c);X(a,"Unclosed predicate expression.");Ib(a,"]")}return b}function Hb(a){if("-"==D(a.a))return F(a.a),new Db(Hb(a));var b=Mb(a);if("|"!=D(a.a))a=b;else{for(b=[b];"|"==F(a.a);)X(a,"Missing next union location path."),b.push(Mb(a));a.a.a--;a=new Eb(b)}return a};function Pb(a,b){if(!a.length)throw Error("Empty XPath expression.");var c=Ea(a);if(Ha(c))throw Error("Invalid XPath expression.");b?"function"==ba(b)||(b=ea(b.lookupNamespaceURI,b)):b=l(null);var d=Gb(new Fb(c,b));if(!Ha(c))throw Error("Bad token: "+F(c));this.evaluate=function(a,b){var c=d.a(new t(a));return new Y(c,b)}} +function Y(a,b){if(0==b)if(a instanceof I)b=4;else if("string"==typeof a)b=2;else if("number"==typeof a)b=1;else if("boolean"==typeof a)b=3;else throw Error("Unexpected evaluation result.");if(2!=b&&1!=b&&3!=b&&!(a instanceof I))throw Error("value could not be converted to the specified type");this.resultType=b;var c;switch(b){case 2:this.stringValue=a instanceof I?Xa(a):""+a;break;case 1:this.numberValue=a instanceof I?+Xa(a):+a;break;case 3:this.booleanValue=a instanceof I?0=c.length?null:c[f++]};this.snapshotItem=function(a){if(6!=b&&7!=b)throw Error("snapshotItem called with wrong result type");return a>=c.length|| +0>a?null:c[a]}}Y.ANY_TYPE=0;Y.NUMBER_TYPE=1;Y.STRING_TYPE=2;Y.BOOLEAN_TYPE=3;Y.UNORDERED_NODE_ITERATOR_TYPE=4;Y.ORDERED_NODE_ITERATOR_TYPE=5;Y.UNORDERED_NODE_SNAPSHOT_TYPE=6;Y.ORDERED_NODE_SNAPSHOT_TYPE=7;Y.ANY_UNORDERED_NODE_TYPE=8;Y.FIRST_ORDERED_NODE_TYPE=9;function Qb(a){this.lookupNamespaceURI=Za(a)} +function Rb(a){a=a||m;var b=a.document;b.evaluate||(a.XPathResult=Y,b.evaluate=function(a,b,e,f){return(new Pb(a,e)).evaluate(b,f)},b.createExpression=function(a,b){return new Pb(a,b)},b.createNSResolver=function(a){return new Qb(a)})}var Sb=["wgxpath","install"],Z=m;Sb[0]in Z||!Z.execScript||Z.execScript("var "+Sb[0]);for(var Tb;Sb.length&&(Tb=Sb.shift());)Sb.length||void 0===Rb?Z[Tb]?Z=Z[Tb]:Z=Z[Tb]={}:Z[Tb]=Rb;})() diff --git a/reader/js/plugin.js b/reader/js/plugin.js new file mode 100644 index 0000000..59946aa --- /dev/null +++ b/reader/js/plugin.js @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2015-2017 Frank de Lange + * Copyright (c) 2013-2014 Lukas Reschke + * + * This file is licensed under the Affero General Public License version 3 + * or later. + * + * See the COPYING-README file. + * + */ + + +(function(OCA) { + + 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.Files_Reader.Plugin + */ + OCA.Files_Reader.Plugin = { + + /** + * @param fileList + */ + attach: function(fileList) { + this._extendFileActions(fileList.fileActions); + }, + + hideControls: function() { + $('#app-content #controls').hide(); + }, + + hide: function() { + if ($('#fileList').length) { + FileList.setViewerMode(false); + } + $("#controls").show(); + $('#app-content #controls').removeClass('hidden'); + if ($('#isPublic').val()) { + $('#imgframe').show(); + $('footer').show(); + $('.directLink').show(); + $('.directDownload').show(); + } + $('iframe').remove(); + }, + + /** + * @param downloadUrl + * @param isFileList + */ + show: function(downloadUrl, mimeType, isFileList) { + var self = this; + var $iframe; + 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); + } else { + $iframe = '