diff --git a/build/css/diva.css b/build/css/diva.css index 70c0142e..862acb9b 100644 --- a/build/css/diva.css +++ b/build/css/diva.css @@ -38,8 +38,10 @@ background-position: center; border: 1px solid #99bbe8; } -.button:hover { - background-color: #fdfdfd; +@media screen and (min-device-width: 769px) { + .button:hover { + background-color: #fdfdfd; + } } .diva-title { text-align: center; @@ -56,11 +58,13 @@ display: none; padding: 8px; float: left; + clear: left; } .diva-tools .diva-tools-left .diva-zoom-buttons-label { display: none; padding: 8px; float: left; + clear: left; } .diva-tools .diva-tools-left .diva-zoom-out-button { display: none; @@ -88,6 +92,7 @@ display: none; padding: 8px; float: left; + clear: left; } .diva-tools .diva-tools-left.in-fullscreen { float: left; @@ -174,6 +179,7 @@ .diva-outer .diva-inner { position: relative; overflow: hidden; + margin: 0 auto; } .diva-outer .diva-inner .diva-page { -webkit-box-shadow: 2px 2px 6px 0 rgba(0, 0, 0, 0.5); @@ -277,11 +283,23 @@ position: relative; top: 0.6em; display: none; + float: left; +} +@media (max-width: 480px) { + .zoom-slider { + width: 100px; + } } .grid-slider { position: relative; top: 0.6em; display: none; + float: left; +} +@media (max-width: 480px) { + .grid-slider { + width: 100px; + } } .diva-throbber { display: none; diff --git a/build/css/diva.min.css b/build/css/diva.min.css index 1a29c621..20758d5f 100644 --- a/build/css/diva.min.css +++ b/build/css/diva.min.css @@ -1 +1 @@ -.hidden{display:none}.grab{cursor:url("../img/openhand.cur"),pointer}.grabbing{cursor:url("../img/closedhand.cur"),move !important}.loading{background:url("../img/loading.gif") no-repeat center}.full-width{width:100% !important;max-width:100% !important}.full-height{height:100% !important;max-height:100% !important}.prevent-selection{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.button{cursor:pointer;height:32px;width:32px;background-color:#f1f1f1;background-repeat:no-repeat;background-position:center;border:1px solid #99bbe8}.button:hover{background-color:#fdfdfd}.diva-title{text-align:center;font-weight:bold;font-size:2em}.diva-tools{margin-top:15px}.diva-tools .diva-tools-left{float:left}.diva-tools .diva-tools-left .diva-slider-label{display:none;padding:8px;float:left}.diva-tools .diva-tools-left .diva-zoom-buttons-label{display:none;padding:8px;float:left}.diva-tools .diva-tools-left .diva-zoom-out-button{display:none;float:left;background-image:url("../img/zoomout.png")}.diva-tools .diva-tools-left .diva-zoom-in-button{display:none;float:left;background-image:url("../img/zoomin.png");margin-left:-1px}.diva-tools .diva-tools-left .diva-grid-out-button{display:none;float:left;background-image:url("../img/zoomout.png")}.diva-tools .diva-tools-left .diva-grid-in-button{display:none;float:left;background-image:url("../img/zoomin.png");margin-left:-1px}.diva-tools .diva-tools-left .diva-buttons-label{display:none;padding:8px;float:left}.diva-tools .diva-tools-left.in-fullscreen{float:left;clear:none}.diva-tools .diva-tools-right{float:right;height:42px}.diva-tools .diva-tools-right .diva-grid-icon{float:right;background-image:url("../img/grid.png")}.diva-tools .diva-tools-right .diva-grid-icon.diva-in-grid{background-image:url("../img/document.png")}.diva-tools .diva-tools-right .diva-link-icon{float:right;background-image:url("../img/link.png")}.diva-tools .diva-tools-right .diva-page-nav{float:left;text-align:right;padding-right:4px;white-space:nowrap;line-height:32px}.diva-tools .diva-tools-right .diva-page-nav .diva-page-label{float:left;padding-top:1px;padding-right:.5em;line-height:32px}.diva-tools .diva-tools-right .diva-page-nav .diva-goto-form{float:right}.diva-tools .diva-tools-right .diva-page-nav .diva-goto-form .diva-input{width:30px;outline:none;margin:0;padding-top:0}.diva-tools.diva-fullscreen-tools{position:fixed;top:0;right:30px;z-index:101;width:230px;height:73px;padding:15px;border:1px solid #ddd;background:#fff;-webkit-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5)}.diva-tools.diva-fullscreen-tools .diva-buttons-label{margin-top:5px;padding:0;clear:both}.diva-tools.diva-fullscreen-tools .diva-page-nav{float:none;line-height:1em}.diva-tools.diva-fullscreen-tools .diva-page-nav .diva-goto-form{margin-top:9px}.diva-tools.diva-fullscreen-tools .diva-page-nav .diva-page-label{float:none;clear:both;line-height:1em}.diva-outer{clear:both;background:#f1f1f1;border:1px solid #99bbe8;position:relative;min-height:100px;min-width:200px;height:700px;overflow:auto}.diva-outer .diva-inner{position:relative;overflow:hidden}.diva-outer .diva-inner .diva-page{-webkit-box-shadow:2px 2px 6px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 6px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 6px 0 rgba(0,0,0,0.5);background:url("../img/loading.gif") no-repeat center;position:absolute}.diva-outer .diva-inner .diva-document-page{-webkit-box-shadow:2px 2px 6px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 6px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 6px 0 rgba(0,0,0,0.5);background:url("../img/loading.gif") no-repeat center;position:absolute;left:0;right:0}.diva-outer .diva-inner .diva-document-page .diva-page-tools{position:absolute;top:-25px;left:0;height:25px;z-index:3}.diva-outer .diva-inner .diva-document-page .diva-page-tools div{display:inline-block;height:25px;width:25px;cursor:pointer}.diva-outer .diva-inner .diva-page-vertical{margin:0 auto;display:inline-block}.diva-outer .diva-inner .diva-page-horizontal{vertical-align:middle;display:inline-block;top:50%;transform:translate(0, -50%);-webkit-transform:translate(0, -50%);-moz-transform:translate(0, -50%);-ms-transform:translate(0, -50%)}.diva-outer .diva-inner .diva-row{position:absolute;width:100%}.diva-outer .diva-inner.diva-grab{cursor:url("../img/openhand.cur"),pointer}.diva-outer .diva-inner.diva-grabbing{cursor:url("../img/closedhand.cur"),move !important}.diva-outer.diva-fullscreen{width:100% !important;max-width:100% !important;height:100% !important;max-height:100% !important;z-index:100;position:fixed !important;top:0;left:0;margin:0;border:0}.diva-fullscreen-icon{background-image:url("../img/fullscreen.png");border-left:0;float:right}.diva-link-popup{background:#fff;border:1px solid #ddd;height:28px;width:230px;position:absolute;padding:5px;z-index:101;-webkit-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5)}.diva-link-popup input{width:226px;margin-top:5px}.diva-link-popup input:focus{outline:none}.diva-link-popup.in-fullscreen{top:150px;right:30px}.diva-hide-scrollbar{overflow:hidden !important}.diva-relative-position{position:relative}.zoom-slider{position:relative;top:.6em;display:none}.grid-slider{position:relative;top:.6em;display:none}.diva-throbber{display:none;position:absolute;width:50px;height:50px;background:url("../img/loading.gif") no-repeat center;background-color:#fff;border:1px solid #ddd;-webkit-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);top:50%;left:50%;margin-left:-25px;margin-top:-25px}.diva-error{position:absolute;width:400px;height:200px;background-color:#fff;border:1px solid #ddd;-webkit-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);top:50%;left:50%;margin-left:-220px;margin-top:-120px;z-index:120;padding:0 1em}.diva-canvas-icon{background:url('../img/plugins/canvas.png') no-repeat;background-position:left center}.diva-canvas-icon:hover{background-position:-25px center}.diva-canvas-icon.new{background-position:-50px center}.diva-canvas-icon.new:hover{background-position:-75px center}#diva-canvas-backdrop{z-index:105;position:fixed;top:0;left:0;bottom:0;right:0;display:none;background:rgba(50,50,50,0.9)}#diva-canvas-tools{color:#333;position:fixed;top:10px;left:10px;width:230px;z-index:108;background:#fff;padding-bottom:10px;-webkit-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5)}#diva-canvas-tools .action-buttons{clear:both;margin-bottom:5px;text-align:right}#diva-canvas-tools .action-buttons a{color:#333;text-decoration:none;background:#f1f1f1;padding:5px;border:1px solid #99bbe8}#diva-canvas-tools .action-buttons a:last-child{border-left:0}#diva-canvas-tools .action-buttons a:hover{background:#fdfdfd}#diva-canvas-toolbar{height:16px;padding:10px;padding-bottom:0}#diva-canvas-toolbar div{height:18px;width:18px;background-repeat:no-repeat;cursor:pointer;z-index:109;display:inline-block;margin-right:5px;background-image:url("../img/actions.png")}#diva-canvas-toolbar span{vertical-align:top;float:right}#diva-canvas-toolwindow{position:relative;margin:10px}#diva-canvas-close:hover{background-position:-20px 0}#diva-canvas-minimise{background-position:-40px 0}#diva-canvas-minimise:hover{background-position:-60px 0}#diva-canvas-buttons div{cursor:pointer;background-image:url("../img/plugins/canvas-buttons.png");background-repeat:no-repeat;width:20px;height:20px;padding:5px;display:inline-block}#diva-canvas-buttons div.clicked{background-color:#ddd}#diva-canvas-buttons .contrast{background-position:5px 5px}#diva-canvas-buttons .contrast:hover,#diva-canvas-buttons .contrast.clicked{background-position:5px -25px}#diva-canvas-buttons .brightness{background-position:-25px 5px}#diva-canvas-buttons .brightness:hover,#diva-canvas-buttons .brightness.clicked{background-position:-25px -25px}#diva-canvas-buttons .rotation{background-position:-55px 5px}#diva-canvas-buttons .rotation:hover,#diva-canvas-buttons .rotation.clicked{background-position:-55px -25px}#diva-canvas-buttons .zoom{background-position:-85px 5px}#diva-canvas-buttons .zoom:hover,#diva-canvas-buttons .zoom.clicked{background-position:-85px -25px}#diva-canvas-buttons .red{background-position:-115px 5px}#diva-canvas-buttons .red:hover,#diva-canvas-buttons .red.clicked{background-position:-115px -25px}#diva-canvas-buttons .green{background-position:-145px 5px}#diva-canvas-buttons .green:hover,#diva-canvas-buttons .green.clicked{background-position:-145px -25px}#diva-canvas-buttons .blue{background-position:-175px 5px}#diva-canvas-buttons .blue:hover,#diva-canvas-buttons .blue.clicked{background-position:-175px -25px}#diva-canvas-pane{background:#ddd;padding-bottom:10px}#diva-canvas-pane p{margin-left:10px;padding-top:10px}#diva-canvas-pane p .link{cursor:pointer}#diva-canvas-pane p .link:hover{text-decoration:underline}#diva-canvas-mode{text-transform:capitalize}#diva-canvas-slider{width:188px;margin:0 auto;display:block}#diva-canvas-slider .handle{margin-left:-6px}#diva-canvas-minimap{height:210px;width:210px;cursor:crosshair;margin-bottom:10px;background:#000}#diva-canvas{position:absolute;left:0;right:0;margin:0 auto;z-index:107;cursor:url("../img/openhand.cur"),pointer}#diva-map-viewbox{border:2px solid #99bbe8;position:absolute;top:10px;left:10px;cursor:crosshair;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:none}.overflow-hidden{overflow:hidden !important}#diva-canvas-wrapper{z-index:106;position:absolute;top:0;left:0;bottom:0;right:0;overflow:scroll}.canvas-throbber{z-index:110;position:fixed}.diva-download-icon{background:url('../img/plugins/download.png') no-repeat;background-position:left center}.diva-download-icon:hover{background-position:-25px center} \ No newline at end of file +.hidden{display:none}.grab{cursor:url("../img/openhand.cur"),pointer}.grabbing{cursor:url("../img/closedhand.cur"),move !important}.loading{background:url("../img/loading.gif") no-repeat center}.full-width{width:100% !important;max-width:100% !important}.full-height{height:100% !important;max-height:100% !important}.prevent-selection{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.button{cursor:pointer;height:32px;width:32px;background-color:#f1f1f1;background-repeat:no-repeat;background-position:center;border:1px solid #99bbe8}@media screen and (min-device-width:769px){.button:hover{background-color:#fdfdfd}}.diva-title{text-align:center;font-weight:bold;font-size:2em}.diva-tools{margin-top:15px}.diva-tools .diva-tools-left{float:left}.diva-tools .diva-tools-left .diva-slider-label{display:none;padding:8px;float:left;clear:left}.diva-tools .diva-tools-left .diva-zoom-buttons-label{display:none;padding:8px;float:left;clear:left}.diva-tools .diva-tools-left .diva-zoom-out-button{display:none;float:left;background-image:url("../img/zoomout.png")}.diva-tools .diva-tools-left .diva-zoom-in-button{display:none;float:left;background-image:url("../img/zoomin.png");margin-left:-1px}.diva-tools .diva-tools-left .diva-grid-out-button{display:none;float:left;background-image:url("../img/zoomout.png")}.diva-tools .diva-tools-left .diva-grid-in-button{display:none;float:left;background-image:url("../img/zoomin.png");margin-left:-1px}.diva-tools .diva-tools-left .diva-buttons-label{display:none;padding:8px;float:left;clear:left}.diva-tools .diva-tools-left.in-fullscreen{float:left;clear:none}.diva-tools .diva-tools-right{float:right;height:42px}.diva-tools .diva-tools-right .diva-grid-icon{float:right;background-image:url("../img/grid.png")}.diva-tools .diva-tools-right .diva-grid-icon.diva-in-grid{background-image:url("../img/document.png")}.diva-tools .diva-tools-right .diva-link-icon{float:right;background-image:url("../img/link.png")}.diva-tools .diva-tools-right .diva-page-nav{float:left;text-align:right;padding-right:4px;white-space:nowrap;line-height:32px}.diva-tools .diva-tools-right .diva-page-nav .diva-page-label{float:left;padding-top:1px;padding-right:.5em;line-height:32px}.diva-tools .diva-tools-right .diva-page-nav .diva-goto-form{float:right}.diva-tools .diva-tools-right .diva-page-nav .diva-goto-form .diva-input{width:30px;outline:none;margin:0;padding-top:0}.diva-tools.diva-fullscreen-tools{position:fixed;top:0;right:30px;z-index:101;width:230px;height:73px;padding:15px;border:1px solid #ddd;background:#fff;-webkit-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5)}.diva-tools.diva-fullscreen-tools .diva-buttons-label{margin-top:5px;padding:0;clear:both}.diva-tools.diva-fullscreen-tools .diva-page-nav{float:none;line-height:1em}.diva-tools.diva-fullscreen-tools .diva-page-nav .diva-goto-form{margin-top:9px}.diva-tools.diva-fullscreen-tools .diva-page-nav .diva-page-label{float:none;clear:both;line-height:1em}.diva-outer{clear:both;background:#f1f1f1;border:1px solid #99bbe8;position:relative;min-height:100px;min-width:200px;height:700px;overflow:auto}.diva-outer .diva-inner{position:relative;overflow:hidden;margin:0 auto}.diva-outer .diva-inner .diva-page{-webkit-box-shadow:2px 2px 6px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 6px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 6px 0 rgba(0,0,0,0.5);background:url("../img/loading.gif") no-repeat center;position:absolute}.diva-outer .diva-inner .diva-document-page{-webkit-box-shadow:2px 2px 6px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 6px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 6px 0 rgba(0,0,0,0.5);background:url("../img/loading.gif") no-repeat center;position:absolute;left:0;right:0}.diva-outer .diva-inner .diva-document-page .diva-page-tools{position:absolute;top:-25px;left:0;height:25px;z-index:3}.diva-outer .diva-inner .diva-document-page .diva-page-tools div{display:inline-block;height:25px;width:25px;cursor:pointer}.diva-outer .diva-inner .diva-page-vertical{margin:0 auto;display:inline-block}.diva-outer .diva-inner .diva-page-horizontal{vertical-align:middle;display:inline-block;top:50%;transform:translate(0, -50%);-webkit-transform:translate(0, -50%);-moz-transform:translate(0, -50%);-ms-transform:translate(0, -50%)}.diva-outer .diva-inner .diva-row{position:absolute;width:100%}.diva-outer .diva-inner.diva-grab{cursor:url("../img/openhand.cur"),pointer}.diva-outer .diva-inner.diva-grabbing{cursor:url("../img/closedhand.cur"),move !important}.diva-outer.diva-fullscreen{width:100% !important;max-width:100% !important;height:100% !important;max-height:100% !important;z-index:100;position:fixed !important;top:0;left:0;margin:0;border:0}.diva-fullscreen-icon{background-image:url("../img/fullscreen.png");border-left:0;float:right}.diva-link-popup{background:#fff;border:1px solid #ddd;height:28px;width:230px;position:absolute;padding:5px;z-index:101;-webkit-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5)}.diva-link-popup input{width:226px;margin-top:5px}.diva-link-popup input:focus{outline:none}.diva-link-popup.in-fullscreen{top:150px;right:30px}.diva-hide-scrollbar{overflow:hidden !important}.diva-relative-position{position:relative}.zoom-slider{position:relative;top:.6em;display:none;float:left}@media (max-width:480px){.zoom-slider{width:100px}}.grid-slider{position:relative;top:.6em;display:none;float:left}@media (max-width:480px){.grid-slider{width:100px}}.diva-throbber{display:none;position:absolute;width:50px;height:50px;background:url("../img/loading.gif") no-repeat center;background-color:#fff;border:1px solid #ddd;-webkit-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);top:50%;left:50%;margin-left:-25px;margin-top:-25px}.diva-error{position:absolute;width:400px;height:200px;background-color:#fff;border:1px solid #ddd;-webkit-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);top:50%;left:50%;margin-left:-220px;margin-top:-120px;z-index:120;padding:0 1em}.diva-canvas-icon{background:url('../img/plugins/canvas.png') no-repeat;background-position:left center}.diva-canvas-icon:hover{background-position:-25px center}.diva-canvas-icon.new{background-position:-50px center}.diva-canvas-icon.new:hover{background-position:-75px center}#diva-canvas-backdrop{z-index:105;position:fixed;top:0;left:0;bottom:0;right:0;display:none;background:rgba(50,50,50,0.9)}#diva-canvas-tools{color:#333;position:fixed;top:10px;left:10px;width:230px;z-index:108;background:#fff;padding-bottom:10px;-webkit-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);-moz-box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5);box-shadow:2px 2px 4px 0 rgba(0,0,0,0.5)}#diva-canvas-tools .action-buttons{clear:both;margin-bottom:5px;text-align:right}#diva-canvas-tools .action-buttons a{color:#333;text-decoration:none;background:#f1f1f1;padding:5px;border:1px solid #99bbe8}#diva-canvas-tools .action-buttons a:last-child{border-left:0}#diva-canvas-tools .action-buttons a:hover{background:#fdfdfd}#diva-canvas-toolbar{height:16px;padding:10px;padding-bottom:0}#diva-canvas-toolbar div{height:18px;width:18px;background-repeat:no-repeat;cursor:pointer;z-index:109;display:inline-block;margin-right:5px;background-image:url("../img/actions.png")}#diva-canvas-toolbar span{vertical-align:top;float:right}#diva-canvas-toolwindow{position:relative;margin:10px}#diva-canvas-close:hover{background-position:-20px 0}#diva-canvas-minimise{background-position:-40px 0}#diva-canvas-minimise:hover{background-position:-60px 0}#diva-canvas-buttons div{cursor:pointer;background-image:url("../img/plugins/canvas-buttons.png");background-repeat:no-repeat;width:20px;height:20px;padding:5px;display:inline-block}#diva-canvas-buttons div.clicked{background-color:#ddd}#diva-canvas-buttons .contrast{background-position:5px 5px}#diva-canvas-buttons .contrast:hover,#diva-canvas-buttons .contrast.clicked{background-position:5px -25px}#diva-canvas-buttons .brightness{background-position:-25px 5px}#diva-canvas-buttons .brightness:hover,#diva-canvas-buttons .brightness.clicked{background-position:-25px -25px}#diva-canvas-buttons .rotation{background-position:-55px 5px}#diva-canvas-buttons .rotation:hover,#diva-canvas-buttons .rotation.clicked{background-position:-55px -25px}#diva-canvas-buttons .zoom{background-position:-85px 5px}#diva-canvas-buttons .zoom:hover,#diva-canvas-buttons .zoom.clicked{background-position:-85px -25px}#diva-canvas-buttons .red{background-position:-115px 5px}#diva-canvas-buttons .red:hover,#diva-canvas-buttons .red.clicked{background-position:-115px -25px}#diva-canvas-buttons .green{background-position:-145px 5px}#diva-canvas-buttons .green:hover,#diva-canvas-buttons .green.clicked{background-position:-145px -25px}#diva-canvas-buttons .blue{background-position:-175px 5px}#diva-canvas-buttons .blue:hover,#diva-canvas-buttons .blue.clicked{background-position:-175px -25px}#diva-canvas-pane{background:#ddd;padding-bottom:10px}#diva-canvas-pane p{margin-left:10px;padding-top:10px}#diva-canvas-pane p .link{cursor:pointer}#diva-canvas-pane p .link:hover{text-decoration:underline}#diva-canvas-mode{text-transform:capitalize}#diva-canvas-slider{width:188px;margin:0 auto;display:block}#diva-canvas-slider .handle{margin-left:-6px}#diva-canvas-minimap{height:210px;width:210px;cursor:crosshair;margin-bottom:10px;background:#000}#diva-canvas{position:absolute;left:0;right:0;margin:0 auto;z-index:107;cursor:url("../img/openhand.cur"),pointer}#diva-map-viewbox{border:2px solid #99bbe8;position:absolute;top:10px;left:10px;cursor:crosshair;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:none}.overflow-hidden{overflow:hidden !important}#diva-canvas-wrapper{z-index:106;position:absolute;top:0;left:0;bottom:0;right:0;overflow:scroll}.canvas-throbber{z-index:110;position:fixed}.diva-download-icon{background:url('../img/plugins/download.png') no-repeat;background-position:left center}.diva-download-icon:hover{background-position:-25px center} \ No newline at end of file diff --git a/build/demo/highlight.html b/build/demo/highlight.html index 51cc5751..11c7954a 100644 --- a/build/demo/highlight.html +++ b/build/demo/highlight.html @@ -9,18 +9,17 @@ - - - - - - - - - - -
- - \ No newline at end of file diff --git a/build/demo/single.html b/build/demo/single.html index c7e868d4..70a48192 100644 --- a/build/demo/single.html +++ b/build/demo/single.html @@ -8,17 +8,29 @@ - - + + + diff --git a/build/index.html b/build/index.html index c39473a4..7a8f97bb 100644 --- a/build/index.html +++ b/build/index.html @@ -13,9 +13,6 @@
  • A basic Diva instance.
  • A demonstration of horizontal scrolling.
  • A demonstration of the highlight plugin.
  • -
  • A demonstration of the image manipulation tools. [1]
  • -
    -

    [1] You will need to disable your browser's Same-origin policy for this demo to work.

    diff --git a/build/js/diva.js b/build/js/diva.js index 227179d3..28be6ab9 100644 --- a/build/js/diva.js +++ b/build/js/diva.js @@ -1,5 +1,5 @@ /* -Copyright (C) 2011-2014 by Wendy Liu, Evan Magoni, Andrew Hankinson, Laurent Pugin +Copyright (C) 2011-2014 by Wendy Liu, Evan Magoni, Andrew Hankinson, Andrew Horwitz, Laurent Pugin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -34,11 +34,7 @@ window.divaPlugins = []; arrowScrollAmount: 40, // The amount (in pixels) to scroll by when using arrow keys blockMobileMove: true, // Prevent moving or scrolling the page on mobile devices objectData: '', // URL to the JSON file that provides the object dimension data - *MANDATORY* - enableAutoHeight: false, // Automatically adjust height based on the window size enableAutoTitle: true, // Shows the title within a div of id diva-title - enableAutoWidth: true, // Automatically adjust width based on the window size - enableCanvas: true, // Used for the canvas plugin - enableDownload: true, // Used for the download plugin enableFilename: true, // Uses filenames and not page numbers for links (i=bm_001.tif, not p=1) enableFullscreen: true, // Enable or disable fullscreen icon (mode still available) enableGotoPage: true, // A "go to page" jump box @@ -80,10 +76,8 @@ window.divaPlugins = []; throbberTimeout: 100, // Number of milliseconds to wait before showing throbber tileHeight: 256, // The height of each tile, in pixels; usually 256 tileWidth: 256, // The width of each tile, in pixels; usually 256 - toolbarParentSelector: null, // The toolbar parent selector. If null, it defaults to the primary diva element. Must be a jQuery selector (leading '#') + toolbarParentSelector: options.parentSelector, // The toolbar parent selector. Must be a jQuery selector (leading '#') verticallyOriented: true, // Determines vertical vs. horizontal orientation - viewerHeightPadding: 15, // Vertical padding when resizing the viewer, if enableAutoHeight is set - viewerWidthPadding: 30, // Horizontal padding when resizing the viewer, if enableAutoWidth is set viewportMargin: 200, // Pretend tiles +/- 200px away from viewport are in zoomLevel: 2 // The initial zoom level (used to store the current zoom level) }; @@ -104,27 +98,26 @@ window.divaPlugins = []; firstRowLoaded: -1, // The index of the first row loaded gridPageWidth: 0, // Holds the max width of each row in grid view. Calculated in loadGrid() hashParamSuffix: '', // Used when there are multiple document viewers on a page - heightProportion: 0, // Stores the original proportion between parentSelector.height and window.height - horizontalOffset: 0, // Used in documentScroll for scrolling more precisely + horizontalOffset: 0, // Distance from the center of the diva element to the top of the current page horizontalPadding: 0, // Either the fixed padding or adaptive padding ID: null, // The prefix of the IDs of the elements (usually 1-diva-) + initialKeyScroll: false, // Holds the initial state of enableKeyScroll + initialSpaceScroll: false, // Holds the initial state of enableSpaceScroll innerSelector: '', // settings.selector + 'inner', for selecting the .diva-inner element + isActiveDiva: true, // In the case that multiple diva panes exist on the same page, this should have events funneled to it. + isScrollable: true, // Used in enable/disableScrollable public methods itemTitle: '', // The title of the document lastPageLoaded: -1, // The ID of the last page loaded (value set later) lastRowLoaded: -1, // The index of the last row loaded loaded: false, // A flag for when everything is loaded and ready to go. maxWidths: [], // The width of the widest page for each zoom level - maxHeights: [], // The width of the widest page for each zoom level + maxHeights: [], // The height of the tallest page for each zoom level maxRatio: 0, // The max height/width ratio (for grid view) - minHeight: 0, // Minimum height of the .diva-outer element, as defined in the CSS minRatio: 0, // The minimum height/width ratio for a page - minWidth: 0, // Minimum width of the .diva-outer element, as defined in the CSS mobileWebkit: false, // Checks if the user is on a touch device (iPad/iPod/iPhone/Android) numPages: 0, // Number of pages in the array numRows: 0, // Number of rows - oldPagesPerRow: 0, // Holds the previous number of pages per row after it is changed oldZoomLevel: -1, // Holds the previous zoom level after zooming in or out - orientationChange: false, // For handling device orientation changes for touch devices outerSelector: '', // settings.selector + 'outer', for selecting the .diva-outer element pages: [], // An array containing the data for all the pages pageLeftOffsets: [], // Distance from the left side of each page to the left side of the diva-inner object @@ -140,23 +133,18 @@ window.divaPlugins = []; resizeTimer: -1, // Holds the ID of the timeout used when resizing the window (for clearing) rowHeight: 0, // Holds the max height of each row in grid view. Calculated in loadGrid() scaleWait: false, // For preventing double-zoom on touch devices (iPad, etc) + scrollbarWidth: 0, // Set to the actual scrollbar width in init() selector: '', // Uses the generated ID prefix to easily select elements singleClick: false, // Used for catching ctrl+double-click events in Firefox in Mac OS - isScrollable: true, // Used in enable/disableScrollable public methods - initialKeyScroll: false, // Holds the initial state of enableKeyScroll - initialSpaceScroll: false, // Holds the initial state of enableSpaceScroll - scrollbarWidth: 0, // Set to the actual scrollbar width in init() + singleTap: false, // Used for caching double-tap events on mobile browsers throbberTimeoutID: -1, // Holds the ID of the throbber loading timeout toolbar: null, // Holds an object with some toolbar-related functions totalHeights: [], // The total height of all pages (stacked together) for each zoom level totalHeight: 0, // The total height for the current zoom level (including padding) totalWidths: [], // The total height of all pages (stacked together) for each zoom level totalWidth: 0, // The total height for the current zoom level (including padding) - verticalOffset: 0, // See horizontalOffset - verticalPadding: 0, // Either the fixed padding or adaptive padding - widthProportion: 0, // Stores the original proportion between parentSelector.width and window.width - viewerXOffset: 0, // Distance between left edge of window and viewer left edge (used for double-click zooming) - viewerYOffset: 0 // Like viewerXOffset but for the top edges + verticalOffset: 0, // Distance from the center of the diva element to the left side of the current page + verticalPadding: 0 // Either the fixed padding or adaptive padding }; $.extend(settings, globals); @@ -220,9 +208,8 @@ window.divaPlugins = []; // Checks if a page or tile is within the viewport horizontally var isHorizontallyInViewport = function (left, right) { - var panelWidth = settings.panelWidth; - var leftOfViewport = document.getElementById(settings.ID + "outer").scrollLeft - settings.viewportMargin; - var rightOfViewport = leftOfViewport + panelWidth + settings.viewportMargin * 2; + var leftOfViewport = $("#" + settings.ID + "outer").scrollLeft() - settings.viewportMargin; + var rightOfViewport = leftOfViewport + settings.panelWidth + settings.viewportMargin * 2; var leftVisible = left >= leftOfViewport && left <= rightOfViewport; var middleVisible = left <= leftOfViewport && right >= rightOfViewport; @@ -234,9 +221,8 @@ window.divaPlugins = []; // Checks if a page or tile is within the viewport vertically var isVerticallyInViewport = function (top, bottom) { - var panelHeight = settings.panelHeight; - var topOfViewport = document.getElementById(settings.ID + "outer").scrollTop - settings.viewportMargin; - var bottomOfViewport = topOfViewport + panelHeight + settings.viewportMargin * 2; + var topOfViewport = $("#" + settings.ID + "outer" ).scrollTop() - settings.viewportMargin; + var bottomOfViewport = topOfViewport + settings.panelHeight + settings.viewportMargin * 2; var topVisible = top >= topOfViewport && top <= bottomOfViewport; var middleVisible = top <= topOfViewport && bottom >= bottomOfViewport; @@ -316,14 +302,33 @@ window.divaPlugins = []; // If the page has not been loaded yet, append the div to the DOM if (!isPageLoaded(pageIndex)) { + var innerElement = document.getElementById(settings.ID + "inner"); + + var pageElement = document.createElement('div'); + pageElement.id = settings.ID + 'page-' + pageIndex; + pageElement.classList.add('diva-document-page'); + pageElement.setAttribute('data-index', pageIndex); + pageElement.setAttribute('data-filename', filename); + pageElement.title = "Page " + (pageIndex + 1); + pageElement.innerHTML = settings.pageTools; + pageElement.style.width = width + 'px'; + pageElement.style.height = height + 'px'; + if (settings.verticallyOriented) - $(document.getElementById(settings.ID + "inner")).append('
    ' + settings.pageTools + '
    '); + { + pageElement.style.top = heightFromTop + 'px'; + pageElement.classList.add('diva-page-vertical'); + } else - $(document.getElementById(settings.ID + "inner")).append('
    ' + settings.pageTools + '
    '); - + { + pageElement.style.left = widthFromLeft + 'px'; + pageElement.classList.add('diva-page-horizontal'); + } + + innerElement.appendChild(pageElement); // Call the callback function executeCallback(settings.onPageLoad, pageIndex, filename, pageSelector); - diva.Events.publish("PageWillLoad", [pageIndex, filename, pageSelector]); + diva.Events.publish("PageWillLoad", [pageIndex, filename, pageSelector], self); // @TODO: Replace this with a notification. // Execute the callback functions for any of the enabled plugins @@ -334,8 +339,10 @@ window.divaPlugins = []; } // There are still tiles to load, so try to load those (after a delay) - settings.pageTimeouts.push(setTimeout(function () + var pageLoadFunction = function (pageIndex) { + var pageElement = document.getElementById(settings.ID + 'page-' + pageIndex); + // If the page is no longer in the viewport, don't load any tiles if (!isPageVisible(pageIndex)) return; @@ -364,6 +371,7 @@ window.divaPlugins = []; // Loop through all the tiles in this page row = 0; + while (row < rows) { col = 0; @@ -383,7 +391,27 @@ window.divaPlugins = []; if (!isTileLoaded(pageIndex, tileIndex)) { if (isTileVisible(pageIndex, row, col)) - content.push('
    '); + { + /* + content.push('
    '); + */ + var tileElem = document.createElement('div'); + tileElem.id = settings.ID + 'tile-' + pageIndex + '-' + tileIndex; + tileElem.classList.add('diva-document-tile'); + tileElem.style.display = 'inline'; + tileElem.style.position = 'absolute'; + tileElem.style.top = top + 'px'; + tileElem.style.left = left + 'px'; + tileElem.style.backgroundImage = "url('" + imageURL + "')"; + tileElem.style.height = tileHeight + "px"; + tileElem.style.width = tileWidth + "px"; + + // content.push(tileElem); + pageElement.appendChild(tileElem); + } else allTilesLoaded = false; // The tile does not need to be loaded - not all have been loaded } @@ -396,18 +424,27 @@ window.divaPlugins = []; } settings.allTilesLoaded[pageIndex] = allTilesLoaded; - $(document.getElementById(settings.ID + 'page-' + pageIndex)).append(content.join('')); executeCallback(settings.onPageLoaded, pageIndex, filename, pageSelector); - diva.Events.publish("PageDidLoad", [pageIndex, filename, pageSelector]); - - }, settings.pageLoadTimeout)); + diva.Events.publish("PageDidLoad", [pageIndex, filename, pageSelector], self); + }; + settings.pageTimeouts.push(setTimeout(pageLoadFunction(pageIndex), settings.pageLoadTimeout)); }; // Delete a page from the DOM; will occur when a page is scrolled out of the viewport var deletePage = function (pageIndex) { - $(document.getElementById(settings.ID + 'page-' + pageIndex)).empty().remove(); + // $(document.getElementById(settings.ID + 'page-' + pageIndex)).empty().remove(); + var theNode = document.getElementById(settings.ID + 'page-' + pageIndex); + + if (theNode === null) + return; + + while (theNode.firstChild) + { + theNode.removeChild(theNode.firstChild); + } + theNode.parentNode.removeChild(theNode); }; // Check if the bottom of a page is above the top of a viewport (scrolling down) @@ -573,19 +610,19 @@ window.divaPlugins = []; var scrollSoFar = (settings.verticallyOriented ? document.getElementById(settings.ID + "outer").scrollTop : document.getElementById(settings.ID + "outer").scrollLeft); executeCallback(settings.onScroll, scrollSoFar); - diva.Events.publish("ViewerDidScroll", scrollSoFar); + diva.Events.publish("ViewerDidScroll", [scrollSoFar], self); if (direction > 0) { // scrolling forwards executeCallback(settings.onScrollDown, scrollSoFar); - diva.Events.publish("ViewerDidScrollDown", [scrollSoFar]); + diva.Events.publish("ViewerDidScrollDown", [scrollSoFar], self); } else if (direction < 0) { // scrolling backwards executeCallback(settings.onScrollUp, scrollSoFar); - diva.Events.publish("ViewerDidScrollUp", [scrollSoFar]); + diva.Events.publish("ViewerDidScrollUp", [scrollSoFar], self); } }; @@ -607,7 +644,7 @@ window.divaPlugins = []; // Check if a row (in grid view) is present in the DOM var isRowLoaded = function (rowIndex) { - return $(settings.selector + 'row-' + rowIndex).length > 0; + return !!document.getElementById(settings.ID + 'row-' + rowIndex); }; var loadRow = function (rowIndex) @@ -619,9 +656,17 @@ window.divaPlugins = []; // Load some data for this and initialise some variables var heightFromTop = (settings.rowHeight * rowIndex) + settings.fixedPadding; var content = []; + var innerElem = document.getElementById(settings.ID + "inner"); + + // Create the row div + var rowDiv = document.createElement('div'); + rowDiv.id = settings.ID + 'row-' + rowIndex; + rowDiv.classList.add('diva-row'); + rowDiv.style.height = settings.rowHeight + 'px'; + rowDiv.style.top = heightFromTop + 'px'; // Create the opening tag for the row div - content.push('
    '); + innerElem.appendChild(rowDiv); // Declare variables used in the loop var i, pageIndex, filename, realWidth, realHeight, pageWidth, pageHeight, leftOffset, imageURL; @@ -651,23 +696,44 @@ window.divaPlugins = []; // Center the page if the height is fixed (otherwise, there is no horizontal padding) leftOffset += (settings.fixedHeightGrid) ? (settings.gridPageWidth - pageWidth) / 2 : 0; - imageURL = settings.iipServerURL + "?FIF=" + imdir + filename + '&HEI=' + (pageHeight + 2) + '&CVT=JPEG'; + imageURL = encodeURI(settings.iipServerURL + "?FIF=" + imdir + filename + '&HEI=' + (pageHeight + 2) + '&CVT=JPEG'); + + settings.pageTopOffsets[pageIndex] = heightFromTop; + settings.pageLeftOffsets[pageIndex] = leftOffset; + // Append the HTML for this page to the string builder array - content.push('
    '); + var pageDiv = document.createElement('div'); + pageDiv.id = settings.ID + 'page-' + pageIndex; + var pageSelector = settings.selector + 'page-' + pageIndex; + pageDiv.classList.add('diva-page'); + pageDiv.style.width = pageWidth + 'px'; + pageDiv.style.height = pageHeight + 'px'; + pageDiv.style.left = leftOffset + 'px'; + pageDiv.setAttribute('data-index', pageIndex); + pageDiv.setAttribute('data-filename', filename); + pageDiv.title = "Page " + (pageIndex + 1); + + rowDiv.appendChild(pageDiv); + + diva.Events.publish("PageWillLoad", [pageIndex, filename, pageSelector], self); // Add each image to a queue so that images aren't loaded unnecessarily addPageToQueue(rowIndex, pageIndex, imageURL, pageWidth, pageHeight); } - - // Append this row to the DOM - content.push('
    '); - $(document.getElementById(settings.ID + "inner")).append(content.join('')); }; var deleteRow = function (rowIndex) { - $(document.getElementById(settings.ID + 'row-' + rowIndex)).empty().remove(); + var theNode = document.getElementById(settings.ID + 'row-' + rowIndex); + if (theNode === null) + return; + + while (theNode.firstChild) + { + theNode.removeChild(theNode.firstChild); + } + theNode.parentNode.removeChild(theNode); }; // Check if the bottom of a row is above the top of the viewport (scrolling down) @@ -769,41 +835,52 @@ window.divaPlugins = []; var newTopScroll = document.getElementById(settings.ID + "outer").scrollTop; executeCallback(settings.onScroll, newTopScroll); - diva.Events.publish("ViewerDidScroll", [newTopScroll]); + diva.Events.publish("ViewerDidScroll", [newTopScroll], self); // If we're scrolling down if (direction > 0) { executeCallback(settings.onScrollDown, newTopScroll); - diva.Events.publish("ViewerDidScrollDown", [newTopScroll]); + diva.Events.publish("ViewerDidScrollDown", [newTopScroll], self); } else if (direction < 0) { // We're scrolling up executeCallback(settings.onScrollUp, newTopScroll); - diva.Events.publish("ViewerDidScrollUp", [newTopScroll]); + diva.Events.publish("ViewerDidScrollUp", [newTopScroll], self); } }; // Used to delay loading of page images in grid view to prevent unnecessary loads var addPageToQueue = function (rowIndex, pageIndex, imageURL, pageWidth, pageHeight) { - settings.pageTimeouts.push(setTimeout(function () + var loadFunction = function (rowIndex, pageIndex, imageURL, pageWidth, pageHeight) { if (isRowVisible(rowIndex)) { - $(settings.selector + 'page-' + pageIndex).html(''); + var imgEl = document.createElement('img'); + imgEl.src = imageURL; + imgEl.style.width = pageWidth + 'px'; + imgEl.style.height = pageHeight + 'px'; + document.getElementById(settings.ID + 'page-' + pageIndex).appendChild(imgEl); } - }, settings.rowLoadTimeout)); + }; + + settings.pageTimeouts.push( + window.setTimeout(loadFunction(rowIndex, pageIndex, imageURL, pageWidth, pageHeight), settings.rowLoadTimeout)); }; // Determines and sets the "current page" (settings.currentPageIndex); called within adjustPages // The "direction" is either 1 (downward scroll) or -1 (upward scroll) var setCurrentPage = function (direction) { - var middleOfViewport = (settings.verticallyOriented ? document.getElementById(settings.ID + "outer").scrollTop : document.getElementById(settings.ID + "outer").scrollLeft) + (settings.panelWidth / 2); var currentPage = settings.currentPageIndex; var pageToConsider = currentPage + direction; + + if(!isPageValid(pageToConsider)) + return false; + + var middleOfViewport = (settings.verticallyOriented ? document.getElementById(settings.ID + "outer").scrollTop + (settings.panelHeight / 2) : document.getElementById(settings.ID + "outer").scrollLeft + (settings.panelWidth / 2)); var changeCurrentPage = false; var pageSelector = settings.selector + 'page-' + pageToConsider; @@ -858,7 +935,7 @@ window.divaPlugins = []; { var filename = settings.pages[pageToConsider].f; executeCallback(settings.onSetCurrentPage, pageToConsider, filename); - diva.Events.publish("VisiblePageDidChange", [pageToConsider, filename]); + diva.Events.publish("VisiblePageDidChange", [pageToConsider, filename], self); } } return true; @@ -901,7 +978,7 @@ window.divaPlugins = []; { var pageIndex = settings.currentPageIndex; var filename = settings.pages[pageIndex].f; - diva.Events.publish("VisiblePageDidChange", [pageIndex, filename]); + diva.Events.publish("VisiblePageDidChange", [pageIndex, filename], self); } } @@ -914,8 +991,8 @@ window.divaPlugins = []; //Helper function for going to the top of a specific page var gotoPageTop = function (pageIndex) { - var verticalOffset = getYOffset(false); - var horizontalOffset = getXOffset(false); + var verticalOffset = getYOffset(false, pageIndex); + var horizontalOffset = getXOffset(false, pageIndex); gotoPage(pageIndex, verticalOffset, horizontalOffset); }; @@ -929,11 +1006,11 @@ window.divaPlugins = []; horizontalOffset = (typeof horizontalOffset !== 'undefined') ? horizontalOffset: 0; verticalOffset = (typeof verticalOffset !== 'undefined') ? verticalOffset : 0; - var desiredVerticalCenter = (settings.pageTopOffsets[pageIndex] || settings.verticalPadding) + verticalOffset; - var desiredTop = desiredVerticalCenter - ($(settings.outerSelector).height() / 2); + var desiredVerticalCenter = settings.pageTopOffsets[pageIndex] + verticalOffset; + var desiredTop = desiredVerticalCenter - parseInt(settings.panelHeight / 2, 10); - var desiredHorizontalCenter = (settings.pageLeftOffsets[pageIndex] || settings.horizontalPadding) + horizontalOffset; - var desiredLeft = desiredHorizontalCenter - ($(settings.outerSelector).width() / 2); + var desiredHorizontalCenter = settings.pageLeftOffsets[pageIndex] + horizontalOffset; + var desiredLeft = desiredHorizontalCenter - parseInt(settings.panelWidth / 2, 10); $(settings.outerSelector).scrollTop(desiredTop); $(settings.outerSelector).scrollLeft(desiredLeft); @@ -943,11 +1020,11 @@ window.divaPlugins = []; var filename = settings.pages[pageIndex].f; executeCallback(settings.onSetCurrentPage, pageIndex, filename); - diva.Events.publish("VisiblePageDidChange", [pageIndex, filename]); + diva.Events.publish("VisiblePageDidChange", [pageIndex, filename], self); // Execute the onJump callback executeCallback(settings.onJump, pageIndex); - diva.Events.publish("ViewerDidJump", [pageIndex]); + diva.Events.publish("ViewerDidJump", [pageIndex], self); }; // Calculates the desired row, then scrolls there @@ -960,7 +1037,7 @@ window.divaPlugins = []; // Pretend that this is the current page (it probably isn't) settings.currentPageIndex = pageIndex; var filename = settings.pages[pageIndex].f; - diva.Events.publish("VisiblePageDidChange", [pageIndex, filename]); + diva.Events.publish("VisiblePageDidChange", [pageIndex, filename], self); }; // Don't call this when not in grid mode please @@ -1016,31 +1093,9 @@ window.divaPlugins = []; { clearViewer(); - // Make sure the zoom level we've been given is valid settings.zoomLevel = getValidZoomLevel(settings.zoomLevel); var z = settings.zoomLevel; - // Calculate the horizontal and vertical inter-page padding - if (settings.adaptivePadding > 0) - { - settings.horizontalPadding = settings.averageWidths[z] * settings.adaptivePadding; - settings.verticalPadding = settings.averageHeights[z] * settings.adaptivePadding; - } - else - { - // It's less than or equal to 0; use fixedPadding instead - settings.horizontalPadding = settings.fixedPadding; - settings.verticalPadding = settings.fixedPadding; - } - - // Make sure the vertical padding is at least 40, if plugin icons are enabled - if (settings.pageTools.length){ - if (settings.verticallyOriented) - settings.verticalPadding = Math.max(40, settings.horizontalPadding); - else - settings.horizontalPadding = Math.max(40, settings.verticalPadding); - } - // Now reset some things that need to be changed after each zoom settings.totalHeight = settings.totalHeights[z] + settings.verticalPadding * (settings.numPages + 1); settings.totalWidth = settings.totalWidths[z] + settings.horizontalPadding * (settings.numPages + 1); @@ -1052,28 +1107,32 @@ window.divaPlugins = []; var heightToSet = Math.max(maxHeightToSet, settings.panelHeight); //Set the inner element to said width + var innerEl = document.getElementById(settings.ID + 'inner'); if (settings.verticallyOriented) { - $(settings.innerSelector).height(Math.round(settings.totalHeight)); - $(settings.innerSelector).width(Math.round(widthToSet)); + innerEl.style.height = Math.round(settings.totalHeight) + 'px'; + innerEl.style.width = Math.round(widthToSet) + 'px'; } else { - $(settings.innerSelector).height(Math.round(heightToSet)); - $(settings.innerSelector).width(Math.round(settings.totalWidth)); + innerEl.style.height = Math.round(heightToSet) + 'px'; + innerEl.style.width = Math.round(settings.totalWidth) + 'px'; } - // Set settings.pageTopOffsets/pageLeftOffsets to determine where we're going to need to scroll + // Set settings.pageTopOffsets/pageLeftOffsets to determine where we're going to need to scroll, reset them in case they were used for grid before var heightSoFar = 0; var widthSoFar = 0; var i; + settings.pageTopOffsets = []; + settings.pageLeftOffsets = []; + for (i = 0; i < settings.numPages; i++) { // First set the height above that page by adding this height to the previous total // A page includes the padding above it - settings.pageTopOffsets[i] = (settings.verticallyOriented ? heightSoFar : (heightToSet - getPageData(i, 'h')) / 2); - settings.pageLeftOffsets[i] = (settings.verticallyOriented ? (widthToSet - getPageData(i, 'w')) / 2 : widthSoFar); + settings.pageTopOffsets[i] = parseInt(settings.verticallyOriented ? heightSoFar : (heightToSet - getPageData(i, 'h')) / 2, 10); + settings.pageLeftOffsets[i] = parseInt(settings.verticallyOriented ? (widthToSet - getPageData(i, 'w')) / 2 : widthSoFar, 10); // Has to be done this way otherwise you get the height of the page included too heightSoFar = settings.pageTopOffsets[i] + getPageData(i, 'h') + settings.verticalPadding; @@ -1109,12 +1168,12 @@ window.divaPlugins = []; if (settings.oldZoomLevel < settings.zoomLevel) { executeCallback(settings.onZoomIn, z); - diva.Events.publish("ViewerDidZoomIn", z); + diva.Events.publish("ViewerDidZoomIn", [z], self); } else { executeCallback(settings.onZoomOut, z); - diva.Events.publish("ViewerDidZoomOut", z); + diva.Events.publish("ViewerDidZoomOut", [z], self); } executeCallback(settings.onZoom, z); @@ -1129,8 +1188,8 @@ window.divaPlugins = []; settings.scaleWait = false; var fileName = settings.pages[settings.currentPageIndex].f; - executeCallback(settings.onDocumentLoaded, settings.lastPageLoaded, fileName); - diva.Events.publish("DocumentDidLoad", [settings.lastPageLoaded, fileName]); + executeCallback(settings.onDocumentLoaded, settings.currentPageIndex, fileName); + diva.Events.publish("DocumentDidLoad", [settings.currentPageIndex, fileName], self); }; var loadGrid = function () @@ -1153,13 +1212,17 @@ window.divaPlugins = []; settings.numRows = Math.ceil(settings.numPages / settings.pagesPerRow); settings.totalHeight = settings.numRows * settings.rowHeight + settings.fixedPadding; - $(settings.innerSelector).height(Math.round(settings.totalHeight)); - $(settings.innerSelector).width(Math.round(settings.panelWidth)); + var innerEl = document.getElementById(settings.ID + 'inner'); + innerEl.style.height = Math.round(settings.totalHeight) + 'px'; + innerEl.style.width = Math.round(settings.panelWidth) + 'px'; // First scroll directly to the row containing the current page gridScroll(); var i, rowIndex; + settings.pageTopOffsets = []; + settings.pageLeftOffsets = []; + // Figure out the row each page is in var np = settings.numPages; @@ -1176,44 +1239,63 @@ window.divaPlugins = []; } }; + //Shortcut for closing fullscreen with the escape key + var escapeListener = function (e) + { + if(e.keyCode == 27) + toggleFullscreen(); + }; + // Handles switching in and out of fullscreen mode // Should only be called after changing settings.inFullscreen var handleModeChange = function (changeView) { - // Save some offsets (required for maintaining scroll position), if it's not the initial load - if (settings.oldZoomLevel >= 0) - { - if (!settings.inGrid) - { - var pageIndex = settings.currentPageIndex; - settings.verticalOffset = getYOffset(false); - settings.horizontalOffset = getXOffset(false); - } - } + var storedOffsetY = getYOffset(true); + var storedOffsetX = getXOffset(true); + var outerElem = document.getElementById(settings.ID + "outer"); + + settings.panelHeight = outerElem.clientHeight - (outerElem.scrollWidth > outerElem.clientWidth ? settings.scrollbarWidth : 0); + settings.panelWidth = outerElem.clientWidth - (outerElem.scrollHeight > outerElem.clientHeight ? settings.scrollbarWidth : 0); + var storedHeight = settings.panelHeight; + var storedWidth = settings.panelWidth; // Toggle the classes $(settings.outerSelector).toggleClass('diva-fullscreen'); $('body').toggleClass('diva-hide-scrollbar'); $(settings.parentSelector).toggleClass('diva-full-width'); - // Compensate: mobileWebkit excludes body margin from window.innerWidth calculation - var bodyMargin = (settings.mobileWebkit) ? parseInt($('body').css('margin')) : 0; - - // If in fullscreen, set margin to 0; if enableAutoWidth, use viewerWidthPadding - var margin = settings.inFullscreen ? '0px' - : settings.enableAutoWidth ? (settings.viewerWidthPadding - bodyMargin).toString() + 'px' - : ''; + // Adjust margin a bit if in mobile + if(settings.mobileWebkit) + { + var leftMarginComped = parseInt($(settings.outerSelector).css('margin-left'), 10) - parseInt($('body').css('margin-left'), 10); + $(settings.outerSelector).css('margin-left', leftMarginComped); + } - $(settings.outerSelector).css('margin-left', margin); + // Execute callbacks + executeCallback(settings.onModeToggle, settings.inFullscreen); + diva.Events.publish("ModeDidSwitch", [settings.inFullscreen], self); - // Reset the panel dimensions - settings.panelHeight = $(settings.outerSelector).height(); - settings.panelWidth = $(settings.outerSelector).width() - settings.scrollbarWidth; - $(settings.innerSelector).width(settings.panelWidth); + // If it has changed, adjust panel size coming out of fullscreen + if (!settings.inFullscreen) + { + adjustBrowserDims(); + } - // Recalculate the viewer offsets - settings.viewerXOffset = $(settings.outerSelector).offset().left; - settings.viewerYOffset = $(settings.outerSelector).offset().top; + if (settings.oldZoomLevel >= 0 && !settings.inGrid) + { + var newHeight = settings.panelHeight; + var newWidth = settings.panelWidth; + if(settings.inFullscreen) + { + settings.verticalOffset = ((newHeight - storedHeight) / 2) + storedOffsetY; + settings.horizontalOffset = ((newWidth - storedWidth) / 2) + storedOffsetX; + } + else + { + settings.verticalOffset = storedOffsetY - ((storedHeight - newHeight) / 2); + settings.verticalOffset = storedOffsetX - ((storedWidth - newWidth) / 2); + } + } // Used by setState when we need to change the view and the mode if (changeView) @@ -1226,18 +1308,10 @@ window.divaPlugins = []; loadViewer(); } - // If it has changed, adjust panel size coming out of fullscreen - if (!settings.inFullscreen) - { - if(settings.mobileWebkit) - adjustMobileWebkitDims(); - else - adjustBrowserDims(); - } - - // Execute callbacks - executeCallback(settings.onModeToggle, settings.inFullscreen); - diva.Events.publish("ModeDidSwitch", [settings.inFullscreen]); + if(settings.inFullscreen) + $(document).on('keyup', escapeListener); + else + $(document).off('keyup', escapeListener); }; // Handles switching in and out of grid view @@ -1248,7 +1322,7 @@ window.divaPlugins = []; executeCallback(settings.onViewToggle, settings.inGrid); // Switch the slider - diva.Events.publish("ViewDidSwitch", [settings.inGrid]); + diva.Events.publish("ViewDidSwitch", [settings.inGrid], self); }; // Called when the fullscreen icon is clicked @@ -1268,6 +1342,18 @@ window.divaPlugins = []; handleViewChange(); }; + //toggles between orientations + var toggleOrientation = function () + { + settings.verticallyOriented = !settings.verticallyOriented; + settings.verticalOffset = getYOffset(false); + settings.horizontalOffset = getXOffset(false); + settings.goDirectlyTo = settings.currentPageIndex; + + loadDocument(); + return settings.verticallyOriented; + }; + // Called after double-click or ctrl+double-click events on pages in document view var handleDocumentDoubleClick = function (event) { @@ -1287,14 +1373,13 @@ window.divaPlugins = []; // Called after double-clicking on a page in grid view var handleGridDoubleClick = function (event) { - // Figure out the page that was clicked, scroll to that page - var sel = document.getElementById(settings.ID + "outer"); - var centerX = (event.pageX - settings.viewerXOffset) + sel.scrollLeft; - var centerY = (event.pageY - settings.viewerYOffset) + sel.scrollTop; - var rowIndex = Math.floor(centerY / settings.rowHeight); - var colIndex = Math.floor(centerX / (settings.panelWidth / settings.pagesPerRow)); - var pageIndex = rowIndex * settings.pagesPerRow + colIndex; + var pageIndex = parseInt($(this).attr('data-index'), 10); settings.goDirectlyTo = pageIndex; + var pageOffset = $(this).offset(); + var zoomProportion = getPageData(pageIndex, "w") / $(this).width(); + + settings.horizontalOffset = (event.pageX - pageOffset.left) * zoomProportion; + settings.verticalOffset = (event.pageY - pageOffset.top) * zoomProportion; // Leave grid view, jump directly to the desired page settings.inGrid = false; @@ -1302,22 +1387,27 @@ window.divaPlugins = []; }; // Handles pinch-zooming for mobile devices - var handlePinchZoom = function (event) + var handlePinchZoom = function (zoomDelta, event) { var newZoomLevel = settings.zoomLevel; // First figure out the new zoom level: - if (event.scale > 1 && newZoomLevel < settings.maxZoomLevel) + if (zoomDelta > 100 && newZoomLevel < settings.maxZoomLevel) newZoomLevel++; - else if (event.scale < 1 && newZoomLevel > settings.minZoomLevel) + else if (zoomDelta < -100 && newZoomLevel > settings.minZoomLevel) newZoomLevel--; else return; - // Set it to true so we have to wait for this one to finish + // Set scaleWait to true so that we wait for this scale event to finish settings.scaleWait = true; - // Has to call handleZoomSlide so that the coordinates are kept + // Store the offset information so that it can be used in loadDocument() + var pageOffset = $(this).offset(); + settings.horizontalOffset = event.pageX - pageOffset.left; + settings.verticalOffset = event.pageY - pageOffset.top; + settings.goDirectlyTo = parseInt($(this).attr('data-index'), 10); //page index + handleZoom(newZoomLevel); }; @@ -1334,14 +1424,14 @@ window.divaPlugins = []; // offsets refer to the distance from the top/left of the current page that the center of the viewport is. // for example: if the viewport is 800 pixels and the active page is 600 pixels wide and starts at 100 pixels, verticalOffset will be 300 pixels. - if(settings.doubleClickZoom) + if (settings.doubleClickZoom) { settings.verticalOffset *= zoomRatio; settings.horizontalOffset *= zoomRatio; settings.doubleClickZoom = false; } else - { + { settings.goDirectlyTo = settings.currentPageIndex; settings.verticalOffset = zoomRatio * getYOffset(true); settings.horizontalOffset = zoomRatio * getXOffset(true); @@ -1351,7 +1441,7 @@ window.divaPlugins = []; settings.zoomLevel = newZoomLevel; // Update the slider - diva.Events.publish("ZoomLevelDidChange", null); + diva.Events.publish("ZoomLevelDidChange", [newZoomLevel], self); loadDocument(); return true; @@ -1366,11 +1456,10 @@ window.divaPlugins = []; if (newPagesPerRow !== newValue) return false; - settings.oldPagesPerRow = settings.zoomLevel; settings.pagesPerRow = newPagesPerRow; // Update the slider - diva.Events.publish("GridRowNumberDidChange", null); + diva.Events.publish("GridRowNumberDidChange", [newPagesPerRow], self); settings.goDirectlyTo = settings.currentPageIndex; loadGrid(); @@ -1378,17 +1467,16 @@ window.divaPlugins = []; return true; }; - var getYOffset = function (centerAligned) + //if currentPosition is true, it will get your current offset position; if currentPosition is false it will get the offset position for the top of the page. + var getYOffset = function (currentPosition, pageIndex) { - var offset, - pageIndex = settings.currentPageIndex; - - if(centerAligned) + var offset; + pageIndex = (typeof(pageIndex) === "undefined" ? settings.currentPageIndex : pageIndex); + if (currentPosition) { - var outerEl = document.getElementById(settings.ID + 'outer'); - var scrollTop = outerEl.scrollTop; - var elementHeight = outerEl.offsetHeight; - + var scrollTop = document.getElementById(settings.ID + 'outer').scrollTop; + var elementHeight = settings.panelHeight; + offset = (scrollTop - settings.pageTopOffsets[pageIndex] + elementHeight / 2); } else @@ -1396,21 +1484,21 @@ window.divaPlugins = []; offset = (settings.verticallyOriented ? (settings.panelHeight / 2) : getPageData(pageIndex, "h") / 2); } + return parseInt(offset, 10); }; - var getXOffset = function (centerAligned) + var getXOffset = function (currentPosition, pageIndex) { - var offset, - pageIndex = settings.currentPageIndex; + var offset; + pageIndex = (typeof(pageIndex) === "undefined" ? settings.currentPageIndex : pageIndex); - if(centerAligned) + if (currentPosition) { - var outerEl = document.getElementById(settings.ID + 'outer'); - var scrollLeft = outerEl.scrollLeft; - var elementWidth = outerEl.offsetWidth; + var scrollLeft = document.getElementById(settings.ID + 'outer').scrollLeft; + var elementWidth = settings.panelWidth; - offset = (scrollLeft - settings.pageLeftOffsets[pageIndex] + elementWidth); + offset = (scrollLeft - settings.pageLeftOffsets[pageIndex] + parseInt(elementWidth / 2, 10)); } else { @@ -1457,95 +1545,17 @@ window.divaPlugins = []; return location.protocol + '//' + location.host + location.pathname + '#' + getURLHash(); }; - // Called in init and when the orientation changes - var adjustMobileWebkitDims = function () - { - settings.viewerXOffset = $(settings.outerSelector).offset().left; - settings.viewerYOffset = $(settings.outerSelector).offset().top; - settings.panelHeight = window.innerHeight - settings.viewerYOffset - settings.viewerHeightPadding; - settings.panelWidth = (settings.enableAutoWidth) ? window.innerWidth - settings.viewerWidthPadding * 2 : window.innerWidth; - - if (settings.enableAutoHeight) - document.getElementById(settings.ID + "outer").style.height = settings.panelHeight + "px"; - - if (settings.enableAutoWidth) - document.getElementById(settings.ID + "outer").style.width = settings.panelWidth + "px"; - }; - - // Will return true if something has changed, false otherwise + // updates panelHeight/panelWidth on resize var adjustBrowserDims = function () { - var parentHeight; - var parentWidth; - - //if parent is body, base these sizes off the window - if (settings.divaIsFullWindow) - { - parentWidth = $(window).innerWidth(); - parentHeight = $(window).innerHeight(); - } - //else off the parent - else - { - parentWidth = $(settings.parentSelector).parent().innerWidth(); - parentHeight = $(settings.parentSelector).parent().innerHeight(); - } - - // if autoHeight/autoWidth are on, resize the parent selector proportionally - if (settings.enableAutoHeight) - { - $(settings.parentSelector).height(parentHeight * settings.heightProportion); - } - - if (settings.enableAutoWidth) - { - $(settings.parentSelector).width(parentWidth * settings.widthProportion); - } + var outerElem = document.getElementById(settings.ID + 'outer'); + settings.panelHeight = outerElem.clientHeight - (outerElem.scrollWidth > outerElem.clientWidth ? settings.scrollbarWidth : 0); + settings.panelWidth = outerElem.clientWidth - (outerElem.scrollHeight > outerElem.clientHeight ? settings.scrollbarWidth : 0); - //reset the offset variables to make them accurate in the case that they've changed - var viewerOffset = $(settings.outerSelector).offset(); - settings.viewerXOffset = viewerOffset.left; - settings.viewerYOffset = viewerOffset.top; - - //calculate the new height based off the proportions - var heightBorderPixels = parseInt($(settings.outerSelector).css('border-top-width')) + parseInt($(settings.outerSelector).css('border-bottom-width')); - parentHeight = $(settings.parentSelector).height(); - var parentYOffset = $(settings.parentSelector).offset().top; - var newHeight = (settings.enableAutoHeight) ? parentHeight - settings.viewerYOffset + parentYOffset - heightBorderPixels : $(settings.outerSelector).height(); - - //calculate the new width - var widthBorderPixels = parseInt($(settings.outerSelector).css('border-left-width')) + parseInt($(settings.outerSelector).css('border-right-width')); - parentWidth = $(settings.parentSelector).width(); - - var newWidth; - if (settings.enableAutoWidth) - newWidth = parentWidth - (settings.viewerWidthPadding * 2) - widthBorderPixels - settings.scrollbarWidth; - else - newWidth = $(settings.outerSelector).width() - settings.scrollbarWidth - widthBorderPixels; - - //if either have changed, reflect that visually - if (newWidth !== settings.panelWidth || newHeight !== settings.panelHeight) - { - // outer width - if (settings.enableAutoHeight) - $(settings.outerSelector).height(newHeight); - if (settings.enableAutoWidth) - $(settings.outerSelector).width(newWidth + settings.scrollbarWidth); - // inner width - settings.panelWidth = newWidth; - settings.panelHeight = newHeight; - return true; - } - - return false; - }; - - // Update the panelHeight and panelWidth based on the window size - var adjustFullscreenDims = function () - { - settings.panelWidth = window.innerWidth - settings.scrollbarWidth; - settings.panelHeight = window.innerHeight; + settings.horizontalOffset = getXOffset(true); + settings.verticalOffset = getYOffset(true); + gotoPage(settings.currentPageIndex, settings.verticalOffset, settings.horizontalOffset); return true; }; @@ -1592,11 +1602,17 @@ window.divaPlugins = []; $(settings.outerSelector).on('dblclick', '.diva-row', function (event) { - handleGridDoubleClick.call(this, event); + handleGridDoubleClick.call($(event.target).parent(), event); }); }; + // Pythagorean theorem to get the distance between two points (used for calculating finger distance for double-tap and pinch-zoom) + var distance = function(x2, x1, y2, y1) + { + return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); + }; + // Binds most of the event handlers (some more in createToolbar) var handleEvents = function () { @@ -1624,34 +1640,31 @@ window.divaPlugins = []; bindMouseEvents(); // Handle the scroll - $(settings.outerSelector).scroll(function () + var scrollFunction = function () { var direction; var newScrollTop = document.getElementById(settings.ID + "outer").scrollTop; var newScrollLeft = document.getElementById(settings.ID + "outer").scrollLeft; if (settings.verticallyOriented || settings.inGrid) - { direction = newScrollTop - settings.previousTopScroll; - } else - { - direction = newScrollLeft - settings.previousLeftScroll; - } + direction = newScrollLeft - settings.previousLeftScroll; //give adjustPages the direction we care about if (settings.inGrid) - { adjustRows(direction); - } else - { adjustPages(direction); - } settings.previousTopScroll = newScrollTop; settings.previousLeftScroll = newScrollLeft; - }); + + settings.horizontalOffset = getXOffset(true); + settings.verticalOffset = getYOffset(true); + }; + + $(settings.outerSelector).scroll(scrollFunction); // Check if the user is on a iPhone or iPod touch or iPad if (settings.mobileWebkit) @@ -1679,50 +1692,103 @@ window.divaPlugins = []; }); } - // Allow pinch-zooming - $('body').bind('gestureend', function (event) + // Inertial scrolling + $(settings.outerSelector).kinetic({ + triggerHardware: true + }); + + // Bind events for pinch-zooming + var start = [], + move = [], + startDistance = 0; + + $(settings.outerSelector).on('touchstart', '.diva-document-page', function(event) { - var e = event.originalEvent; + if (event.originalEvent.touches.length === 2) + { + start = [event.originalEvent.touches[0].clientX, + event.originalEvent.touches[0].clientY, + event.originalEvent.touches[1].clientX, + event.originalEvent.touches[1].clientY]; + + startDistance = distance(start[2], start[0], start[3], start[1]); + } + }); - if (!settings.scaleWait) + $(settings.outerSelector).on('touchmove', '.diva-document-page', function(event) + { + if (event.originalEvent.touches.length === 2) { - // Save the page we're currently on so we scroll there - settings.goDirectlyTo = settings.currentPageIndex; + move = [event.originalEvent.touches[0].clientX, + event.originalEvent.touches[0].clientY, + event.originalEvent.touches[1].clientX, + event.originalEvent.touches[1].clientY]; - if (settings.inGrid) - { - settings.inGrid = false; - handleViewChange(); - } - else + var moveDistance = distance(move[2], move[0], move[3], move[1]); + var zoomDelta = moveDistance - startDistance; + + if (!settings.scaleWait) { - handlePinchZoom(e); + // Save the page we're currently on so we scroll there + settings.goDirectlyTo = settings.currentPageIndex; + + if (settings.inGrid) + { + settings.inGrid = false; + handleViewChange(); + } + else + { + handlePinchZoom.call(this, zoomDelta, event); + } } } - return false; }); - // Listen to orientation change event - $(window).bind('orientationchange', function (event) - { - settings.orientationChange = true; - adjustMobileWebkitDims(); + var firstTapCoordinates = {}, + tapDistance = 0; - // Reload the viewer to account for the resized viewport - settings.goDirectlyTo = settings.currentPageIndex; - loadViewer(); - }); + var bindDoubleTap = function(event) + { + if (settings.singleTap) + { + // Doubletap has occurred + var touchEvent = { + pageX: event.originalEvent.changedTouches[0].clientX, + pageY: event.originalEvent.changedTouches[0].clientY + }; + + // If first tap is close to second tap (prevents interference with scale event) + tapDistance = distance(firstTapCoordinates.pageX, touchEvent.pageX, firstTapCoordinates.pageY, touchEvent.pageY); + if (tapDistance < 50 && settings.zoomLevel < settings.maxZoomLevel) + if (settings.inGrid) + handleGridDoubleClick.call($(event.target).parent(), touchEvent); + else + handleDocumentDoubleClick.call(this, touchEvent); - // Inertial scrolling - $(settings.outerSelector).kinetic({ - triggerHardware: true, - filterTarget: function(target) + settings.singleTap = false; + firstTapCoordinates = {}; + } + else { - if (target.className === 'diva-canvas-icon' || target.className === 'diva-download-icon') - return false; - return true; + settings.singleTap = true; + firstTapCoordinates.pageX = event.originalEvent.changedTouches[0].clientX; + firstTapCoordinates.pageY = event.originalEvent.changedTouches[0].clientY; + + // Cancel doubletap after 250 milliseconds + settings.singleTapTimeout = setTimeout(function() + { + settings.singleTap = false; + firstTapCoordinates = {}; + }, 250); } - }); + }; + + // Document view: Double-tap to zoom in + $(settings.outerSelector).on('touchend', '.diva-document-page', bindDoubleTap); + + // Grid view: Double-tap to jump to current page in document view + $(settings.outerSelector).on('touchend', '.diva-page', bindDoubleTap); } // Only check if either scrollBySpace or scrollByKeys is enabled @@ -1741,6 +1807,9 @@ window.divaPlugins = []; // Catch the key presses in document $(document).keydown(function (event) { + if(!settings.isActiveDiva) + return; + // Space or page down - go to the next page if ((settings.enableSpaceScroll && event.keyCode === spaceKey) || (settings.enableKeyScroll && event.keyCode === pageDownKey)) { @@ -1748,53 +1817,45 @@ window.divaPlugins = []; return false; } - // Page up - go to the previous page - if (settings.enableKeyScroll && event.keyCode === pageUpKey) - { - $(settings.outerSelector).scrollTop(document.getElementById(settings.ID + "outer").scrollTop - settings.panelHeight); - return false; - } - - // Up arrow - scroll up - if (settings.enableKeyScroll && event.keyCode === upArrowKey) - { - $(settings.outerSelector).scrollTop(document.getElementById(settings.ID + "outer").scrollTop - settings.arrowScrollAmount); - return false; - } - - // Down arrow - scroll down - if (settings.enableKeyScroll && event.keyCode === downArrowKey) - { - $(settings.outerSelector).scrollTop(document.getElementById(settings.ID + "outer").scrollTop + settings.arrowScrollAmount); - return false; - } - - // Left arrow - scroll left - if (settings.enableKeyScroll && event.keyCode === leftArrowKey) - { - $(settings.outerSelector).scrollLeft(document.getElementById(settings.ID + "outer").scrollLeft - settings.arrowScrollAmount); - return false; - } - - // Right arrow - scroll right - if (settings.enableKeyScroll && event.keyCode === rightArrowKey) - { - $(settings.outerSelector).scrollLeft(document.getElementById(settings.ID + "outer").scrollLeft + settings.arrowScrollAmount); - return false; - } - - // Home key - go to the beginning of the document - if (settings.enableKeyScroll && event.keyCode === homeKey) - { - $(settings.outerSelector).scrollTop(0); - return false; - } - - // End key - go to the end of the document - if (settings.enableKeyScroll && event.keyCode === endKey) + if (settings.enableKeyScroll) { - $(settings.outerSelector).scrollTop(settings.totalHeight); - return false; + switch (event.keyCode) + { + case pageUpKey: + // Page up - go to the previous page + $(settings.outerSelector).scrollTop(document.getElementById(settings.ID + "outer").scrollTop - settings.panelHeight); + return false; + + case upArrowKey: + // Up arrow - scroll up + $(settings.outerSelector).scrollTop(document.getElementById(settings.ID + "outer").scrollTop - settings.arrowScrollAmount); + return false; + + case downArrowKey: + // Down arrow - scroll down + $(settings.outerSelector).scrollTop(document.getElementById(settings.ID + "outer").scrollTop + settings.arrowScrollAmount); + return false; + + case leftArrowKey: + // Left arrow - scroll left + $(settings.outerSelector).scrollLeft(document.getElementById(settings.ID + "outer").scrollLeft - settings.arrowScrollAmount); + return false; + + case rightArrowKey: + // Right arrow - scroll right + $(settings.outerSelector).scrollLeft(document.getElementById(settings.ID + "outer").scrollLeft + settings.arrowScrollAmount); + return false; + + case homeKey: + // Home key - go to the beginning of the document + $(settings.outerSelector).scrollTop(0); + return false; + + case endKey: + // End key - go to the end of the document + $(settings.outerSelector).scrollTop(settings.totalHeight); + return false; + } } }); @@ -1803,25 +1864,42 @@ window.divaPlugins = []; { $(window).resize(function () { - var adjustSuccess = (settings.inFullscreen) ? adjustFullscreenDims() : adjustBrowserDims(); - if (adjustSuccess) + adjustBrowserDims(); + // Cancel any previously-set resize timeouts + clearTimeout(settings.resizeTimer); + + settings.resizeTimer = setTimeout(function () { - // Cancel any previously-set resize timeouts - clearTimeout(settings.resizeTimer); + settings.goDirectlyTo = settings.currentPageIndex; + settings.verticalOffset = getYOffset(true); + settings.horizontalOffset = getXOffset(true); + loadViewer(); + }, 200); + }); + } + else + { + var orientationEvent = "onorientationchange" in window ? "orientationchange" : "resize"; + $(window).bind(orientationEvent, function (event) + { + var oldWidth = settings.panelWidth; + var oldHeight = settings.panelHeight; + adjustBrowserDims(); - settings.resizeTimer = setTimeout(function () - { - settings.goDirectlyTo = settings.currentPageIndex; - loadViewer(); - }, 200); - } + settings.horizontalOffset -= (settings.panelWidth - oldWidth) / 2; + settings.verticalOffset -= (settings.panelHeight - oldHeight) / 2; + + // Reload the viewer to account for the resized viewport + settings.goDirectlyTo = settings.currentPageIndex; + loadViewer(); }); } } }; // Handles all status updating etc (both fullscreen and not) - var createToolbar = function () { + var createToolbar = function () + { // Prepare the HTML for the various components var gridIconHTML = (settings.enableGridIcon) ? '
    ' : ''; var linkIconHTML = (settings.enableLinkIcon) ? '' : ''; @@ -1839,11 +1917,7 @@ window.divaPlugins = []; var toolbarHTML = '
    ' + zoomSliderHTML + zoomButtonsHTML + gridSliderHTML + gridButtonsHTML + zoomSliderLabelHTML + zoomButtonsLabelHTML + gridSliderLabelHTML + gridButtonsLabelHTML + '
    ' + fullscreenIconHTML + linkIconHTML + gridIconHTML + '
    ' + gotoPageHTML + pageNumberHTML + '
    '; - - if (settings.toolbarParentSelector) - $(settings.toolbarParentSelector).prepend('
    ' + toolbarHTML + '
    '); - else - $(settings.parentSelector).prepend('
    ' + toolbarHTML + '
    '); + $(settings.toolbarParentSelector).prepend('
    ' + toolbarHTML + '
    '); // bind zoom slider $(settings.selector + 'zoom-slider').on('input', function(e) @@ -1892,7 +1966,8 @@ window.divaPlugins = []; }); // Bind fullscreen button - $(settings.selector + 'fullscreen').click(function() { + $(settings.selector + 'fullscreen').click(function() + { toggleFullscreen(); }); @@ -1997,13 +2072,13 @@ window.divaPlugins = []; if (!settings.inFullscreen) { // Leaving fullscreen - $(settings.selector + 'tools-left').after($(settings.selector + 'tools-right')); + //$(settings.selector + 'tools-left').after($(settings.selector + 'tools-right')); $(settings.selector + 'tools-left').removeClass('in-fullscreen'); } else { // Entering fullscreen - $(settings.selector + 'tools-right').after($(settings.selector + 'tools-left')); + //$(settings.selector + 'tools-right').after($(settings.selector + 'tools-left')); $(settings.selector + 'tools-left').addClass('in-fullscreen'); } }; @@ -2031,11 +2106,11 @@ window.divaPlugins = []; { updateCurrentPage: function () { - $(settings.selector + 'current-page').text(settings.currentPageIndex + 1); + document.getElementById(settings.ID + 'current-page').textContent = settings.currentPageIndex + 1; }, setNumPages: function (newNumber) { - $(settings.selector + 'num-pages').text(newNumber); + document.getElementById(settings.ID + 'num-pages').textContent = newNumber; }, updateZoomSlider: function () { @@ -2046,12 +2121,12 @@ window.divaPlugins = []; } // Update the slider label - $(settings.selector + 'zoom-level').text(settings.zoomLevel); + document.getElementById(settings.ID + 'zoom-level').textContent = settings.zoomLevel; }, updateZoomButtons: function () { - // Update the buttons label - $(settings.selector + 'zoom-level').text(settings.zoomLevel); + // Update the buttons label + document.getElementById(settings.ID + 'zoom-level').textContent = settings.zoomLevel; }, updateGridSlider: function () { @@ -2062,12 +2137,12 @@ window.divaPlugins = []; } // Update the slider label - $(settings.selector + 'pages-per-row').text(settings.pagesPerRow); + document.getElementById(settings.ID + 'pages-per-row').textContent = settings.pagesPerRow; }, updateGridButtons: function () { // Update the buttons label - $(settings.selector + 'pages-per-row').text(settings.pagesPerRow); + document.getElementById(settings.ID + 'pages-per-row').textContent = settings.pagesPerRow; }, switchView: switchView, switchMode: switchMode @@ -2108,7 +2183,7 @@ window.divaPlugins = []; var clickEvent = (settings.mobileWebkit) ? 'touchend' : 'click'; $(settings.outerSelector).on(clickEvent, '.diva-' + plugin.pluginName + '-icon', function (event) { - plugin.handleClick.call(this, event, settings); + plugin.handleClick.call(this, event, settings, self); }); } @@ -2210,7 +2285,10 @@ window.divaPlugins = []; var iParamPage = getPageIndex(iParam); if (isPageValid(iParamPage)) + { settings.goDirectlyTo = iParamPage; + settings.currentPageIndex = iParamPage; + } } else { @@ -2219,7 +2297,10 @@ window.divaPlugins = []; var pParam = parseInt($.getHashParam('p' + settings.hashParamSuffix), 10) - 1; if (isPageValid(pParam)) + { settings.goDirectlyTo = pParam; + settings.currentPageIndex = pParam; + } } // Execute the setup hook for each plugin (if defined) @@ -2255,43 +2336,32 @@ window.divaPlugins = []; settings.divaIsFullWindow = true; } - // Adjust the document panel dimensions for touch devices - if (settings.mobileWebkit) - { - adjustMobileWebkitDims(); - } - else if (settings.divaIsFullWindow) + // Adjust the document panel dimensions + adjustBrowserDims(); + + // Make sure the value for settings.goDirectlyTo is valid + if (!isPageValid(parseInt(settings.goDirectlyTo), 10)) + settings.goDirectlyTo = 0; + + // Calculate the horizontal and vertical inter-page padding + if (settings.adaptivePadding > 0) { - //so we shall use window instead - settings.widthProportion = $(settings.parentSelector).width() / $(window).innerWidth(); - // Do not overflow the window in the event that the initial CSS height is greater than the initial window size - settings.heightProportion = Math.min(0.9, $(settings.parentSelector).height() / $(window).innerHeight()); - adjustBrowserDims(); + var z = settings.zoomLevel; + settings.horizontalPadding = parseInt(settings.averageWidths[z] * settings.adaptivePadding, 10); + settings.verticalPadding = parseInt(settings.averageHeights[z] * settings.adaptivePadding, 10); } else { - //but otherwise, parent is cool - settings.widthProportion = $(settings.parentSelector).width() / $(settings.parentSelector).parent().innerWidth(); - settings.heightProportion = $(settings.parentSelector).height() / $(settings.parentSelector).parent().innerHeight(); - adjustBrowserDims(); + // It's less than or equal to 0; use fixedPadding instead + settings.horizontalPadding = settings.fixedPadding; + settings.verticalPadding = settings.fixedPadding; } - // Set padding - if (settings.enableAutoWidth) + // Make sure the vertical padding is at least 40, if plugin icons are enabled + if (settings.pageTools.length) { - // mobileWebkit does not include body margin in window.innerWidth, so we manually offset the viewer - if (settings.mobileWebkit) - { - var bodyMargin = parseInt($('body').css('margin')); - $(settings.outerSelector).css('margin-left', settings.viewerWidthPadding - bodyMargin); - } - else - $(settings.outerSelector).css('margin-left', settings.viewerWidthPadding); - } - - // Make sure the value for settings.goDirectlyTo is valid - if (!isPageValid(parseInt(settings.goDirectlyTo), 10)) - settings.goDirectlyTo = 0; + settings.verticalPadding = Math.max(40, settings.verticalPadding); + } // y - vertical offset from the top of the relevant page var yParam = parseInt($.getHashParam('y' + settings.hashParamSuffix), 10); @@ -2322,9 +2392,12 @@ window.divaPlugins = []; else loadViewer(); + //prep dimensions one last time now that pages have loaded + adjustBrowserDims(); + // Execute the callback executeCallback(settings.onReady, settings); - diva.Events.publish("ViewerDidLoad", [settings]); + diva.Events.publish("ViewerDidLoad", [settings], self); // signal that everything should be set up and ready to go. settings.loaded = true; @@ -2404,10 +2477,6 @@ window.divaPlugins = []; settings.inGrid = (settings.inGrid && gridParam !== 'false') || goIntoGrid; settings.inFullscreen = (settings.inFullscreen && fullscreenParam !== 'false') || goIntoFullscreen; - // Store the minimum and maximum height too - settings.minHeight = parseInt($(settings.outerSelector).css('min-height'), 10); - settings.minWidth = parseInt($(settings.outerSelector).css('min-width'), 10); - // Do the initial AJAX request and viewer loading setupViewer(); @@ -2571,15 +2640,16 @@ window.divaPlugins = []; return this.setZoomLevel(settings.zoomLevel - 1); }; - // Uses the isVerticallyInViewport() function, but relative to a page // Check if something (e.g. a highlight box on a particular page) is visible - this.inViewport = function (pageNumber, topOffset, height) + this.inViewport = function (pageNumber, leftOffset, topOffset, width, height) { var pageIndex = pageNumber - 1; var top = settings.pageTopOffsets[pageIndex] + topOffset; var bottom = top + height; + var left = settings.pageLeftOffsets[pageIndex] + leftOffset; + var right = left + width; - return isVerticallyInViewport(top, bottom); + return isVerticallyInViewport(top, bottom) && isHorizontallyInViewport(left, right); }; //Public wrapper for isPageVisible @@ -2632,7 +2702,8 @@ window.divaPlugins = []; // Returns false if in grid view initially, true otherwise this.enterGridView = function () { - if (!settings.inGrid) { + if (!settings.inGrid) + { toggleGrid(); return true; } @@ -2760,8 +2831,8 @@ window.divaPlugins = []; else if (isPageValid(state.p)) settings.goDirectlyTo = state.p; - settings.horizontalOffset = parseInt(state.x, 10); - settings.verticalOffset = parseInt(state.y, 10); + horizontalOffset = parseInt(state.x, 10); + verticalOffset = parseInt(state.y, 10); // Only change the zoom if state.z is valid if (state.z >= settings.minZoomLevel && state.z <= settings.maxZoomLevel) @@ -2776,9 +2847,14 @@ window.divaPlugins = []; // The parameter determines if we need to change the view as well settings.inFullscreen = state.f; handleModeChange(settings.inGrid !== state.g); + settings.horizontalOffset = horizontalOffset; + settings.verticalOffset = verticalOffset; + gotoPage(pageIndex, settings.verticalOffset, settings.horizontalOffset); } else { + settings.horizontalOffset = horizontalOffset; + settings.verticalOffset = verticalOffset; // Don't need to change the mode, may need to change view if (settings.inGrid !== state.g) { @@ -2829,6 +2905,46 @@ window.divaPlugins = []; } }; + //Changes between horizontal layout and vertical layout. Returns true if document is now vertically oriented, false otherwise. + this.toggleOrientation = function () + { + return toggleOrientation(); + }; + + //Returns distance between the northwest corners of diva-inner and current page + this.getPageOffset = function(pageIndex) + { + return { + 'top': parseInt(settings.pageTopOffsets[pageIndex]), + 'left': parseInt(settings.pageLeftOffsets[pageIndex]) + }; + }; + + //Returns the page position and size (ulx, uly, h, w properties) of page pageIndex when there are pagesPerRow pages per row + //TODO: calculate all grid height levels and store them so this can be AtGridLevel(pageIndex, pagesPerRow) ? + this.getPageDimensionsAtCurrentGridLevel = function(pageIndex) + { + pageIndex = (isPageValid(pageIndex) ? pageIndex : settings.currentPageIndex); + + var pageHeight = settings.rowHeight - settings.fixedPadding; + var pageWidth = (settings.fixedHeightGrid) ? (settings.rowHeight - settings.fixedPadding) * getPageData(pageIndex, 'w') / getPageData(pageIndex, 'h') : settings.gridPageWidth; + + return { + 'height': parseInt(pageHeight, 10), + 'width': parseInt(pageWidth, 10) + }; + }; + + this.activate = function () + { + settings.isActiveDiva = true; + }; + + this.deactivate = function () + { + settings.isActiveDiva = false; + }; + // Destroys this instance, tells plugins to do the same (for testing) this.destroy = function () { diff --git a/build/js/diva.min.js b/build/js/diva.min.js index 83f866de..b1a2c292 100644 --- a/build/js/diva.min.js +++ b/build/js/diva.min.js @@ -1,110 +1,115 @@ -Storage.prototype.setObject=function(b,f){this.setItem(b,JSON.stringify(f))};Storage.prototype.getObject=function(b){return(b=this.getItem(b))&&JSON.parse(b)};(function(b){var f=1;b.generateId=function(b){var c;do c=f++ +(b?"-"+b:"");while(document.getElementById(c));return c}})(jQuery); +Storage.prototype.setObject=function(b,e){this.setItem(b,JSON.stringify(e))};Storage.prototype.getObject=function(b){return(b=this.getItem(b))&&JSON.parse(b)};(function(b){var e=1;b.generateId=function(b){var c;do c=e++ +(b?"-"+b:"");while(document.getElementById(c));return c}})(jQuery); (function(b){b.getScrollbarWidth=function(){var b=document.createElement("p");b.style.width="100%";b.style.height="200px";var d=document.createElement("div");d.style.position="absolute";d.style.top="0px";d.style.left="0px";d.style.visibility="hidden";d.style.width="200px";d.style.height="150px";d.style.overflow="hidden";d.appendChild(b);document.body.appendChild(d);var c=b.offsetWidth;d.style.overflow="scroll";b=b.offsetWidth;c==b&&(b=d.clientWidth);document.body.removeChild(d);return c-b}})(jQuery); (function(b){b.getHashParam=function(b){var d=window.location.hash;if(""!==d){var c=0c?d.substring(c,b):0>b?d.substring(c):""}return!1}})(jQuery); -(function(b){b.updateHashParam=function(f,d){var c=b.getHashParam(f),a=window.location.hash;if(c!==d)if("string"==typeof c){var k=0:first",acceptPropagatedEvent:!0,preventDefault:!0},f||{}),c={mouseDownHandler:function(a){if(1!=a.which||!a.data.acceptPropagatedEvent&&a.target!=this)return!1;a.data.lastCoord={left:a.clientX,top:a.clientY};b.event.add(document,"mouseup",c.mouseUpHandler,a.data);b.event.add(document,"mousemove",c.mouseMoveHandler,a.data);if(a.data.preventDefault)return a.preventDefault(),!1},mouseMoveHandler:function(a){var b=a.clientX- +(function(b){b.updateHashParam=function(e,d){var c=b.getHashParam(e),a=window.location.hash;if(c!==d)if("string"==typeof c){var l=0:first",acceptPropagatedEvent:!0,preventDefault:!0},e||{}),c={mouseDownHandler:function(a){if(1!=a.which||!a.data.acceptPropagatedEvent&&a.target!=this)return!1;a.data.lastCoord={left:a.clientX,top:a.clientY};b.event.add(document,"mouseup",c.mouseUpHandler,a.data);b.event.add(document,"mousemove",c.mouseMoveHandler,a.data);if(a.data.preventDefault)return a.preventDefault(),!1},mouseMoveHandler:function(a){var b=a.clientX- a.data.lastCoord.left,c=a.clientY-a.data.lastCoord.top;a.data.scrollable.scrollLeft(a.data.scrollable.scrollLeft()-b);a.data.scrollable.scrollTop(a.data.scrollable.scrollTop()-c);a.data.lastCoord={left:a.clientX,top:a.clientY};if(a.data.preventDefault)return a.preventDefault(),!1},mouseUpHandler:function(a){b.event.remove(document,"mousemove",c.mouseMoveHandler);b.event.remove(document,"mouseup",c.mouseUpHandler);if(a.data.preventDefault)return a.preventDefault(),!1}};this.each(function(){var a={scrollable:b(this), acceptPropagatedEvent:d.acceptPropagatedEvent,preventDefault:d.preventDefault};b(this).find(d.dragSelector).bind("mousedown",a,c.mouseDownHandler)})}})(jQuery); -(function(b){var f={cursor:"move",decelerate:!0,triggerHardware:!1,y:!0,x:!0,slowdown:0.9,maxvelocity:40,throttleFPS:60,movingClass:{up:"kinetic-moving-up",down:"kinetic-moving-down",left:"kinetic-moving-left",right:"kinetic-moving-right"},deceleratingClass:{up:"kinetic-decelerating-up",down:"kinetic-decelerating-down",left:"kinetic-decelerating-left",right:"kinetic-decelerating-right"}};window.requestAnimationFrame||(window.requestAnimationFrame=function(){return window.webkitRequestAnimationFrame|| -window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a,b){window.setTimeout(a,1E3/60)}}());b.support=b.support||{};b.extend(b.support,{touch:"ontouchend"in document});var d=function(){return!1},c=function(a,b){return 0===Math.floor(Math.abs(a))?0:a*b},a=function(a,b){var c=a;0b&&(c=b):a<0-b&&(c=0-b);return c},k=function(a,b){this.removeClass(a.movingClass.up).removeClass(a.movingClass.down).removeClass(a.movingClass.left).removeClass(a.movingClass.right).removeClass(a.deceleratingClass.up).removeClass(a.deceleratingClass.down).removeClass(a.deceleratingClass.left).removeClass(a.deceleratingClass.right); -0a.velocity&&this.addClass(b.left);0a.velocityY&&this.addClass(b.up)},g=function(a,b){b.velocity=0;b.velocityY=0;b.decelerate=!0;"function"===typeof b.stopped&&b.stopped.call(a,b)},l=function(a,b){var d=a[0];b.x&&0new Date(H.getTime()+z))H=new Date,w&&(n||q)&&(x&&(b(x).blur(),x=null,g.focus()),m.decelerate=!1,m.velocity=m.velocityY=0,g[0].scrollLeft=m.scrollLeft=m.x?g[0].scrollLeft-(a-n):g[0].scrollLeft, -g[0].scrollTop=m.scrollTop=m.y?g[0].scrollTop-(c-q):g[0].scrollTop,p=n,v=q,n=a,q=c,F(),k.call(g,m,m.movingClass),"function"===typeof m.moved&&m.moved.call(g,m))};m.events={touchStart:function(a){var b;if(A(a.target)){b=a.originalEvent.touches[0];var c=b.clientX;b=b.clientY;w=!0;m.velocity=p=0;m.velocityY=v=0;n=c;q=b;a.stopPropagation()}},touchMove:function(a){var b;w&&(b=a.originalEvent.touches[0],r(b.clientX,b.clientY),a.preventDefault&&a.preventDefault())},inputDown:function(a){if(A(a.target)){var b= -a.clientX,c=a.clientY;w=!0;m.velocity=p=0;m.velocityY=v=0;n=b;q=c;x=a.target;"IMG"===a.target.nodeName&&a.preventDefault();a.stopPropagation()}},inputEnd:function(a){n&&p&&!1===m.decelerate&&(m.decelerate=!0,F(),n=p=w=!1,l(g,m));x=null;a.preventDefault&&a.preventDefault()},inputMove:function(a){w&&(r(a.clientX,a.clientY),a.preventDefault&&a.preventDefault())},scroll:function(a){"function"===typeof m.moved&&m.moved.call(g,m);a.preventDefault&&a.preventDefault()},inputClick:function(a){if(0=d&&b<=c||b<=d&&e>=c||e>=d&&e<=c},n=function(b,e){var c=a.panelHeight,d=document.getElementById(a.ID+"outer").scrollTop-a.viewportMargin,c=d+c+2*a.viewportMargin;return b>=d&&b<=c||b<=d&&e>=c||e>=d&&e<=c},s=function(b){return 0<=b&&b'+ -a.pageTools+""):b(document.getElementById(a.ID+"inner")).append('
    '+a.pageTools+"
    "),g(a.onPageLoad,h,e,u),diva.Events.publish("PageWillLoad",[h,e,u]),a.plugins)g(a.plugins[r].onPageLoad,h,e,u);a.pageTimeouts.push(setTimeout(function(){if(y(h)){var f=a.imageDir+"/",k=l(h,"r"),r=l(h,"c"),A=[],m= -!0,F=0,ja=d-(k-1)*a.tileHeight,G=c-(r-1)*a.tileWidth,D,R,p,q,J,Z;baseImageURL=a.iipServerURL+"?FIF="+f+e+"&JTL="+(a.zoomLevel+a.pages[h].m-a.realMaxZoom)+",";for(f=0;f'):m=!1}F++;D++}f++}a.allTilesLoaded[h]=m;b(document.getElementById(a.ID+"page-"+h)).append(A.join(""));g(a.onPageLoaded,h,e,u);diva.Events.publish("PageDidLoad",[h,e,u])}},a.pageLoadTimeout))}}, -m=function(h){b(document.getElementById(a.ID+"page-"+h)).empty().remove()},O=function(b){if(a.verticallyOriented){b=a.pageTopOffsets[b]+l(b,"h")+a.verticalPadding;var e=document.getElementById(a.ID+"outer").scrollTop}else b=a.pageLeftOffsets[b]+l(b,"w")+a.horizontalPadding,e=document.getElementById(a.ID+"outer").scrollLeft;return b=be},q=function(b,e){0');var c,d,f,k,u,g,r=a.imageDir+"/",F=a.pagesPerRow;for(c=0;c');R(h,d,f,g,k)}e.push("");b(document.getElementById(a.ID+"inner")).append(e.join(""))}},x=function(h){b(document.getElementById(a.ID+"row-"+h)).empty().remove()},u=function(b){b=a.rowHeight*(b+1);var e=document.getElementById(a.ID+ -"outer").scrollTop;return be},A=function(b,e){0')},a.rowLoadTimeout))},D=function(b){var e=(a.verticallyOriented?document.getElementById(a.ID+"outer").scrollTop:document.getElementById(a.ID+"outer").scrollLeft)+a.panelWidth/2,c=a.currentPageIndex,d=c+b,f=!1;0>b?a.verticallyOriented?0<=d&&a.pageTopOffsets[d]+l(d,"h")+a.verticalPadding>=e&&(f=!0):0<=d&&a.pageLeftOffsets[d]+l(d,"w")+a.horizontalPadding>=e&&(f=!0):0b?0<=c&&(a.rowHeight*e>=f||a.rowHeight*c>=d)&&(k=!0):0=a.minZoomLevel&&b<=a.maxZoomLevel?b:a.minZoomLevel},$=function(b){return b>=a.minPagesPerRow&&b<=a.maxPagesPerRow?b:a.maxPagesPerRow},aa=function(){a.allTilesLoaded=[];b(a.outerSelector).scrollTop(0); -b(a.innerSelector).empty();a.firstPageLoaded=0;a.firstRowLoaded=-1;a.previousTopScroll=0;a.previousLeftScroll=0;for(clearTimeout(a.resizeTimer);a.pageTimeouts.length;)clearTimeout(a.pageTimeouts.pop())},N=function(){a.inGrid?ba():ca()},ca=function(){aa();a.zoomLevel=U(a.zoomLevel);var h=a.zoomLevel;0a.firstRowLoaded?e:a.firstRowLoaded,H(e),a.lastRowLoaded=e)},X=function(c){0<=a.oldZoomLevel&&!a.inGrid&&(a.verticalOffset=P(!1),a.horizontalOffset=Q(!1));b(a.outerSelector).toggleClass("diva-fullscreen");b("body").toggleClass("diva-hide-scrollbar");b(a.parentSelector).toggleClass("diva-full-width");var e=a.mobileWebkit?parseInt(b("body").css("margin")):0,e=a.inFullscreen?"0px":a.enableAutoWidth?(a.viewerWidthPadding-e).toString()+ -"px":"";b(a.outerSelector).css("margin-left",e);a.panelHeight=b(a.outerSelector).height();a.panelWidth=b(a.outerSelector).width()-a.scrollbarWidth;b(a.innerSelector).width(a.panelWidth);a.viewerXOffset=b(a.outerSelector).offset().left;a.viewerYOffset=b(a.outerSelector).offset().top;c?(a.inGrid=!a.inGrid,B()):N();a.inFullscreen||(a.mobileWebkit?V():W());g(a.onModeToggle,a.inFullscreen);diva.Events.publish("ModeDidSwitch",[a.inFullscreen])},B=function(){N();g(a.onViewToggle,a.inGrid);diva.Events.publish("ViewDidSwitch", -[a.inGrid])},E=function(){a.goDirectlyTo=a.currentPageIndex;a.inFullscreen=!a.inFullscreen;X(!1)},C=function(){a.goDirectlyTo=a.currentPageIndex;a.inGrid=!a.inGrid;B()},da=function(c){var e=b(this).offset();a.doubleClickZoom=!0;a.horizontalOffset=c.pageX-e.left;a.verticalOffset=c.pageY-e.top;a.goDirectlyTo=parseInt(b(this).attr("data-index"),10);M(c.ctrlKey?a.zoomLevel-1:a.zoomLevel+1)},M=function(b){var e=U(b);if(e!==b)return!1;b=Math.pow(2,e-a.zoomLevel);a.doubleClickZoom?(a.verticalOffset*=b,a.horizontalOffset*= -b,a.doubleClickZoom=!1):(a.goDirectlyTo=a.currentPageIndex,a.verticalOffset=b*P(!0),a.horizontalOffset=b*Q(!0));a.oldZoomLevel=a.zoomLevel;a.zoomLevel=e;diva.Events.publish("ZoomLevelDidChange",null);ca();return!0},T=function(b){var e=$(b);if(e!==b)return!1;a.oldPagesPerRow=a.zoomLevel;a.pagesPerRow=e;diva.Events.publish("GridRowNumberDidChange",null);a.goDirectlyTo=a.currentPageIndex;ba();return!0},P=function(b){var e;e=a.currentPageIndex;b?(b=document.getElementById(a.ID+"outer"),e=b.scrollTop- -a.pageTopOffsets[e]+b.offsetHeight/2):e=a.verticallyOriented?a.panelHeight/2:l(e,"h")/2;return parseInt(e,10)},Q=function(b){var e;e=a.currentPageIndex;b?(b=document.getElementById(a.ID+"outer"),e=b.scrollLeft-a.pageLeftOffsets[e]+b.offsetWidth):e=a.verticallyOriented?l(e,"w")/2:a.panelWidth/2;return parseInt(e,10)},ea=function(){return{f:a.inFullscreen,g:a.inGrid,z:a.zoomLevel,n:a.pagesPerRow,i:a.enableFilename?a.pages[a.currentPageIndex].f:!1,p:a.enableFilename?!1:a.currentPageIndex+1,y:a.inGrid? -!1:P(!0),x:a.inGrid?!1:Q(!0)}},fa=function(){var b=ea(),e=[],c;for(c in b)!1!==b[c]&&e.push(c+a.hashParamSuffix+"="+b[c]);return e.join("&")},ga=function(){return location.protocol+"//"+location.host+location.pathname+"#"+fa()},V=function(){a.viewerXOffset=b(a.outerSelector).offset().left;a.viewerYOffset=b(a.outerSelector).offset().top;a.panelHeight=window.innerHeight-a.viewerYOffset-a.viewerHeightPadding;a.panelWidth=a.enableAutoWidth?window.innerWidth-2*a.viewerWidthPadding:window.innerWidth;a.enableAutoHeight&& -(document.getElementById(a.ID+"outer").style.height=a.panelHeight+"px");a.enableAutoWidth&&(document.getElementById(a.ID+"outer").style.width=a.panelWidth+"px")},W=function(){var c,e;a.divaIsFullWindow?(e=b(window).innerWidth(),c=b(window).innerHeight()):(e=b(a.parentSelector).parent().innerWidth(),c=b(a.parentSelector).parent().innerHeight());a.enableAutoHeight&&b(a.parentSelector).height(c*a.heightProportion);a.enableAutoWidth&&b(a.parentSelector).width(e*a.widthProportion);c=b(a.outerSelector).offset(); -a.viewerXOffset=c.left;a.viewerYOffset=c.top;e=parseInt(b(a.outerSelector).css("border-top-width"))+parseInt(b(a.outerSelector).css("border-bottom-width"));c=b(a.parentSelector).height();var d=b(a.parentSelector).offset().top;c=a.enableAutoHeight?c-a.viewerYOffset+d-e:b(a.outerSelector).height();d=parseInt(b(a.outerSelector).css("border-left-width"))+parseInt(b(a.outerSelector).css("border-right-width"));e=b(a.parentSelector).width();e=a.enableAutoWidth?e-2*a.viewerWidthPadding-d-a.scrollbarWidth: -b(a.outerSelector).width()-a.scrollbarWidth-d;return e!==a.panelWidth||c!==a.panelHeight?(a.enableAutoHeight&&b(a.outerSelector).height(c),a.enableAutoWidth&&b(a.outerSelector).width(e+a.scrollbarWidth),a.panelWidth=e,a.panelHeight=c,!0):!1},ha=function(){a.mobileWebkit||b(a.outerSelector+", "+a.innerSelector).dragscrollable({dragSelector:".diva-dragger",acceptPropagatedEvent:!0});b(a.outerSelector).on("dblclick",".diva-document-page",function(a){da.call(this,a)});b(a.outerSelector).on("contextmenu", -".diva-document-page",function(b){if(b.ctrlKey)return clearTimeout(a.singleClickTimeout),a.singleClick?(da.call(this,b),a.singleClick=!1):(a.singleClick=!0,a.singleClickTimeout=setTimeout(function(){a.singleClick=!1},500)),!1});b(a.outerSelector).on("dblclick",".diva-row",function(b){var e=document.getElementById(a.ID+"outer");a.goDirectlyTo=Math.floor((b.pageY-a.viewerYOffset+e.scrollTop)/a.rowHeight)*a.pagesPerRow+Math.floor((b.pageX-a.viewerXOffset+e.scrollLeft)/(a.panelWidth/a.pagesPerRow));a.inGrid= -!1;B()})},ka=function(){b(a.innerSelector).mouseover(function(){b(this).removeClass("diva-grabbing").addClass("diva-grab")});b(a.innerSelector).mouseout(function(){b(this).removeClass("diva-grab")});b(a.innerSelector).mousedown(function(){b(this).removeClass("diva-grab").addClass("diva-grabbing")});b(a.innerSelector).mouseup(function(){b(this).removeClass("diva-grabbing").addClass("diva-grab")});ha();b(a.outerSelector).scroll(function(){var b,c=document.getElementById(a.ID+"outer").scrollTop,d=document.getElementById(a.ID+ -"outer").scrollLeft;b=a.verticallyOriented||a.inGrid?c-a.previousTopScroll:d-a.previousLeftScroll;if(a.inGrid){0>b?(A(a.firstRowLoaded,-1),J(-1),r(a.lastRowLoaded,-1)):0b)q(a.firstPageLoaded,b),D(-1),v(a.lastPageLoaded,b);else if(0b&&(g(a.onScrollUp,h),diva.Events.publish("ViewerDidScrollUp",[h]));a.previousTopScroll=c;a.previousLeftScroll=d});if(a.mobileWebkit){var c=[];c.push(''); -c.push('');c.push('');b("head").append(c.join("\n"));a.blockMobileMove&&b("body").bind("touchmove",function(a){a.originalEvent.preventDefault();return!1});b("body").bind("gestureend",function(b){b=b.originalEvent;if(!a.scaleWait)if(a.goDirectlyTo=a.currentPageIndex,a.inGrid)a.inGrid=!1,B();else a:{var c=a.zoomLevel;if(1b.scale&&c>a.minZoomLevel)c--; -else break a;a.scaleWait=!0;M(c)}return!1});b(window).bind("orientationchange",function(b){a.orientationChange=!0;V();a.goDirectlyTo=a.currentPageIndex;N()});b(a.outerSelector).kinetic({triggerHardware:!0,filterTarget:function(a){return"diva-canvas-icon"===a.className||"diva-download-icon"===a.className?!1:!0}})}if(a.enableSpaceScroll||a.enableKeyScroll)b(document).keydown(function(c){if(a.enableSpaceScroll&&32===c.keyCode||a.enableKeyScroll&&34===c.keyCode)return b(a.outerSelector).scrollTop(document.getElementById(a.ID+ -"outer").scrollTop+a.panelHeight),!1;if(a.enableKeyScroll&&33===c.keyCode)return b(a.outerSelector).scrollTop(document.getElementById(a.ID+"outer").scrollTop-a.panelHeight),!1;if(a.enableKeyScroll&&38===c.keyCode)return b(a.outerSelector).scrollTop(document.getElementById(a.ID+"outer").scrollTop-a.arrowScrollAmount),!1;if(a.enableKeyScroll&&40===c.keyCode)return b(a.outerSelector).scrollTop(document.getElementById(a.ID+"outer").scrollTop+a.arrowScrollAmount),!1;if(a.enableKeyScroll&&37===c.keyCode)return b(a.outerSelector).scrollLeft(document.getElementById(a.ID+ -"outer").scrollLeft-a.arrowScrollAmount),!1;if(a.enableKeyScroll&&39===c.keyCode)return b(a.outerSelector).scrollLeft(document.getElementById(a.ID+"outer").scrollLeft+a.arrowScrollAmount),!1;if(a.enableKeyScroll&&36===c.keyCode)return b(a.outerSelector).scrollTop(0),!1;if(a.enableKeyScroll&&35===c.keyCode)return b(a.outerSelector).scrollTop(a.totalHeight),!1}),a.mobileWebkit||b(window).resize(function(){var b;a.inFullscreen?(a.panelWidth=window.innerWidth-a.scrollbarWidth,a.panelHeight=window.innerHeight, -b=!0):b=W();b&&(clearTimeout(a.resizeTimer),a.resizeTimer=setTimeout(function(){a.goDirectlyTo=a.currentPageIndex;N()},200))})},la=function(){var c='
    '+("slider"===a.enableZoomControls?'':"")+("buttons"===a.enableZoomControls?'
    ':"")+("slider"===a.enableGridControls?'':"")+("buttons"===a.enableGridControls?'
    ':"")+("slider"=== -a.enableZoomControls?'
    Zoom level: '+a.zoomLevel+"
    ":"")+("buttons"===a.enableZoomControls?'
    Zoom level: '+a.zoomLevel+"
    ":"")+("slider"===a.enableGridControls?'
    Pages per row: '+a.pagesPerRow+"
    ": -"")+("buttons"===a.enableGridControls?'
    Pages per row: '+a.pagesPerRow+"
    ":"")+'
    '+(a.enableFullscreen?'
    ':"")+(a.enableLinkIcon?'':"")+(a.enableGridIcon?'
    ':"")+'
    '+(a.enableGotoPage?'
    ':"")+('
    Page 1 of '+a.numPages+"
    ")+"
    ";a.toolbarParentSelector?b(a.toolbarParentSelector).prepend('
    '+c+"
    "):b(a.parentSelector).prepend('
    '+c+"
    ");b(a.selector+"zoom-slider").on("input",function(a){a=parseInt(this.value,10);M(a)});b(a.selector+"zoom-slider").on("change",function(b){b=parseInt(this.value,10);b!==a.zoomLevel&&M(b)});b(a.selector+"zoom-out-button").click(function(){M(a.zoomLevel+ --1)});b(a.selector+"zoom-in-button").click(function(){M(a.zoomLevel+1)});b(a.selector+"grid-slider").on("input",function(a){a=parseInt(this.value,10);T(a)});b(a.selector+"grid-slider").on("change",function(b){b=parseInt(this.value,10);b!==a.zoomLevel&&T(b)});b(a.selector+"fullscreen").click(function(){E()});b(a.selector+"grid-out-button").click(function(){T(a.pagesPerRow-1)});b(a.selector+"grid-in-button").click(function(){T(a.pagesPerRow+1)});b(a.selector+"grid-icon").click(function(){C()});b(a.selector+ -"goto-page").submit(function(){var c=parseInt(b(a.selector+"goto-page-input").val(),10)-1;s(c)?a.inGrid?I(c):S(c):alert("Invalid page number");return!1});b(a.selector+"link-icon").click(function(){b("body").prepend('');if(a.inFullscreen)b(a.selector+"link-popup").addClass("in-fullscreen");else{var c=b(a.outerSelector).offset().left+a.panelWidth,c=c+(a.scrollbarWidth- -240-1),e=b(a.outerSelector).offset().top+1;b(a.selector+"link-popup").removeClass("in-fullscreen").css({top:e+"px",left:c+"px"})}b("body").mouseup(function(c){c=c.target.id;c!==a.ID+"link-popup"&&c!==a.ID+"link-popup-input"&&b(a.selector+"link-popup").remove()});b(a.outerSelector).scroll(function(){b(a.selector+"link-popup").remove()});b(a.selector+"link-popup input").click(function(){b(this).focus().select()});return!1});var e=a.inGrid?"grid":"zoom";b(a.selector+e+"-slider").show();b(a.selector+ -e+"-out-button").show();b(a.selector+e+"-in-button").show();b(a.selector+e+"-slider-label").show();b(a.selector+e+"-buttons-label").show();return{updateCurrentPage:function(){b(a.selector+"current-page").text(a.currentPageIndex+1)},setNumPages:function(c){b(a.selector+"num-pages").text(c)},updateZoomSlider:function(){a.zoomLevel!==b(a.selector+"zoom-slider").val()&&b(a.selector+"zoom-slider").val(a.zoomLevel);b(a.selector+"zoom-level").text(a.zoomLevel)},updateZoomButtons:function(){b(a.selector+ -"zoom-level").text(a.zoomLevel)},updateGridSlider:function(){a.pagesPerRow!==b(a.selector+"grid-slider").val()&&b(a.selector+"grid-slider").val(a.pagesPerRow);b(a.selector+"pages-per-row").text(a.pagesPerRow)},updateGridButtons:function(){b(a.selector+"pages-per-row").text(a.pagesPerRow)},switchView:function(){b(a.selector+e+"-slider").hide();b(a.selector+e+"-out-button").hide();b(a.selector+e+"-in-button").hide();b(a.selector+e+"-slider-label").hide();b(a.selector+e+"-buttons-label").hide();e=a.inGrid? -"grid":"zoom";b(a.selector+e+"-slider").show();b(a.selector+e+"-out-button").show();b(a.selector+e+"-in-button").show();b(a.selector+e+"-slider-label").show();b(a.selector+e+"-buttons-label").show();b(a.selector+"grid-icon").toggleClass("diva-in-grid")},switchMode:function(){b(a.selector+"tools").toggleClass("diva-fullscreen-tools");a.inFullscreen?(b(a.selector+"tools-right").after(b(a.selector+"tools-left")),b(a.selector+"tools-left").addClass("in-fullscreen")):(b(a.selector+"tools-left").after(b(a.selector+ -"tools-right")),b(a.selector+"tools-left").removeClass("in-fullscreen"))}}},ma=function(){if(window.divaPlugins){var c=[];b.each(window.divaPlugins,function(e,d){var u=d.pluginName[0].toUpperCase()+d.pluginName.substring(1);a["enable"+u]&&d.init(a,f)&&(u=d.titleText||u+" plugin","function"===typeof d.handleClick&&(c.push('
    '),u=a.mobileWebkit?"touchend":"click",b(a.outerSelector).on(u,".diva-"+d.pluginName+"-icon",function(b){d.handleClick.call(this, -b,a)})),a.plugins.push(d))});c.length&&(a.pageTools='
    '+c.join("")+"
    ")}},ia=function(){clearTimeout(a.throbberTimeoutID);b(a.selector+"throbber").hide()},na=function(){var c='
    ';b(a.outerSelector).append(c);a.throbberTimeoutID=setTimeout(function(){b(a.selector+"throbber").show()},a.throbberTimeout);b.ajax({url:a.objectData,cache:!0,dataType:"json",error:function(c,d,h){ia();c='

    Error

    Invalid objectData. Error code: '+ -d+" "+h+"

    ";0===a.objectData.lastIndexOf("http",0)&&""===h&&(h=a.objectData.replace(/https?:\/\//i,"").split(/[/?#]/)[0],location.hostname!==h&&(c+='

    Attempted to access cross-origin data without CORS.

    You may need to update your server configuration to support CORS. For help, see the cross-site request documentation.

    '));c+="
    ";b(a.outerSelector).append(c)},success:function(c, -d,h){ia();a.pages=c.pgs;a.maxRatio=c.dims.max_ratio;a.minRatio=c.dims.min_ratio;a.itemTitle=c.item_title;a.numPages=c.pgs.length;a.maxWidths=c.dims.max_w;a.maxHeights=c.dims.max_h;a.averageWidths=c.dims.a_wid;a.averageHeights=c.dims.a_hei;a.totalHeights=c.dims.t_hei;a.totalWidths=c.dims.t_wid;a.realMaxZoom=c.max_zoom;a.maxZoomLevel=0<=a.maxZoomLevel&&a.maxZoomLevel<=c.max_zoom?a.maxZoomLevel:c.max_zoom;a.minZoomLevel=0<=a.minZoomLevel&&a.minZoomLevel<=a.maxZoomLevel?a.minZoomLevel:0;a.zoomLevel=U(a.zoomLevel); -a.minPagesPerRow=Math.max(2,a.minPagesPerRow);a.maxPagesPerRow=Math.max(a.minPagesPerRow,a.maxPagesPerRow);a.enableFilename?(c=b.getHashParam("i"+a.hashParamSuffix),c=p(c)):c=parseInt(b.getHashParam("p"+a.hashParamSuffix),10)-1;s(c)&&(a.goDirectlyTo=c);b.each(a.plugins,function(b,c){g(c.setupHook,a)});a.enableToolbar&&(a.toolbar=la(),diva.Events.subscribe("VisiblePageDidChange",a.toolbar.updateCurrentPage),diva.Events.subscribe("ModeDidSwitch",a.toolbar.switchMode),diva.Events.subscribe("ViewDidSwitch", +(function(b){var e={cursor:"move",decelerate:!0,triggerHardware:!1,y:!0,x:!0,slowdown:0.9,maxvelocity:40,throttleFPS:60,movingClass:{up:"kinetic-moving-up",down:"kinetic-moving-down",left:"kinetic-moving-left",right:"kinetic-moving-right"},deceleratingClass:{up:"kinetic-decelerating-up",down:"kinetic-decelerating-down",left:"kinetic-decelerating-left",right:"kinetic-decelerating-right"}};window.requestAnimationFrame||(window.requestAnimationFrame=function(){return window.webkitRequestAnimationFrame|| +window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(a,b){window.setTimeout(a,1E3/60)}}());b.support=b.support||{};b.extend(b.support,{touch:"ontouchend"in document});var d=function(){return!1},c=function(a,b){return 0===Math.floor(Math.abs(a))?0:a*b},a=function(a,b){var c=a;0b&&(c=b):a<0-b&&(c=0-b);return c},l=function(a,b){this.removeClass(a.movingClass.up).removeClass(a.movingClass.down).removeClass(a.movingClass.left).removeClass(a.movingClass.right).removeClass(a.deceleratingClass.up).removeClass(a.deceleratingClass.down).removeClass(a.deceleratingClass.left).removeClass(a.deceleratingClass.right); +0a.velocity&&this.addClass(b.left);0a.velocityY&&this.addClass(b.up)},h=function(a,b){b.velocity=0;b.velocityY=0;b.decelerate=!0;"function"===typeof b.stopped&&b.stopped.call(a,b)},m=function(a,b){var d=a[0];b.x&&0new Date(J.getTime()+z))J=new Date,w&&(n||s)&&(H&&(b(H).blur(),H=null,h.focus()),k.decelerate=!1,k.velocity=k.velocityY=0,h[0].scrollLeft=k.scrollLeft=k.x?h[0].scrollLeft-(a-n):h[0].scrollLeft, +h[0].scrollTop=k.scrollTop=k.y?h[0].scrollTop-(c-s):h[0].scrollTop,r=n,y=s,n=a,s=c,f(),l.call(h,k,k.movingClass),"function"===typeof k.moved&&k.moved.call(h,k))};k.events={touchStart:function(a){var b;if(q(a.target)){b=a.originalEvent.touches[0];var c=b.clientX;b=b.clientY;w=!0;k.velocity=r=0;k.velocityY=y=0;n=c;s=b;a.stopPropagation()}},touchMove:function(a){var b;w&&(b=a.originalEvent.touches[0],p(b.clientX,b.clientY),a.preventDefault&&a.preventDefault())},inputDown:function(a){if(q(a.target)){var b= +a.clientX,c=a.clientY;w=!0;k.velocity=r=0;k.velocityY=y=0;n=b;s=c;H=a.target;"IMG"===a.target.nodeName&&a.preventDefault();a.stopPropagation()}},inputEnd:function(a){n&&r&&!1===k.decelerate&&(k.decelerate=!0,f(),n=r=w=!1,m(h,k));H=null;a.preventDefault&&a.preventDefault()},inputMove:function(a){w&&(p(a.clientX,a.clientY),a.preventDefault&&a.preventDefault())},scroll:function(a){"function"===typeof k.moved&&k.moved.call(h,k);a.preventDefault&&a.preventDefault()},inputClick:function(a){if(0=c&&A<=d||A<=c&&g>=d||g>=c&&g<=d},n=function(A,g){var c=b("#"+a.ID+"outer").scrollTop()-a.viewportMargin,d=c+a.panelHeight+2*a.viewportMargin;return A>=c&&A<=d||A<=c&&g>=d||g>=c&&g<=d},t=function(b){return 0<= +b&&bg},s=function(b,g){0g},q=function(b,g){0b?a.verticallyOriented?0<=c&&a.pageTopOffsets[c]+ +m(c,"h")+a.verticalPadding>=d&&(f=!0):0<=c&&a.pageLeftOffsets[c]+m(c,"w")+a.horizontalPadding>=d&&(f=!0):0b?0<=c&&(a.rowHeight*g>=f||a.rowHeight*c>=d)&&(h=!0):0=a.minZoomLevel&&b<=a.maxZoomLevel?b:a.minZoomLevel},ea=function(b){return b>= +a.minPagesPerRow&&b<=a.maxPagesPerRow?b:a.maxPagesPerRow},fa=function(){a.allTilesLoaded=[];b(a.outerSelector).scrollTop(0);b(a.innerSelector).empty();a.firstPageLoaded=0;a.firstRowLoaded=-1;a.previousTopScroll=0;a.previousLeftScroll=0;for(clearTimeout(a.resizeTimer);a.pageTimeouts.length;)clearTimeout(a.pageTimeouts.pop())},Q=function(){a.inGrid?ga():X()},X=function(){fa();a.zoomLevel=v(a.zoomLevel);var b=a.zoomLevel;a.totalHeight=a.totalHeights[b]+a.verticalPadding*(a.numPages+1);a.totalWidth=a.totalWidths[b]+ +a.horizontalPadding*(a.numPages+1);var c=a.maxHeights[b]+2*a.verticalPadding,d=Math.max(a.maxWidths[b]+2*a.horizontalPadding,a.panelWidth),c=Math.max(c,a.panelHeight),f=document.getElementById(a.ID+"inner");a.verticallyOriented?(f.style.height=Math.round(a.totalHeight)+"px",f.style.width=Math.round(d)+"px"):(f.style.height=Math.round(c)+"px",f.style.width=Math.round(a.totalWidth)+"px");var q=0,p=0;a.pageTopOffsets=[];a.pageLeftOffsets=[];for(f=0;fa.firstRowLoaded?c: +a.firstRowLoaded,J(c),a.lastRowLoaded=c)},ha=function(a){27==a.keyCode&&D()},Y=function(c){var g=K(!0),d=L(!0),f=document.getElementById(a.ID+"outer");a.panelHeight=f.clientHeight-(f.scrollWidth>f.clientWidth?a.scrollbarWidth:0);a.panelWidth=f.clientWidth-(f.scrollHeight>f.clientHeight?a.scrollbarWidth:0);var f=a.panelHeight,q=a.panelWidth;b(a.outerSelector).toggleClass("diva-fullscreen");b("body").toggleClass("diva-hide-scrollbar");b(a.parentSelector).toggleClass("diva-full-width");if(a.mobileWebkit){var p= +parseInt(b(a.outerSelector).css("margin-left"),10)-parseInt(b("body").css("margin-left"),10);b(a.outerSelector).css("margin-left",p)}h(a.onModeToggle,a.inFullscreen);diva.Events.publish("ModeDidSwitch",[a.inFullscreen],e);a.inFullscreen||T();if(0<=a.oldZoomLevel&&!a.inGrid){var p=a.panelHeight,k=a.panelWidth;a.inFullscreen?(a.verticalOffset=(p-f)/2+g,a.horizontalOffset=(k-q)/2+d):(a.verticalOffset=g-(f-p)/2,a.verticalOffset=d-(q-k)/2)}c?(a.inGrid=!a.inGrid,E()):Q();if(a.inFullscreen)b(document).on("keyup", +ha);else b(document).off("keyup",ha)},E=function(){Q();h(a.onViewToggle,a.inGrid);diva.Events.publish("ViewDidSwitch",[a.inGrid],e)},D=function(){a.goDirectlyTo=a.currentPageIndex;a.inFullscreen=!a.inFullscreen;Y(!1)},F=function(){a.goDirectlyTo=a.currentPageIndex;a.inGrid=!a.inGrid;E()},Z=function(c){var g=b(this).offset();a.doubleClickZoom=!0;a.horizontalOffset=c.pageX-g.left;a.verticalOffset=c.pageY-g.top;a.goDirectlyTo=parseInt(b(this).attr("data-index"),10);P(c.ctrlKey?a.zoomLevel-1:a.zoomLevel+ +1)},ia=function(c){var g=parseInt(b(this).attr("data-index"),10);a.goDirectlyTo=g;var d=b(this).offset(),g=m(g,"w")/b(this).width();a.horizontalOffset=(c.pageX-d.left)*g;a.verticalOffset=(c.pageY-d.top)*g;a.inGrid=!1;E()},P=function(b){var c=v(b);if(c!==b)return!1;b=Math.pow(2,c-a.zoomLevel);a.doubleClickZoom?(a.verticalOffset*=b,a.horizontalOffset*=b,a.doubleClickZoom=!1):(a.goDirectlyTo=a.currentPageIndex,a.verticalOffset=b*K(!0),a.horizontalOffset=b*L(!0));a.oldZoomLevel=a.zoomLevel;a.zoomLevel= +c;diva.Events.publish("ZoomLevelDidChange",[c],e);X();return!0},W=function(b){var c=ea(b);if(c!==b)return!1;a.pagesPerRow=c;diva.Events.publish("GridRowNumberDidChange",[c],e);a.goDirectlyTo=a.currentPageIndex;ga();return!0},K=function(b,c){var d;c="undefined"===typeof c?a.currentPageIndex:c;d=b?document.getElementById(a.ID+"outer").scrollTop-a.pageTopOffsets[c]+a.panelHeight/2:a.verticallyOriented?a.panelHeight/2:m(c,"h")/2;return parseInt(d,10)},L=function(b,c){var d;c="undefined"===typeof c?a.currentPageIndex: +c;d=b?document.getElementById(a.ID+"outer").scrollLeft-a.pageLeftOffsets[c]+parseInt(a.panelWidth/2,10):a.verticallyOriented?m(c,"w")/2:a.panelWidth/2;return parseInt(d,10)},ja=function(){return{f:a.inFullscreen,g:a.inGrid,z:a.zoomLevel,n:a.pagesPerRow,i:a.enableFilename?a.pages[a.currentPageIndex].f:!1,p:a.enableFilename?!1:a.currentPageIndex+1,y:a.inGrid?!1:K(!0),x:a.inGrid?!1:L(!0)}},ka=function(){var b=ja(),c=[],d;for(d in b)!1!==b[d]&&c.push(d+a.hashParamSuffix+"="+b[d]);return c.join("&")}, +la=function(){return location.protocol+"//"+location.host+location.pathname+"#"+ka()},T=function(){var b=document.getElementById(a.ID+"outer");a.panelHeight=b.clientHeight-(b.scrollWidth>b.clientWidth?a.scrollbarWidth:0);a.panelWidth=b.clientWidth-(b.scrollHeight>b.clientHeight?a.scrollbarWidth:0);a.horizontalOffset=L(!0);a.verticalOffset=K(!0);U(a.currentPageIndex,a.verticalOffset,a.horizontalOffset);return!0},ma=function(){a.mobileWebkit||b(a.outerSelector+", "+a.innerSelector).dragscrollable({dragSelector:".diva-dragger", +acceptPropagatedEvent:!0});b(a.outerSelector).on("dblclick",".diva-document-page",function(a){Z.call(this,a)});b(a.outerSelector).on("contextmenu",".diva-document-page",function(b){if(b.ctrlKey)return clearTimeout(a.singleClickTimeout),a.singleClick?(Z.call(this,b),a.singleClick=!1):(a.singleClick=!0,a.singleClickTimeout=setTimeout(function(){a.singleClick=!1},500)),!1});b(a.outerSelector).on("dblclick",".diva-row",function(a){ia.call(b(a.target).parent(),a)})},aa=function(a,b,c,d){return Math.sqrt((a- +b)*(a-b)+(c-d)*(c-d))},qa=function(){b(a.innerSelector).mouseover(function(){b(this).removeClass("diva-grabbing").addClass("diva-grab")});b(a.innerSelector).mouseout(function(){b(this).removeClass("diva-grab")});b(a.innerSelector).mousedown(function(){b(this).removeClass("diva-grab").addClass("diva-grabbing")});b(a.innerSelector).mouseup(function(){b(this).removeClass("diva-grabbing").addClass("diva-grab")});ma();b(a.outerSelector).scroll(function(){var b,c=document.getElementById(a.ID+"outer").scrollTop, +d=document.getElementById(a.ID+"outer").scrollLeft;b=a.verticallyOriented||a.inGrid?c-a.previousTopScroll:d-a.previousLeftScroll;if(a.inGrid){0>b?(q(a.firstRowLoaded,-1),I(-1),p(a.lastRowLoaded,-1)):0b)s(a.firstPageLoaded,b),x(-1),y(a.lastPageLoaded,b);else if(0b&&(h(a.onScrollUp,g),diva.Events.publish("ViewerDidScrollUp",[g],e));a.previousTopScroll=c;a.previousLeftScroll=d;a.horizontalOffset=L(!0);a.verticalOffset=K(!0)});if(a.mobileWebkit){var c=[];c.push(''); +c.push('');c.push('');b("head").append(c.join("\n"));a.blockMobileMove&&b("body").bind("touchmove",function(a){a.originalEvent.preventDefault();return!1});b(a.outerSelector).kinetic({triggerHardware:!0});var d=[],f=[],k=0;b(a.outerSelector).on("touchstart",".diva-document-page",function(a){2===a.originalEvent.touches.length&&(d=[a.originalEvent.touches[0].clientX,a.originalEvent.touches[0].clientY, +a.originalEvent.touches[1].clientX,a.originalEvent.touches[1].clientY],k=aa(d[2],d[0],d[3],d[1]))});b(a.outerSelector).on("touchmove",".diva-document-page",function(c){if(2===c.originalEvent.touches.length){f=[c.originalEvent.touches[0].clientX,c.originalEvent.touches[0].clientY,c.originalEvent.touches[1].clientX,c.originalEvent.touches[1].clientY];var d=aa(f[2],f[0],f[3],f[1])-k;if(!a.scaleWait)if(a.goDirectlyTo=a.currentPageIndex,a.inGrid)a.inGrid=!1,E();else a:{var g=a.zoomLevel;if(100d&&g>a.minZoomLevel)g--;else break a;a.scaleWait=!0;d=b(this).offset();a.horizontalOffset=c.pageX-d.left;a.verticalOffset=c.pageY-d.top;a.goDirectlyTo=parseInt(b(this).attr("data-index"),10);P(g)}}});var C={},m=0,c=function(c){if(a.singleTap){var d={pageX:c.originalEvent.changedTouches[0].clientX,pageY:c.originalEvent.changedTouches[0].clientY};m=aa(C.pageX,d.pageX,C.pageY,d.pageY);50>m&&a.zoomLevel'+("slider"===a.enableZoomControls?'':"")+("buttons"===a.enableZoomControls?'
    ':"")+("slider"===a.enableGridControls?'':"")+("buttons"===a.enableGridControls?'
    ':"")+("slider"===a.enableZoomControls?'
    Zoom level: '+a.zoomLevel+"
    ":"")+("buttons"===a.enableZoomControls?'
    Zoom level: '+a.zoomLevel+"
    ":"")+("slider"===a.enableGridControls?'
    Pages per row: '+a.pagesPerRow+"
    ":"")+("buttons"===a.enableGridControls?'
    Pages per row: '+a.pagesPerRow+"
    ":"")+'
    '+(a.enableFullscreen?'
    ':"")+(a.enableLinkIcon?'':"")+(a.enableGridIcon?'
    ':"")+'
    '+(a.enableGotoPage?'
    ':"")+('
    Page 1 of '+a.numPages+"
    ")+"
    ";b(a.toolbarParentSelector).prepend('
    '+c+"
    ");b(a.selector+"zoom-slider").on("input",function(a){a=parseInt(this.value,10);P(a)});b(a.selector+"zoom-slider").on("change",function(b){b=parseInt(this.value,10);b!==a.zoomLevel&&P(b)});b(a.selector+"zoom-out-button").click(function(){P(a.zoomLevel+-1)});b(a.selector+"zoom-in-button").click(function(){P(a.zoomLevel+ +1)});b(a.selector+"grid-slider").on("input",function(a){a=parseInt(this.value,10);W(a)});b(a.selector+"grid-slider").on("change",function(b){b=parseInt(this.value,10);b!==a.zoomLevel&&W(b)});b(a.selector+"fullscreen").click(function(){D()});b(a.selector+"grid-out-button").click(function(){W(a.pagesPerRow-1)});b(a.selector+"grid-in-button").click(function(){W(a.pagesPerRow+1)});b(a.selector+"grid-icon").click(function(){F()});b(a.selector+"goto-page").submit(function(){var c=parseInt(b(a.selector+ +"goto-page-input").val(),10)-1;t(c)?a.inGrid?G(c):V(c):alert("Invalid page number");return!1});b(a.selector+"link-icon").click(function(){b("body").prepend('');if(a.inFullscreen)b(a.selector+"link-popup").addClass("in-fullscreen");else{var c=b(a.outerSelector).offset().left+a.panelWidth,c=c+(a.scrollbarWidth-240-1),d=b(a.outerSelector).offset().top+1;b(a.selector+ +"link-popup").removeClass("in-fullscreen").css({top:d+"px",left:c+"px"})}b("body").mouseup(function(c){c=c.target.id;c!==a.ID+"link-popup"&&c!==a.ID+"link-popup-input"&&b(a.selector+"link-popup").remove()});b(a.outerSelector).scroll(function(){b(a.selector+"link-popup").remove()});b(a.selector+"link-popup input").click(function(){b(this).focus().select()});return!1});var d=a.inGrid?"grid":"zoom";b(a.selector+d+"-slider").show();b(a.selector+d+"-out-button").show();b(a.selector+d+"-in-button").show(); +b(a.selector+d+"-slider-label").show();b(a.selector+d+"-buttons-label").show();return{updateCurrentPage:function(){document.getElementById(a.ID+"current-page").textContent=a.currentPageIndex+1},setNumPages:function(b){document.getElementById(a.ID+"num-pages").textContent=b},updateZoomSlider:function(){a.zoomLevel!==b(a.selector+"zoom-slider").val()&&b(a.selector+"zoom-slider").val(a.zoomLevel);document.getElementById(a.ID+"zoom-level").textContent=a.zoomLevel},updateZoomButtons:function(){document.getElementById(a.ID+ +"zoom-level").textContent=a.zoomLevel},updateGridSlider:function(){a.pagesPerRow!==b(a.selector+"grid-slider").val()&&b(a.selector+"grid-slider").val(a.pagesPerRow);document.getElementById(a.ID+"pages-per-row").textContent=a.pagesPerRow},updateGridButtons:function(){document.getElementById(a.ID+"pages-per-row").textContent=a.pagesPerRow},switchView:function(){b(a.selector+d+"-slider").hide();b(a.selector+d+"-out-button").hide();b(a.selector+d+"-in-button").hide();b(a.selector+d+"-slider-label").hide(); +b(a.selector+d+"-buttons-label").hide();d=a.inGrid?"grid":"zoom";b(a.selector+d+"-slider").show();b(a.selector+d+"-out-button").show();b(a.selector+d+"-in-button").show();b(a.selector+d+"-slider-label").show();b(a.selector+d+"-buttons-label").show();b(a.selector+"grid-icon").toggleClass("diva-in-grid")},switchMode:function(){b(a.selector+"tools").toggleClass("diva-fullscreen-tools");a.inFullscreen?b(a.selector+"tools-left").addClass("in-fullscreen"):b(a.selector+"tools-left").removeClass("in-fullscreen")}}}, +sa=function(){if(window.divaPlugins){var c=[];b.each(window.divaPlugins,function(d,f){var q=f.pluginName[0].toUpperCase()+f.pluginName.substring(1);a["enable"+q]&&f.init(a,e)&&(q=f.titleText||q+" plugin","function"===typeof f.handleClick&&(c.push('
    '),q=a.mobileWebkit?"touchend":"click",b(a.outerSelector).on(q,".diva-"+f.pluginName+"-icon",function(b){f.handleClick.call(this,b,a,e)})),a.plugins.push(f))});c.length&&(a.pageTools='
    '+ +c.join("")+"
    ")}},na=function(){clearTimeout(a.throbberTimeoutID);b(a.selector+"throbber").hide()},ta=function(){var c='
    ';b(a.outerSelector).append(c);a.throbberTimeoutID=setTimeout(function(){b(a.selector+"throbber").show()},a.throbberTimeout);b.ajax({url:a.objectData,cache:!0,dataType:"json",error:function(c,d,f){na();c='

    Error

    Invalid objectData. Error code: '+d+" "+f+ +"

    ";0===a.objectData.lastIndexOf("http",0)&&""===f&&(f=a.objectData.replace(/https?:\/\//i,"").split(/[/?#]/)[0],location.hostname!==f&&(c+='

    Attempted to access cross-origin data without CORS.

    You may need to update your server configuration to support CORS. For help, see the cross-site request documentation.

    '));c+="
    ";b(a.outerSelector).append(c)},success:function(c, +d,f){na();a.pages=c.pgs;a.maxRatio=c.dims.max_ratio;a.minRatio=c.dims.min_ratio;a.itemTitle=c.item_title;a.numPages=c.pgs.length;a.maxWidths=c.dims.max_w;a.maxHeights=c.dims.max_h;a.averageWidths=c.dims.a_wid;a.averageHeights=c.dims.a_hei;a.totalHeights=c.dims.t_hei;a.totalWidths=c.dims.t_wid;a.realMaxZoom=c.max_zoom;a.maxZoomLevel=0<=a.maxZoomLevel&&a.maxZoomLevel<=c.max_zoom?a.maxZoomLevel:c.max_zoom;a.minZoomLevel=0<=a.minZoomLevel&&a.minZoomLevel<=a.maxZoomLevel?a.minZoomLevel:0;a.zoomLevel=v(a.zoomLevel); +a.minPagesPerRow=Math.max(2,a.minPagesPerRow);a.maxPagesPerRow=Math.max(a.minPagesPerRow,a.maxPagesPerRow);a.enableFilename?(c=b.getHashParam("i"+a.hashParamSuffix),c=r(c)):c=parseInt(b.getHashParam("p"+a.hashParamSuffix),10)-1;t(c)&&(a.goDirectlyTo=c,a.currentPageIndex=c);b.each(a.plugins,function(b,c){h(c.setupHook,a)});a.enableToolbar&&(a.toolbar=ra(),diva.Events.subscribe("VisiblePageDidChange",a.toolbar.updateCurrentPage),diva.Events.subscribe("ModeDidSwitch",a.toolbar.switchMode),diva.Events.subscribe("ViewDidSwitch", a.toolbar.switchView),diva.Events.subscribe("ZoomLevelDidChange",a.toolbar.updateZoomSlider),diva.Events.subscribe("ZoomLevelDidChange",a.toolbar.updateZoomButtons),diva.Events.subscribe("GridRowNumberDidChange",a.toolbar.updateGridSlider),diva.Events.subscribe("ZoomLevelDidChange",a.toolbar.updateGridButtons));b(a.selector+"current label").text(a.numPages);a.enableAutoTitle&&b(a.parentSelector).prepend('
    '+a.itemTitle+"
    ");b(a.parentSelector).parent()[0]!== -document.body||b(a.parentSelector).siblings().not("#diva-canvas-backdrop")[0]||(a.divaIsFullWindow=!0);a.mobileWebkit?V():(a.divaIsFullWindow?(a.widthProportion=b(a.parentSelector).width()/b(window).innerWidth(),a.heightProportion=Math.min(0.9,b(a.parentSelector).height()/b(window).innerHeight())):(a.widthProportion=b(a.parentSelector).width()/b(a.parentSelector).parent().innerWidth(),a.heightProportion=b(a.parentSelector).height()/b(a.parentSelector).parent().innerHeight()),W());a.enableAutoWidth&& -(a.mobileWebkit?(c=parseInt(b("body").css("margin")),b(a.outerSelector).css("margin-left",a.viewerWidthPadding-c)):b(a.outerSelector).css("margin-left",a.viewerWidthPadding));s(parseInt(a.goDirectlyTo),10)||(a.goDirectlyTo=0);c=parseInt(b.getHashParam("y"+a.hashParamSuffix),10);isNaN(c)?a.verticalOffset=P(!1):a.verticalOffset=c;c=parseInt(b.getHashParam("x"+a.hashParamSuffix),10);isNaN(c)?a.horizontalOffset=Q(!1):a.horizontalOffset=c;a.inFullscreen?X(!1):N();g(a.onReady,a);diva.Events.publish("ViewerDidLoad", -[a]);a.loaded=!0}})},Y=function(){return a.loaded?!0:(console.warn("The viewer is not completely initialized. This is likely because it is still downloading data. To fix this, only call this function if the isReady() method returns true."),!1)};(function(){a.scrollbarWidth=b.getScrollbarWidth();a.mobileWebkit=void 0!==window.orientation;a.ID=b.generateId("diva-");a.selector="#"+a.ID;var c=parseInt(a.ID,10);1');b(a.outerSelector).append('
    ');c=parseInt(b.getHashParam("n"+a.hashParamSuffix),10);c>=a.minPagesPerRow&&c<=a.maxPagesPerRow&&(a.pagesPerRow=c);c=b.getHashParam("z"+a.hashParamSuffix);""!==c&&(c=parseInt(c,10),c>=a.minZoomLevel&&(a.zoomLevel=c));var c=b.getHashParam("g"+a.hashParamSuffix),e="true"===c,d=b.getHashParam("f"+a.hashParamSuffix);a.inGrid=a.inGrid&& -"false"!==c||e;a.inFullscreen=a.inFullscreen&&"false"!==d||"true"===d;a.minHeight=parseInt(b(a.outerSelector).css("min-height"),10);a.minWidth=parseInt(b(a.outerSelector).css("min-width"),10);na();ma();ka()})();this.getItemTitle=function(){return a.itemTitle};this.gotoPageByNumber=function(a){a-=1;return s(a)?(S(a),!0):!1};this.gotoPageByIndex=function(a){return s(a)?(S(a),!0):!1};this.getCurrentPage=function(){console.warn("The call to getCurrentPage is deprecated. Use getCurrentPageIndex instead."); -return a.currentPageIndex};this.getNumberOfPages=function(){return Y()?a.numPages:!1};this.getPageDimensionsAtZoomLevel=function(b,c){if(!Y())return!1;c>a.maxZoomLevel&&(c=a.maxZoomLevel);var d=a.pages[b].d[parseInt(c,10)];return{width:d.w,height:d.h}};this.getCurrentPageDimensionsAtCurrentZoomLevel=function(){return this.getPageDimensionsAtZoomLevel(a.currentPageIndex,a.zoomLevel)};this.isReady=function(){return a.loaded};this.getCurrentPageIndex=function(){return a.currentPageIndex};this.getCurrentPageFilename= -function(){return a.pages[a.currentPageIndex].f};this.getCurrentPageNumber=function(){return a.currentPageIndex+1};this.getFilenames=function(){for(var b=[],c=0;c=a.minZoomLevel&&b.z<=a.maxZoomLevel&&(a.zoomLevel=b.z);b.n>=a.minPagesPerRow&&b.n<=a.maxPagesPerRow&&(a.pagesPerRow=b.n);a.inFullscreen!==b.f?(a.inFullscreen=b.f,X(a.inGrid!==b.g)):a.inGrid!==b.g?(a.inGrid=b.g,B()):N()};this.enableScrollable=function(){a.isScrollable||(ha(), -a.enableKeyScroll=a.initialKeyScroll,a.enableSpaceScroll=a.initialSpaceScroll,b(a.outerSelector).css("overflow","auto"),a.isScrollable=!0)};this.disableScrollable=function(){a.isScrollable&&(b(a.innerSelector+".diva-dragger").unbind("mousedown"),b(a.outerSelector).unbind("dblclick"),b(a.outerSelector).unbind("contextmenu"),b(a.outerSelector).css("overflow","hidden"),a.initialKeyScroll=a.enableKeyScroll,a.initialSpaceScroll=a.enableSpaceScroll,a.enableKeyScroll=!1,a.enableSpaceScroll=!1,a.isScrollable= -!1)};this.destroy=function(){b("body").removeClass("diva-hide-scrollbar");b(a.parentSelector).empty().removeData("diva");b.each(a.plugins,function(b,c){g(c.destroy,a,f)});b(a.parentSelector).removeAttr("style").removeAttr("class");diva.Events.unsubscribeAll()}};b.fn.diva=function(d){return this.each(function(){var c=b(this);if(!c.data("diva")){d.parentSelector=c;var a=new f(this,d);c.data("diva",a)}})}})(jQuery);(function(b){window.divaPlugins.push(function(){var f={},d={},c={},a,k,g,l={brightnessMax:150,brightnessMin:-100,brightnessStep:1,contrastMax:3,contrastMin:-1,contrastStep:0.05,localStoragePrefix:"canvas-",mobileWebkitMaxZoom:2,onInit:null,rgbMax:50,rgbMin:-50,throbberFadeSpeed:200,throbberTimeout:100,buttons:["contrast","brightness","rotation","zoom"]},p=function(b,c){var d=b.context,f=b.size/2,k=-(b.width/2),g=-(b.height/2);d.clearRect(0,0,b.size,b.size);d.save();d.translate(f,f);d.rotate(c*Math.PI/ -180);d.drawImage(a,k,g,b.width,b.height);d.restore();b.data=d.getImageData(0,0,b.size,b.size)},t=function(){for(var a in k)if(k[a].current!==k[a].previous)return!0;return!1},n=function(){p(d,k.rotation.current);L(d)},s=function(){var a=k.rotation.current,d=k.zoom.current,g=k.zoom.previous;if(a!==k.rotation.previous||d!==g){var r=b("#diva-canvas-wrapper").scrollLeft(),l=b("#diva-canvas-wrapper").scrollTop(),m=c.viewport.width/2,n=c.viewport.height/2,r=r+m-f.centerX,q=-(l+n-f.centerY),G=(k.rotation.previous- -a)*Math.PI/180,l=Math.cos(G)*r-Math.sin(G)*q+f.centerX,r=-(Math.sin(G)*r+Math.cos(G)*q)+f.centerY,d=Math.pow(2,d-g),m=d*l-m,n=d*r-n;p(f,a);b("#diva-canvas-wrapper").scrollLeft(m);b("#diva-canvas-wrapper").scrollTop(n)}if(t()){L(f);for(var I in k)k[I].previous=k[I].current}},y=function(a){var b=k[a].current!==k[a].initial;return k[a].current!==k[a].previous||b},L=function(a){var b=a.data,d=a.context.createImageData(b),f=d.data,g,l;g=0;for(l=f.length;g";if("SecurityError"!==k.name)throw k;l+='

    You may need to update your server configuration in order to use the image manipulation tools. For help, see the canvas cross-site data documentation.

    '; -b("#diva-canvas-backdrop").append(l);z()}void 0===g&&(l=a,d.canvas=document.getElementById("diva-canvas-minimap"),d.size=c.mapSize,d.canvas.width=d.size,d.canvas.height=d.size,d.context=d.canvas.getContext("2d"),d.context.fillRect(0,0,d.size,d.size),d.scaleFactor=c.mapSize/f.size,d.cornerX=f.cornerX*d.scaleFactor,d.cornerY=f.cornerY*d.scaleFactor,d.width=l.width*d.scaleFactor,d.height=l.height*d.scaleFactor,d.context.drawImage(l,d.cornerX,d.cornerY,d.width,d.height),d.data=d.context.getImageData(0, -0,c.mapSize,c.mapSize),b("#diva-map-viewbox").show(),m());n();s(f);z();"function"===typeof g&&g.call(g)}},K=function(){var a=k[g],c=a.current,a=a.transform?a.transform(c):c;b("#diva-canvas-value").html(a)},q=function(){b("#diva-canvas-slider").val(k[g].current)},v=function(a){a=c.zoomWidthRatio*Math.pow(2,a);return c.proxyURL?c.proxyURL+"?f="+c.filename+"&w="+a:c.iipServerURL+"?FIF="+(c.imageDir+"/")+c.filename+"&WID="+a+"&CVT=JPEG"},w=function(){(0',r.push(v);r='
    '+('
    Test
    '+r.join("")+'

    contrast: 0 (Reset)


    ')+ -'
    ';b("body").append(r);c.mapSize=b("#diva-canvas-minimap").width();b("#diva-canvas-buttons div").click(function(){b("#diva-canvas-buttons .clicked").removeClass("clicked");y(b(this).attr("class"))});var y=function(a){g=a;a=k[g];b("#diva-canvas-buttons ."+g).addClass("clicked");b("#diva-canvas-mode").text(g);var c=a.current,d=a.transform?a.transform(c):c,f=document.getElementById("diva-canvas-slider");f.min=a.min;f.max=a.max; -f.step=a.step;b("#diva-canvas-slider").val(c);b("#diva-canvas-value").html(d)};y("contrast");b("#diva-canvas-slider").on("input",function(a){k[g].current=parseFloat(this.value);K();n()});b("#diva-canvas-reset-all").click(function(){for(var a in k)k[a].current=k[a].initial;K();q();n()});b("#diva-canvas-reset").click(function(){k[g].current=k[g].initial;K();q();n()});b("#diva-canvas-apply").click(function(){t()&&(w(),setTimeout(function(){k.zoom.current!==k.zoom.previous?x(k.zoom.current):(s(),z(), -H())},c.throbberTimeout))});b("#diva-canvas-close").click(function(){b("body").removeClass("overflow-hidden");f.context.clearRect(0,0,f.size,f.size);d.context.clearRect(0,0,d.size,d.size);b("#diva-canvas-wrapper").scrollTop(0).scrollLeft(0);b("#diva-canvas-backdrop").hide();b("#diva-map-viewbox").hide();z();A();K();q();b("#diva-canvas-buttons .clicked").removeClass("clicked");y("contrast");diva.Events.publish("CanvasViewDidHide")});b("#diva-canvas-minimise").click(function(){b("#diva-canvas-toolwindow").slideToggle("fast")}); -b(window).resize(function(){c.viewport={height:window.innerHeight-a.scrollbarWidth,width:window.innerWidth-a.scrollbarWidth};c.inCanvas&&m()});b("#diva-canvas-wrapper").scroll(function(){c.inCanvas&&m()});b("#diva-canvas-minimap, #diva-map-viewbox").mouseup(function(a){var f=b("#diva-canvas-minimap").offset(),k=(a.pageX-f.left)/d.scaleFactor;a=(a.pageY-f.top)/d.scaleFactor;b("#diva-canvas-wrapper").scrollTop(a-c.viewport.height/2);b("#diva-canvas-wrapper").scrollLeft(k-c.viewport.width/2)});b("#diva-canvas").mousedown(function(){b(this).addClass("grabbing")}).mouseup(function(){b(this).removeClass("grabbing")}); +document.body||b(a.parentSelector).siblings().not("#diva-canvas-backdrop")[0]||(a.divaIsFullWindow=!0);T();t(parseInt(a.goDirectlyTo),10)||(a.goDirectlyTo=0);0');b(a.outerSelector).append('
    ');c=parseInt(b.getHashParam("n"+a.hashParamSuffix),10);c>=a.minPagesPerRow&& +c<=a.maxPagesPerRow&&(a.pagesPerRow=c);c=b.getHashParam("z"+a.hashParamSuffix);""!==c&&(c=parseInt(c,10),c>=a.minZoomLevel&&(a.zoomLevel=c));var c=b.getHashParam("g"+a.hashParamSuffix),d="true"===c,f=b.getHashParam("f"+a.hashParamSuffix);a.inGrid=a.inGrid&&"false"!==c||d;a.inFullscreen=a.inFullscreen&&"false"!==f||"true"===f;ta();sa();qa()})();this.getItemTitle=function(){return a.itemTitle};this.gotoPageByNumber=function(a){a-=1;return t(a)?(V(a),!0):!1};this.gotoPageByIndex=function(a){return t(a)? +(V(a),!0):!1};this.getCurrentPage=function(){console.warn("The call to getCurrentPage is deprecated. Use getCurrentPageIndex instead.");return a.currentPageIndex};this.getNumberOfPages=function(){return ba()?a.numPages:!1};this.getPageDimensionsAtZoomLevel=function(b,c){if(!ba())return!1;c>a.maxZoomLevel&&(c=a.maxZoomLevel);var d=a.pages[b].d[parseInt(c,10)];return{width:d.w,height:d.h}};this.getCurrentPageDimensionsAtCurrentZoomLevel=function(){return this.getPageDimensionsAtZoomLevel(a.currentPageIndex, +a.zoomLevel)};this.isReady=function(){return a.loaded};this.getCurrentPageIndex=function(){return a.currentPageIndex};this.getCurrentPageFilename=function(){return a.pages[a.currentPageIndex].f};this.getCurrentPageNumber=function(){return a.currentPageIndex+1};this.getFilenames=function(){for(var b=[],c=0;c=a.minZoomLevel&&b.z<=a.maxZoomLevel&&(a.zoomLevel=b.z);b.n>= +a.minPagesPerRow&&b.n<=a.maxPagesPerRow&&(a.pagesPerRow=b.n);a.inFullscreen!==b.f?(a.inFullscreen=b.f,Y(a.inGrid!==b.g),a.horizontalOffset=horizontalOffset,a.verticalOffset=verticalOffset,U(c,a.verticalOffset,a.horizontalOffset)):(a.horizontalOffset=horizontalOffset,a.verticalOffset=verticalOffset,a.inGrid!==b.g?(a.inGrid=b.g,E()):Q())};this.enableScrollable=function(){a.isScrollable||(ma(),a.enableKeyScroll=a.initialKeyScroll,a.enableSpaceScroll=a.initialSpaceScroll,b(a.outerSelector).css("overflow", +"auto"),a.isScrollable=!0)};this.disableScrollable=function(){a.isScrollable&&(b(a.innerSelector+".diva-dragger").unbind("mousedown"),b(a.outerSelector).unbind("dblclick"),b(a.outerSelector).unbind("contextmenu"),b(a.outerSelector).css("overflow","hidden"),a.initialKeyScroll=a.enableKeyScroll,a.initialSpaceScroll=a.enableSpaceScroll,a.enableKeyScroll=!1,a.enableSpaceScroll=!1,a.isScrollable=!1)};this.toggleOrientation=function(){a.verticallyOriented=!a.verticallyOriented;a.verticalOffset=K(!1);a.horizontalOffset= +L(!1);a.goDirectlyTo=a.currentPageIndex;X();return a.verticallyOriented};this.getPageOffset=function(b){return{top:parseInt(a.pageTopOffsets[b]),left:parseInt(a.pageLeftOffsets[b])}};this.getPageDimensionsAtCurrentGridLevel=function(b){b=t(b)?b:a.currentPageIndex;var c=a.rowHeight-a.fixedPadding;b=a.fixedHeightGrid?(a.rowHeight-a.fixedPadding)*m(b,"w")/m(b,"h"):a.gridPageWidth;return{height:parseInt(c,10),width:parseInt(b,10)}};this.activate=function(){a.isActiveDiva=!0};this.deactivate=function(){a.isActiveDiva= +!1};this.destroy=function(){b("body").removeClass("diva-hide-scrollbar");b(a.parentSelector).empty().removeData("diva");b.each(a.plugins,function(b,c){h(c.destroy,a,e)});b(a.parentSelector).removeAttr("style").removeAttr("class");diva.Events.unsubscribeAll()}};b.fn.diva=function(d){return this.each(function(){var c=b(this);if(!c.data("diva")){d.parentSelector=c;var a=new e(this,d);c.data("diva",a)}})}})(jQuery);(function(b){window.divaPlugins.push(function(){var e={},d={},c={},a,l,h,m={brightnessMax:150,brightnessMin:-100,brightnessStep:1,contrastMax:3,contrastMin:-1,contrastStep:0.05,localStoragePrefix:"canvas-",mobileWebkitMaxZoom:2,onInit:null,rgbMax:50,rgbMin:-50,throbberFadeSpeed:200,throbberTimeout:100,buttons:["contrast","brightness","rotation","zoom"]},r=function(b,c){var d=b.context,e=b.size/2,h=-(b.width/2),l=-(b.height/2);d.clearRect(0,0,b.size,b.size);d.save();d.translate(e,e);d.rotate(c*Math.PI/ +180);d.drawImage(a,h,l,b.width,b.height);d.restore();b.data=d.getImageData(0,0,b.size,b.size)},u=function(){for(var a in l)if(l[a].current!==l[a].previous)return!0;return!1},n=function(){r(d,l.rotation.current);O(d)},t=function(){var a=l.rotation.current,d=l.zoom.current,h=l.zoom.previous;if(a!==l.rotation.previous||d!==h){var k=b("#diva-canvas-wrapper").scrollLeft(),m=b("#diva-canvas-wrapper").scrollTop(),n=c.viewport.width/2,t=c.viewport.height/2,k=k+n-e.centerX,s=-(m+t-e.centerY),G=(l.rotation.previous- +a)*Math.PI/180,m=Math.cos(G)*k-Math.sin(G)*s+e.centerX,k=-(Math.sin(G)*k+Math.cos(G)*s)+e.centerY,d=Math.pow(2,d-h),n=d*m-n,t=d*k-t;r(e,a);b("#diva-canvas-wrapper").scrollLeft(n);b("#diva-canvas-wrapper").scrollTop(t)}if(u()){O(e);for(var v in l)l[v].previous=l[v].current}},B=function(a){var b=l[a].current!==l[a].initial;return l[a].current!==l[a].previous||b},O=function(a){var b=a.data,d=a.context.createImageData(b),e=d.data,h,k;h=0;for(k=e.length;h";if("SecurityError"!==f.name)throw f;l+='

    You may need to update your server configuration in order to use the image manipulation tools. For help, see the canvas cross-site data documentation.

    '; +b("#diva-canvas-backdrop").append(l);z()}void 0===h&&(l=a,d.canvas=document.getElementById("diva-canvas-minimap"),d.size=c.mapSize,d.canvas.width=d.size,d.canvas.height=d.size,d.context=d.canvas.getContext("2d"),d.context.fillRect(0,0,d.size,d.size),d.scaleFactor=c.mapSize/e.size,d.cornerX=e.cornerX*d.scaleFactor,d.cornerY=e.cornerY*d.scaleFactor,d.width=l.width*d.scaleFactor,d.height=l.height*d.scaleFactor,d.context.drawImage(l,d.cornerX,d.cornerY,d.width,d.height),d.data=d.context.getImageData(0, +0,c.mapSize,c.mapSize),b("#diva-map-viewbox").show(),k());n();t(e);z();"function"===typeof h&&h.call(h)}},M=function(){var a=l[h],c=a.current,a=a.transform?a.transform(c):c;b("#diva-canvas-value").html(a)},s=function(){b("#diva-canvas-slider").val(l[h].current)},y=function(a){a=c.zoomWidthRatio*Math.pow(2,a);return c.proxyURL?c.proxyURL+"?f="+c.filename+"&w="+a:c.iipServerURL+"?FIF="+(c.imageDir+"/")+c.filename+"&WID="+a+"&CVT=JPEG"},w=function(){(0',r.push(x);r='
    '+('
    Test
    '+r.join("")+ +'

    contrast: 0 (Reset)


    ')+'
    ';b("body").append(r); +c.mapSize=b("#diva-canvas-minimap").width();b("#diva-canvas-buttons div").click(function(){b("#diva-canvas-buttons .clicked").removeClass("clicked");B(b(this).attr("class"))});var B=function(a){h=a;a=l[h];b("#diva-canvas-buttons ."+h).addClass("clicked");b("#diva-canvas-mode").text(h);var c=a.current,d=a.transform?a.transform(c):c,e=document.getElementById("diva-canvas-slider");e.min=a.min;e.max=a.max;e.step=a.step;b("#diva-canvas-slider").val(c);b("#diva-canvas-value").html(d)};B("contrast");b("#diva-canvas-slider").on("input", +function(a){l[h].current=parseFloat(this.value);M();n()});b("#diva-canvas-reset-all").click(function(){for(var a in l)l[a].current=l[a].initial;M();s();n()});b("#diva-canvas-reset").click(function(){l[h].current=l[h].initial;M();s();n()});b("#diva-canvas-apply").click(function(){u()&&(w(),setTimeout(function(){l.zoom.current!==l.zoom.previous?H(l.zoom.current):(t(),z(),J())},c.throbberTimeout))});b("#diva-canvas-close").click(function(){b("body").removeClass("overflow-hidden");e.context.clearRect(0, +0,e.size,e.size);d.context.clearRect(0,0,d.size,d.size);b("#diva-canvas-wrapper").scrollTop(0).scrollLeft(0);b("#diva-canvas-backdrop").hide();b("#diva-map-viewbox").hide();z();q.enableScrollable();b(document).off("keydown",N);p();M();s();b("#diva-canvas-buttons .clicked").removeClass("clicked");B("contrast");diva.Events.publish("CanvasViewDidHide")});b("#diva-canvas-minimise").click(function(){b("#diva-canvas-toolwindow").slideToggle("fast")});b(window).resize(function(){c.viewport={height:window.innerHeight- +a.scrollbarWidth,width:window.innerWidth-a.scrollbarWidth};c.inCanvas&&k()});b("#diva-canvas-wrapper").scroll(function(){c.inCanvas&&k()});b("#diva-canvas-minimap, #diva-map-viewbox").mouseup(function(a){var e=b("#diva-canvas-minimap").offset(),f=(a.pageX-e.left)/d.scaleFactor;a=(a.pageY-e.top)/d.scaleFactor;b("#diva-canvas-wrapper").scrollTop(a-c.viewport.height/2);b("#diva-canvas-wrapper").scrollLeft(f-c.viewport.width/2)});b("#diva-canvas").mousedown(function(){b(this).addClass("grabbing")}).mouseup(function(){b(this).removeClass("grabbing")}); c.mobileWebkit?b("#diva-canvas-wrapper").kinetic():b("#diva-canvas-wrapper").dragscrollable({acceptPropagatedEvent:!0});"function"===typeof c.onInit&&c.onInit.call(this,c);return!0},pluginName:"canvas",titleText:"View the image on a canvas and adjust various settings",setupHook:function(a){c.viewport={height:window.innerHeight-a.scrollbarWidth,width:window.innerWidth-a.scrollbarWidth};c.minZoomLevel=a.minZoomLevel;c.maxZoomLevel=a.maxZoomLevel;c.mobileWebkit&&(c.maxZoomLevel=Math.min(c.maxZoomLevel, -c.mobileWebkitMaxZoom));k.zoom.min=c.minZoomLevel;k.zoom.max=c.maxZoomLevel},handleClick:function(a,d){var f=b(this).parent().parent(),l=b(f).attr("data-filename"),m=b(f).width()-1,n=d.zoomLevel,p;c.zoomWidthRatio=m/Math.pow(2,n);c.pluginIcon=b(this);c.mobileWebkit&&(n=Math.min(c.maxZoomLevel,n));c.filename=l;k.zoom.initial=n;k.zoom.current=n;if(l=localStorage.getObject(c.localStoragePrefix+c.filename))for(p in l)k[p].current=l[p],p===g&&(K(),q()),"zoom"===p&&(n=l[p]);k.zoom.previous=n;b("body").addClass("overflow-hidden"); -b("#diva-canvas-backdrop").show();c.inCanvas=!0;n=v(n);b("#diva-canvas-info").text(b(f).attr("title"));w();diva.Events.publish("CanvasViewDidActivate",[f]);O(n)},onPageLoad:function(a,d,f){null!==localStorage.getItem(c.localStoragePrefix+d)&&b(f).find(".diva-canvas-icon").addClass("new")},destroy:function(a,c){b("#diva-canvas-backdrop").remove()}}}())})(jQuery);(function(b){window.divaPlugins.push(function(){var f,d;return{init:function(b,a){f=b.iipServerURL;d=b.imageDir;return!0},pluginName:"download",titleText:"Download image at the given zoom level",handleClick:function(c){var a=b(this).parent().parent();c=b(a).attr("data-filename");a=b(a).width()-1;window.open(f+"?FIF="+(d+"/")+c+"&WID="+a+"&CVT=JPEG")}}}())})(jQuery);(function(b){window.divaPlugins.push(function(){return{init:function(b,d){function c(a,c,g){var l=b.parentSelector.data("highlights");if("undefined"!==typeof l){if(l.hasOwnProperty(a)){c=d.getInstanceId()+"page-"+a;c=document.getElementById(c);g=l[a].regions;var p=l[a].colour;a=l[a].divClass;for(var l=d.getMaxZoomLevel()-d.getZoomLevel(),t=g.length;t--;){var n=document.createElement("div");n.style.width=g[t].width/Math.pow(2,l)+"px";n.style.height=g[t].height/Math.pow(2,l)+"px";n.style.top=g[t].uly/ -Math.pow(2,l)+"px";n.style.left=g[t].ulx/Math.pow(2,l)+"px";n.style.background=p;n.style.border="1px solid #555";n.style.position="absolute";n.style.zIndex=100;n.className=a;"undefined"!==typeof g[t].divID&&(n.id=g[t].divID);c.appendChild(n)}}diva.Events.publish("HighlightCompleted")}}b.parentSelector.data("highlights",{});diva.Events.subscribe("PageWillLoad",c);d.resetHighlights=function(){for(var a=document.getElementById(b.ID+"inner").getElementsByClassName(b.ID+"highlight"),c=a.length;c--;)a[c].parentNode.removeChild(a[c]); -b.parentSelector.data("highlights",{})};d.removeHighlightsOnPage=function(a){var c=b.parentSelector.data("highlights");if(c.hasOwnProperty(a)){for(var g=d.getInstanceId()+"page-"+a,g=document.getElementById(g),l=g.getElementsByTagName("div"),p=c[a].divClass,t=l.length;t--;)l[t].className===p&&g.removeChild(l[t]);delete c[a]}};d.highlightOnPages=function(a,b,c,f){for(var p=a.length;p--;)d.highlightOnPage(a[p],b,c,f)};d.highlightOnPage=function(a,k,g,l){"undefined"===typeof g&&(g="rgba(255, 0, 0, 0.2)"); -l="undefined"===typeof l?b.ID+"highlight":b.ID+"highlight "+l;d.getMaxZoomLevel();b.parentSelector.data("highlights")[a]={regions:k,colour:g,divClass:l};d.isPageInViewport(a)&&c(a,null,null);return!0};return!0},destroy:function(b,d){b.parentSelector.removeData("highlights")},pluginName:"highlight",titleText:"Highlight regions of pages"}}())})(jQuery);(function(b){window.divaPlugins.push(function(){return{init:function(b,d){return!0},pluginName:"text",titleText:"View the text of this page"}}())})(jQuery); +c.mobileWebkitMaxZoom));l.zoom.min=c.minZoomLevel;l.zoom.max=c.maxZoomLevel},handleClick:function(a,d,e){a=b(this).parent().parent();var k=b(a).attr("data-filename"),m=b(a).width()-1;d=d.zoomLevel;var n;c.zoomWidthRatio=m/Math.pow(2,d);c.pluginIcon=b(this);c.mobileWebkit&&(d=Math.min(c.maxZoomLevel,d));c.filename=k;l.zoom.initial=d;l.zoom.current=d;if(k=localStorage.getObject(c.localStoragePrefix+c.filename))for(n in k)l[n].current=k[n],n===h&&(M(),s()),"zoom"===n&&(d=k[n]);l.zoom.previous=d;b("body").addClass("overflow-hidden"); +b("#diva-canvas-backdrop").show();e.disableScrollable();b(document).keydown(N);c.inCanvas=!0;e=y(d);b("#diva-canvas-info").text(b(a).attr("title"));w();diva.Events.publish("CanvasViewDidActivate",[a]);R(e)},onPageLoad:function(a,d,e){null!==localStorage.getItem(c.localStoragePrefix+d)&&b(e).find(".diva-canvas-icon").addClass("new")},destroy:function(a,c){b("#diva-canvas-backdrop").remove()}}}())})(jQuery);(function(b){window.divaPlugins.push(function(){var e,d;return{init:function(b,a){e=b.iipServerURL;d=b.imageDir;return!0},pluginName:"download",titleText:"Download image at the given zoom level",handleClick:function(c){var a=b(this).parent().parent();c=b(a).attr("data-filename");a=b(a).width()-1;window.open(e+"?FIF="+(d+"/")+c+"&WID="+a+"&CVT=JPEG")}}}())})(jQuery);(function(b){window.divaPlugins.push(function(){return{init:function(b,d){function c(a,c,h){var m=b.parentSelector.data("highlights");if("undefined"!==typeof m){if(m.hasOwnProperty(a)){c=d.getInstanceId()+"page-"+a;c=document.getElementById(c);h=m[a].regions;var r=m[a].colour,m=m[a].divClass,u=d.getMaxZoomLevel();b.inGrid?(a=d.getPageDimensionsAtZoomLevel(a,u).width,a=Math.log(a/c.clientWidth)/Math.log(2)):a=u-d.getZoomLevel();for(u=h.length;u--;){var n=document.createElement("div");n.style.width= +h[u].width/Math.pow(2,a)+"px";n.style.height=h[u].height/Math.pow(2,a)+"px";n.style.top=h[u].uly/Math.pow(2,a)+"px";n.style.left=h[u].ulx/Math.pow(2,a)+"px";n.style.background=r;n.style.border="1px solid #555";n.style.position="absolute";n.style.zIndex=100;n.className=m;"undefined"!==typeof h[u].divID&&(n.id=h[u].divID);c.appendChild(n)}}diva.Events.publish("HighlightCompleted")}}b.parentSelector.data("highlights",{});diva.Events.subscribe("PageWillLoad",c);d.resetHighlights=function(){for(var a= +document.getElementById(b.ID+"inner").getElementsByClassName(b.ID+"highlight"),c=a.length;c--;)a[c].parentNode.removeChild(a[c]);b.parentSelector.data("highlights",{})};d.removeHighlightsOnPage=function(a){var c=b.parentSelector.data("highlights");if(c.hasOwnProperty(a)){for(var h=d.getInstanceId()+"page-"+a,h=document.getElementById(h),m=h.getElementsByTagName("div"),r=c[a].divClass,u=m.length;u--;)m[u].className===r&&h.removeChild(m[u]);delete c[a]}};d.highlightOnPages=function(a,b,c,e){for(var r= +a.length;r--;)d.highlightOnPage(a[r],b,c,e)};d.highlightOnPage=function(a,l,h,m){"undefined"===typeof h&&(h="rgba(255, 0, 0, 0.2)");m="undefined"===typeof m?b.ID+"highlight":b.ID+"highlight "+m;d.getMaxZoomLevel();b.parentSelector.data("highlights")[a]={regions:l,colour:h,divClass:m};d.isPageInViewport(a)&&c(a,null,null);return!0};return!0},destroy:function(b,d){b.parentSelector.removeData("highlights")},pluginName:"highlight",titleText:"Highlight regions of pages"}}())})(jQuery); diff --git a/build/js/plugins/canvas.js b/build/js/plugins/canvas.js index 6172d505..92d43345 100644 --- a/build/js/plugins/canvas.js +++ b/build/js/plugins/canvas.js @@ -456,6 +456,37 @@ Adds an adjustment icon next to each image }); }; + var bindCanvasKeyEvents = function (event) + { + var upArrowKey = 38, + downArrowKey = 40, + leftArrowKey = 37, + rightArrowKey = 39; + + switch (event.keyCode) + { + case upArrowKey: + // Up arrow - scroll up + $('#diva-canvas-wrapper').scrollTop(document.getElementById('diva-canvas-wrapper').scrollTop - settings.arrowScrollAmount); + return false; + + case downArrowKey: + // Down arrow - scroll down + $('#diva-canvas-wrapper').scrollTop(document.getElementById('diva-canvas-wrapper').scrollTop + settings.arrowScrollAmount); + return false; + + case leftArrowKey: + // Left arrow - scroll left + $('#diva-canvas-wrapper').scrollLeft(document.getElementById('diva-canvas-wrapper').scrollLeft - settings.arrowScrollAmount); + return false; + + case rightArrowKey: + // Right arrow - scroll right + $('#diva-canvas-wrapper').scrollLeft(document.getElementById('diva-canvas-wrapper').scrollLeft + settings.arrowScrollAmount); + return false; + } + }; + var retval = { init: function (divaSettings, divaInstance) @@ -474,6 +505,7 @@ Adds an adjustment icon next to each image settings.imageDir = divaSettings.imageDir; settings.selector = divaSettings.selector; settings.mobileWebkit = divaSettings.mobileWebkit; + settings.arrowScrollAmount = divaSettings.arrowScrollAmount; // Set up the settings for the sliders/icons sliders = { @@ -714,6 +746,10 @@ Adds an adjustment icon next to each image $('#diva-map-viewbox').hide(); hideThrobber(); + // Re-enable scrolling of diva when it is in the background + divaInstance.enableScrollable(); + $(document).off('keydown', bindCanvasKeyEvents); + // Reset everything resetSliders(); updateSliderLabel(); @@ -817,7 +853,7 @@ Adds an adjustment icon next to each image sliders.zoom.max = settings.maxZoomLevel; }, - handleClick: function(event, divaSettings) + handleClick: function(event, divaSettings, divaInstance) { // loadCanvas() calls all the other necessary functions to load var page = $(this).parent().parent(); @@ -866,6 +902,11 @@ Adds an adjustment icon next to each image $('body').addClass('overflow-hidden'); $('#diva-canvas-backdrop').show(); + // Disable scrolling on main diva instance + divaInstance.disableScrollable(); + // Enable canvas scrolling + $(document).keydown(bindCanvasKeyEvents); + // Set this to true so events can be captured settings.inCanvas = true; diff --git a/build/js/plugins/highlight.js b/build/js/plugins/highlight.js index 565f1323..251f1451 100644 --- a/build/js/plugins/highlight.js +++ b/build/js/plugins/highlight.js @@ -49,7 +49,19 @@ Allows you to highlight regions of a page image var divClass = highlightObj[pageIdx].divClass; var maxZoom = divaInstance.getMaxZoomLevel(); - var zoomDifference = maxZoom - divaInstance.getZoomLevel(); + var zoomDifference; + + if (divaSettings.inGrid) + { + var maxZoomWidth = divaInstance.getPageDimensionsAtZoomLevel(pageIdx, maxZoom).width; + var currentWidth = pageObj.clientWidth; + var widthProportion = maxZoomWidth / currentWidth; + zoomDifference = Math.log(widthProportion) / Math.log(2); + } + else + { + zoomDifference = maxZoom - divaInstance.getZoomLevel(); + } var j = regions.length; while (j--) diff --git a/build/processing/process.py b/build/processing/process.py index 769cd031..e99bdf4c 100644 --- a/build/processing/process.py +++ b/build/processing/process.py @@ -30,13 +30,28 @@ from optparse import OptionParser """ -This is a python script that will process all the images in a directory and -try to convert them into the JPEG 2000 image format. You must have the Kakadu -JPEG 2000 tools installed, most importantly the kdu_compress command. - -You can download these tools for free at: +This is a python script/module that will process all the images in a directory +and try to convert them into the JPEG2000 or Pyramid TIFF image formats. You +must have the ImageMagick "convert" executable installed to run this script. +We assume the location of this executable to be "/usr/local/bin/convert" unless +otherwise specified with the "-i" option/convert_location parameter. + +To convert files to JPEG2000, specify the "-t jpeg" option when running this +script or set the image_type parameter to "jpeg" when creating a DivaConverter +object. This requires the "kdu_compress" executable included with the Kakadu +JPEG2000 library; we assume the location of this executable to be +"/usr/local/bin/kdu_compress" unless otherwise specified with the "-k" +option/kdu_compress_location parameter. + +You can download this library for free at: http://www.kakadusoftware.com/index.php?option=com_content&task=view&id=26&Itemid=22 +To convert files to Pyramid TIFF, specify the "-t tiff" option when running this +script or set the image_type parameter to "tiff" when creating a DivaConverter +object. This requires the "vipsCC" Python module included with an installation +of the VIPS image processing suite. If you are installing VIPS using Homebrew +on Mac OS X, make sure to run "brew install vips --with-imagemagick". + Dependencies: Python (version < 3.0) Kakadu Command-line Utilities @@ -44,38 +59,53 @@ Usage: Either run it with - python process_jp2.py [directory] + python process.py [input_directory] [output_directory] [data_output_directory] or chmod it to executable (chmod +x process.py) and run it with - ./process_jp2.py directory + ./process.py [input_directory] [output_directory] [data_output_directory] You can also use this as a Python module: - import process_jp2 - c = DivaConverter(input_directory, output_directory) + import process + c = DivaConverter(input_directory, output_directory, data_output_directory) c.convert() """ -PATH_TO_IMAGEMAGICK = "/usr/local/bin/convert" -PATH_TO_KDU_COMPRESS = "/usr/local/bin/kdu_compress" -VALID_EXTENSIONS = [".jpg", ".jpeg", ".tif", ".tiff", ".JPG", ".JPEG", ".TIF", ".TIFF", '.png', '.PNG'] - +VALID_INPUT_EXTENSIONS = [".jpg", ".jpeg", ".tif", ".tiff", ".JPG", ".JPEG", ".TIF", ".TIFF", '.png', '.PNG'] class DivaConverter(object): - def __init__(self, input_directory, output_directory, data_output_directory, image_type="jpeg"): + def __init__(self, input_directory, output_directory, data_output_directory, **kwargs): self.input_directory = os.path.abspath(input_directory) self.output_directory = os.path.abspath(output_directory) self.data_output_directory = os.path.abspath(data_output_directory) self.verbose = True - self.image_type = image_type + self.image_type = kwargs['image_type'] self.compression = "none" + self.convert_location = kwargs['convert_location'] + self.kdu_compress_location = kwargs['kdu_compress_location'] + + if not os.path.exists(self.convert_location): + print(("You do not have the ImageMagick 'convert' executable installed at {0}.").format(self.convert_location)) + print("If this path is incorrect, please specify an alternate location using the '-i (location)' command line option for this script.") + sys.exit(-1) if self.image_type == "tiff": try: from vipsCC import VImage - except ImportError: + except ImportError as e: print("You have specified TIFF as the output format, but do not have the VIPS Python library installed.") sys.exit(-1) + elif self.image_type == "jpeg": + if not os.path.exists(self.kdu_compress_location): + print(("You have specified JP2 as the output format, but do not have the kdu_compress executable installed at {0}.").format(self.kdu_compress_location)) + print("If this path is incorrect, please specify an alternate location using the '-k (location)' command line option for this script.") + sys.exit(-1) + + else: + print("The '-t' option must either be 'tiff' for Pyramid TIFF or 'jpeg' for JPEG2000. Omitting the '-t' option will default to 'jpeg'.") + print("Usage: process.py -t tiff input_directory output_directory data_output_directory") + sys.exit(-1) + def convert(self): if not os.path.isdir(self.output_directory): os.mkdir(self.output_directory) @@ -92,11 +122,11 @@ def convert(self): tdir = tempfile.mkdtemp() input_file = os.path.join(tdir, "{0}.tiff".format(name)) - output_file = os.path.join(self.output_directory, "{0}.{1}".format(name, self.__image_type)) + output_file = os.path.join(self.output_directory, "{0}.{1}".format(name, self.image_type)) if self.verbose: print("Using ImageMagick to pre-convert {0} to TIFF".format(image)) - subprocess.call([PATH_TO_IMAGEMAGICK, + subprocess.call([self.convert_location, "-compress", "None", image, input_file]) @@ -126,7 +156,7 @@ def convert(self): return True def __process_jpeg2000(self, input_file, output_file): - subprocess.call([PATH_TO_KDU_COMPRESS, + subprocess.call([self.kdu_compress_location, "-i", input_file, "-o", output_file, "Clevels=5", @@ -152,7 +182,7 @@ def __filter_fnames(self, fname): return False if fname == "Thumbs.db": return False - if os.path.splitext(fname)[-1].lower() not in VALID_EXTENSIONS: + if os.path.splitext(fname)[-1].lower() not in VALID_INPUT_EXTENSIONS: return False return True @@ -174,7 +204,9 @@ def __alphanum_key(self, s): if __name__ == "__main__": usage = "%prog [options] input_directory output_directory data_output_directory" parser = OptionParser(usage) - parser.add_option("-t", "--type", action="store", default="jpeg", help="The type of images this script should produce. Options are 'jpeg' or 'tiff'", dest="type") + parser.add_option("-t", "--type", action="store", default="jpeg", help="The type of images this script should produce. Options are 'jpeg' or 'tiff'.", dest="type") + parser.add_option("-k", "--kdu-compress-location", action="store", default="/usr/local/bin/kdu_compress", help="The location of the 'kdu_compress' executable provided by the Kakadu JPEG2000 library.", dest="kdu_compress_location") + parser.add_option("-i", "--imagemagick-convert-location", action="store", default="/usr/local/bin/convert", help="The location of the 'convert' executable provided by ImageMagick.", dest="convert_location") options, args = parser.parse_args() if len(args) < 3: @@ -186,6 +218,8 @@ def __alphanum_key(self, s): 'input_directory': args[0], 'output_directory': args[1], 'data_output_directory': args[2], + 'kdu_compress_location': options.kdu_compress_location, + 'convert_location': options.convert_location, 'image_type': options.type } diff --git a/build/processing/readme.md b/build/processing/readme.md deleted file mode 100644 index e69de29b..00000000 diff --git a/build/readme.md b/build/readme.md index 630cef96..33719d53 100644 --- a/build/readme.md +++ b/build/readme.md @@ -1,10 +1,11 @@ -Diva.js +

    + + + +

    +Diva.js [![Build Status](https://travis-ci.org/DDMAL/diva.js.svg?branch=develop)](http://travis-ci.org/DDMAL/diva.js) ========================================= -[![Build Status](https://travis-ci.org/DDMAL/diva.js.svg?branch=develop)](http://travis-ci.org/DDMAL/diva.js) - -## Description - Diva.js (Document Image Viewer with AJAX) is a JavaScript book image viewer designed to present multi-page documents at multiple resolutions. Version 3.0 contains many new features and improvements: