├── VERSION
├── public
├── javascripts
│ └── DV
│ │ ├── views
│ │ ├── navigationExpander.jst
│ │ ├── annotationNav.jst
│ │ ├── chapterNav.jst
│ │ ├── descriptionContainer.jst
│ │ ├── pages.jst
│ │ ├── navControls.jst
│ │ ├── pageAnnotation.jst
│ │ ├── unsupported.jst
│ │ ├── header.jst
│ │ ├── viewer.jst
│ │ └── annotation.jst
│ │ ├── lib
│ │ ├── initializer.js
│ │ ├── model.js
│ │ ├── elements.js
│ │ ├── inflector.js
│ │ ├── class.js
│ │ ├── history.js
│ │ ├── dragReporter.js
│ │ ├── stateMachine.js
│ │ ├── annotation.js
│ │ └── pageSet.js
│ │ ├── events
│ │ ├── ViewSearch.js
│ │ ├── ViewText.js
│ │ ├── ViewDocument.js
│ │ ├── ViewAnnotation.js
│ │ ├── navigation.js
│ │ ├── history.js
│ │ └── events.js
│ │ ├── states
│ │ ├── ViewEntity.js
│ │ ├── ViewText.js
│ │ ├── ViewSearch.js
│ │ ├── ViewAnnotation.js
│ │ ├── ViewDocument.js
│ │ └── states.js
│ │ ├── helpers
│ │ ├── navigation.js
│ │ ├── editor.js
│ │ ├── annotations.js
│ │ ├── construction.js
│ │ └── search.js
│ │ ├── models
│ │ ├── chapter.js
│ │ ├── page.js
│ │ ├── document.js
│ │ └── annotation.js
│ │ ├── elements
│ │ └── elements.js
│ │ ├── controllers
│ │ ├── documentViewer.js
│ │ └── api.js
│ │ ├── vendor
│ │ ├── jquery.easing.compatibility.js
│ │ ├── jquery.scrollTo-min.js
│ │ └── jquery.acceptInput.js
│ │ ├── schema
│ │ └── schema.js
│ │ └── tests
│ │ └── testsuite.css
├── stylesheets
│ └── DV
│ │ ├── components
│ │ ├── ui.css
│ │ ├── ui-header.css
│ │ ├── reset.css
│ │ ├── view-document.css
│ │ ├── unsupported.css
│ │ ├── ui-text.css
│ │ ├── view-text.css
│ │ ├── ui-zoom.css
│ │ ├── view-search.css
│ │ ├── ui-menu.css
│ │ ├── structure.css
│ │ ├── view-annotations.css
│ │ ├── dropShadow.css
│ │ ├── pages.css
│ │ ├── ui-search.css
│ │ └── ui-navigation.css
│ │ └── plain.css
├── images
│ └── DV
│ │ ├── tab.png
│ │ ├── grab.cur
│ │ ├── white.png
│ │ ├── grabbing.cur
│ │ ├── tab-note.png
│ │ ├── embed
│ │ ├── bar.gif
│ │ ├── black.png
│ │ ├── box-bl.gif
│ │ ├── box-bl.png
│ │ ├── box-br.gif
│ │ ├── box-br.png
│ │ ├── box-tl.gif
│ │ ├── box-tl.png
│ │ ├── box-tla.gif
│ │ ├── box-tla.png
│ │ ├── box-top.gif
│ │ ├── box-top.png
│ │ ├── box-tr.gif
│ │ ├── box-tr.png
│ │ ├── corner.png
│ │ ├── indent.gif
│ │ ├── shadow.png
│ │ ├── slider.gif
│ │ ├── spinner.gif
│ │ ├── box-bottom.gif
│ │ ├── box-bottom.png
│ │ ├── box-left.gif
│ │ ├── box-left.png
│ │ ├── box-right.gif
│ │ ├── box-right.png
│ │ ├── bullet4x4.gif
│ │ ├── highlight.gif
│ │ ├── leftArrow.gif
│ │ ├── rightArrow.gif
│ │ ├── shadow-white.gif
│ │ ├── box-bl-private.gif
│ │ ├── box-bl-private.png
│ │ ├── box-br-private.gif
│ │ ├── box-br-private.png
│ │ ├── box-tl-private.gif
│ │ ├── box-tl-private.png
│ │ ├── box-tla-private.gif
│ │ ├── box-tla-private.png
│ │ ├── box-top-private.gif
│ │ ├── box-top-private.png
│ │ ├── box-tr-private.gif
│ │ ├── box-tr-private.png
│ │ ├── controlsArrows.gif
│ │ ├── corner-private.png
│ │ ├── box-left-private.gif
│ │ ├── box-left-private.png
│ │ ├── box-right-private.gif
│ │ ├── box-right-private.png
│ │ ├── box-bottom-private.gif
│ │ └── box-bottom-private.png
│ │ ├── expanders.gif
│ │ ├── tab-note-ie.png
│ │ ├── tab-private.png
│ │ ├── tabActive.png
│ │ ├── tabActive-ie.png
│ │ ├── browsers
│ │ ├── chrome.gif
│ │ ├── firefox.gif
│ │ └── safari.gif
│ │ ├── tab-note-private.png
│ │ ├── tabActive-private.png
│ │ ├── interface
│ │ ├── arrow-left.gif
│ │ ├── arrow-right.gif
│ │ ├── blank_page.jpg
│ │ ├── newspaper.png
│ │ ├── arrow-left-noresults.gif
│ │ └── arrow-right-noresults.gif
│ │ ├── tab-note-ie-private.png
│ │ └── tabActive-ie-private.png
└── assets
│ ├── plain.css.gz
│ ├── viewer.css.gz
│ ├── viewer.js.gz
│ ├── viewer.jst.gz
│ ├── fallback.css.gz
│ ├── templates.js.gz
│ ├── plain-datauri.css.gz
│ ├── fallback-datauri.css.gz
│ ├── viewer-datauri.css.gz
│ ├── plain.css
│ ├── plain-datauri.css
│ └── viewer.jst
├── viewer.html
├── config
└── assets.yml
├── README.rdoc
├── NOTICE
└── viewer-debug.html
/VERSION:
--------------------------------------------------------------------------------
1 | 0.0.1
--------------------------------------------------------------------------------
/public/javascripts/DV/views/navigationExpander.jst:
--------------------------------------------------------------------------------
1 | Expand
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/ui.css:
--------------------------------------------------------------------------------
1 | .DV-trigger{
2 | cursor: pointer;
3 | cursor: hand;
4 | }
--------------------------------------------------------------------------------
/public/images/DV/tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/tab.png
--------------------------------------------------------------------------------
/public/assets/plain.css.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/assets/plain.css.gz
--------------------------------------------------------------------------------
/public/assets/viewer.css.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/assets/viewer.css.gz
--------------------------------------------------------------------------------
/public/assets/viewer.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/assets/viewer.js.gz
--------------------------------------------------------------------------------
/public/assets/viewer.jst.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/assets/viewer.jst.gz
--------------------------------------------------------------------------------
/public/images/DV/grab.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/grab.cur
--------------------------------------------------------------------------------
/public/images/DV/white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/white.png
--------------------------------------------------------------------------------
/public/assets/fallback.css.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/assets/fallback.css.gz
--------------------------------------------------------------------------------
/public/assets/templates.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/assets/templates.js.gz
--------------------------------------------------------------------------------
/public/images/DV/grabbing.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/grabbing.cur
--------------------------------------------------------------------------------
/public/images/DV/tab-note.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/tab-note.png
--------------------------------------------------------------------------------
/public/images/DV/embed/bar.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/bar.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/black.png
--------------------------------------------------------------------------------
/public/images/DV/expanders.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/expanders.gif
--------------------------------------------------------------------------------
/public/images/DV/tab-note-ie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/tab-note-ie.png
--------------------------------------------------------------------------------
/public/images/DV/tab-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/tab-private.png
--------------------------------------------------------------------------------
/public/images/DV/tabActive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/tabActive.png
--------------------------------------------------------------------------------
/public/assets/plain-datauri.css.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/assets/plain-datauri.css.gz
--------------------------------------------------------------------------------
/public/images/DV/embed/box-bl.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-bl.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-bl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-bl.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-br.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-br.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-br.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-br.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-tl.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-tl.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-tl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-tl.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-tla.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-tla.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-tla.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-tla.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-top.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-top.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-top.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-tr.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-tr.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-tr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-tr.png
--------------------------------------------------------------------------------
/public/images/DV/embed/corner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/corner.png
--------------------------------------------------------------------------------
/public/images/DV/embed/indent.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/indent.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/shadow.png
--------------------------------------------------------------------------------
/public/images/DV/embed/slider.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/slider.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/spinner.gif
--------------------------------------------------------------------------------
/public/images/DV/tabActive-ie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/tabActive-ie.png
--------------------------------------------------------------------------------
/public/assets/fallback-datauri.css.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/assets/fallback-datauri.css.gz
--------------------------------------------------------------------------------
/public/assets/viewer-datauri.css.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/assets/viewer-datauri.css.gz
--------------------------------------------------------------------------------
/public/images/DV/browsers/chrome.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/browsers/chrome.gif
--------------------------------------------------------------------------------
/public/images/DV/browsers/firefox.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/browsers/firefox.gif
--------------------------------------------------------------------------------
/public/images/DV/browsers/safari.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/browsers/safari.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-bottom.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-bottom.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-bottom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-bottom.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-left.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-left.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-left.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-right.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-right.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-right.png
--------------------------------------------------------------------------------
/public/images/DV/embed/bullet4x4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/bullet4x4.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/highlight.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/highlight.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/leftArrow.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/leftArrow.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/rightArrow.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/rightArrow.gif
--------------------------------------------------------------------------------
/public/images/DV/tab-note-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/tab-note-private.png
--------------------------------------------------------------------------------
/public/images/DV/embed/shadow-white.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/shadow-white.gif
--------------------------------------------------------------------------------
/public/images/DV/tabActive-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/tabActive-private.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-bl-private.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-bl-private.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-bl-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-bl-private.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-br-private.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-br-private.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-br-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-br-private.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-tl-private.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-tl-private.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-tl-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-tl-private.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-tla-private.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-tla-private.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-tla-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-tla-private.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-top-private.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-top-private.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-top-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-top-private.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-tr-private.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-tr-private.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-tr-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-tr-private.png
--------------------------------------------------------------------------------
/public/images/DV/embed/controlsArrows.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/controlsArrows.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/corner-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/corner-private.png
--------------------------------------------------------------------------------
/public/images/DV/interface/arrow-left.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/interface/arrow-left.gif
--------------------------------------------------------------------------------
/public/images/DV/interface/arrow-right.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/interface/arrow-right.gif
--------------------------------------------------------------------------------
/public/images/DV/interface/blank_page.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/interface/blank_page.jpg
--------------------------------------------------------------------------------
/public/images/DV/interface/newspaper.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/interface/newspaper.png
--------------------------------------------------------------------------------
/public/images/DV/tab-note-ie-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/tab-note-ie-private.png
--------------------------------------------------------------------------------
/public/images/DV/tabActive-ie-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/tabActive-ie-private.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-left-private.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-left-private.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-left-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-left-private.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-right-private.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-right-private.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-right-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-right-private.png
--------------------------------------------------------------------------------
/public/images/DV/embed/box-bottom-private.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-bottom-private.gif
--------------------------------------------------------------------------------
/public/images/DV/embed/box-bottom-private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/embed/box-bottom-private.png
--------------------------------------------------------------------------------
/public/images/DV/interface/arrow-left-noresults.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/interface/arrow-left-noresults.gif
--------------------------------------------------------------------------------
/public/images/DV/interface/arrow-right-noresults.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/document-viewer/frontend/public/images/DV/interface/arrow-right-noresults.gif
--------------------------------------------------------------------------------
/public/javascripts/DV/views/annotationNav.jst:
--------------------------------------------------------------------------------
1 |
2 |
3 | <%= title %>
4 | p.<%= page %>
5 |
6 |
--------------------------------------------------------------------------------
/public/javascripts/DV/views/chapterNav.jst:
--------------------------------------------------------------------------------
1 |
2 |
3 | <%= navigationExpander %>
4 | <%= title %>p. <%= pageNumber %>
5 |
6 | <%= noteViews %>
7 |
--------------------------------------------------------------------------------
/public/javascripts/DV/views/descriptionContainer.jst:
--------------------------------------------------------------------------------
1 | <% if (description) { %>
2 |
3 |
4 | Toggle Description
5 | Description
6 |
7 |
<%= description %>
8 |
9 | <% } %>
10 |
--------------------------------------------------------------------------------
/public/javascripts/DV/lib/initializer.js:
--------------------------------------------------------------------------------
1 | window.$j = jQuery.noConflict();
2 | window.DV = window.DV || {};
3 |
4 | DV.register = function(_name, _instance) {
5 | if(!window.DV[_name]){
6 | window.DV[_name] = _instance;
7 | }
8 | };
9 | // IE6 backgroundImageCache hack
10 | if($j.browser.msie === true && $j.browser.version == 6){
11 | document.execCommand('BackgroundImageCache', false, true);
12 | }
13 |
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/ui-header.css:
--------------------------------------------------------------------------------
1 | #DV-header{
2 | padding:10px 0;
3 | }
4 |
5 | #DV-branding{
6 | font-family:Arial,Helvetica,sans-serif;
7 | font-size:15px;
8 | font-weight:bold;
9 | padding: 0 5px 0 0;
10 | }
11 |
12 | #DV-headerHat{
13 | padding: 15px 0 5px;
14 | margin: 0 10px 10px 15px;
15 | position:relative;
16 | }
17 |
18 | #DV-title{
19 | font-family: Georgia,Times,serif;
20 | font-size: 20px;
21 | font-weight: normal;
22 | }
--------------------------------------------------------------------------------
/public/javascripts/DV/events/ViewSearch.js:
--------------------------------------------------------------------------------
1 | DV.Schema.events.ViewSearch = {
2 | next: function(e){
3 | var nextPage = this.models.document.nextPage();
4 | this.loadText(nextPage);
5 |
6 | },
7 | previous: function(e){
8 | var previousPage = this.models.document.previousPage();
9 | this.loadText(previousPage);
10 |
11 | },
12 | search: function(e){
13 | this.helpers.getSearchResponse(this.elements.searchInput.val());
14 |
15 | return false;
16 | }
17 | };
--------------------------------------------------------------------------------
/public/javascripts/DV/states/ViewEntity.js:
--------------------------------------------------------------------------------
1 | DV.Schema.states.ViewEntity = {
2 | enter: function(sourceState) {
3 | this.dragReporter.unBind();
4 | this.elements.window.scrollTop(0);
5 | },
6 | ViewEntity: function(name, offset, length) {
7 | this.helpers.toggleContent('viewSearch');
8 | this.helpers.showEntity(name, offset, length);
9 | },
10 | exit: function(destinationState) {
11 | this.elements.searchInput.val('');
12 | this.helpers.cleanUpSearch();
13 | return true;
14 | }
15 | };
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/reset.css:
--------------------------------------------------------------------------------
1 | #DV-docViewer .clearfix:after {
2 | content: ".";
3 | display: block;
4 | height: 0;
5 | clear: both;
6 | visibility: hidden;
7 | }
8 |
9 | #DV-docViewer .clearfix {display: inline-block;}
10 |
11 | /* Hides from IE-mac \*/
12 | * html #DV-docViewer .clearfix {height: 1%;}
13 | #DV-docViewer .clearfix {display: block;}
14 | /* End hide from IE-mac */
15 |
16 | #DV-docViewer a,
17 | #DV-docViewer a:visited{
18 | color:#004276;
19 | }
20 |
21 | #DV-docViewer{
22 | overflow:hidden;
23 | }
--------------------------------------------------------------------------------
/public/javascripts/DV/events/ViewText.js:
--------------------------------------------------------------------------------
1 | DV.Schema.events.ViewText = {
2 | next: function(e){
3 | var nextPage = this.models.document.nextPage();
4 | this.loadText(nextPage);
5 |
6 | DV.history.save('text/p'+(nextPage+1));
7 | },
8 | previous: function(e){
9 | var previousPage = this.models.document.previousPage();
10 | this.loadText(previousPage);
11 |
12 | DV.history.save('text/p'+(previousPage+1));
13 |
14 | },
15 | search: function(e){
16 | e.preventDefault();
17 | this.states.ViewSearch();
18 |
19 | return false;
20 | }
21 | };
--------------------------------------------------------------------------------
/public/javascripts/DV/views/pages.jst:
--------------------------------------------------------------------------------
1 |
2 |
p. <%= pageNumber %>
3 |
4 |
5 |
Loading
6 |
Loading
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/public/javascripts/DV/events/ViewDocument.js:
--------------------------------------------------------------------------------
1 | DV.Schema.events.ViewDocument = {
2 | next: function(){
3 | var nextPage = this.models.document.nextPage();
4 | this.helpers.jump(nextPage);
5 |
6 | DV.history.save('document/p'+(nextPage+1));
7 | },
8 | previous: function(e){
9 | var previousPage = this.models.document.previousPage();
10 | this.helpers.jump(previousPage);
11 |
12 | DV.history.save('document/p'+(previousPage+1));
13 | },
14 | search: function(e){
15 | e.preventDefault();
16 |
17 | this.states.ViewSearch();
18 | return false;
19 | }
20 | }
--------------------------------------------------------------------------------
/public/javascripts/DV/states/ViewText.js:
--------------------------------------------------------------------------------
1 | DV.Schema.states.ViewText = {
2 |
3 | enter: function(sourceState){
4 | this.dragReporter.unBind();
5 | this.helpers.resetNavigationState();
6 | this.elements.window.scrollTop(0);
7 | this.acceptInput.allow();
8 | this.pageSet.zoomText();
9 | return true;
10 | },
11 | ViewText: function(){
12 | this.helpers.toggleContent('viewText');
13 | this.events.loadText();
14 |
15 | return true;
16 | },
17 | exit: function(destinationState){
18 | this.helpers.resetNavigationState();
19 | this.elements.collection.width(this.models.pages.width + 110);
20 | return true;
21 | }
22 | };
--------------------------------------------------------------------------------
/public/javascripts/DV/views/navControls.jst:
--------------------------------------------------------------------------------
1 |
2 |
«
3 |
4 | Page
5 | Annot.
6 | 1
7 | of
8 | <%= totalPages %>
9 | <%= totalAnnotations %>
10 |
11 |
12 |
»
13 |
--------------------------------------------------------------------------------
/public/javascripts/DV/helpers/navigation.js:
--------------------------------------------------------------------------------
1 | _.extend(DV.Schema.helpers, {
2 | resetNavigationState: function(){
3 | var elements = this.elements;
4 | elements.chaptersContainer[0].id = '';
5 | elements.navigation[0].id = '';
6 | },
7 | setActiveChapter: function(chapterId){
8 | this.elements.chaptersContainer.attr('id','DV-selectedChapter-'+chapterId);
9 | },
10 | setActiveAnnotationInNav: function(annotationId){
11 | if(annotationId){
12 | this.elements.navigation.attr('id','DV-selectedAnnotation-'+annotationId);
13 | }else{
14 | this.elements.navigation.attr('id','');
15 | }
16 | }
17 | });
18 |
--------------------------------------------------------------------------------
/public/javascripts/DV/states/ViewSearch.js:
--------------------------------------------------------------------------------
1 | DV.Schema.states.ViewSearch = {
2 |
3 | enter: function(sourceState){
4 | this.dragReporter.unBind();
5 | this.elements.window.scrollTop(0);
6 |
7 | if(this.elements.searchInput.val() == ''){
8 | this.elements.searchInput.val(searchRequest);
9 | }else{
10 | var searchRequest = this.elements.searchInput.val();
11 | }
12 |
13 | this.helpers.getSearchResponse(searchRequest);
14 | this.acceptInput.deny();
15 | return true;
16 | },
17 | ViewSearch: function(){
18 | this.helpers.toggleContent('viewSearch');
19 |
20 | return true;
21 | },
22 | exit: function(destinationState){
23 | this.elements.searchInput.val('');
24 | this.helpers.cleanUpSearch();
25 | return true;
26 | }
27 | };
--------------------------------------------------------------------------------
/public/javascripts/DV/states/ViewAnnotation.js:
--------------------------------------------------------------------------------
1 | DV.Schema.states.ViewAnnotation = {
2 | enter: function(sourceState){
3 | this.elements.window.scrollTop(0);
4 | this.activeAnnotationId = null;
5 | this.acceptInput.deny();
6 | // Nudge IE to force the annotations to repaint.
7 | if (jQuery.browser.msie) {
8 | this.elements.annotations.css({zoom : 0});
9 | this.elements.annotations.css({zoom : 1});
10 | }
11 | return true;
12 | },
13 | ViewAnnotation: function(){
14 |
15 | this.helpers.toggleContent('viewAnnotations');
16 | this.compiled.next();
17 |
18 |
19 | return true;
20 | },
21 | exit: function(destinationState){
22 | this.helpers.resetNavigationState();
23 | this.activeAnnotationId = null;
24 | return true;
25 | }
26 | };
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/view-document.css:
--------------------------------------------------------------------------------
1 | .DV-viewDocument #DV-annotations,
2 | .DV-viewDocument #DV-text,
3 | .DV-viewDocument #DV-search,
4 | #p0,
5 | #p1,
6 | #p2{
7 | display:none;
8 | }
9 |
10 | .DV-viewDocument #p0,
11 | .DV-viewDocument #p1,
12 | .DV-viewDocument #p2{
13 | display:block;
14 | }
15 |
16 | .DV-coverVisible .DV-viewDocument #p0,
17 | .DV-coverVisible .DV-viewDocument #p1,
18 | .DV-coverVisible .DV-viewDocument #p2{
19 | background:none;
20 | }
21 |
22 | .DV-viewDocument #DV-currentAnnotationPrefix,
23 | .DV-viewDocument #DV-totalAnnotations{
24 | display:none;
25 | }
26 |
27 | .DV-viewDocument #DV-currentPagePrefix,
28 | .DV-viewDocument #DV-totalPages{
29 | display:inline;
30 | }
31 |
32 | .DV-viewDocument .DV-coverVisible .DV-cover{
33 | cursor:pointer !important;
34 | }
35 |
36 | .DV-viewDocument .DV-annotationRegionBorder {
37 | display: block;
38 | }
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/unsupported.css:
--------------------------------------------------------------------------------
1 | #DV-unsupported {
2 | text-align: center;
3 | font: 16px Helvetica, Arial, sans-serif;
4 | width: 400px;
5 | margin: 30px;
6 | }
7 | #DV-unsupported .DV-intro {
8 | font-weight: bold;
9 | }
10 | #DV-unsupported .DV-browsers {
11 | margin: 20px 20px;
12 | height: 90px;
13 | }
14 | #DV-unsupported .DV-browser {
15 | float: left;
16 | width: 70px;
17 | margin: 0 20px;
18 | line-height: 30px;
19 | }
20 | #DV-unsupported .DV-image {
21 | width: 70px; height: 67px;
22 | clear: both;
23 | }
24 | #DV-unsupported #DV-safari {
25 | background: url(../../../images/DV/browsers/safari.gif);
26 | }
27 | #DV-unsupported #DV-chrome {
28 | background: url(../../../images/DV/browsers/chrome.gif);
29 | }
30 | #DV-unsupported #DV-firefox {
31 | background: url(../../../images/DV/browsers/firefox.gif);
32 | }
33 | #DV-unsupported .DV-after {
34 | margin-top: 20px;
35 | }
--------------------------------------------------------------------------------
/public/javascripts/DV/states/ViewDocument.js:
--------------------------------------------------------------------------------
1 | DV.Schema.states.ViewDocument = {
2 | enter: function(sourceState){
3 | this.helpers.addObserver('drawPages');
4 | this.dragReporter.setBinding();
5 | this.elements.window.mouseleave($j.proxy(this.dragReporter.stop, this.dragReporter));
6 | this.acceptInput.allow();
7 | return true;
8 | },
9 | ViewDocument: function(){
10 | this.helpers.toggleContent('viewDocument');
11 |
12 | this.helpers.setActiveChapter(this.models.chapters.getChapterId(this.models.document.currentIndex()));
13 |
14 | this.helpers.jump(this.models.document.currentIndex());
15 | return true;
16 | },
17 | exit: function(destinationState){
18 | if(this.activeAnnotation){
19 | this.pageSet.cleanUp();
20 | }
21 | this.helpers.removeObserver('drawPages');
22 | this.elements.chaptersContainer[0].id = '';
23 | this.dragReporter.unBind();
24 | return true;
25 | }
26 | };
--------------------------------------------------------------------------------
/public/javascripts/DV/views/pageAnnotation.jst:
--------------------------------------------------------------------------------
1 |
2 |
3 |
p. <%= pageNumber %>
4 |
5 |
6 |
7 |
8 |
16 |
17 |
18 | <%= text %>
19 |
20 |
21 |
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/ui-text.css:
--------------------------------------------------------------------------------
1 | #DV-textPage{
2 | min-height:867px;
3 | background-color:#fff;
4 | margin: 10px auto;
5 | -moz-box-shadow: 0 0 1em #a9a9a9;
6 | -webkit-box-shadow: 0 0 1em #a9a9a9;
7 | }
8 |
9 | #DV-textCurrentPage{
10 | color:#000;
11 | font-size:10px;
12 | font-family:Arial,Helvetica,sans-serif;
13 | position:absolute;
14 | left:0;
15 | padding-left:8px;
16 | top:30px;
17 | font-weight:bold;
18 | }
19 |
20 | #DV-textContents {
21 | background-color:#FFFFFF;
22 | color:#333333;
23 | font-size:14px;
24 | font-family: courier, monotype;
25 | line-height:1.4em;
26 | overflow: hidden;
27 | white-space: pre-wrap; /* css-3 */
28 | white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
29 | white-space: -pre-wrap; /* Opera 4-6 */
30 | white-space: -o-pre-wrap; /* Opera 7 */
31 | word-wrap: break-word; /* Internet Explorer 5.5+ */
32 | padding:50px;
33 | margin: 0 auto;
34 | }
--------------------------------------------------------------------------------
/public/javascripts/DV/lib/model.js:
--------------------------------------------------------------------------------
1 | // basic model class
2 | DV.model = function(_super,methods){
3 | this.set('application',_super);
4 | if(methods != null){
5 | this.addMethods(methods);
6 | }
7 | if(this.setup){
8 | this.setup();
9 | }
10 | };
11 | // Used to add methods to your model
12 | DV.model.prototype.addMethods = function(methods){
13 | for (var key in methods){
14 | this.set(key,methods[key]);
15 | };
16 | };
17 | // base getter
18 | DV.model.prototype.get = function(attr){
19 | return this[attr];
20 | };
21 | // base setter
22 | DV.model.prototype.set = function(attr,value){
23 | if(attr !== 'set' && attr !== 'get' && attr !== 'bind'){
24 | this[attr] = value;
25 | return this[attr];
26 | }else{
27 | return false;
28 | }
29 | };
30 | // Probably dont need this anymore
31 | DV.model.prototype.bind = function(object, method){
32 | return function() {
33 | return method.apply(object, arguments);
34 | };
35 | };
36 |
37 |
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/view-text.css:
--------------------------------------------------------------------------------
1 | .DV-viewText #DV-pageCollection{
2 | cursor: text;
3 | }
4 |
5 | .DV-viewText .DV-set,
6 | .DV-viewText #DV-bar,
7 | .DV-viewText #DV-annotations{
8 | display:none;
9 | }
10 |
11 | .DV-viewText #DV-text{
12 | display:block;
13 | }
14 |
15 | .DV-viewText #DV-currentAnnotationPrefix,
16 | .DV-viewText #DV-totalAnnotations{
17 | display:none;
18 | }
19 |
20 | .DV-viewText #DV-sidebar #DV-well .DV-chaptersContainer div.DV-hasChildren div,
21 | .DV-viewText #DV-sidebar #DV-well .DV-chaptersContainer span.DV-expander{
22 | display:none !important;
23 | }
24 |
25 | .DV-viewText #DV-sidebar #DV-well .DV-chaptersContainer div.DV-hasChildren div.DV-first{
26 | display:block !important;
27 | }
28 |
29 | .DV-viewText #DV-sidebar #DV-well .DV-chaptersContainer div.DV-hasChildren div.DV-first .DV-trigger{
30 | margin-left:-1px;
31 | }
32 |
33 | .DV-viewText .DV-annotationMarker,
34 | .DV-viewText .DV-chapter{
35 | margin-left:14px;
36 | }
37 |
38 | #DV-textView{
39 | display:none;
40 | }
41 |
42 | #DV-docViewer.DV-searchable #DV-textView{
43 | display:inline;
44 | }
--------------------------------------------------------------------------------
/public/javascripts/DV/models/chapter.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | var chaptersModel = new DV.model(DV.Schema,{
4 |
5 | init : function() {
6 | this.loadChapters();
7 | },
8 |
9 | // Load (or reload) the chapter model from the schema's defined sections.
10 | loadChapters : function() {
11 | var chapters = this.chapters = DV.Schema.data.chapters = [];
12 | _.each(DV.Schema.data.sections, function(sec) {
13 | sec.id = sec.id || _.uniqueId();
14 | var range = sec.pages.split('-');
15 | var start = parseInt(range[0], 10);
16 | var end = parseInt(range[0], 10);
17 | for (var i=range[0]-1; i
2 |
3 | <% if (DV.Schema.document.resources && DV.Schema.document.resources.pdf) { %>
4 |
Download this document as a PDF
5 | <% } %>
6 |
7 |
8 | To use the Document Viewer you need to
upgrade your browser:
9 |
10 |
28 |
32 |
33 |
--------------------------------------------------------------------------------
/public/javascripts/DV/elements/elements.js:
--------------------------------------------------------------------------------
1 | // We cache DOM references to improve speed and reduce DOM queries
2 | DV.Schema.elements =
3 | [
4 | { name: 'browserDocument', query: document },
5 | { name: 'browserWindow', query: window },
6 | { name: 'header', query: 'div#DV-header'},
7 | { name: 'viewer', query: 'div#DV-docViewer'},
8 | { name: 'window', query: 'div#DV-pages'},
9 | { name: 'sets', query: 'div.DV-set'},
10 | { name: 'pages', query: 'div.DV-page'},
11 | { name: 'metas', query: 'div.DV-pageMeta'},
12 | { name: 'bar', query: 'div#DV-bar'},
13 | { name: 'currentPage', query: 'span#DV-currentPage'},
14 | { name: 'well', query: 'div#DV-well'},
15 | { name: 'collection', query: 'div#DV-pageCollection'},
16 | { name: 'annotations', query: 'div#DV-annotations'},
17 | { name: 'navigation', query: 'div#DV-well div.DV-navigation' },
18 | { name: 'chaptersContainer', query: 'div#DV-well div.DV-chaptersContainer' },
19 | { name: 'searchInput', query: 'input#DV-searchInput' },
20 | { name: 'textCurrentPage', query: 'span#DV-textCurrentPage' },
21 | { name: 'coverPages', query: 'div.DV-cover' }
22 | ];
--------------------------------------------------------------------------------
/public/javascripts/DV/lib/elements.js:
--------------------------------------------------------------------------------
1 | DV.Elements = DV.Class.extend({
2 | init: function(elements){
3 | if(!elements){
4 | throw('Elements to query must be defined');
5 | return;
6 | }
7 | this.names = [];
8 |
9 | if(elements.constructor === Array){
10 | return this.getElements(elements);
11 | }else{
12 | return this.getElement(elements);
13 | }
14 | },
15 | // Get and store an element reference
16 | getElement: function(elementQuery,force){
17 | if(this[elementQuery.name] && force === null){
18 | return;
19 | }else{
20 | this[elementQuery.name] = jQuery(elementQuery.query);
21 | this.names.push(elementQuery.name);
22 | return this;
23 | }
24 | },
25 | // Get a collection of elements
26 | getElements: function(querySet,force){
27 | for (var i = querySet.length - 1; i >= 0; i--){
28 | this.getElement(querySet[i],force);
29 | };
30 | return this;
31 | },
32 |
33 | // Remove all references and bindings
34 | destroy: function(){
35 | for(var i = 0,len=this.names.length; i < len; i++){
36 | this[this.names[i]].unbind();
37 | this[this.names[i]].die();
38 | delete this[this.names[i]];
39 | }
40 | delete this.names;
41 | }
42 | });
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/ui-zoom.css:
--------------------------------------------------------------------------------
1 | .DV-zoomControls{
2 | font-family:Arial,Helvetica,sans-serif;
3 | font-size:11px;
4 | float: right;
5 | margin: 8px 20px 0 0;
6 | position: absolute;
7 | right:-10px;
8 | }
9 |
10 | #DV-docViewer.DV-searchable .DV-zoomControls {
11 | right:235px;
12 | }
13 |
14 | .DV-zoomLabel{
15 | color:#333333;
16 | display:inline;
17 | float:left;
18 | font-family:Arial,Helvetica,sans-serif;
19 | font-size:11px;
20 | padding:3px 16px 0 0;
21 | margin: 3px 0 0 -74px;
22 | position:relative;
23 | }
24 |
25 | #DV-zoomBox{
26 | background: url(../../../images/DV/embed/bar.gif) repeat-x 0 88%;
27 | height:20px;
28 | width:85px;
29 | float: left;
30 | position:relative;
31 | margin-right:25px;
32 | }
33 |
34 | #DV-zoomBox .ui-slider-handle{
35 | height:12px;
36 | width:12px;
37 | position:absolute;
38 | left:0;
39 | top:0;
40 | margin-top:5px;
41 | margin-left:-5px;
42 | background: transparent url(../../../images/DV/embed/slider.gif) no-repeat 0 0;
43 | outline: none;
44 | }
45 |
46 | .DV-zoomControls .DV-trigger{
47 | font-size:11px;
48 | text-decoration:none;
49 | font-family:Arial,Helvetica,sans-serif;
50 | color:#004276;
51 | }
52 |
53 | .DV-triggers .DV-selected{
54 | font-weight:bold;
55 | color:#000;
56 | }
57 |
--------------------------------------------------------------------------------
/public/javascripts/DV/events/ViewAnnotation.js:
--------------------------------------------------------------------------------
1 | DV.Schema.events.ViewAnnotation = {
2 | next: function(e){
3 | var application = this.application;
4 | var activeAnnotationId = application.activeAnnotationId;
5 | var annotationsModel = this.models.annotations;
6 | var nextAnnotation = (activeAnnotationId === null) ?
7 | annotationsModel.getFirstAnnotation() : annotationsModel.getNextAnnotation(activeAnnotationId);
8 |
9 | if (!nextAnnotation){
10 | return false;
11 | }
12 |
13 | application.pageSet.showAnnotation(nextAnnotation);
14 | this.helpers.setAnnotationPosition(nextAnnotation.position);
15 |
16 |
17 | },
18 | previous: function(e){
19 | var application = this.application;
20 | var activeAnnotationId = application.activeAnnotationId;
21 | var annotationsModel = this.models.annotations;
22 |
23 | var previousAnnotation = (!activeAnnotationId) ?
24 | annotationsModel.getFirstAnnotation() : annotationsModel.getPreviousAnnotation(activeAnnotationId);
25 | if (!previousAnnotation){
26 | return false;
27 | }
28 |
29 | application.pageSet.showAnnotation(previousAnnotation);
30 | this.helpers.setAnnotationPosition(previousAnnotation.position);
31 |
32 |
33 | },
34 | search: function(e){
35 | e.preventDefault();
36 | this.states.ViewSearch();
37 |
38 | return false;
39 | }
40 | };
--------------------------------------------------------------------------------
/public/javascripts/DV/views/header.jst:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/viewer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document Title
8 |
9 |
10 |
11 |
12 |
13 |
14 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
Loading
25 |
26 |
27 | The Document Viewer requires that you enable Javascript.
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/view-search.css:
--------------------------------------------------------------------------------
1 | .DV-viewSearch #DV-pages{
2 | background-color:#999;
3 | }
4 |
5 | .DV-viewSearch #DV-textPage{
6 | background-color:#eee;
7 | }
8 |
9 | .DV-viewSearch .DV-zoomControls{
10 | display:none;
11 | }
12 |
13 | .DV-viewSearch #DV-pageCollection{
14 | cursor: text;
15 | }
16 |
17 | .DV-viewSearch #DV-annotations,
18 | .DV-viewSearch #DV-bar{
19 | display:none;
20 | }
21 |
22 | .DV-viewSearch #DV-search,
23 | .DV-viewSearch #DV-searchBar{
24 | display:block;
25 | }
26 |
27 | .DV-viewSearch #DV-totalAnnotations,
28 | .DV-viewSearch #DV-currentAnnotationPrefix{
29 | display:none;
30 | }
31 |
32 | .DV-viewSearch #DV-textPage{
33 | margin-top:50px;
34 | }
35 |
36 | .DV-viewSearch #DV-textCurrentPage{
37 | top:60px;
38 | }
39 |
40 | .DV-viewSearch #DV-sidebar #DV-well .DV-chaptersContainer div.DV-hasChildren div,
41 | .DV-viewSearch #DV-sidebar #DV-well .DV-chaptersContainer span.DV-expander,
42 | .DV-viewSearch .DV-annotationMarker{
43 | display:none !important;
44 | }
45 |
46 | .DV-viewSearch #DV-sidebar #DV-well .DV-chaptersContainer div.DV-hasChildren div.DV-first{
47 | display:block !important;
48 | }
49 |
50 | .DV-viewSearch #DV-sidebar #DV-well .DV-chaptersContainer div.DV-hasChildren div.DV-first span.DV-trigger{
51 | margin-left:-1px;
52 | }
53 |
54 | .DV-viewSearch #DV-textContents,
55 | .DV-viewSearch #DV-textPage{
56 | background-color:#c5c5c5;
57 | }
58 |
59 | .DV-viewSearch .DV-annotationMarker,
60 | .DV-viewSearch .DV-chapter{
61 | margin-left:14px;
62 | }
--------------------------------------------------------------------------------
/config/assets.yml:
--------------------------------------------------------------------------------
1 | embed_images: datauri
2 | template_function: _.template
3 |
4 | javascripts:
5 | viewer:
6 | - public/javascripts/DV/vendor/jquery-1.4.2.js
7 | - public/javascripts/DV/vendor/jquery-ui-1.8.1.custom.min.js
8 | - public/javascripts/DV/vendor/jquery.scrollTo-min.js
9 | - public/javascripts/DV/vendor/underscore.js
10 | - public/javascripts/DV/vendor/jquery.easing.compatibility.js
11 | - public/javascripts/DV/vendor/jquery.acceptInput.js
12 | - public/javascripts/DV/lib/initializer.js
13 | - public/javascripts/DV/lib/class.js
14 | - public/javascripts/DV/lib/history.js
15 | - public/javascripts/DV/lib/*.js
16 | - public/javascripts/DV/schema/*.js
17 | - public/javascripts/DV/elements/*.js
18 | - public/javascripts/DV/models/*.js
19 | - public/javascripts/DV/events/events.js
20 | - public/javascripts/DV/events/View*.js
21 | - public/javascripts/DV/events/*.js
22 | - public/javascripts/DV/helpers/helpers.js
23 | - public/javascripts/DV/helpers/*.js
24 | - public/javascripts/DV/states/states.js
25 | - public/javascripts/DV/states/*.js
26 | - public/javascripts/DV/controllers/documentViewer.js
27 | - public/javascripts/DV/controllers/*.js
28 |
29 | templates:
30 | - public/javascripts/DV/views/*.jst
31 |
32 | stylesheets:
33 | viewer:
34 | - public/stylesheets/DV/components/reset.css
35 | - public/stylesheets/DV/components/structure.css
36 | - public/stylesheets/DV/components/ui.css
37 | - public/stylesheets/DV/components/*.css
38 |
39 | plain:
40 | - public/stylesheets/DV/plain.css
41 |
42 |
--------------------------------------------------------------------------------
/public/javascripts/DV/lib/inflector.js:
--------------------------------------------------------------------------------
1 | window.Inflector = {
2 |
3 | camelize: function(s) {
4 | var parts = s.split('-'), len = parts.length;
5 | if (len == 1) return parts[0];
6 |
7 | var camelized = s.charAt(0) == '-'
8 | ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
9 | : parts[0];
10 |
11 | for (var i = 1; i < len; i++)
12 | camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
13 |
14 | return camelized;
15 | },
16 |
17 | capitalize: function(s) {
18 | return s.charAt(0).toUpperCase() + s.substring(1).toLowerCase();
19 | },
20 |
21 | underscore: function(s) {
22 | return s.replace(/::/g, '/').replace(/([A-Z]+)([A-Z][a-z])/g,'$1_$2').replace(/([a-z\d])([A-Z])/g,'$1_$2').replace(/-/g,'_').toLowerCase();
23 | },
24 |
25 | dasherize: function(s) {
26 | return s.replace(/_/g,'-');
27 | },
28 |
29 | singularize: function(s) {
30 | return s.replace(/e?s$/, '');
31 | },
32 |
33 | // Only works for words that pluralize by adding an 's'.
34 | pluralize: function(s, count) {
35 | return count != 1 ? s + 's' : s;
36 | },
37 |
38 | classify: function(s) {
39 | return this.camelize(this.capitalize(this.dasherize(this.singularize(s))));
40 | },
41 |
42 | truncate : function(s, length, truncation) {
43 | length = length || 30;
44 | truncation = _.isUndefined(truncation) ? '...' : truncation;
45 | return s.length > length ? s.slice(0, length - truncation.length) + truncation : s;
46 | },
47 |
48 | // Borrowed from Prototype 1.6
49 | stripTags: function(s) {
50 | return s.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
51 | }
52 |
53 |
54 | };
--------------------------------------------------------------------------------
/public/javascripts/DV/helpers/editor.js:
--------------------------------------------------------------------------------
1 | _.extend(DV.Schema.helpers,{
2 | showAnnotationEdit : function(e) {
3 | var annoEl = $j(e.target).closest(this.annotationClassName);
4 | annoEl.addClass('DV-editing');
5 | $j('.DV-annotationTextArea', annoEl).focus();
6 | },
7 | cancelAnnotationEdit : function(e) {
8 | var annoEl = $j(e.target).closest(this.annotationClassName);
9 | var anno = this.getAnnotationModel(annoEl);
10 | $j('.DV-annotationTitleInput', annoEl).val(anno.title);
11 | $j('.DV-annotationTextArea', annoEl).val(anno.text);
12 | if (anno.unsaved) {
13 | this.models.annotations.removeAnnotation(anno);
14 | } else {
15 | annoEl.removeClass('DV-editing');
16 | }
17 | },
18 | saveAnnotation : function(e, option) {
19 | var annoEl = $j(e.target).closest(this.annotationClassName);
20 | var anno = this.getAnnotationModel(annoEl);
21 | if (!anno) return;
22 | anno.title = $j('.DV-annotationTitleInput', annoEl).val();
23 | anno.text = $j('.DV-annotationTextArea', annoEl).val();
24 | if (option == 'onlyIfText' && (!anno.title || anno.title == 'Untitled Note') && !anno.text) {
25 | return this.models.annotations.removeAnnotation(anno);
26 | }
27 | this.models.annotations.refreshAnnotation(anno);
28 | annoEl.removeClass('DV-editing');
29 | DV.api.redraw();
30 | this.models.annotations.fireSaveCallbacks(anno);
31 | },
32 | deleteAnnotation : function(e) {
33 | var annoEl = $j(e.target).closest(this.annotationClassName);
34 | var anno = this.getAnnotationModel(annoEl);
35 | this.models.annotations.removeAnnotation(anno);
36 | this.models.annotations.fireDeleteCallbacks(anno);
37 | }
38 | });
--------------------------------------------------------------------------------
/public/javascripts/DV/events/navigation.js:
--------------------------------------------------------------------------------
1 | _.extend(DV.Schema.events, {
2 | handleNavigation: function(e){
3 | var el = $j(e.target);
4 | var parentEl = el.parent();
5 |
6 | if(el.hasClass('DV-trigger') || parentEl.hasClass('DV-trigger')){
7 |
8 | if(el.hasClass('DV-expander')){
9 | return parentEl.parent().toggleClass('DV-expanded');
10 |
11 | }else if(parentEl.hasClass('DV-first')){
12 | // its a header, take it to the page
13 | parentEl.parent().addClass('DV-expanded');
14 | var cid = parseInt(parentEl.parent()[0].id.replace('DV-chapter-',''), 10);
15 | var chapterIndex = parseInt(this.models.chapters.getChapterPosition(cid),10);
16 | var pageNumber = parseInt(chapterIndex,10)+1;
17 |
18 | if(this.application.state === 'ViewText'){
19 | this.loadText(chapterIndex);
20 | DV.history.save('text/p'+pageNumber);
21 | }else if(this.application.state === 'ViewDocument'){
22 | this.helpers.jump(chapterIndex);
23 | DV.history.save('document/p'+pageNumber);
24 | }else{
25 | return false;
26 | }
27 |
28 | }else if(parentEl[0].tagName.toUpperCase() === 'DIV'){
29 | var aid = parentEl[0].id.replace('DV-annotationMarker-','');
30 | var annotation = this.models.annotations.getAnnotation(aid);
31 | var pageNumber = parseInt(annotation.index,10)+1;
32 |
33 | if(this.application.state === 'ViewText'){
34 | this.loadText(annotation.index);
35 |
36 | DV.history.save('text/p'+pageNumber);
37 | }else{
38 | this.application.pageSet.showAnnotation(annotation);
39 | }
40 |
41 | }else{
42 | return false;
43 | }
44 | }
45 | }
46 | });
--------------------------------------------------------------------------------
/public/javascripts/DV/controllers/documentViewer.js:
--------------------------------------------------------------------------------
1 | DV.controller = new DV.stateMachine(DV.Schema.states,
2 | {
3 | events : DV.Schema.events,
4 | elements : DV.Schema.elements,
5 | helpers : DV.Schema.helpers,
6 | models : DV.Schema.models
7 | }
8 | );
9 |
10 | // The origin function, kicking off the entire documentViewer render.
11 | DV.load = function(documentRep, options) {
12 | options = options || {};
13 | DV.container = options.container || document.body;
14 | DV.options = options;
15 |
16 | // Once we have the JSON representation in-hand, finish loading the viewer.
17 | var continueLoad = DV.loadJSON = function(json) {
18 | DV.Schema.importCanonicalDocument(json);
19 | DV.controller.states.InitialLoad();
20 | if (options.afterLoad) options.afterLoad();
21 | if (DV.afterLoad) DV.afterLoad();
22 | };
23 |
24 | // If we've been passed the JSON directly, we can go ahead,
25 | // otherwise make a JSONP request to fetch it.
26 | var jsonLoad = function() {
27 | if (_.isString(documentRep)) {
28 | if (documentRep.match(/\.js$/)) {
29 | $j.getScript(documentRep);
30 | } else {
31 | var crossDomain = DV.controller.helpers.isCrossDomain(documentRep);
32 | if (crossDomain) documentRep = documentRep + '?callback=?';
33 | $j.getJSON(documentRep, continueLoad);
34 | }
35 | } else {
36 | continueLoad(documentRep);
37 | }
38 | };
39 |
40 | // If we're being asked the fetch the templates, load them remotely before
41 | // continuing.
42 | if (options.templates) {
43 | $j.getScript(options.templates, jsonLoad);
44 | } else {
45 | jsonLoad();
46 | }
47 | };
48 |
49 | // If the document viewer has been loaded dynamically, allow the external
50 | // script to specify the onLoad behavior.
51 | if (DV.onload) setTimeout(DV.onload, 0);
52 |
53 |
--------------------------------------------------------------------------------
/public/javascripts/DV/vendor/jquery.easing.compatibility.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery Easing Compatibility v1 - http://gsgd.co.uk/sandbox/jquery.easing.php
3 | *
4 | * Adds compatibility for applications that use the pre 1.2 easing names
5 | *
6 | * Copyright (c) 2007 George Smith
7 | * Licensed under the MIT License:
8 | * http://www.opensource.org/licenses/mit-license.php
9 | */
10 |
11 | jQuery.extend( jQuery.easing,
12 | {
13 | easeIn: function (x, t, b, c, d) {
14 | return jQuery.easing.easeInQuad(x, t, b, c, d);
15 | },
16 | easeOut: function (x, t, b, c, d) {
17 | return jQuery.easing.easeOutQuad(x, t, b, c, d);
18 | },
19 | easeInOut: function (x, t, b, c, d) {
20 | return jQuery.easing.easeInOutQuad(x, t, b, c, d);
21 | },
22 | expoin: function(x, t, b, c, d) {
23 | return jQuery.easing.easeInExpo(x, t, b, c, d);
24 | },
25 | expoout: function(x, t, b, c, d) {
26 | return jQuery.easing.easeOutExpo(x, t, b, c, d);
27 | },
28 | expoinout: function(x, t, b, c, d) {
29 | return jQuery.easing.easeInOutExpo(x, t, b, c, d);
30 | },
31 | bouncein: function(x, t, b, c, d) {
32 | return jQuery.easing.easeInBounce(x, t, b, c, d);
33 | },
34 | bounceout: function(x, t, b, c, d) {
35 | return jQuery.easing.easeOutBounce(x, t, b, c, d);
36 | },
37 | bounceinout: function(x, t, b, c, d) {
38 | return jQuery.easing.easeInOutBounce(x, t, b, c, d);
39 | },
40 | elasin: function(x, t, b, c, d) {
41 | return jQuery.easing.easeInElastic(x, t, b, c, d);
42 | },
43 | elasout: function(x, t, b, c, d) {
44 | return jQuery.easing.easeOutElastic(x, t, b, c, d);
45 | },
46 | elasinout: function(x, t, b, c, d) {
47 | return jQuery.easing.easeInOutElastic(x, t, b, c, d);
48 | },
49 | backin: function(x, t, b, c, d) {
50 | return jQuery.easing.easeInBack(x, t, b, c, d);
51 | },
52 | backout: function(x, t, b, c, d) {
53 | return jQuery.easing.easeOutBack(x, t, b, c, d);
54 | },
55 | backinout: function(x, t, b, c, d) {
56 | return jQuery.easing.easeInOutBack(x, t, b, c, d);
57 | }
58 | });
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/ui-menu.css:
--------------------------------------------------------------------------------
1 | #DV-Controls{
2 | background-color:#f0f4f5;
3 | height:37px;
4 | border-bottom:1px solid #ABABAB;
5 | border-top:1px solid #ABABAB;
6 | margin-top:10px;
7 | position:relative;
8 | }
9 |
10 | .DV-views{
11 | list-style-type:none;
12 | float:left;
13 | display:inline;
14 | margin:0 0 0 10px; padding:0;
15 | }
16 |
17 | .DV-views div{
18 | list-style-type:none;
19 | float:left;
20 | display:inline;
21 | margin:8px 0 0; padding:0;
22 | }
23 |
24 | .DV-ie6 .DV-views{
25 | position:absolute;
26 | }
27 |
28 | .DV-views div span{
29 | display:block;
30 | padding:8px 14px;
31 | background-color:#f4f4f4;
32 | border:1px solid #ababab;
33 | font-family:Arial,Helvetica,sans-serif;
34 | font-size:10px;
35 | text-decoration:none;
36 | height:12px;
37 | border-left:none;
38 | border-bottom:1px solid #ababab;
39 | text-transform:uppercase;
40 | color:#666;
41 | }
42 |
43 | .DV-ie6 .DV-views div span{
44 | display:inline-block;
45 | padding-bottom:7px;
46 | }
47 |
48 | .DV-views div.DV-first span{
49 | border-left:1px solid #ababab;
50 | }
51 |
52 | .DV-views div span:hover,
53 | .DV-viewDocument .DV-views #DV-documentView span,
54 | .DV-viewAnnotations .DV-views #DV-annotationView span,
55 | .DV-viewText .DV-views #DV-textView span,
56 | .DV-viewSearch .DV-views #DV-textView span{
57 | text-decoration:none;
58 | background-color:#fff;
59 | color:#000;
60 | }
61 |
62 | .DV-views div a:focus{
63 | outline:0;
64 | }
65 |
66 | .DV-viewDocument .DV-views #DV-documentView span,
67 | .DV-viewAnnotations .DV-views #DV-annotationView span,
68 | .DV-viewText .DV-views #DV-textView span,
69 | .DV-viewSearch .DV-views #DV-textView span{
70 | border-bottom:1px solid #fff;
71 | font-weight:bold;
72 | }
73 |
74 |
75 | .DV-ie6.DV-viewDocument .DV-views #DV-documentView span,
76 | .DV-ie6.DV-viewAnnotations .DV-views #DV-annotationView span,
77 | .DV-ie6.DV-viewText .DV-views #DV-textView span,
78 | .DV-ie6.DV-viewSearch .DV-views #DV-textView span{
79 | padding-bottom:8px;
80 | }
--------------------------------------------------------------------------------
/public/javascripts/DV/lib/class.js:
--------------------------------------------------------------------------------
1 | // Inspired by base2 and Prototype
2 | (function(){
3 | var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
4 |
5 | // The base Class implementation (does nothing)
6 | DV.Class = function(){};
7 |
8 | // Create a new Class that inherits from this class
9 | DV.Class.extend = function(prop) {
10 | var _super = this.prototype;
11 |
12 | // Instantiate a base class (but only create the instance,
13 | // don't run the init constructor)
14 | initializing = true;
15 | var prototype = new this();
16 | initializing = false;
17 |
18 | // Copy the properties over onto the new prototype
19 | for (var name in prop) {
20 | // Check if we're overwriting an existing function
21 | prototype[name] = typeof prop[name] == "function" &&
22 | typeof _super[name] == "function" && fnTest.test(prop[name]) ?
23 | (function(name, fn){
24 | return function() {
25 | var tmp = this._super;
26 |
27 | // Add a new ._super() method that is the same method
28 | // but on the super-class
29 | this._super = _super[name];
30 |
31 | // The method only need to be bound temporarily, so we
32 | // remove it when we're done executing
33 | var ret = fn.apply(this, arguments);
34 | this._super = tmp;
35 |
36 | return ret;
37 | };
38 | })(name, prop[name]) :
39 | prop[name];
40 | }
41 |
42 | // The dummy class constructor
43 | function Class() {
44 | // All construction is actually done in the init method
45 | if ( !initializing && this.init )
46 | this.init.apply(this, arguments);
47 | }
48 |
49 | // Populate our constructed prototype object
50 | Class.prototype = prototype;
51 |
52 | // Enforce the constructor to be what we expect
53 | Class.constructor = Class;
54 |
55 | // And make this class extendable
56 | Class.extend = arguments.callee;
57 |
58 | return Class;
59 | };
60 | })();
61 |
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/structure.css:
--------------------------------------------------------------------------------
1 | /* Only global rule. Hide overflow. */
2 | body, html{
3 | overflow: hidden;
4 | }
5 |
6 | #DV-docViewer{
7 | position: relative;
8 | text-align: left;
9 | line-height: normal;
10 | }
11 |
12 | #DV-docViewer-Container{
13 | position:absolute;
14 | top: 39px; bottom: 0px; left: 0px; right: 0px;
15 | margin: 0;
16 | overflow: hidden;
17 | border: 1px solid #ababab; border-left: 0; border-right: 0;
18 | }
19 |
20 | #DV-bar{
21 | width:1px;
22 | }
23 |
24 | #DV-docViewer table{
25 | border-collapse:collapse;
26 | position:relative;
27 | }
28 |
29 | #DV-docViewer td{
30 | position:relative;
31 | vertical-align:top;
32 | }
33 |
34 | #DV-annotations {
35 | padding: 0 60px;
36 | }
37 |
38 | #DV-well{
39 | width:265px;
40 | position:absolute;
41 | border-left:1px solid #ababab;
42 | left: auto; top: 0; bottom: 0; right: 0;
43 | overflow-y:auto;
44 | background: white;
45 | }
46 |
47 | #DV-navControls{
48 | background-color: #fff;
49 | background-repeat: repeat-x;
50 | background-image: url(../../../images/DV/embed/shadow-white.gif);
51 | }
52 |
53 | #DV-pages{
54 | background-color:#ccc;
55 | overflow: auto;
56 | position: absolute;
57 | left: 0; right: 266px; top: 0; bottom: 0;
58 | z-index:10001;
59 | }
60 |
61 | #DV-pageCollection{
62 | margin: 20px auto;
63 | position:relative;
64 | z-index:0;
65 | }
66 |
67 | #DV-pageCollection{
68 | cursor: url(../../../images/DV/grab.cur), auto;
69 | cursor: -moz-grab;
70 | }
71 |
72 | #DV-pageCollection.DV-dragging {
73 | cursor: url(../../../images/DV/grabbing.cur), auto;
74 | cursor: -moz-grabbing;
75 | }
76 |
77 | #DV-loadingDocument {
78 | margin-top: 10px;
79 | text-align:center;
80 | }
81 |
82 | #DV-loadingDocument span{
83 | font-family:Arial,Helvetica,sans-serif;
84 | font-weight:normal;
85 | font-size:12px;
86 | color:#666;
87 | padding:10px;
88 | font-style:oblique;
89 | padding-left:24px;
90 | margin: 10px auto;
91 | background:url(../../../images/DV/embed/spinner.gif) no-repeat left 8px;
92 | }
93 |
94 | #DV-loadingDocument strong{
95 | font-weight:normal;
96 | color:#666;
97 | }
--------------------------------------------------------------------------------
/public/javascripts/DV/states/states.js:
--------------------------------------------------------------------------------
1 | DV.Schema.states = {
2 | // state values
3 | isFocus: true,
4 | // IE activeElement tracker
5 | activeElement: null,
6 | observers: [],
7 | windowDimensions: {},
8 | scrollPosition: null,
9 | checkTimer: {},
10 | busy: false,
11 | annotationToLoadId: null,
12 | dragReporter: null,
13 | compiled: {},
14 | tracker: {},
15 |
16 | InitialLoad: {
17 | enter: function(sourceState){
18 | // If we're in an unsupported browser ... bail.
19 | if (this.helpers.unsupportedBrowser()) return;
20 |
21 | // Insert the Document Viewer HTML into the DOM.
22 | this.helpers.renderViewer();
23 | this.scrollBarWidth = ($j.browser.msie === true) ? 19 : 17;
24 |
25 | // Assign element references.
26 | this.events.elements = this.helpers.elements = this.elements = new DV.Elements(this.pendingElements);
27 |
28 | // Build the data models
29 | this.models.document.init();
30 | this.models.pages.init();
31 | this.models.chapters.init();
32 | this.models.annotations.init();
33 |
34 | // Render included components, and hide unused portions of the UI.
35 | this.helpers.renderComponents();
36 |
37 | // Render chapters and notes navigation:
38 | this.helpers.renderNavigation();
39 |
40 | // Instantiate pageset and build accordingly
41 | this.pageSet = new DV.pageSet(this);
42 | this.pageSet.buildPages();
43 |
44 | // BindEvents
45 | this.helpers.bindEvents(this);
46 | },
47 | InitialLoad: function(){
48 | this.helpers.positionViewer();
49 | this.models.document.computeOffsets();
50 | this.helpers.addObserver('drawPages');
51 | this.helpers.registerHashChangeEvents();
52 | this.helpers.handleInitialState();
53 | },
54 | exit: function(destinationState){
55 | this.dragReporter = new DV.dragReporter('#DV-pageCollection',$j.proxy(this.helpers.shift, this), { ignoreSelector: '.DV-annotationRegion,.DV-annotationContent' });
56 | // Start polling every 100ms
57 | this.helpers.startCheckTimer();
58 | }
59 | }
60 | };
61 |
--------------------------------------------------------------------------------
/public/javascripts/DV/vendor/jquery.scrollTo-min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * jQuery.ScrollTo - Easy element scrolling using jQuery.
3 | * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
4 | * Dual licensed under MIT and GPL.
5 | * Date: 5/25/2009
6 | * @author Ariel Flesler
7 | * @version 1.4.2
8 | *
9 | * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
10 | */
11 | ;(function(d){var k=d.scrollTo=function(a,i,e){d(window).scrollTo(a,i,e)};k.defaults={axis:'xy',duration:parseFloat(d.fn.jquery)>=1.3?0:1};k.window=function(a){return d(window)._scrollable()};d.fn._scrollable=function(){return this.map(function(){var a=this,i=!a.nodeName||d.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!i)return a;var e=(a.contentWindow||a).document||a.ownerDocument||a;return d.browser.safari||e.compatMode=='BackCompat'?e.body:e.documentElement})};d.fn.scrollTo=function(n,j,b){if(typeof j=='object'){b=j;j=0}if(typeof b=='function')b={onAfter:b};if(n=='max')n=9e9;b=d.extend({},k.defaults,b);j=j||b.speed||b.duration;b.queue=b.queue&&b.axis.length>1;if(b.queue)j/=2;b.offset=p(b.offset);b.over=p(b.over);return this._scrollable().each(function(){var q=this,r=d(q),f=n,s,g={},u=r.is('html,body');switch(typeof f){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(f)){f=p(f);break}f=d(f,this);case'object':if(f.is||f.style)s=(f=d(f)).offset()}d.each(b.axis.split(''),function(a,i){var e=i=='x'?'Left':'Top',h=e.toLowerCase(),c='scroll'+e,l=q[c],m=k.max(q,i);if(s){g[c]=s[h]+(u?0:l-r.offset()[h]);if(b.margin){g[c]-=parseInt(f.css('margin'+e))||0;g[c]-=parseInt(f.css('border'+e+'Width'))||0}g[c]+=b.offset[h]||0;if(b.over[h])g[c]+=f[i=='x'?'width':'height']()*b.over[h]}else{var o=f[h];g[c]=o.slice&&o.slice(-1)=='%'?parseFloat(o)/100*m:o}if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],m);if(!a&&b.queue){if(l!=g[c])t(b.onAfterFirst);delete g[c]}});t(b.onAfter);function t(a){r.animate(g,j,b.easing,a&&function(){a.call(this,n,b)})}}).end()};k.max=function(a,i){var e=i=='x'?'Width':'Height',h='scroll'+e;if(!d(a).is('html,body'))return a[h]-d(a)[e.toLowerCase()]();var c='client'+e,l=a.ownerDocument.documentElement,m=a.ownerDocument.body;return Math.max(l[h],m[h])-Math.min(l[c],m[c])};function p(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);
--------------------------------------------------------------------------------
/public/javascripts/DV/views/viewer.jst:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <%= header %>
5 |
6 |
7 |
8 |
9 | CLOSE
10 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
38 | <%= pages %>
39 |
40 |
41 |
42 |
43 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/public/assets/plain.css:
--------------------------------------------------------------------------------
1 | #DV-docViewer.DV-embedded{border:1px solid #c3c3c3;}#DV-headerHat,#DV-title,.DV-contentsHeader{display:none!important;}#DV-header{padding:0;border-bottom:2px solid #979797;position:relative;z-index:20000;box-shadow:0 0 25px rgba(0,0,0,.5);-webkit-box-shadow:0 0 25px rgba(0,0,0,.5);-moz-box-shadow:0 0 25px rgba(0,0,0,.5);}#DV-Controls{margin-top:0;border:0;background:#d7d7d7;background:-webkit-gradient(linear,left top,left bottom,from(#EAEAEA),to(#C2C2C2));background:-moz-linear-gradient(top,#EAEAEA,#C2C2C2);filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#EAEAEA',EndColorStr='#C2C2C2');text-shadow:0 1px 1px #fff;color:#2C2C2C;overflow:hidden;}#DV-searchInput{width:170px;border:1px solid #999;padding:3px 3px;-moz-border-radius:4px;}#DV-searchSubmit{background:#e7e7e7;color:#4F4F4F;height:auto;padding:3px 10px;font-weight:bold;border:1px solid #999;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px;background:-webkit-gradient(linear,left top,left bottom,from(#fefefe),to(#c4c4c4));background:-moz-linear-gradient(top,#fefefe,#c4c4c4);filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#FEFEFE',EndColorStr='#C4C4C4');text-shadow:0 1px 1px #fff;cursor:pointer;font-size:11px;}div.DV-ie #DV-searchSubmit{font-size:10px;padding:4px 3px 3px;}#DV-docViewer-Container{margin:0;border:0;}#DV-pages{padding-bottom:16px;background:#bbb;}#DV-well{padding-bottom:16px;}#DV-descriptionHead{text-transform:none;color:black;}#DV-descriptionText{background:white;padding:5px 14px 10px;}.DV-views{position:relative;z-index:10;}.DV-views div span{border-bottom:0!important;background:#e3e3e3;color:black!important;background:-webkit-gradient(linear,left top,left bottom,from(#E3E3E3),to(#C2C2C2));background:-moz-linear-gradient(top,#EAEAEA,#C2C2C2);filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#EAEAEA',EndColorStr='#C2C2C2');}.DV-views #DV-documentView span{-webkit-border-top-left-radius:5px;-moz-border-radius-topleft:5px;}#DV-textView span{-webkit-border-top-right-radius:5px;-moz-border-radius-topright:5px;}.DV-viewDocument .DV-views #DV-documentView span,.DV-viewAnnotations .DV-views #DV-annotationView span,.DV-viewText .DV-views #DV-textView span,.DV-viewSearch .DV-views #DV-textView span{background:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#a0a0a0));background:-moz-linear-gradient(top,#fff,#a0a0a0);filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#FFFFFF',EndColorStr='#A0A0A0');}
--------------------------------------------------------------------------------
/public/assets/plain-datauri.css:
--------------------------------------------------------------------------------
1 | #DV-docViewer.DV-embedded{border:1px solid #c3c3c3;}#DV-headerHat,#DV-title,.DV-contentsHeader{display:none!important;}#DV-header{padding:0;border-bottom:2px solid #979797;position:relative;z-index:20000;box-shadow:0 0 25px rgba(0,0,0,.5);-webkit-box-shadow:0 0 25px rgba(0,0,0,.5);-moz-box-shadow:0 0 25px rgba(0,0,0,.5);}#DV-Controls{margin-top:0;border:0;background:#d7d7d7;background:-webkit-gradient(linear,left top,left bottom,from(#EAEAEA),to(#C2C2C2));background:-moz-linear-gradient(top,#EAEAEA,#C2C2C2);filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#EAEAEA',EndColorStr='#C2C2C2');text-shadow:0 1px 1px #fff;color:#2C2C2C;overflow:hidden;}#DV-searchInput{width:170px;border:1px solid #999;padding:3px 3px;-moz-border-radius:4px;}#DV-searchSubmit{background:#e7e7e7;color:#4F4F4F;height:auto;padding:3px 10px;font-weight:bold;border:1px solid #999;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px;background:-webkit-gradient(linear,left top,left bottom,from(#fefefe),to(#c4c4c4));background:-moz-linear-gradient(top,#fefefe,#c4c4c4);filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#FEFEFE',EndColorStr='#C4C4C4');text-shadow:0 1px 1px #fff;cursor:pointer;font-size:11px;}div.DV-ie #DV-searchSubmit{font-size:10px;padding:4px 3px 3px;}#DV-docViewer-Container{margin:0;border:0;}#DV-pages{padding-bottom:16px;background:#bbb;}#DV-well{padding-bottom:16px;}#DV-descriptionHead{text-transform:none;color:black;}#DV-descriptionText{background:white;padding:5px 14px 10px;}.DV-views{position:relative;z-index:10;}.DV-views div span{border-bottom:0!important;background:#e3e3e3;color:black!important;background:-webkit-gradient(linear,left top,left bottom,from(#E3E3E3),to(#C2C2C2));background:-moz-linear-gradient(top,#EAEAEA,#C2C2C2);filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#EAEAEA',EndColorStr='#C2C2C2');}.DV-views #DV-documentView span{-webkit-border-top-left-radius:5px;-moz-border-radius-topleft:5px;}#DV-textView span{-webkit-border-top-right-radius:5px;-moz-border-radius-topright:5px;}.DV-viewDocument .DV-views #DV-documentView span,.DV-viewAnnotations .DV-views #DV-annotationView span,.DV-viewText .DV-views #DV-textView span,.DV-viewSearch .DV-views #DV-textView span{background:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#a0a0a0));background:-moz-linear-gradient(top,#fff,#a0a0a0);filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#FFFFFF',EndColorStr='#A0A0A0');}
--------------------------------------------------------------------------------
/public/javascripts/DV/schema/schema.js:
--------------------------------------------------------------------------------
1 | DV.Schema = function(){
2 | return{
3 | models: {},
4 | views: {},
5 | states: {},
6 | helpers: {},
7 | events: {},
8 | elements: {},
9 | text: {},
10 | data: {
11 | zoomLevel : 700,
12 | pageWidthPadding : 20,
13 | additionalPaddingOnPage : 30,
14 | state : { page: { previous: 0, current: 0, next: 1 } }
15 | },
16 |
17 | // Imports the document's JSON representation into the DV.Schema form that
18 | // the models expect.
19 | importCanonicalDocument : function(json) {
20 | // Ensure at least empty arrays for sections.
21 | json.sections = json.sections || [];
22 | json.annotations = json.annotations || [];
23 |
24 | this.document = $j.extend(true, {}, json);
25 | // Everything after this line is for back-compatibility.
26 | this.data.title = json.title;
27 | this.data.totalPages = json.pages;
28 | this.data.totalAnnotations = json.annotations.length;
29 | this.data.sections = json.sections;
30 | this.data.chapters = [];
31 | this.data.annotationsById = {};
32 | this.data.annotationsByPage = {};
33 | _.each(json.annotations, $j.proxy(this.loadAnnotation, this));
34 | },
35 |
36 | // Load an annotation into the Schema, starting from the canonical format.
37 | loadAnnotation : function(anno) {
38 | if (anno.id) anno.server_id = anno.id;
39 | var idx = anno.page - 1;
40 | anno.id = _.uniqueId();
41 | anno.title = anno.title || 'Untitled Note';
42 | anno.text = anno.content || '';
43 | anno.access = anno.access || 'public';
44 | anno.type = anno.location && anno.location.image ? 'region' : 'page';
45 | if (anno.type === 'region') {
46 | var loc = $j.map(anno.location.image.split(','), function(n, i) { return parseInt(n, 10); });
47 | anno.y1 = loc[0]; anno.x2 = loc[1]; anno.y2 = loc[2]; anno.x1 = loc[3];
48 | }else if(anno.type === 'page'){
49 | anno.y1 = 0; anno.x2 = 0; anno.y2 = 0; anno.x1 = 0;
50 | }
51 | this.data.annotationsById[anno.id] = anno;
52 | var page = this.data.annotationsByPage[idx] = this.data.annotationsByPage[idx] || [];
53 | var insertionIndex = _.sortedIndex(page, anno, function(a){ return a.y1; });
54 | page.splice(insertionIndex, 0, anno);
55 | return anno;
56 | }
57 | };
58 | }();
59 |
--------------------------------------------------------------------------------
/public/javascripts/DV/views/annotation.jst:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | <%= text %>
40 |
41 |
42 |
43 |
44 |
45 |
Delete
46 |
Save
47 |
Cancel
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/public/javascripts/DV/tests/testsuite.css:
--------------------------------------------------------------------------------
1 | body, div, h1 { font-family: 'trebuchet ms', verdana, arial; margin: 0; padding: 0 }
2 | body {font-size: 10pt; }
3 | h1 { padding: 15px; font-size: large; background-color: #06b; color: white; }
4 | h1 a { color: white; }
5 | h2 { padding: 10px; background-color: #eee; color: black; margin: 0; font-size: small; font-weight: normal }
6 |
7 | .pass { color: green; }
8 | .fail { color: red; }
9 | p.result { margin-left: 1em; }
10 |
11 | #banner { height: 2em; border-bottom: 1px solid white; }
12 | h2.pass { background-color: green; }
13 | h2.fail { background-color: red; }
14 |
15 | div.testrunner-toolbar { background: #eee; border-top: 1px solid black; padding: 10px; }
16 |
17 | ol#tests li strong { cursor:pointer; }
18 |
19 | div#fx-tests h4 {
20 | background: red;
21 | }
22 |
23 | div#fx-tests h4.pass {
24 | background: green;
25 | }
26 |
27 | div#fx-tests div.box {
28 | background: red url(data/cow.jpg) no-repeat;
29 | overflow: hidden;
30 | border: 2px solid #000;
31 | }
32 |
33 | div#fx-tests div.overflow {
34 | overflow: visible;
35 | }
36 |
37 | div.inline {
38 | display: inline;
39 | }
40 |
41 | div.autoheight {
42 | height: auto;
43 | }
44 |
45 | div.autowidth {
46 | width: auto;
47 | }
48 |
49 | div.autoopacity {
50 | opacity: auto;
51 | }
52 |
53 | div.largewidth {
54 | width: 100px;
55 | }
56 |
57 | div.largeheight {
58 | height: 100px;
59 | }
60 |
61 | div.largeopacity {
62 | filter: progid:DXImageTransform.Microsoft.Alpha(opacity=100);
63 | }
64 |
65 | div.medwidth {
66 | width: 50px;
67 | }
68 |
69 | div.medheight {
70 | height: 50px;
71 | }
72 |
73 | div.medopacity {
74 | opacity: 0.5;
75 | filter: progid:DXImageTransform.Microsoft.Alpha(opacity=50);
76 | }
77 |
78 | div.nowidth {
79 | width: 0px;
80 | }
81 |
82 | div.noheight {
83 | height: 0px;
84 | }
85 |
86 | div.noopacity {
87 | opacity: 0;
88 | filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0);
89 | }
90 |
91 | div.hidden {
92 | display: none;
93 | }
94 |
95 | div#fx-tests div.widewidth {
96 | background-repeat: repeat-x;
97 | }
98 |
99 | div#fx-tests div.wideheight {
100 | background-repeat: repeat-y;
101 | }
102 |
103 | div#fx-tests div.widewidth.wideheight {
104 | background-repeat: repeat;
105 | }
106 |
107 | div#fx-tests div.noback {
108 | background-image: none;
109 | }
110 |
111 | div.chain, div.chain div { width: 100px; height: 20px; position: relative; float: left; }
112 | div.chain div { position: absolute; top: 0px; left: 0px; }
113 |
114 | div.chain.test { background: red; }
115 | div.chain.test div { background: green; }
116 |
117 | div.chain.out { background: green; }
118 | div.chain.out div { background: red; display: none; }
119 |
120 | div#show-tests * { display: none; }
121 |
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/view-annotations.css:
--------------------------------------------------------------------------------
1 | .DV-viewAnnotations .DV-set,
2 | .DV-viewAnnotations #DV-text,
3 | .DV-viewAnnotations #DV-search,
4 | .DV-viewAnnotations #DV-bar{
5 | display:none;
6 | }
7 |
8 | .DV-viewAnnotations #DV-annotations,
9 | .DV-viewAnnotations .DV-annotationContent{
10 | display:block;
11 | }
12 |
13 | .DV-viewAnnotations .DV-annotationRegion{
14 | position: absolute;
15 | left: -10000px;
16 | width: 0; height: 0;
17 | }
18 |
19 | .DV-viewAnnotations .DV-annotationTab{
20 |
21 | filter:none;
22 | display:none !important;
23 | }
24 |
25 | .DV-viewAnnotations .DV-annotationGoto{
26 | display:inline;
27 | }
28 |
29 | .DV-viewAnnotations .DV-pageNoteAnnotationTab{
30 | display:none;
31 | }
32 |
33 | .DV-viewAnnotations .DV-annotationNext,
34 | .DV-viewAnnotations .DV-annotationPrevious{
35 | display:none !important;
36 | }
37 |
38 | .DV-viewAnnotations .DV-annotationBG{
39 | margin-top:0;
40 | position:relative;
41 | clear:left;
42 | }
43 |
44 | .DV-viewAnnotations .DV-annotation,
45 | .DV-getHeights .DV-annotation {
46 | position:relative;
47 | top:0 !important;
48 | display: inline-block;
49 | margin: 0 auto 25px;
50 |
51 | background: rgb(255, 227, 37);
52 | background: rgba(255, 227, 37, .9);
53 |
54 | -webkit-border-radius:4px;
55 | -moz-border-radius:4px;
56 | border-radius:4px;
57 |
58 | -webkit-box-shadow: 1px 1px 3px rgb(0,0,0);
59 | -webkit-box-shadow: 1px 1px 3px rgba(0,0,0,.2);
60 |
61 | -moz-box-shadow: 1px 1px 3px rgb(0,0,0);
62 | -moz-box-shadow: 1px 1px 3px rgba(0,0,0,.2);
63 |
64 | box-shadow: 1px 1px 3px rgb(0,0,0);
65 | box-shadow: 1px 1px 3px rgba(0,0,0,.2);
66 | }
67 | .DV-viewAnnotations .DV-annotation.DV-private {
68 | background: rgb(107, 194, 248);
69 | background: rgba(107, 194, 248, .9);
70 | }
71 |
72 | /*hack to control scrollbar width in webkit*/
73 | .DV-viewAnnotations .DV-annotation:after {
74 | content: ".";
75 | display: block;
76 | height: 0;
77 | clear: both;
78 | visibility: hidden;
79 | }
80 |
81 | /* Hides from IE-mac \*/
82 | * html .DV-viewAnnotations .DV-annotation {height: 1%;}
83 | .DV-viewAnnotations .DV-annotation {display: block;}
84 | /* End hide from IE-mac */
85 |
86 | .DV-viewAnnotations #DV-currentPagePrefix,
87 | .DV-viewAnnotations #DV-totalPages{
88 | display:none;
89 | }
90 |
91 | .DV-viewAnnotations #DV-currentAnnotationPrefix,
92 | .DV-viewAnnotations #DV-totalAnnotations{
93 | display:inline;
94 | }
95 |
96 |
97 | .DV-ie .DV-viewAnnotations .DV-annotationLabel {
98 | float:none;
99 | left:0;
100 | position:absolute;
101 | top:7px;
102 | }
103 |
104 | .DV-viewAnnotations .DV-noChildren{
105 | display:none !important;
106 | }
107 |
108 | .DV-viewAnnotations .DV-hasChildren{
109 | display:block !important;
110 | }
111 |
--------------------------------------------------------------------------------
/public/javascripts/DV/events/history.js:
--------------------------------------------------------------------------------
1 | _.extend(DV.Schema.events, {
2 | // [document-slug]#document/p[pageID]
3 | handleHashChangeViewDocumentPage: function(page){
4 | var pageIndex = parseInt(page,10) - 1;
5 | if(this.application.state === 'ViewDocument'){
6 | this.application.pageSet.cleanUp();
7 | this.helpers.jump(pageIndex);
8 | }else{
9 | this.models.document.setPageIndex(pageIndex);
10 | this.states.ViewDocument();
11 | }
12 | },
13 | // [document-slug]#p=1
14 | handleHashChangeLegacyViewDocumentPage: function(page){
15 | var pageIndex = parseInt(page,10) - 1;
16 | this.handleHashChangeViewDocumentPage(page);
17 | },
18 | // [document-slug]#document/p[pageID]/a[annotationID]
19 | handleHashChangeViewDocumentAnnotation: function(page,annotation){
20 | var pageIndex = parseInt(page,10) - 1;
21 | var annotation = parseInt(annotation,10);
22 |
23 | if(this.application.state === 'ViewDocument'){
24 | this.application.pageSet.showAnnotation(this.application.models.annotations.byId[annotation]);
25 | }else{
26 | this.models.document.setPageIndex(pageIndex);
27 | this.application.pageSet.setActiveAnnotation(annotation);
28 | this.states.ViewDocument();
29 | }
30 |
31 | },
32 | // [document-slug]#annotation/a[annotationID]
33 | handleHashChangeViewAnnotationAnnotation: function(annotation){
34 |
35 | var annotation = parseInt(annotation,10);
36 | var application = this.application;
37 |
38 | if(application.state === 'ViewAnnotation'){
39 | application.pageSet.showAnnotation(this.application.models.annotations.byId[annotation]);
40 | }else{
41 | application.activeAnnotationId = annotation;
42 | this.states.ViewAnnotation();
43 | }
44 | },
45 | // Default route if all else fails
46 | handleHashChangeDefault: function(){
47 |
48 | this.application.pageSet.cleanUp();
49 | this.models.document.setPageIndex(0);
50 |
51 | if(this.application.state === 'ViewDocument'){
52 | this.helpers.jump(0);
53 | DV.history.save('document/p1');
54 | }else{
55 | this.states.ViewDocument();
56 | }
57 |
58 | },
59 | // [document-slug]#text/p[pageID]
60 | handleHashChangeViewText: function(page){
61 | var pageIndex = parseInt(page,10) - 1;
62 | if(this.application.state === 'ViewText'){
63 | this.events.loadText(pageIndex);
64 | }else{
65 | this.models.document.setPageIndex(pageIndex);
66 | this.states.ViewText();
67 | }
68 | },
69 | // [document-slug]#search/[searchString]
70 | handleHashChangeViewSearchRequest: function(page,query){
71 | var pageIndex = parseInt(page,10) - 1;
72 | this.elements.searchInput.val(decodeURIComponent(query));
73 |
74 | if(this.application.state !== 'ViewSearch'){
75 | this.models.document.setPageIndex(pageIndex);
76 | }
77 | this.states.ViewSearch();
78 | },
79 | handleHashChangeViewEntity: function(page, name, offset, length) {
80 | page = parseInt(page,10) - 1;
81 | name = decodeURIComponent(name);
82 | this.elements.searchInput.val(name);
83 | this.models.document.setPageIndex(page);
84 | this.states.ViewEntity(name, parseInt(offset, 10), parseInt(length, 10));
85 | }
86 | });
87 |
--------------------------------------------------------------------------------
/public/javascripts/DV/helpers/annotations.js:
--------------------------------------------------------------------------------
1 | _.extend(DV.Schema.helpers, {
2 | getAnnotationModel : function(annoEl) {
3 | var annoId = parseInt(annoEl.attr('rel').match(/\d+/), 10);
4 | return this.models.annotations.getAnnotation(annoId);
5 | },
6 | // Return the annotation Object that connects with the element in the DOM
7 | getAnnotationObject: function(annotation){
8 |
9 | var annotation = $j(annotation);
10 | var annotationId = annotation.attr('id').replace(/DV\-annotation\-|DV\-listAnnotation\-/,'');
11 | var pageId = annotation.closest('div.DV-set').attr('id');
12 |
13 | for(var i = 0; (annotationObject = this.application.pageSet.pages[pageId].annotations[i]); i++){
14 | if(annotationObject.id == annotationId){
15 | // cleanup
16 | annotation = null;
17 | return annotationObject;
18 | }
19 | }
20 |
21 | return false;
22 |
23 | },
24 | // Set of bridges to access annotation methods
25 | // Toggle
26 | annotationBridgeToggle: function(e){
27 | e.preventDefault();
28 | var annotationObject = this.getAnnotationObject($j(e.target).closest(this.annotationClassName));
29 | annotationObject.toggle();
30 | },
31 | // Show annotation
32 | annotationBridgeShow: function(e){
33 | e.preventDefault();
34 | var annotationObject = this.getAnnotationObject($j(e.target).closest(this.annotationClassName));
35 | annotationObject.show();
36 | },
37 | // Hide annotation
38 | annotationBridgeHide: function(e){
39 | e.preventDefault();
40 | var annotationObject = this.getAnnotationObject($j(e.target).closest(this.annotationClassName));
41 | annotationObject.hide(true);
42 | },
43 | // Jump to the next annotation
44 | annotationBridgeNext: function(e){
45 | e.preventDefault();
46 | var annotationObject = this.getAnnotationObject($j(e.target).closest(this.annotationClassName));
47 | annotationObject.next();
48 | },
49 | // Jump to the previous annotation
50 | annotationBridgePrevious: function(e){
51 | e.preventDefault();
52 | var annotationObject = this.getAnnotationObject($j(e.target).closest(this.annotationClassName));
53 | annotationObject.previous();
54 | },
55 | // Update currentpage text to indicate current annotation
56 | setAnnotationPosition: function(_position){
57 | this.elements.currentPage.text(_position);
58 | },
59 | // Update active annotation limits
60 | setActiveAnnotationLimits: function(annotation){
61 | var annotation = (annotation) ? annotation : this.application.activeAnnotation;
62 |
63 | if(!annotation || annotation == null){
64 | return;
65 | }
66 |
67 | var elements = this.elements;
68 | var aPage = annotation.page;
69 | var aEl = annotation.annotationEl;
70 | var aPosTop = annotation.position.top;
71 | var _trackAnnotation = this.events.trackAnnotation;
72 |
73 | if(annotation.type === 'page'){
74 | _trackAnnotation.h = aEl.find('div.DV-annotationBG').outerHeight()+aPage.getOffset();
75 | _trackAnnotation.combined = (aPage.getOffset()) - elements.window.height();
76 | }else{
77 | _trackAnnotation.h = aEl.find('div.DV-annotationBG').height()+aPosTop+20+aPage.getOffset();
78 | _trackAnnotation.combined = (aPosTop+20+aPage.getOffset()) - elements.window.height();
79 | }
80 |
81 |
82 | }
83 | });
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/dropShadow.css:
--------------------------------------------------------------------------------
1 | /* inset shadows */
2 | .DV-ds-insetTop{
3 | position:absolute;
4 | top:0;
5 | left:0;
6 | right:0;
7 | height:5px;
8 | z-index:3010;
9 | }
10 |
11 | .DV-ds-insetBottom{
12 | position:absolute;
13 | bottom:0;
14 | left:0;
15 | right:0;
16 | height:5px;
17 | z-index:3010;
18 | }
19 |
20 | .DV-ds-insetLeft{
21 | position:absolute;
22 | width:100%;
23 | top:0;
24 | left:0;
25 | width:5px;
26 | z-index:3010;
27 | }
28 |
29 | .DV-ds-insetRight{
30 | position:absolute;
31 | top:0;
32 | right:0;
33 | width:5px;
34 | z-index:3010;
35 | }
36 |
37 | .DV-ie6 .DV-ds-insetRight{
38 | right:-1px;
39 | }
40 |
41 | /* base shadow fade rules*/
42 | .DV-ds{
43 | position:absolute;
44 | background-color:#000;
45 | }
46 |
47 | .DV-ds-1{
48 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=5)";
49 | filter:progid:DXImageTransform.Microsoft.Alpha(opacity=5);
50 | opacity:.05;
51 | }
52 |
53 | .DV-ds-2{
54 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=4)";
55 | filter:progid:DXImageTransform.Microsoft.Alpha(opacity=4);
56 | opacity:.04;
57 | }
58 |
59 | .DV-ds-3{
60 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=3)";
61 | filter:progid:DXImageTransform.Microsoft.Alpha(opacity=3);
62 | opacity:.03;
63 | }
64 |
65 | .DV-ds-4{
66 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=2)";
67 | filter:progid:DXImageTransform.Microsoft.Alpha(opacity=2);
68 | opacity:.02;
69 | }
70 |
71 | .DV-ds-5{
72 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=2)";
73 | filter:progid:DXImageTransform.Microsoft.Alpha(opacity=1);
74 | opacity:.01;
75 | }
76 |
77 | /* inset shadows - top */
78 | .DV-ds-insetTop .DV-ds{
79 | top:0;
80 | left:0;
81 | right:0;
82 | }
83 |
84 | /* inset shadows - bottom */
85 | .DV-ds-insetBottom .DV-ds{
86 | bottom:0;
87 | left:0;
88 | right:0;
89 | }
90 |
91 | /* top|bottom rules */
92 | .DV-ds-insetBottom .DV-ds-1,
93 | .DV-ds-insetTop .DV-ds-1{
94 | height: 1px;
95 | }
96 |
97 | .DV-ds-insetBottom .DV-ds-2,
98 | .DV-ds-insetTop .DV-ds-2{
99 | height: 2px;
100 | }
101 |
102 | .DV-ds-insetBottom .DV-ds-3,
103 | .DV-ds-insetTop .DV-ds-3{
104 | height: 3px;
105 | }
106 |
107 | .DV-ds-insetBottom .DV-ds-4,
108 | .DV-ds-insetTop .DV-ds-4{
109 | height: 4px;
110 | }
111 |
112 | .DV-ds-insetBottom .DV-ds-5,
113 | .DV-ds-insetTop .DV-ds-5{
114 | height: 5px;
115 | }
116 |
117 | /* inset shadows - left */
118 | .DV-ds-insetLeft .DV-ds{
119 | top:0;
120 | left:0;
121 | bottom:0;
122 | }
123 |
124 | /* inset shadows - bottom */
125 | .DV-ds-insetRight .DV-ds{
126 | top:0;
127 | right:0;
128 | bottom:0;
129 | }
130 |
131 | /* left|right rules */
132 | .DV-ds-insetLeft .DV-ds-1,
133 | .DV-ds-insetRight .DV-ds-1{
134 | width: 1px;
135 | }
136 |
137 | .DV-ds-insetLeft .DV-ds-2,
138 | .DV-ds-insetRight .DV-ds-2{
139 | width: 2px;
140 | }
141 |
142 | .DV-ds-insetLeft .DV-ds-3,
143 | .DV-ds-insetRight .DV-ds-3{
144 | width: 3px;
145 | }
146 |
147 | .DV-ds-insetLeft .DV-ds-4,
148 | .DV-ds-insetRight .DV-ds-4{
149 | width: 4px;
150 | }
151 |
152 | .DV-ds-insetLeft .DV-ds-5,
153 | .DV-ds-insetRight .DV-ds-5{
154 | width: 5px;
155 | }
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/pages.css:
--------------------------------------------------------------------------------
1 | #DV-documentCell{
2 | background-color:#ccc;
3 | }
4 |
5 | #DV-documentCell.DV-coverVisible{
6 | background-color:#444;
7 | }
8 |
9 | .DV-cover{
10 | left:0;
11 | position:absolute;
12 | top:0;
13 | visibility:visible;
14 | z-index:1000;
15 | }
16 |
17 | .DV-pageMeta{
18 | font-family:Arial,Helvetica,sans-serif;
19 | height:20px;
20 | width:100%; height: 0;
21 | left:0;
22 | top:0;
23 | position:absolute;
24 | z-index:20101;
25 | }
26 |
27 | .DV-pageNumber {
28 | display:inline;
29 | float:left;
30 | margin-left:0;
31 | margin-top:0;
32 | position:relative;
33 | z-index:12000;
34 | zoom:1;
35 | font-size:10px;
36 | font-weight:bold;
37 | padding-left:8px;
38 | }
39 |
40 | .DV-annotation .DV-pageNumber{
41 | display:none;
42 | }
43 |
44 | .DV-pageNumber{
45 | margin-top:20px;
46 | }
47 |
48 | .DV-layer-page .DV-pageNumber{
49 | margin-left:10px;
50 | position:absolute;
51 | }
52 |
53 | .DV-viewAnnotations .DV-pageNumber{
54 | display:inline;
55 | float:left;
56 | font-family:Arial,Helvetica,sans-serif;
57 | font-size:10px;
58 | margin-left:12px;
59 | margin-top:10px;
60 | position:relative;
61 | z-index:1200;
62 | }
63 |
64 | .DV-page{
65 | position:relative;
66 | left:0;
67 | top:0;
68 | -moz-box-shadow: 0 0 1em #a9a9a9;
69 | -webkit-box-shadow: 0 0 1em #a9a9a9;
70 | background-color:#dfdfdf;
71 | overflow:visible;
72 | }
73 |
74 | .DV-pageImage{
75 | visibility:hidden;
76 | position:absolute;
77 | z-index:1;
78 | top:0;
79 | left:0;
80 | }
81 |
82 | .DV-loaded .DV-pageImage{
83 | visibility:visible;
84 | -moz-user-select:none;
85 | }
86 |
87 | .DV-pageImage,
88 | .DV-annotationExcerptImage,
89 | .DV-excerptHighLevel img{
90 | -ms-interpolation-mode: bicubic;
91 | }
92 |
93 | #DV-pages.DV-coverVisible{
94 | background-color:#444;
95 | cursor:pointer;
96 | }
97 |
98 | #DV-pages.DV-coverVisible .DV-page{
99 | -moz-box-shadow: 0 0 1em #333;
100 | -webkit-box-shadow: 0 0 1em #333;
101 | background-color:#fff;
102 | }
103 |
104 | #DV-pages.DV-coverVisible .DV-pageImage{
105 | opacity:.4;
106 | background-color:#000;
107 | }
108 |
109 | /* different opacity to handle IE opacity rendering bug */
110 | .DV-ie #DV-pages.DV-coverVisible .DV-pageImage{
111 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=45)";
112 | filter: alpha(opacity=45);
113 | }
114 |
115 | .DV-coverVisible .DV-cover{
116 | background-color:#000;
117 | -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=45)";
118 | filter: alpha(opacity=55);
119 | opacity:.6;
120 | cursor:pointer !important;
121 | }
122 |
123 | .DV-coverVisible .DV-page,
124 | .DV-coverVisible #DV-pageCollection{
125 | cursor:pointer !important;
126 | }
127 |
128 | .DV-loading .DV-pageImage{
129 | visibility:hidden !important;
130 | }
131 |
132 | .DV-loading-top,
133 | .DV-loading-bottom{
134 | right:0;
135 | top:0;
136 | position:absolute;
137 | padding:4px;
138 | background-color:#fff;
139 | color:#aaa;
140 | font-family:Arial,Helvetica,sans-serif;
141 | font-size:10px;
142 | text-align:center;
143 | }
144 |
145 | .DV-loaded .DV-loading-bottom{
146 | bottom:0;
147 | }
148 |
149 | .DV-loaded .DV-loading-top,
150 | .DV-loaded .DV-loading-bottom{
151 | display:none;
152 | }
153 |
154 | .DV-set{
155 | position:absolute;
156 | top:0;
157 | left:0;
158 | padding-left:45px;
159 | }
160 |
161 | #p0,
162 | #p1,
163 | #p2{
164 | display:none;
165 | padding-left:60px;
166 | z-index:15999;
167 | }
168 |
169 | .DV-activePage{
170 | z-index:16000 !important;
171 | }
172 |
--------------------------------------------------------------------------------
/public/stylesheets/DV/plain.css:
--------------------------------------------------------------------------------
1 | /* DocumentCloud overrides to the DocViewer CSS go here: */
2 |
3 | /* Global rules, default for the plain style. */
4 | body, html {
5 | margin: 0;
6 | padding: 0;
7 | }
8 |
9 | #DV-docViewer {
10 | border: 1px solid #c3c3c3;
11 | }
12 | #DV-headerHat, #DV-title, .DV-contentsHeader {
13 | display: none !important;
14 | }
15 | #DV-header {
16 | padding: 0;
17 | border-bottom: 2px solid #979797;
18 | position: relative;
19 | z-index: 20000;
20 | box-shadow: 0 0 25px rgba(0,0,0,.5); -webkit-box-shadow: 0 0 25px rgba(0,0,0,.5); -moz-box-shadow: 0 0 25px rgba(0,0,0,.5);
21 | }
22 | #DV-Controls {
23 | margin-top: 0;
24 | border: 0;
25 | background: #d7d7d7;
26 | background: -webkit-gradient(linear, left top, left bottom, from(#EAEAEA), to(#C2C2C2));
27 | background: -moz-linear-gradient(top, #EAEAEA, #C2C2C2);
28 | filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#EAEAEA', EndColorStr='#C2C2C2');
29 | text-shadow: 0px 1px 1px #fff;
30 | color: #2C2C2C;
31 | overflow: hidden;
32 | }
33 | #DV-searchInput {
34 | width: 170px;
35 | border: 1px solid #999;
36 | padding: 3px 3px;
37 | -moz-border-radius: 4px;
38 | }
39 | #DV-searchSubmit {
40 | background: #e7e7e7;
41 | color: #4F4F4F;
42 | height: auto;
43 | padding: 3px 10px;
44 | font-weight: bold;
45 | border: 1px solid #999;
46 | border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px;
47 | background: -webkit-gradient(linear, left top, left bottom, from(#fefefe), to(#c4c4c4));
48 | background: -moz-linear-gradient(top, #fefefe, #c4c4c4);
49 | filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#FEFEFE', EndColorStr='#C4C4C4');
50 | text-shadow: 0px 1px 1px #fff;
51 | cursor: pointer;
52 | font-size:11px;
53 | }
54 | div.DV-ie #DV-searchSubmit {
55 | font-size: 10px;
56 | padding: 4px 3px 3px;
57 | }
58 |
59 | #DV-docViewer-Container {
60 | margin: 0;
61 | border: 0;
62 | }
63 | #DV-pages {
64 | background: #bbb;
65 | }
66 |
67 | #DV-well {
68 | padding-bottom: 16px;
69 | }
70 | #DV-descriptionHead {
71 | text-transform: none;
72 | color: black;
73 | }
74 | #DV-descriptionText {
75 | background: white;
76 | padding: 5px 14px 10px;
77 | }
78 |
79 | .DV-views {
80 | position: relative;
81 | z-index: 10;
82 | }
83 | .DV-views div span {
84 | border-bottom: 0 !important;
85 | background: #e3e3e3;
86 | color: black !important;
87 | background: -webkit-gradient(linear, left top, left bottom, from(#E3E3E3), to(#C2C2C2));
88 | background: -moz-linear-gradient(top, #EAEAEA, #C2C2C2);
89 | filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#EAEAEA', EndColorStr='#C2C2C2');
90 | }
91 | .DV-views #DV-documentView span {
92 | -webkit-border-top-left-radius: 5px; -moz-border-radius-topleft: 5px;
93 | }
94 | #DV-textView span {
95 | -webkit-border-top-right-radius: 5px; -moz-border-radius-topright: 5px;
96 | }
97 | .DV-viewDocument .DV-views #DV-documentView span,
98 | .DV-viewAnnotations .DV-views #DV-annotationView span,
99 | .DV-viewText .DV-views #DV-textView span,
100 | .DV-viewSearch .DV-views #DV-textView span {
101 | background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#a0a0a0));
102 | background: -moz-linear-gradient(top, #fff, #a0a0a0);
103 | filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#FFFFFF', EndColorStr='#A0A0A0');
104 | }
105 |
--------------------------------------------------------------------------------
/public/javascripts/DV/lib/history.js:
--------------------------------------------------------------------------------
1 | // Handles JavaScript history management and callbacks. To use, register a
2 | // regexp that matches the history hash with its corresponding callback:
3 | //
4 | // dc.history.register(/^#search/, controller.runSearch);
5 | //
6 | // And then you can save arbitrary history fragments.
7 | //
8 | // dc.history.save('search/freedom/p3');
9 | //
10 | DV.history = {
11 |
12 | // The interval at which the window location is polled.
13 | URL_CHECK_INTERVAL : 500,
14 |
15 | // We need to use an iFrame to save history if we're in an old version of IE.
16 | USE_IFRAME : jQuery.browser.msie && jQuery.browser.version < 8,
17 |
18 | // The ordered list of history handlers matchers and callbacks.
19 | handlers : [],
20 | defaultCallback: null,
21 |
22 | // The current recorded window.location.hash.
23 | hash : window.location.hash,
24 |
25 | // Initialize history with an empty set of handlers.
26 | // Bind to the HTML5 'onhashchange' callback, if it exists. Otherwise,
27 | // start polling the window location.
28 | initialize : function() {
29 | _.bindAll(this, 'checkURL');
30 | if (this.USE_IFRAME) this.iframe = jQuery('').hide().appendTo('body')[0].contentWindow;
31 | if ('onhashchange' in window) {
32 | window.onhashchange = this.checkURL;
33 | } else {
34 | setInterval(this.checkURL, this.URL_CHECK_INTERVAL);
35 | }
36 | },
37 |
38 | // Register a history handler. Pass a regular expression that can be used to
39 | // match your URLs, and the callback to be invoked with the remainder of the
40 | // hash, when matched.
41 | register : function(matcher, callback) {
42 | this.handlers.push({matcher : matcher, callback : callback});
43 | },
44 |
45 | // Save a moment into browser history. Make sure you've registered a handler
46 | // for it. You're responsible for pre-escaping the URL fragment.
47 | save : function(hash) {
48 | window.location.hash = this.hash = (hash ? '#' + hash : '');
49 | if (this.USE_IFRAME && (this.iframe && (this.hash != this.iframe.location.hash))) {
50 | this.iframe.document.open().close();
51 | this.iframe.location.hash = this.hash;
52 | }
53 | },
54 |
55 | // Check the current URL hash against the recorded one, firing callbacks.
56 | checkURL : function() {
57 | var current = (this.USE_IFRAME ? this.iframe : window).location.hash;
58 | if (!current ||
59 | current == this.hash ||
60 | '#' + current == this.hash ||
61 | current == decodeURIComponent(this.hash)) return false;
62 | if (this.USE_IFRAME) window.location.hash = current;
63 | this.loadURL(true);
64 | },
65 |
66 | // Load the history callback associated with the current page fragment. On
67 | // pages that support history, this method should be called at page load,
68 | // after all the history callbacks have been registered.
69 | // executeCallbacks must be passed as true, otherwise true/false will returned based on positive route matches.
70 | loadURL : function(executeCallbacks) {
71 | var hash = this.hash = window.location.hash;
72 |
73 | // go through matches in reverse order so that oldest rules are executed last
74 | for(var i = this.handlers.length-1; i >= 0; i--){
75 | var match = hash.match(this.handlers[i].matcher);
76 | if (match) {
77 | if(executeCallbacks === true){
78 | this.handlers[i].callback.apply(this.handlers[i].callback,match.slice(1,match.length));
79 | }
80 | return true;
81 | }
82 | }
83 | if(this.defaultCallback != null && executeCallbacks === true){
84 | this.defaultCallback();
85 | }else{
86 | return false;
87 | }
88 | }
89 |
90 | };
91 |
92 | jQuery(document).ready(function(){ DV.history.initialize(); });
--------------------------------------------------------------------------------
/public/javascripts/DV/lib/dragReporter.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | var dragReporter = function(toWatch,dispatcher,argHash){
3 | if(!jQuery){
4 | throw('You need jQuery for the dragReporter!');
5 | return;
6 | }
7 | if(!toWatch || !dispatcher){
8 | throw('You need jQuery for the dragReporter!');
9 | return;
10 | }
11 | for(var key in argHash){
12 | this[key] = argHash[key];
13 | }
14 | this.dispatcher = dispatcher;
15 | this.toWatch = jQuery(toWatch);
16 | this.boundReporter = jQuery.proxy(this.mouseMoveReporter,this);
17 | this.boundMouseUpReporter = jQuery.proxy(this.mouseUpReporter,this);
18 | this.boundMouseDownReporter = jQuery.proxy(this.mouseDownReporter,this);
19 | this.boundEase = jQuery.proxy(this.boundEase,this);
20 |
21 | this.setBinding();
22 | };
23 | dragReporter.prototype.pageY = null;
24 | dragReporter.prototype.pageX = null;
25 | dragReporter.prototype.oldPageY = 0;
26 | dragReporter.prototype.dispatcher = null;
27 | dragReporter.prototype.boundReporter = null;
28 | dragReporter.prototype.boundMouseUpReporter = null;
29 | dragReporter.prototype.boundMouseDownReporter = null;
30 | dragReporter.prototype.boundEase = null;
31 | dragReporter.prototype.toWatch = null;
32 | dragReporter.prototype.sensativity = 1.5;
33 | dragReporter.prototype.updateTimer = null;
34 | dragReporter.prototype.ignoreSelector = null;
35 | dragReporter.prototype.dragClassName = 'DV-dragging';
36 |
37 | dragReporter.prototype.shouldIgnore = function(e) {
38 | if (!this.ignoreSelector) return false;
39 | var el = jQuery(e.target);
40 | return el.parents().is(this.ignoreSelector) || el.is(this.ignoreSelector);
41 | };
42 |
43 | dragReporter.prototype.mouseUpReporter = function(e){
44 | if (this.shouldIgnore(e)) return true;
45 | e.preventDefault();
46 | clearInterval(this.updateTimer);
47 | // this.boundEase(this.oldPageY-this.pageY);
48 |
49 | this.stop();
50 | };
51 |
52 | dragReporter.prototype.oldPositionUpdater = function(){
53 | this.oldPageY = this.pageY;
54 | };
55 |
56 | dragReporter.prototype.stop = function(){
57 | this.toWatch.removeClass(this.dragClassName);
58 | this.toWatch.unbind('mousemove');
59 | };
60 | dragReporter.prototype.setBinding = function(){
61 | this.toWatch.mouseup(this.boundMouseUpReporter);
62 | this.toWatch.mousedown(this.boundMouseDownReporter);
63 | };
64 | dragReporter.prototype.unBind = function(){
65 | this.toWatch.unbind('mouseup',this.boundMouseUpReporter);
66 | this.toWatch.unbind('mousedown',this.boundMouseDownReporter);
67 | };
68 | dragReporter.prototype.destroy = function(){
69 | this.unBind();
70 | this.toWatch = null;
71 | };
72 | dragReporter.prototype.mouseDownReporter = function(e){
73 | if (this.shouldIgnore(e)) return true;
74 | e.preventDefault();
75 | this.pageY = e.pageY;
76 | this.pageX = e.pageX;
77 | this.oldPageY = e.pageY;
78 |
79 | this.updateTimer = setInterval(jQuery.proxy(this.oldPositionUpdater,this),1200);
80 |
81 | this.toWatch.addClass(this.dragClassName);
82 | this.toWatch.mousemove(this.boundReporter);
83 |
84 | };
85 | dragReporter.prototype.mouseMoveReporter = function(e){
86 | if (this.shouldIgnore(e)) return true;
87 | e.preventDefault();
88 | var delta = Math.round(this.sensativity * (this.pageY - e.pageY));
89 | var direction = (delta > 0) ? 'down' : 'up';
90 | this.pageY = e.pageY;
91 |
92 | if(delta === 0){
93 | return;
94 | }else{
95 | this.dispatcher({ event: e, delta: delta, direction: direction });
96 | }
97 | };
98 |
99 | DV.register('dragReporter',dragReporter);
100 |
101 | }).call(this);
102 |
--------------------------------------------------------------------------------
/README.rdoc:
--------------------------------------------------------------------------------
1 | ____ _ ___
2 | / __ \____ ____| | / (_)__ _ _____ _____
3 | / / / / __ \/ ___/ | / / / _ \ | /| / / _ \/ ___/
4 | / /_/ / /_/ / /__ | |/ / / __/ |/ |/ / __/ /
5 | /_____/\____/\___/ |___/_/\___/|__/|__/\___/_/
6 |
7 |
8 | == Source
9 | * The frontend branch is home to all of the HTML, CSS, and Javascript you'll need to get a static viewer up and running.
10 | * The rails branch (TK) contains a Rails-based admin you can use to create, manage, and serve viewers.
11 |
12 | == Browser Support
13 | All core functionality is supported as far back as IE6. However, users with modern browsers(Firefox 3.5, Safari 4, Chrome) will notice a much improved view. The markup and css used to support IE6 is pretty atrocious. New templates to take more aggressive use of CSS3 treats like rounded corners and gradients are on the roadmap.
14 |
15 | == Usage
16 |
17 | Take a peek at the plain.html template to see how to load in a Document. All you really need to do is point to a Document Viewer JSON file and specify the target element to embed the viewer:
18 |
19 | DV.load(JSON_FILE, { container: element_selector });
20 |
21 | *JSON_FILE*: Either an inline json object, or the path to a remote json object - http://documents.nytimes.com/goldman-sachs-internal-emails.json
22 |
23 | * *container*: The element to contain the Document Viewer - '#DV-container'
24 |
25 |
26 | == Data Formats: Documents
27 | All data should be formatted as JSON. When provided a cross domain url, DV will attempt a JSONP request.
28 | Examples of this in use can be found here:
29 | http://documents.nytimes.com/goldman-sachs-internal-emails.json
30 |
31 | {
32 | title : DOCUMENT_TITLE,
33 | description : DOCUMENT_DESCRIPTION,
34 | id : DOCUMENT_ID,
35 | pages : TOTAL_PAGES,
36 |
37 | annotations :
38 | [
39 | {
40 | title : ANNOTATION_TITLE,
41 | page : PAGE_INDEX,
42 | content : ANNOTATION_DESCRIPTION
43 | location : { image: "x1, y1, x2, y2" },
44 | }
45 | ],
46 |
47 | sections :
48 | [
49 | { title : CHAPTER_TITLE, pages: "1-10" },
50 | { title : CHAPTER_TITLE, pages: "11-20" }
51 | ],
52 |
53 | resources :
54 | {
55 | page : { text: TEXT_URL_FORMAT, image: IMAGE_URL_FORMAT },
56 | related_story : LINK_URL,
57 | pdf : ORIGINAL_PDF_URL,
58 | search : SEARCH_UTILITY_URL
59 | }
60 | }
61 |
62 |
63 | == Data Formats: Search
64 | All data should be formatted as JSON. When provided a cross domain url, DV will attempt a JSONP request.
65 |
66 | {
67 | matches : NUMBER_OF_PAGES_WITH_MATCHES,
68 | results : [PAGE_NUMBER,PAGE_NUMBER,PAGE_NUMBER],
69 | query : SEARCH_QUERY
70 | }
71 |
72 |
73 | * *matches* : The number of pages with matches.
74 | * *results* : An array of page numbers with matches. NOT zero based.
75 | * *query* : Your search query.
76 |
77 |
78 | == Requirements
79 | === Jammit
80 |
81 | We're using the excellent Jammit asset compression library from the DocumentCloud project to compress assets and render JS templates. Anytime you make a change to a template, you'll need to run jammit command to render out the views.
82 |
83 | jammit -c ASSET_CONFIG_PATH
84 |
85 |
86 | Details on installing and using the Jammit library can be found at http://documentcloud.github.com/jammit/
87 |
88 |
89 | == Styling the Viewer
90 | The template provided comes in two forms:
91 |
92 | ===plain.html
93 | This is the production facing view that uses the latest compressed assets and views.
94 |
95 | ===debug.html
96 | Should only be used for development and debugging purposes. You'll need to keep this up to date should add or remove new assets.
97 |
98 | All view templates can be found in javascripts/DV/views
99 | To see your changes you'll need to be sure to run the jammit command to re-render your views.
100 |
101 |
102 | == Copyright
103 | Copyright © 2010 The New York Times. See LICENSE for details.
--------------------------------------------------------------------------------
/public/javascripts/DV/controllers/api.js:
--------------------------------------------------------------------------------
1 | DV.api = {
2 |
3 | // Return the current page of the document.
4 | currentPage : function() {
5 | return DV.controller.models.document.currentPage();
6 | },
7 |
8 | // Return the current zoom factor of the document.
9 | currentZoom : function() {
10 | var doc = DV.controller.models.document;
11 | return doc.zoomLevel / doc.ZOOM_RANGES[1];
12 | },
13 |
14 | // Return the total number of pages in the document.
15 | numberOfPages : function() {
16 | return DV.controller.models.document.totalPages;
17 | },
18 |
19 | // Change the documents' sections, re-rendering the navigation. "sections"
20 | // should be an array of sections in the canonical format:
21 | // {title: "Chapter 1", pages: "1-12"}
22 | setSections : function(sections) {
23 | DV.Schema.data.sections = sections;
24 | DV.controller.models.chapters.loadChapters();
25 | this.redraw();
26 | },
27 |
28 | // Get a list of every section in the document.
29 | getSections : function() {
30 | return _.clone(DV.Schema.data.sections || []);
31 | },
32 |
33 | // Get the document's description.
34 | getDescription : function() {
35 | return DV.Schema.document.description;
36 | },
37 |
38 | // Set the document's description and update the sidebar.
39 | setDescription : function(desc) {
40 | DV.Schema.document.description = desc;
41 | $j('#DV-description').remove();
42 | $j('.DV-navigation').prepend(JST.descriptionContainer({description: desc}));
43 | },
44 |
45 | // Get the document's related article url.
46 | getRelatedArticle : function() {
47 | return DV.Schema.document.resources.related_article;
48 | },
49 |
50 | // Set the document's related article url.
51 | setRelatedArticle : function(url) {
52 | DV.Schema.document.resources.related_article = url;
53 | $('#DV-storyLink a').attr({href : url});
54 | $('#DV-storyLink').toggle(!!url);
55 | },
56 |
57 | // Get the document's title.
58 | getTitle : function() {
59 | return DV.Schema.document.title;
60 | },
61 |
62 | // Set the document's title.
63 | setTitle : function(title) {
64 | DV.Schema.document.title = title;
65 | document.title = title;
66 | },
67 |
68 | // Set the page text for the given page of a document in the local cache.
69 | setPageText : function(text, pageNumber) {
70 | DV.Schema.text[pageNumber - 1] = text;
71 | },
72 |
73 | // Redraw the UI. Call redraw(true) to also redraw annotations and pages.
74 | redraw : function(redrawAll) {
75 | if (redrawAll) DV.controller.models.annotations.renderAnnotations();
76 | DV.controller.helpers.renderNavigation();
77 | DV.controller.helpers.renderComponents();
78 | if (redrawAll) {
79 | DV.controller.elements.window.removeClass('DV-coverVisible');
80 | DV.controller.pageSet.buildPages({noNotes : true});
81 | }
82 | },
83 |
84 | // Add a new annotation to the document, prefilled to any extent.
85 | addAnnotation : function(anno) {
86 | anno = DV.Schema.loadAnnotation(anno);
87 | DV.controller.models.annotations.sortAnnotations();
88 | this.redraw(true);
89 | DV.controller.pageSet.showAnnotation(anno, {active: true, noJump : true, edit : true});
90 | return anno;
91 | },
92 |
93 | // Register a callback for when an annotation is saved.
94 | onAnnotationSave : function(callback) {
95 | DV.controller.models.annotations.saveCallbacks.push(callback);
96 | },
97 |
98 | // Register a callback for when an annotation is deleted.
99 | onAnnotationDelete : function(callback) {
100 | DV.controller.models.annotations.deleteCallbacks.push(callback);
101 | },
102 |
103 | // Request the loading of an external CSS file.
104 | loadCSS : function(url) {
105 | var link = document.createElement('link');
106 | $j(link).attr({
107 | rel: "stylesheet",
108 | type: "text/css",
109 | href: url
110 | }).appendTo($j('head'));
111 | },
112 |
113 | // Request the loading of an external JS file.
114 | loadJS : function(url, callback) {
115 | $j.getScript(url, callback);
116 | }
117 |
118 | };
119 |
--------------------------------------------------------------------------------
/public/javascripts/DV/lib/stateMachine.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The StateMachine module provides a way to control and monitor state in your application
3 | * @module StateMachine
4 | */
5 | (function(){
6 |
7 | var stateMachine = function(states,argHash){
8 | this.pendingElements = argHash.elements;
9 | if(argHash.models){
10 | _.extend(this.models, argHash.models)
11 | }
12 |
13 | this.compile(states,argHash);
14 | };
15 |
16 | stateMachine.prototype.state = null;
17 | stateMachine.prototype.elements = null;
18 | stateMachine.prototype.helpers = null;
19 | stateMachine.prototype.states = null;
20 | stateMachine.prototype.models = {};
21 | stateMachine.prototype.events = null;
22 |
23 | stateMachine.prototype.compile = function(states,argHash){
24 |
25 | this.events = argHash.events
26 | this.helpers = argHash.helpers;
27 | this.states = this.compileStates(states);
28 |
29 | this.events = this.compileMethods(this.events,
30 | { application : this,
31 | states : this.states,
32 | elements : this.elements,
33 | helpers : this.helpers,
34 | models : this.models,
35 | // this allows us to bind events to call the method corresponding to the current state
36 | compile : function(){
37 | var a = this.application;
38 | var methodName = arguments[0];
39 |
40 | return function(){
41 | if(!a.events[a.getState()][methodName]){
42 | a.events[methodName].apply(a.events,arguments);
43 | }else{
44 | a.events[a.getState()][methodName].apply(a.events,arguments);
45 | }
46 | };
47 | }
48 | }
49 | );
50 |
51 | this.helpers = this.compileMethods(this.helpers,
52 | {
53 | application : this,
54 | states : this.states,
55 | elements : this.elements,
56 | events : this.events,
57 | models : this.models
58 | }
59 | );
60 |
61 | this.states = this.compileMethods(this.states,
62 | {
63 | application : this,
64 | helpers : this.helpers,
65 | elements : this.elements,
66 | events : this.events,
67 | models : this.models
68 | }
69 | );
70 |
71 | };
72 |
73 | stateMachine.prototype.compileStates = function(states){
74 | var modifiedStates = {};
75 | var me2 = this;
76 |
77 | for(var key in states){
78 |
79 | if(states[key] === null || states[key] === false || !states[key].enter){
80 | this[key] = states[key];
81 | continue;
82 | }
83 |
84 | modifiedStates[key] = (function(_key){
85 | var me = me2;
86 | return function(){
87 | var currentState = me.getState();
88 | if(currentState === _key){
89 | return;
90 | }
91 | if(states[currentState] != null) {
92 | var stateChangeResponse = states[currentState].exit.call(me,_key);
93 | if(stateChangeResponse === false){
94 | return false;
95 | }
96 | }
97 | me.setState(_key);
98 | states[_key].enter.call(me,currentState);
99 | states[_key][_key].apply(me,arguments);
100 | };
101 |
102 | })(key);
103 |
104 | modifiedStates[key].exit = function(_key){
105 | var me = this;
106 | return function(){
107 | states[_key].exit.call(me);
108 | };
109 | }(key);
110 |
111 | }
112 | return modifiedStates;
113 | };
114 |
115 | stateMachine.prototype.compileMethods = function(methods,references){
116 | for(var key in references){
117 | methods[key] = references[key];
118 | }
119 | return methods;
120 | };
121 |
122 | stateMachine.prototype.getState = function(){
123 | return this.state;
124 | };
125 |
126 | stateMachine.prototype.setState = function(state){
127 | this.state = state;
128 | return this.state;
129 | };
130 |
131 | DV.register('stateMachine', stateMachine);
132 |
133 | }).call(this);
--------------------------------------------------------------------------------
/public/javascripts/DV/vendor/jquery.acceptInput.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | // When the next click or keypress happens, anywhere on the screen, hide the
3 | // element. 'clickable' makes the element and its contents clickable without
4 | // hiding. The 'onHide' callback runs when the hide fires, and has a chance
5 | // to cancel it.
6 | jQuery.fn.autohide = function(options) {
7 | var me = this;
8 | options = _.extend({clickable : null, onHide : null}, options || {});
9 | me._autoignore = true;
10 | setTimeout(function(){ delete me._autoignore; }, 0);
11 |
12 | if (!me._autohider) {
13 | me.forceHide = function(e) {
14 | if (!e && options.onHide) options.onHide();
15 | me.hide();
16 |
17 | jQuery(document).unbind('click', me._autohider);
18 | jQuery(document).unbind('keypress', me._autohider);
19 | me._autohider = null;
20 | me.forceHide = null;
21 | };
22 | me._autohider = function(e) {
23 | if (me._autoignore) return;
24 | if (options.clickable && (me[0] == e.target || _.include(jQuery(e.target).parents(), me[0]))) return;
25 | if (options.onHide && !options.onHide(e)) return;
26 | me.forceHide(e);
27 | };
28 | jQuery(document).bind('click', this._autohider);
29 | jQuery(document).bind('keypress', this._autohider);
30 | }
31 | };
32 |
33 | jQuery.fn.acceptInput = function(options) {
34 | var config = {
35 | delay: 1000,
36 | callback: null,
37 | className: 'acceptInput',
38 | initialStateClassName: 'acceptInput-awaitingActivity',
39 | typingStateClassName: 'acceptInput-acceptingInput',
40 | inputClassName: 'acceptInput-textField'
41 | };
42 |
43 | if (options){
44 | jQuery.extend(config, options);
45 | }
46 | this.editTimer = null;
47 |
48 | this.deny = function(){
49 | this.parent().addClass('stopAcceptingInput');
50 | };
51 |
52 | this.allow = function(){
53 | this.parent().removeClass('stopAcceptingInput');
54 | };
55 |
56 |
57 | this.each(function(i,el){
58 | // element-specific code here
59 | if(jQuery(el).parent().hasClass(config.initialStateClassName)){
60 | return true;
61 | }
62 | el = jQuery(el);
63 |
64 | var elWrapped = el.wrap(' ');
65 | elWrapped = elWrapped.parent();
66 |
67 | var inputElement = jQuery(' ').appendTo(elWrapped);
68 |
69 | inputElement.bind('blur',function(){
70 |
71 | elWrapped.addClass(config.initialStateClassName).removeClass(config.typingStateClassName);
72 | inputElement.hide();
73 | el.show();
74 |
75 | });
76 |
77 |
78 | inputElement.bind('keyup',function(){
79 | var val = inputElement.attr('value');
80 | el.text(val);
81 | if(config.changeCallBack){
82 | jQuery.fn.acceptInput.editTimer = setTimeout(config.changeCallBack,500);
83 | }
84 | });
85 |
86 | inputElement.bind('keydown',function(){
87 | if(jQuery.fn.acceptInput.editTimer){
88 | clearTimeout(jQuery.fn.acceptInput.editTimer);
89 | }
90 | });
91 |
92 | elWrapped.bind('click', function(){
93 | if(elWrapped.hasClass('stopAcceptingInput')) return;
94 | if(elWrapped.hasClass(config.initialStateClassName)){
95 |
96 | var autoHider = function(){
97 | elWrapped.addClass(config.initialStateClassName).removeClass(config.typingStateClassName);
98 | };
99 |
100 | jQuery(inputElement).autohide({ clickable: true, onHide: $j.proxy(autoHider,this) });
101 |
102 | el.hide();
103 | inputElement.attr('value',el.text()).show()[0].focus();
104 | inputElement[0].select();
105 | elWrapped.addClass(config.typingStateClassName).removeClass(config.initialStateClassName);
106 |
107 | }
108 | });
109 | });
110 |
111 | return this;
112 |
113 | };
114 |
115 | }).call(this);
116 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | NYT Document Viewer
2 | Copyright (c) 2010 The New York Times co.
3 |
4 |
5 | The NYT Document Viewer includes the following software:
6 | ---------------------------------------------------------------------------
7 | jQuery
8 | Copyright (c) 2010 John Resig, http://jquery.com/
9 |
10 | Permission is hereby granted, free of charge, to any person obtaining
11 | a copy of this software and associated documentation files (the
12 | "Software"), to deal in the Software without restriction, including
13 | without limitation the rights to use, copy, modify, merge, publish,
14 | distribute, sublicense, and/or sell copies of the Software, and to
15 | permit persons to whom the Software is furnished to do so, subject to
16 | the following conditions:
17 |
18 | The above copyright notice and this permission notice shall be
19 | included in all copies or substantial portions of the Software.
20 |
21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 |
29 | ---------------------------------------------------------------------------
30 | jQuery UI
31 | Copyright (c) 2010 Paul Bakaus, http://jqueryui.com/
32 |
33 | This software consists of voluntary contributions made by many
34 | individuals (AUTHORS.txt, http://jqueryui.com/about) For exact
35 | contribution history, see the revision history and logs, available
36 | at http://jquery-ui.googlecode.com/svn/
37 |
38 | Permission is hereby granted, free of charge, to any person obtaining
39 | a copy of this software and associated documentation files (the
40 | "Software"), to deal in the Software without restriction, including
41 | without limitation the rights to use, copy, modify, merge, publish,
42 | distribute, sublicense, and/or sell copies of the Software, and to
43 | permit persons to whom the Software is furnished to do so, subject to
44 | the following conditions:
45 |
46 | The above copyright notice and this permission notice shall be
47 | included in all copies or substantial portions of the Software.
48 |
49 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
50 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
51 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
52 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
53 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
54 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
55 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
56 |
57 | ---------------------------------------------------------------------------
58 | Underscore
59 | Copyright (c) 2010 Jeremy Ashkenas, DocumentCloud
60 |
61 | Permission is hereby granted, free of charge, to any person
62 | obtaining a copy of this software and associated documentation
63 | files (the "Software"), to deal in the Software without
64 | restriction, including without limitation the rights to use,
65 | copy, modify, merge, publish, distribute, sublicense, and/or sell
66 | copies of the Software, and to permit persons to whom the
67 | Software is furnished to do so, subject to the following
68 | conditions:
69 |
70 | The above copyright notice and this permission notice shall be
71 | included in all copies or substantial portions of the Software.
72 |
73 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
74 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
75 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
76 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
77 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
78 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
79 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
80 | OTHER DEALINGS IN THE SOFTWARE.
81 |
82 | ---------------------------------------------------------------------------
83 | jQuery.ScrollTo - Easy element scrolling using jQuery.
84 |
85 | Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
86 | Dual licensed under MIT and GPL.
87 | Date: 5/25/2009
88 | @author Ariel Flesler
89 | @version 1.4.2
90 |
91 | http://flesler.blogspot.com/2007/10/jqueryscrollto.html
92 |
--------------------------------------------------------------------------------
/public/javascripts/DV/models/page.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | // The PageModel represents the set of pages in the document, containing the
4 | // image sources for each page, and the page proportions.
5 | var pageModel = new DV.model(DV.Schema, {
6 |
7 | // Real page heights
8 | pageHeights : [],
9 |
10 | // In pixels.
11 | BASE_WIDTH : 700,
12 | BASE_HEIGHT : 906,
13 |
14 | // Factors for scaling from image size to zoomlevel.
15 | SCALE_FACTORS : {'500': 0.714, '700': 1.0, '800': 0.8, '900': 0.9, '1000': 1.0},
16 |
17 | // For viewing page text.
18 | TEXT_PADDING : 100,
19 |
20 | // Initializing the page model guesses at a default pageHeight -- we'll
21 | // know for sure when the first page image is loaded.
22 | init: function() {
23 |
24 | this.zoomLevel = DV.controller.models.document.zoomLevel;
25 | this.baseWidth = this.BASE_WIDTH;
26 | this.baseHeight = this.BASE_HEIGHT;
27 | this.width = this.zoomLevel;
28 | this.height = this.baseHeight * this.zoomFactor();
29 | this.numPagesLoaded = 0;
30 |
31 | zoomRanges = DV.controller.models.document.ZOOM_RANGES;
32 | },
33 |
34 | // Get the complete image URL for a particular page.
35 | imageURL: function(index) {
36 | var url = DV.Schema.document.resources.page.image;
37 | var size = this.zoomLevel > this.BASE_WIDTH ? 'large' : 'normal';
38 | var pageNumber = index + 1;
39 | if (DV.Schema.document.resources.page.zeropad) pageNumber = this.zeroPad(pageNumber, 5);
40 | url = url.replace(/\{size\}/, size);
41 | url = url.replace(/\{page\}/, pageNumber);
42 | return url;
43 | },
44 |
45 | zeroPad : function(num, count) {
46 | var string = num.toString();
47 | while (string.length < count) string = '0' + string;
48 | return string;
49 | },
50 |
51 | // The zoom factor is the ratio of the image width to the baseline width.
52 | zoomFactor : function() {
53 | return this.zoomLevel / this.BASE_WIDTH;
54 | },
55 |
56 | // Resize or zoom the pages width and height.
57 | resize : function(zoomLevel) {
58 | if (zoomLevel) {
59 | if (zoomLevel == this.zoomLevel) return;
60 | var previousFactor = this.zoomFactor();
61 | this.zoomLevel = zoomLevel || this.zoomLevel;
62 | var scale = this.zoomFactor() - previousFactor + 1;
63 | this.width = Math.round(this.baseWidth * this.zoomFactor());
64 | this.height = Math.round(this.height * scale);
65 | this.averageHeight = Math.round(this.averageHeight * scale);
66 | }
67 | DV.controller.elements.sets.width(this.zoomLevel);
68 | DV.controller.elements.collection.css({width : this.width + 110 });
69 | },
70 |
71 | // TODO: figure out why this isn't working on the demo doc.
72 | updateHeight: function(image, pageIndex) {
73 | var h = this.getPageHeight(pageIndex);
74 | if (h === image.height) return;
75 |
76 | var height = image.height * (this.zoomLevel > this.BASE_WIDTH ? 0.7 : 1.0);
77 | this.setPageHeight(pageIndex, height);
78 | this.updateBaseHeightBasedOnAveragePageHeight(image);
79 | DV.controller.models.document.computeOffsets();
80 | // DV.controller.pageSet.reflowPages();
81 | DV.controller.pageSet.simpleReflowPages();
82 | },
83 |
84 | // Update the base height
85 | // TODO ... either adjust this or reset it on Zoom.
86 | updateBaseHeightBasedOnAveragePageHeight: function(image) {
87 | this.averageHeight = ((this.averageHeight * this.numPagesLoaded) + image.height) / (this.numPagesLoaded + 1);
88 | this.numPagesLoaded += 1;
89 | if (this.updateTimeout) clearTimeout(this.updateTimeout);
90 | this.updateTimeout = setTimeout($j.proxy(function() {
91 | this.updateTimeout = null;
92 | var newAverage = Math.round(this.averageHeight);
93 | if (Math.abs(newAverage - this.height) > 10) {
94 | this.height = newAverage;
95 | this.baseHeight = Math.round(this.height / this.zoomFactor());
96 | }
97 | }, this), 500);
98 | },
99 |
100 | // set the real page height
101 | setPageHeight: function(pageIndex, pageHeight){
102 | this.pageHeights[pageIndex] = pageHeight;
103 | },
104 |
105 | // get the real page height
106 | getPageHeight: function(pageIndex) {
107 | var realHeight = this.pageHeights[pageIndex];
108 | return realHeight ? realHeight * this.zoomFactor() : this.height;
109 | }
110 |
111 | });
112 |
113 | DV.Schema.models.pages = pageModel;
114 |
115 | }).call(this);
116 |
--------------------------------------------------------------------------------
/public/stylesheets/DV/components/ui-search.css:
--------------------------------------------------------------------------------
1 | .DV-searchPagination{
2 | text-align:center;
3 | float:none;
4 | display:inline;
5 | color:#666;
6 | text-decoration:uppercase;
7 | background-color:#fff;
8 | font-family:Arial,Helvetica,sans-serif;
9 | }
10 |
11 | #DV-searchBox.clearfix {
12 | position: absolute;
13 | right: 8px; top: 7px;
14 | display: none;
15 | }
16 |
17 | #DV-docViewer #DV-searchBox {
18 | display: none;
19 | position: static;
20 | float: right;
21 | width: 255px;
22 | margin-top: 6px;
23 | }
24 |
25 | #DV-docViewer.DV-searchable #DV-searchBox {
26 | display:inline;
27 | }
28 |
29 | #DV-searchSubmit{
30 | display:block;
31 | background-color:#f7f7f7;
32 | border:1px solid #ccc;
33 | padding:2px 3px 4px;
34 | height:25px;
35 | border-radius:2px;
36 | -moz-border-radius:2px;
37 | -webkit-border-radius:2px;
38 | vertical-align:middle;
39 | }
40 |
41 | .DV-searchSubmit{
42 | float:left;
43 | display:inline;
44 | }
45 |
46 | #DV-searchInput{
47 | display:block;
48 | background-color:#fff;
49 | border:1px solid #dadada;
50 | font-size:12px;
51 | padding:4px 2px 3px;
52 | height:16px;
53 | width:173px;
54 | margin-right:5px;
55 | }
56 |
57 | #DV-searchInput[type="search"] {
58 | margin: 4px 10px 0 0;
59 | }
60 |
61 | .DV-ie #DV-searchInput{
62 | margin-top:-1px;
63 | }
64 |
65 | #DV-searchInput:focus{
66 | border:1px solid #aaa;
67 | }
68 |
69 | .DV-searchInput{
70 | float:left;
71 | display:inline;
72 | }
73 |
74 | #DV-searchBarWrapper {
75 | position: relative;
76 | z-index:10002;
77 | }
78 |
79 | #DV-searchBar{
80 | position:absolute;
81 | top:0px;
82 | left:0px;
83 | right: 282px;
84 | height:50px;
85 | background: url(../../../images/DV/embed/shadow.png) repeat-x 0 bottom;
86 | font-family:Arial,Helvetica,sans-serif;
87 | display:none;
88 | }
89 |
90 | .DV-searchMatch{
91 | background-color:#c7c7c7;
92 | -moz-box-shadow: 0 1px 5px #999;
93 | -webkit-box-shadow: 0 1px 5px #999;
94 | padding: 1px;
95 | border:1px solid #fff;
96 | color:#000;
97 | }
98 |
99 | .DV-highlightedMatch{
100 | background: #f1e90f url(../../../images/DV/embed/highlight.gif) repeat-x 0 bottom;
101 | padding: 3px 3px 2px;
102 | -moz-border-radius: 3px;
103 | background-color:#fff;
104 | -moz-border-radius: 3px;
105 | -webkit-border-radius: 3px;
106 | -moz-box-shadow: 0 0 5px #666;
107 | -webkit-box-shadow: 0 0 5px #666;
108 | border: 1px solid #f5e800;
109 | padding: 1px;
110 | color:#000;
111 | }
112 |
113 | .DV-ViewSearch #DV-searchBar{
114 | display:block;
115 | }
116 |
117 | #DV-closeSearch{
118 | float:right;
119 | display:inline;
120 | margin: 16px 15px 0 0;
121 | font-size: 10px;
122 | color:#777;
123 | text-decoration:none;
124 | }
125 |
126 | .DV-resultPrevious,
127 | .DV-resultNext{
128 | text-decoration:none;
129 | }
130 |
131 | #DV-closeSearch:hover,
132 | .DV-resultPrevious:hover,
133 | .DV-resultNext:hover{
134 | text-decoration:underline;
135 | }
136 |
137 | .DV-noResult .DV-resultPrevious,
138 | .DV-noResult .DV-resultNext{
139 | display:none;
140 | }
141 |
142 | .DV-foundResult .DV-resultPrevious,
143 | .DV-foundResult .DV-resultNext{
144 | display:inline;
145 | }
146 |
147 | .DV-resultPrevious{
148 | padding-left:19px;
149 | padding-right:8px;
150 | font-size:10px;
151 | font-weight:bold;
152 | text-transform:uppercase;
153 | border-right:1px solid #ccc;
154 | margin-right:10px;
155 | }
156 |
157 | .DV-resultNext{
158 | padding-left:8px;
159 | padding-right:19px;
160 | font-size:10px;
161 | font-weight:bold;
162 | text-transform:uppercase;
163 | border-left:1px solid #ccc;
164 | margin-left:10px;
165 | }
166 |
167 | #DV-searchResults span{
168 | font-weight:bold;
169 | font-size:11px;
170 | color:#000;
171 | }
172 |
173 | #DV-searchResults{
174 | margin: 10px auto;
175 | padding-left:45px;
176 | text-align:center;
177 | width:auto;
178 | }
179 | #DV-searchResults.DV-noResults .DV-resultPrevious,
180 | #DV-searchResults.DV-noResults .DV-resultNext{
181 | display:none;
182 | }
183 |
184 | span.DV-searchItem{
185 | background-color:#fff;
186 | border:1px solid #bababa;
187 | padding: 2px 1px;
188 | }
189 |
190 | span.DV-highlighted{
191 | background-color:#fff;
192 | border:1px solid #bababa;
193 | padding: 2px 1px;
194 | -moz-border-radius: 2px;
195 | -webkit-border-radius: 2px;
196 | }
197 |
198 | #DV-textSearch{
199 | display:none;
200 | }
201 |
202 | .DV-searchingText #DV-textSearch{
203 | position:absolute;
204 | display:block;
205 | top:0;
206 | left:0;
207 | width:300px;
208 | height:25px;
209 | background-color:#fff;
210 | opacity:.8;
211 | -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
212 | filter: alpha(opacity=80);
213 | border-bottom:1px solid #ddd;
214 | }
215 |
--------------------------------------------------------------------------------
/public/javascripts/DV/models/document.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | var documentModel = new DV.model(DV.Schema,
3 | {
4 | currentPageIndex: 0,
5 | offsets: [],
6 | baseHeightsPortion: [],
7 | baseHeightsPortionOffsets: [],
8 | paddedOffsets: [],
9 | totalDocumentHeight: 0,
10 | totalPages: 0,
11 | scrollBarWidth: 0,
12 | additionalPaddingOnPage: 0,
13 |
14 | ZOOM_RANGES: [500, 700, 800, 900, 1000],
15 |
16 | init: function(){
17 | var data = DV.Schema.data;
18 |
19 | this.state = data.state;
20 | this.baseImageURL = data.baseImageURL;
21 | this.additionalPaddingOnPage = data.additionalPaddingOnPage;
22 | this.pageWidthPadding = data.pageWidthPadding;
23 | this.zoomLevel = DV.options.zoom || data.zoomLevel;
24 | this.totalPages = data.totalPages;
25 | this.chapterModel = DV.controller.models.chapters;
26 | this.pageModel = this.application.models.pages;
27 | this.setScrollBarWidth();
28 |
29 | },
30 | setPageIndex : function(index) {
31 | this.currentPageIndex = index;
32 | DV.controller.elements.currentPage.text(this.currentPage());
33 | this.application.helpers.setActiveChapter(this.chapterModel.getChapterId(index));
34 | return index;
35 | },
36 | currentPage : function() {
37 | return this.currentPageIndex + 1;
38 | },
39 | currentIndex : function() {
40 | return this.currentPageIndex;
41 | },
42 | nextPage : function() {
43 | var nextIndex = this.currentIndex() + 1;
44 | if (nextIndex >= this.totalPages) return this.currentIndex();
45 | return this.setPageIndex(nextIndex);
46 | },
47 | previousPage : function() {
48 | var previousIndex = this.currentIndex() - 1;
49 | if (previousIndex < 0) return this.currentIndex();
50 | return this.setPageIndex(previousIndex);
51 | },
52 | zoom: function(zoomLevel,force){
53 | if(this.zoomLevel != zoomLevel || force === true){
54 | this.zoomLevel = zoomLevel;
55 | this.application.models.pages.resize(this.zoomLevel);
56 | this.application.models.annotations.renderAnnotations();
57 | this.computeOffsets();
58 | }
59 | },
60 | computeOffsets: function() {
61 | // this.application.helpers.removeObserver('drawPages');
62 |
63 | var annotationModel = this.application.models.annotations;
64 | var totalDocHeight = 0;
65 | var adjustedOffset = 0;
66 | var len = this.totalPages;
67 | var diff = 0;
68 | var scrollPos = DV.controller.elements.window[0].scrollTop;
69 |
70 | for(var i = 0; i < len; i++) {
71 | if(annotationModel.offsetsAdjustments[i]){
72 | adjustedOffset = annotationModel.offsetsAdjustments[i];
73 | }
74 |
75 | var pageHeight = this.pageModel.getPageHeight(i);
76 | var previousOffset = this.offsets[i];
77 | var h = this.offsets[i] = adjustedOffset + totalDocHeight;
78 |
79 | if((previousOffset !== h) && (h - pageHeight < scrollPos)) {
80 | diff += (h - previousOffset - diff);
81 | }
82 |
83 | this.baseHeightsPortion[i] = Math.round((pageHeight + this.additionalPaddingOnPage) / 3);
84 | this.baseHeightsPortionOffsets[i] = (i == 0) ? 0 : h - this.baseHeightsPortion[i];
85 |
86 | totalDocHeight += (pageHeight + this.additionalPaddingOnPage);
87 | }
88 |
89 | // artificially set the scrollbar height
90 | if(totalDocHeight != this.totalDocumentHeight){
91 | diff = (this.totalDocumentHeight != 0) ? diff : totalDocHeight - this.totalDocumentHeight;
92 | this.application.helpers.setDocHeight(totalDocHeight,diff);
93 | this.totalDocumentHeight = totalDocHeight;
94 | }
95 |
96 | // this.application.helpers.addObserver('drawPages');
97 | },
98 |
99 | // TODO: Fix to not touch the body.
100 | getScrollBarWidth: function(){
101 | var _body = document.body;
102 | _bodyStyle = _body.style;
103 |
104 | _bodyStyle.overflow = 'hidden';
105 | var width = _body.clientWidth;
106 | _bodyStyle.overflow = 'scroll';
107 | width -= _body.clientWidth;
108 |
109 | if(!width){
110 | width = _body.offsetWidth-_body.clientWidth;
111 | }
112 |
113 | _bodyStyle.overflow = '';
114 |
115 | return width;
116 | },
117 | setScrollBarWidth: function(){
118 | this.set('scrollBarWidth',this.getScrollBarWidth());
119 | },
120 | getOffset: function(_index){
121 | return this.offsets[_index];
122 | }
123 | }
124 | );
125 | DV.Schema.models.document = documentModel;
126 | }).call(this);
127 |
--------------------------------------------------------------------------------
/public/javascripts/DV/events/events.js:
--------------------------------------------------------------------------------
1 | // This manages events for different states activated through DV interface actions like clicks, mouseovers, etc.
2 | DV.Schema.events = {
3 | // Change zoom level and causes a reflow and redraw of pages.
4 | zoom: function(zoomLevel){
5 | this.application.pageSet.zoom({ zoomLevel: zoomLevel });
6 |
7 | // Adjust the drag sensativity for largest zoom level
8 | var ranges = this.application.models.document.ZOOM_RANGES;
9 | if(ranges[ranges.length-1] == zoomLevel){
10 | this.application.dragReporter.sensativity = 1.5;
11 | }else{
12 | this.application.dragReporter.sensativity = 1;
13 | }
14 | },
15 |
16 | // Draw (or redraw) the visible pages on the screen.
17 | drawPages: function() {
18 | if (DV.controller.state != 'ViewDocument') return;
19 | var doc = this.models.document;
20 | var offsets = doc.baseHeightsPortionOffsets;
21 | var scrollPos = this.application.scrollPosition = this.elements.window[0].scrollTop;
22 |
23 | var currentPage = _.sortedIndex(offsets, scrollPos);
24 | if (offsets[currentPage] == scrollPos) currentPage++;
25 | var currentIndex = currentPage - 1;
26 | var pageIds = this.helpers.sortPages(currentIndex);
27 |
28 |
29 |
30 | var total = doc.totalPages;
31 | if (doc.currentPage() != currentPage) doc.setPageIndex(currentIndex);
32 |
33 | if (currentPage === 1) return this.drawFirstPage(pageIds);
34 | if (currentPage === total) return this.drawLastPage(pageIds);
35 | return this.drawPageAt(pageIds, currentIndex);
36 | },
37 |
38 | // Draw the first page of the document.
39 | drawFirstPage : function(pageIds) {
40 | this.application.pageSet.draw(
41 | [ { label: pageIds[0], index: 0, currentPage: true },
42 | { label: pageIds[1], index: 1 },
43 | { label: pageIds[2], index: 2 } ]
44 | );
45 |
46 | },
47 |
48 | // Draw the final page of the document.
49 | drawLastPage : function(pageIds) {
50 | var i = this.models.document.totalPages - 1;
51 | this.application.pageSet.draw(
52 | [ { label: pageIds[0], index: i-1 },
53 | { label: pageIds[1], index: i, currentPage: true } ]
54 | );
55 | },
56 |
57 | // Draw the page at the given index.
58 | drawPageAt : function(pageIds, index) {
59 | this.application.pageSet.draw(
60 | [ { label: pageIds[0], index: index - 1 },
61 | { label: pageIds[1], index: index, currentPage: true },
62 | { label: pageIds[2], index: index + 1 } ]
63 | );
64 | },
65 |
66 | check: function(){
67 | var application = this.application;
68 | if(application.busy === false){
69 | application.busy = true;
70 |
71 | for(var i = 0; i < this.application.observers.length; i++){
72 | this[application.observers[i]].call(this);
73 | }
74 | application.busy = false;
75 | }
76 | },
77 |
78 | loadText: function(pageIndex,afterLoad){
79 |
80 | pageIndex = (!pageIndex) ? this.models.document.currentIndex() : parseInt(pageIndex,10);
81 | this._previousTextIndex = pageIndex;
82 |
83 | var me = this;
84 |
85 | var processText = function(text) {
86 |
87 | var pageNumber = parseInt(pageIndex,10)+1;
88 | me.handleTextResponse(text);
89 | me.elements.currentPage.text(pageNumber);
90 | me.elements.textCurrentPage.text('p. '+(pageNumber));
91 | me.models.document.setPageIndex(pageIndex);
92 | me.helpers.setActiveChapter(me.models.chapters.getChapterId(pageIndex));
93 |
94 |
95 | if(afterLoad) afterLoad.call(me.helpers);
96 | };
97 |
98 | if (DV.Schema.text[pageIndex]) {
99 | return processText(DV.Schema.text[pageIndex]);
100 | }
101 |
102 | var handleResponse = $j.proxy(function(response) {
103 |
104 | processText(DV.Schema.text[pageIndex] = response);
105 | }, this);
106 |
107 | $j('#DV-textContents').text('');
108 |
109 | var textURI = DV.Schema.document.resources.page.text.replace('{page}', pageIndex + 1);
110 | var crossDomain = this.helpers.isCrossDomain(textURI);
111 | if (crossDomain) textURI += '?callback=?';
112 | $j[crossDomain ? 'getJSON' : 'get'](textURI, {}, handleResponse);
113 | },
114 |
115 | handleTextResponse: function(text){
116 | $j('#DV-textContents').text(text);
117 | },
118 | resetTracker: function(){
119 | this.application.activeAnnotation = null;
120 | this.trackAnnotation.combined = null;
121 | this.trackAnnotation.h = null;
122 | },
123 | trackAnnotation: function(){
124 | var application = this.application;
125 | var helpers = this.helpers;
126 | var scrollPosition = this.elements.window[0].scrollTop;
127 |
128 | if(application.activeAnnotation){
129 | var annotation = application.activeAnnotation;
130 | var trackAnnotation = this.trackAnnotation;
131 |
132 |
133 | if(trackAnnotation.id != annotation.id){
134 | trackAnnotation.id = annotation.id;
135 | helpers.setActiveAnnotationLimits(annotation);
136 | }
137 |
138 | if(scrollPosition > trackAnnotation.h || scrollPosition < trackAnnotation.combined){
139 |
140 |
141 | annotation.hide(true);
142 | application.pageSet.setActiveAnnotation(null);
143 | application.activeAnnotation = null;
144 | trackAnnotation.h = null;
145 | trackAnnotation.id = null;
146 | trackAnnotation.combined = null;
147 | }
148 | }else{
149 | application.pageSet.setActiveAnnotation(null);
150 | application.activeAnnotation = null;
151 | trackAnnotation.h = null;
152 | trackAnnotation.id = null;
153 | trackAnnotation.combined = null;
154 | helpers.removeObserver('trackAnnotation');
155 | }
156 | }
157 | };
--------------------------------------------------------------------------------
/public/javascripts/DV/helpers/construction.js:
--------------------------------------------------------------------------------
1 | // Renders the navigation sidebar for chapters and annotations.
2 | _.extend(DV.Schema.helpers, {
3 | renderViewer: function(){
4 | var doc = DV.Schema.document;
5 | var pagesHTML = this.constructPages();
6 | var description = (doc.description) ? doc.description : null;
7 | var storyURL = doc.resources.related_article;
8 |
9 | var headerHTML = JST.header(
10 | {
11 | id : doc.id,
12 | search_type : (window.navigator.userAgent.match(/webkit/i)) ? 'search' : 'text',
13 | story_url : storyURL,
14 | title : doc.title || ''
15 | });
16 |
17 | var pdfURL = doc.resources.pdf;
18 | pdfURL = pdfURL ? 'Original Document (PDF) ' : '';
19 |
20 | $j(DV.container).html(JST.viewer(
21 | { pages: pagesHTML,
22 | header: headerHTML,
23 | pdf_url: pdfURL,
24 | story_url: storyURL,
25 | descriptionContainer: JST.descriptionContainer({ description: description})
26 | }
27 | ));
28 | },
29 | renderNavigation : function() {
30 | var chapterViews = [], bolds = [], expandIcons = [], expanded = [], navigationExpander = JST.navigationExpander({}),nav=[],notes = [],chapters = [];
31 |
32 | /* ---------------------------------------------------- start the nav helper methods */
33 | var getAnnotionsByRange = function(rangeStart, rangeEnd){
34 | var annotations = [];
35 | for(var i = rangeStart, len = rangeEnd; i < len; i++){
36 | if(notes[i]){
37 | annotations.push(notes[i]);
38 | nav[i] = '';
39 | }
40 | }
41 | return annotations.join('');
42 | };
43 |
44 | var createChapter = function(chapter){
45 | var selectionRule = "#DV-selectedChapter-" + chapter.id + " #DV-chapter-" + chapter.id;
46 |
47 | bolds.push(selectionRule+" .DV-first span.DV-trigger");
48 | return (JST.chapterNav(chapter));
49 | };
50 |
51 | var createNavAnnotations = function(annotationIndex){
52 | var renderedAnnotations = [];
53 | var annotations = DV.Schema.data.annotationsByPage[annotationIndex];
54 |
55 | for (var j=0; j= 1){
72 | for(var i=0; i';
104 | $j('head').append(navStylesheet);
105 | // cleanup
106 | chaptersContainer = null;
107 |
108 | },
109 |
110 | // Hide or show all of the comoponents on the page that may or may not be
111 | // present, depending on what the document provides.
112 | renderComponents : function() {
113 | // Hide the overflow of the body, if we're at the top level.
114 | if (DV.container == document.body) {
115 | $j(document.body).css({margin : 0, padding : 0, overflow : 'hidden'});
116 | }
117 |
118 | // Hide annotations, if there are none:
119 | var showAnnotations = _.any(this.models.annotations.byId);
120 | $j('#DV-annotationView')[showAnnotations ? 'show' : 'hide']();
121 |
122 | // Hide the searchBox, if it's disabled.
123 | var showSearch = !!DV.Schema.document.resources.search;
124 | if (showSearch) this.elements.viewer.addClass('DV-searchable');
125 |
126 | // Hide the entire sidebar, if there are no annotations or sections.
127 | var showChapters = this.models.chapters.chapters.length > 0;
128 |
129 | // Remove and re-render the nav controls.
130 | $j('#DV-navControls').remove();
131 | var navControls = JST.navControls({
132 | totalPages: DV.Schema.data.totalPages,
133 | totalAnnotations: DV.Schema.data.totalAnnotations
134 | });
135 |
136 | $j('#DV-well .DV-navControlsContainer').html(navControls);
137 | $j('#DV-sidebar').show();
138 |
139 | // Set the currentPage element reference.
140 | this.elements.currentPage = $j('span#DV-currentPage');
141 | this.models.document.setPageIndex(this.models.document.currentIndex());
142 | }
143 | });
--------------------------------------------------------------------------------
/viewer-debug.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document Title
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
Loading
34 |
35 |
36 | The Document Viewer requires that you enable Javascript.
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/public/javascripts/DV/lib/annotation.js:
--------------------------------------------------------------------------------
1 | DV.Annotation = DV.Class.extend({
2 |
3 | init: function(argHash){
4 | this.position = { top: argHash.top, left: argHash.left };
5 | this.dimensions = { width: argHash.width, height: argHash.height };
6 | this.page = argHash.page;
7 | this.pageEl = argHash.pageEl;
8 | this.annotationContainerEl = argHash.annotationContainerEl;
9 | this.application = this.page.set.application;
10 | this.annotationEl = null;
11 | this.renderedHTML = argHash.renderedHTML;
12 | this.type = argHash.type;
13 | this.id = argHash.id;
14 | this.model = this.application.models.annotations.getAnnotation(this.id);
15 | this.state = 'collapsed';
16 | this.active = false;
17 | this.remove();
18 | this.add();
19 |
20 | if(argHash.active){
21 | this.application.helpers.setActiveAnnotationLimits(this);
22 | this.application.events.resetTracker();
23 | this.active = null;
24 | // this.application.elements.window[0].scrollTop += this.annotationEl.offset().top;
25 | this.show();
26 | if (argHash.showEdit) this.showEdit();
27 | }
28 | },
29 |
30 | // Add annotation to page
31 | add: function(){
32 | if(this.type === 'page'){
33 | this.annotationEl = this.renderedHTML.insertBefore(this.annotationContainerEl);
34 | }else{
35 | if(this.page.annotations.length > 0){
36 | for(var i = 0,len = this.page.annotations.length;i 0) ? true : false;
6 |
7 | var text = hasResults ? 'of '+response.results.length + ' ' : ' ';
8 | $j('span#DV-totalSearchResult').text(text);
9 | $j('span#DV-searchQuery').text(response.query);
10 | if (hasResults) {
11 | DV.history.save('search/p'+response.results[0]+'/'+response.query);
12 | this.events.loadText(response.results[0] - 1, this.highlightSearchResponses);
13 | } else {
14 | this.highlightSearchResponses();
15 | }
16 | }, this);
17 |
18 | var failResponse = function() {
19 | $j('#DV-currentSearchResult').text('Search is not available at this time');
20 | $j('span#DV-searchQuery').text(query);
21 | $j('#DV-searchResults').addClass('DV-noResults');
22 | };
23 |
24 | var searchURI = DV.Schema.document.resources.search.replace('{query}', encodeURIComponent(query));
25 | if (DV.controller.helpers.isCrossDomain(searchURI)) searchURI += '&callback=?';
26 | $j.ajax({url : searchURI, dataType : 'json', success : handleResponse, error : failResponse});
27 | },
28 | acceptInputCallBack: function(){
29 | var pageIndex = parseInt(this.elements.currentPage.text(),10) - 1;
30 | // sanitize input
31 |
32 | pageIndex = (pageIndex === '') ? 0 : pageIndex;
33 | pageIndex = (pageIndex < 0) ? 0 : pageIndex;
34 | pageIndex = (pageIndex+1 > this.models.document.totalPages) ? this.models.document.totalPages-1 : pageIndex;
35 | var pageNumber = pageIndex+1;
36 |
37 | this.elements.currentPage.text(pageNumber);
38 | $j('.DV-pageNumberContainer input').val(pageNumber);
39 |
40 | if(this.application.state === 'ViewDocument'){
41 | DV.history.save('document/p'+pageNumber);
42 | this.jump(pageIndex);
43 | }else if(this.application.state === 'ViewText'){
44 | DV.history.save('text/p'+pageNumber);
45 | this.events.loadText(pageIndex);
46 | }
47 |
48 | },
49 | highlightSearchResponses: function(){
50 |
51 | var application = this.application;
52 | var response = application.searchResponse;
53 |
54 | if(!response) return false;
55 |
56 | var results = response.results;
57 | var currentResultEl = $j('#DV-currentSearchResult');
58 |
59 | if (results.length == 0){
60 | currentResultEl.text('No Results');
61 | $j('#DV-searchResults').addClass('DV-noResults');
62 | }else{
63 | $j('#DV-searchResults').removeClass('DV-noResults');
64 | }
65 | for(var i = 0; i < response.results.length; i++){
66 | if(this.models.document.currentPage() === response.results[i]){
67 | currentResultEl.text('Page ' + (i+1) + ' ');
68 | break;
69 | }
70 | }
71 | var textContent = $j('#DV-textContents');
72 | var currentPageText = textContent.text();
73 | var pattern = new RegExp(response.query,"ig");
74 | var replacement = currentPageText.replace(pattern,'$& ');
75 |
76 | textContent.html(replacement);
77 |
78 | var highlightIndex = (application.toHighLight) ? application.toHighLight : 0;
79 | this.highlightMatch(highlightIndex);
80 |
81 | // cleanup
82 | currentResultEl = null;
83 | textContent = null;
84 |
85 | },
86 | // Highlight a single instance of an entity on the page. Make sure to
87 | // convert into proper UTF8 before trying to get the entity length, and
88 | // then back into UTF16 again.
89 | highlightEntity: function(offset, length) {
90 | $j('#DV-searchResults').addClass('DV-noResults');
91 | var textContent = $j('#DV-textContents');
92 | var text = textContent.text();
93 | var pre = text.substr(0, offset);
94 | var entity = text.substr(offset, length);
95 | var post = text.substr(offset + length);
96 | text = [pre, '', entity, ' ', post].join('');
97 | textContent.html(text);
98 | this.highlightMatch(0);
99 | },
100 |
101 | highlightMatch: function(index){
102 | var highlightsOnThisPage = $j('#DV-textContents span.DV-searchMatch');
103 | if (highlightsOnThisPage.length == 0) return false;
104 | var currentPageIndex = this.getCurrentSearchPageIndex();
105 | var toHighLight = this.application.toHighLight;
106 |
107 | if(toHighLight){
108 | if(toHighLight !== false){
109 | if(toHighLight === 'last'){
110 | index = highlightsOnThisPage.length - 1;
111 | }else if(toHighLight === 'first'){
112 | index = 0;
113 | }else{
114 | index = toHighLight;
115 | }
116 | }
117 | toHighLight = false;
118 | }
119 | var searchResponse = this.application.searchResponse;
120 | if (searchResponse) {
121 | if(index === (highlightsOnThisPage.length)){
122 |
123 | if(searchResponse.results.length === currentPageIndex+1){
124 | return;
125 | }
126 | toHighLight = 'first';
127 | this.events.loadText(searchResponse.results[currentPageIndex + 1] - 1,this.highlightSearchResponses);
128 |
129 | return;
130 | }else if(index === -1){
131 | if(currentPageIndex-1 < 0){
132 | return false;
133 | }
134 | toHighLight = 'last';
135 | this.events.loadText(searchResponse.results[currentPageIndex - 1] - 1,this.highlightSearchResponses);
136 |
137 | return;
138 | }
139 | highlightsOnThisPage.removeClass('DV-highlightedMatch');
140 | }
141 |
142 | var match = $j('#DV-textContents span.DV-searchMatch:eq('+index+')');
143 | match.addClass('DV-highlightedMatch');
144 |
145 | this.elements.window.scrollTo(match.position().top-50,{ axis: 'y' });
146 | if (searchResponse) searchResponse.highlighted = index;
147 |
148 | // cleanup
149 | highlightsOnThisPage = null;
150 | match = null;
151 | },
152 | getCurrentSearchPageIndex: function(){
153 | var searchResponse = this.application.searchResponse;
154 | if(!searchResponse) {
155 | return false;
156 | }
157 | var docModel = this.models.document;
158 | for(var i = 0,len = searchResponse.results.length; iparseInt(oldOffset, 10)) ? scrollPos - oldOffset : oldOffset - scrollPos;
79 |
80 | var diffPercentage = diff / this.application.models.pages.height;
81 |
82 |
83 |
84 | // this.position();
85 | this.reflowPages();
86 | this.zoomText();
87 |
88 | if(this.application.activeAnnotation != null){
89 | // FIXME:
90 |
91 | var args =
92 | {
93 | index: this.application.models.document.currentIndex(),
94 | top: this.application.activeAnnotation.y1,
95 | id: this.application.activeAnnotation.id
96 | };
97 | this.application.activeAnnotation = null;
98 |
99 | this.showAnnotation(args);
100 | this.application.helpers.setActiveAnnotationLimits(this.application.activeAnnotation);
101 | }else{
102 | var _offset = Math.round(this.application.models.pages.height * diffPercentage);
103 | this.application.helpers.jump(this.application.models.document.currentIndex(),_offset);
104 | }
105 | },
106 |
107 | // Zoom the text container.
108 | zoomText: function() {
109 | var padding = this.application.models.pages.TEXT_PADDING;
110 | var width = this.application.models.pages.zoomLevel - padding;
111 | $j('#DV-textContents').width(width);
112 | $j('#DV-textPage').width(width + padding);
113 | this.application.elements.collection.css({'width' : width + padding + padding});
114 | },
115 |
116 | // draw the pages
117 | draw: function(pageCollection){
118 | for(var i = 0, pageCollectionLength = pageCollection.length; i < pageCollectionLength;i++){
119 | var page = this.pages[pageCollection[i].label];
120 | if (page) page.draw({ index: pageCollection[i].index, pageNumber: pageCollection[i].index+1});
121 | }
122 | },
123 | redraw : function(stopResetOfPosition, redrawAnnotations) {
124 |
125 | var _index = this.application.models.document.currentIndex();
126 | if (this.pages['p0']) this.pages['p0'].draw({ force: true, forceAnnotationRedraw : redrawAnnotations });
127 | if (this.pages['p1']) this.pages['p1'].draw({ force: true, forceAnnotationRedraw : redrawAnnotations });
128 | if (this.pages['p2']) this.pages['p2'].draw({ force: true, forceAnnotationRedraw : redrawAnnotations });
129 |
130 | if(this.application.activeAnnotation){
131 | this.application.helpers.jump(this.application.activeAnnotation.page.index,this.application.activeAnnotation.position.top - 37);
132 | }
133 | },
134 | // set the annotation to load ahead of time
135 | setActiveAnnotation: function(annotationId, edit){
136 | this.application.annotationToLoadId = annotationId;
137 | this.application.annotationToLoadEdit = edit ? annotationId : null;
138 | },
139 | // a funky fucking mess to jump to the annotation that is active
140 | showAnnotation: function(argHash, showHash){
141 | showHash = showHash || {};
142 |
143 | // if state is ViewAnnotation, jump to the appropriate position in the view
144 | // else
145 | // hide active annotations and locate the position of the next annotation
146 | // NOTE: This needs work
147 | if(this.application.state === 'ViewAnnotation'){
148 |
149 | var offset = $j('#DV-annotations div[rel=aid-'+argHash.id+']')[0].offsetTop;
150 | this.application.elements.window.scrollTop(offset+10,'fast');
151 | this.application.helpers.setActiveAnnotationInNav(argHash.id);
152 | this.application.activeAnnotationId = argHash.id;
153 | DV.history.save('annotation/a'+argHash.id);
154 | return;
155 | }else{
156 | this.application.helpers.removeObserver('trackAnnotation');
157 | this.application.activeAnnotationId = null;
158 | if(this.application.activeAnnotation != null){
159 | this.application.activeAnnotation.hide();
160 | }
161 | this.setActiveAnnotation(argHash.id, showHash.edit);
162 |
163 | var offset = argHash.top-36;
164 |
165 | // this.application.helpers.jump(this.application.models.document.currentIndex(),this.application.activeAnnotation.position.top - 37);
166 | //
167 |
168 |
169 | for(var i = 0; i <= 2; i++){
170 | if (this.pages['p' + i]) {
171 | for(var n = 0; n < this.pages['p'+i].annotations.length; n++){
172 | if(this.pages['p'+i].annotations[n].id === argHash.id){
173 | if (!showHash.noJump) {
174 | this.application.helpers.jump(argHash.index, offset);
175 | }
176 | this.pages['p'+i].annotations[n].show(showHash);
177 | return;
178 | }
179 | }
180 | }
181 | }
182 |
183 |
184 | if (!showHash.noJump){
185 |
186 | this.application.helpers.jump(argHash.index,offset);
187 | }
188 |
189 | }
190 | }
191 | });
192 |
--------------------------------------------------------------------------------
/public/javascripts/DV/models/annotation.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | var annotationModel = new DV.model(DV.Schema,{
4 | offsetsAdjustments: [],
5 | offsetAdjustmentSum: 0,
6 |
7 | init: function(){
8 | this.saveCallbacks = [];
9 | this.deleteCallbacks = [];
10 | this.byId = DV.Schema.data.annotationsById;
11 | this.byPage = DV.Schema.data.annotationsByPage;
12 | this.bySortOrder = this.sortAnnotations();
13 | this.annotationLeftPageBuffer = 25;
14 | },
15 |
16 | render: function(annotation){
17 | var documentModel = this.application.models.document;
18 | var pageModel = this.application.models.pages;
19 | var zoom = pageModel.zoomFactor();
20 | var adata = annotation;
21 | var _default = 0;
22 |
23 | if(adata.type === 'page'){
24 |
25 | adata._y1 = _default;
26 | adata._y2 = _default;
27 | adata._x1 = _default;
28 | adata._x2 = _default;
29 | adata.top = _default;
30 |
31 | }else{
32 | adata._y1 = Math.round(adata.y1 * zoom);
33 | adata._y2 = Math.round(adata.y2 * zoom);
34 | if(adata.x1 < this.annotationLeftPageBuffer){
35 | adata.x1 = this.annotationLeftPageBuffer;
36 | }
37 | adata._x1 = Math.round(adata.x1 * zoom);
38 | adata._x2 = Math.round(adata.x2 * zoom);
39 | adata.top = adata._y1 - 6;
40 | }
41 |
42 | adata.width = pageModel.width;
43 | adata.pageNumber = adata.page;
44 | adata.bgWidth = adata.width;
45 | adata.bWidth = adata.width - 66;
46 | adata.excerptWidth = (adata._x2 - adata._x1) - 10;
47 | adata.excerptMarginLeft = adata._x1 - 18;
48 | adata.excerptLeft = adata._x1 - 25;
49 | adata.excerptHeight = adata._y2 - adata._y1;
50 | adata.index = adata.page - 1;
51 | adata.image = pageModel.imageURL(adata.index);
52 | adata.imageLeft = adata._x1;
53 | adata.imageTop = adata._y1 + 2;
54 | adata.imageWidth = pageModel.width;
55 | adata.imageHeight = Math.round(pageModel.height * zoom);
56 | adata.regionLeft = adata._x1;
57 | adata.regionWidth = adata._x2 - adata._x1 ;
58 | adata.regionHeight = adata._y2 - adata._y1;
59 | adata.excerptDSHeight = adata.excerptHeight - 6;
60 | adata.DSOffset = 3;
61 |
62 | adata.orderClass = '';
63 | if (adata.first == true) adata.orderClass += ' DV-firstAnnotation';
64 | if (adata.last == true) adata.orderClass += ' DV-lastAnnotation';
65 |
66 | var template = (adata.type === 'page') ? 'pageAnnotation' : 'annotation';
67 | return JST[template](adata);
68 | },
69 |
70 | // Re-sort the list of annotations when its contents change.
71 | sortAnnotations : function() {
72 | return this.bySortOrder = _.sortBy(_.values(this.byId), function(anno) {
73 | return anno.page * 10000 + anno.y1;
74 | });
75 | },
76 |
77 | // Renders each annotation into it's HTML format.
78 | renderAnnotations: function(){
79 | for (var i=0; i
');
5 | window.JST.annotationNav = _.template(' <%= title %> p.<%= page %>
');
6 | window.JST.chapterNav = _.template(' <%= navigationExpander %> <%= title %>p. <%= pageNumber %>
<%= noteViews %>
');
7 | window.JST.descriptionContainer = _.template('<% if (description) { %> Toggle Description Description
<%= description %>
<% } %>');
8 | window.JST.header = _.template('');
9 | window.JST.navControls = _.template(' « Page Annot. 1 of <%= totalPages %> <%= totalAnnotations %>
» ');
10 | window.JST.navigationExpander = _.template('Expand ');
11 | window.JST.pageAnnotation = _.template('');
12 | window.JST.pages = _.template(' p. <%= pageNumber %>
Loading Loading
');
13 | window.JST.unsupported = _.template(' To use the Document Viewer you need to upgrade to a modern browser:
');
14 | window.JST.viewer = _.template('');
15 | })();
--------------------------------------------------------------------------------