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