1 // VIEW 2 3 /** 4 * A track that displays tiled images (PNGs, or other images) along 5 * the reference sequence. 6 * @class 7 * @extends Track 8 */ 9 function ImageTrack(config, refSeq, browserParams) { 10 Track.call(this, config.label, config.key, 11 false, browserParams.changeCallback); 12 13 if( !refSeq.end ) 14 return; 15 16 this.refSeq = refSeq; 17 this.trackPadding = browserParams.trackPadding || 0; 18 19 this.config = config; 20 21 // TODO: the imagestore should be passed in as an arg to the 22 // constructor, not instantiated here 23 var storeclass = config.backendVersion == 0 ? TiledImageStore.Fixed_v0 : TiledImageStore.Fixed; 24 this.store = new storeclass({ 25 refSeq: refSeq, 26 urlTemplate: config.urlTemplate, 27 baseUrl: config.baseUrl, 28 track: this 29 }); 30 dojo.connect( this.store, 'loadSuccess', this, 'loadSuccess' ); 31 dojo.connect( this.store, 'loadFail', this, 'loadFail' ); 32 33 this.store.load(); 34 } 35 36 ImageTrack.prototype = new Track(""); 37 38 ImageTrack.prototype.loadSuccess = function(o,url) { 39 this.empty = this.store.empty; 40 this.setLoaded(); 41 }; 42 43 ImageTrack.prototype.setViewInfo = function(heightUpdate, numBlocks, 44 trackDiv, labelDiv, 45 widthPct, widthPx, scale) { 46 Track.prototype.setViewInfo.apply( this, arguments ); 47 this.setLabel( this.key ); 48 }; 49 50 ImageTrack.prototype.handleImageError = function(ev) { 51 var img = ev.currentTarget || ev.srcElement; 52 img.style.display = "none"; 53 dojo.stopEvent(ev); 54 }; 55 56 57 /** 58 * @private 59 */ 60 ImageTrack.prototype.makeImageLoadHandler = function( img, blockIndex, blockWidth, composeCallback ) { 61 var handler = dojo.hitch( this, function() { 62 this.imageHeight = img.height; 63 img.style.height = img.height + "px"; 64 img.style.width = (100 * (img.baseWidth / blockWidth)) + "%"; 65 this.heightUpdate( img.height, blockIndex ); 66 if( composeCallback ) 67 composeCallback(); 68 return true; 69 }); 70 71 if( ! dojo.isIE ) 72 return handler; 73 else 74 // in IE, have to delay calling it for a (arbitrary) 1/4 75 // second because the image's height is not always 76 // available when the onload event fires. >:-{ 77 return function() { 78 window.setTimeout(handler,250); 79 }; 80 81 }; 82 83 ImageTrack.prototype.fillBlock = function(blockIndex, block, 84 leftBlock, rightBlock, 85 leftBase, rightBase, 86 scale, stripeWidth, 87 containerStart, containerEnd) { 88 var blockWidth = rightBase - leftBase; 89 var images = this.store.getImages( scale, leftBase, rightBase ); 90 var im; 91 92 dojo.forEach( images, function(im) { 93 im.className = 'image-track'; 94 if (!(im.parentNode && im.parentNode.parentNode)) { 95 im.style.position = "absolute"; 96 im.style.left = (100 * ((im.startBase - leftBase) / blockWidth)) + "%"; 97 switch (this.config.align) { 98 case "top": 99 im.style.top = "0px"; 100 break; 101 case "bottom": 102 default: 103 im.style.bottom = this.trackPadding + "px"; 104 break; 105 } 106 block.appendChild(im); 107 } 108 109 // make an onload handler for when the image is fetched that 110 // will update the height and width of the track 111 var loadhandler = this.makeImageLoadHandler( im, blockIndex, blockWidth ); 112 if( im.complete ) 113 // just call the handler ourselves if the image is already loaded 114 loadhandler(); 115 else 116 // otherwise schedule it 117 dojo.connect( im, "onload", loadhandler ); 118 119 }, this); 120 }; 121 122 ImageTrack.prototype.startZoom = function(destScale, destStart, destEnd) { 123 if (this.empty) return; 124 this.store.clearCache(); 125 this.store.getImages( destScale, destStart, destEnd ); 126 }; 127 128 ImageTrack.prototype.endZoom = function(destScale, destBlockBases) { 129 Track.prototype.clear.apply(this); 130 }; 131 132 ImageTrack.prototype.clear = function() { 133 Track.prototype.clear.apply(this); 134 this.store.clearCache(); 135 }; 136 137 ImageTrack.prototype.transfer = function(sourceBlock, destBlock, scale, 138 containerStart, containerEnd) { 139 if (!(sourceBlock && destBlock)) return; 140 141 var children = sourceBlock.childNodes; 142 var destLeft = destBlock.startBase; 143 var destRight = destBlock.endBase; 144 var im; 145 for (var i = 0; i < children.length; i++) { 146 im = children[i]; 147 if ("startBase" in im) { 148 //if sourceBlock contains an image that overlaps destBlock, 149 if ((im.startBase < destRight) 150 && ((im.startBase + im.baseWidth) > destLeft)) { 151 //move image from sourceBlock to destBlock 152 im.style.left = (100 * ((im.startBase - destLeft) / (destRight - destLeft))) + "%"; 153 destBlock.appendChild(im); 154 } else { 155 // don't move it, and even uncache it 156 this.store.unCacheImage( im ); 157 } 158 } 159 } 160 }; 161 162