X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/1ff260641b29888f28d24acb58195ea231207494..5667153616be3469413bc0fe8925bbbc4937be70:/apps/wolnelektury_core/static/js/picture.js

diff --git a/apps/wolnelektury_core/static/js/picture.js b/apps/wolnelektury_core/static/js/picture.js
index 052392a32..0c2e35b84 100644
--- a/apps/wolnelektury_core/static/js/picture.js
+++ b/apps/wolnelektury_core/static/js/picture.js
@@ -1,247 +1,251 @@
 
 (function($) {
-    $.widget('wl.pictureviewer', {
-
-	options: {
-	    steps: 6, // steps of zoom
-	    max: -1, // max zoom in percent
-	    plus_button: undefined,
-	    minus_button: undefined,
-	    height: 500, // height to scale to initially
-	},
-
-
-	_create: function() {
-	    var self = this;
-	    /* Calibrate */
-	    self._zoom = 0;
-
-	    // the initial thumbnailed picture
-
-
-	    var img = self.element.find('img.initial').get(0);
-
-	    self.initial_size = [ 
-		img.naturalWidth,
-		img.naturalHeight
-	    ];
-
-	    self.element.width(self.initial_size[0]);
-	    self.element.height(self.initial_size[1]);
-	    
-	    self.initial_position = self.element.offset();
-
-	    var original = self.element.find('img.original').get(0);
-	    self._original = false;
-	    self.original_loeaded = undefined; // callback
-	    self._original_loaded = false;
-
-	    self.spinner = $("#spinner").progressSpin();
-
-	    $(original).load(function() {
-		console.log("loaded original");
-		self._original_loaded = true;
-		self.spinner.stop();
-		var cb = self.original_loaded;
-		self.original_loaded = undefined;
-		if (cb)
-		    cb()
-	    });
-	    
-	    if (self.options.max <= 0) {
-		self.options.max = original.naturalWidth
-		    * 100 / self.initial_size[0];
-	    }
-
-	    self.element.css({
-		'margin': 0,
-	    });
-
-	    self.element.offset(self.initial_position);
-	    //      self.element.draggable({containment:"parent"});
-
-	    if (self.options.plus_button)
-		self.options.plus_button.click(
-		    function(ev) { self.zoom(1); });
-	    if (self.options.minus_button)
-		self.options.minus_button.click(
-		    function(ev) { self.zoom(-1); });
-
-	    self.options.areas_links.hover(function() {
-		$this = $(this);
-		var coords = $this.data("coords");
-		this._picture_mark = self.createMark({
-		    label: $this.text(),
-		    coords: coords,
-		});
-	    }, function() {
-		$(this._picture_mark).remove();
-		this._picture_mark = undefined;
-	    });
-	    return self;
-	},
-
-	natural_size: function() {
-	    var img = this.element.find('img.original').get(0);
-	    return [ img.naturalWidth, img.naturalHeight ] 
-	},
-
-	currentZoom: function() { return this._zoom; },
-
-	initOriginal: function() {
-	    var self = this;
-	    function subst_original() {
-		self.element.find("img.initial").remove();
-		self.element.find("img.loading").removeClass("loading");
-		self._original = true;
-	    }
-	    if (!this._original) {
-		if (this._original_loaded) {
-		    return subst_original();
-		} else {
-		    self.original_loaded = subst_original;
-		    self.spinner.start();
-		}
-	    }
-
-	},
-
-	zoom: function(steps) {
-	    this.initOriginal();
-	    var t = this._zoom + steps;
-	    return this.zoomTo(t);
-	},
-
-	zoomForStep: function(step) {
-	    // 0 => initial
-	    // max_step-1 => max %
-	    return 100 + (this.options.max - 100) / this.options.steps * step
-	},
-
-	zoomTo: function(level) {
-	    if (level < 0 || level > this.options.steps)
-		return;
-	    var ratio = this.zoomForStep(level) / 100;
-	    var new_width  = ratio * this.initial_size[0];
-	    var new_height = ratio * this.initial_size[1];
-	    var target = {
-		'width': new_width,
-		'left': Math.max(0, 
-				 this.initial_position.left 
-				 - (new_width - this.initial_size[0])/2),
-		'top': Math.max(0, 
-				this.initial_position.top 
-				- (new_height - this.initial_size[1])/2),
-	    };
-
-	    this._zoom = level;
-
-	    this.element.css(target);
-	   
-
-//	    this.element.animate(target, 1200); // default duration=400
-	},
-
-	allowedPosition: function(off) {
-	    var x = undefined, fix_x = undefined;
-	    var y = undefined, fix_y = undefined;
-	    var w = this.element.width();
-	    var h = this.element.height();
-	    var cw = $(window).width();
-	    var ch = $(window).height();
-	    var off = off || this.element.offset();
-
-	    if (w <= cw) {
-		var x = off.left;
-		if (x < 0) 
-		    fix_x = 0;
-		if (x + w > cw)
-		    fix_x = cw - w;
-	    } else {
-		if (x > 0)
-		    fix_x = 0;
-		if (x + w < cw)
-		    fix_x = cw - w;
-	    }
-
-	    if (h <= ch) {
-		var y = off.top;
-		if (y < 0)
-		    fix_y = 0;
-		if (y + h > ch)
-		    fix_y = ch - h;
-	    } else {
-		if (y > 0)
-		    fix_y = 0;
-		if (y + h < ch)
-		    fix_y = ch - h;
-	    }
-	    if (fix_x !== undefined || fix_y !== undefined)
-		return { top: fix_y, left: fix_x };
-	    return undefined;
-
-	},
-
-	// mark
-	// {
-	//  label: "...",
-	//  coords: [x, y, w, h]
-	// }
-	createMark: function(mark) {
-	    var $mark = $('<div class="mark"><div class="label">' + 
-			  mark.label + '</div></div>');
-	    var ratio = this.zoomForStep(this.currentZoom()) *
-		this.initial_size[0] / (100 * this.natural_size()[0]);
-	    var scale = function (v) { 
-		return v * ratio; 
-	    }
-	    if (mark.coords[1][0] < 0 || mark.coords[1][1] < 0) { // whole
-		var s = self.natural_size();
-		if (mark.coords[1][0] < 0) mark.coords[1][0] = s[0];
-		if (mark.coords[1][1] < 0) mark.coords[1][1] = s[1];
-	    }
-
-	    var coords = [[scale(mark.coords[0][0]), scale(mark.coords[0][1])],
-			  [scale(mark.coords[1][0]), scale(mark.coords[1][1])]];
-	    this.element.append($mark);
-	    $mark.width(coords[1][0] - coords[0][0]);
-	    $mark.height(coords[1][1] - coords[0][1]);
-	    $mark.css({left: coords[0][0], top: coords[0][1]});
-	    return $mark.get(0);
-	},
-    });
-}(jQuery));
-
-
-$(document).ready(function(){
-    $(".picture-wrap").pictureviewer({
-	plus_button: $(".toolbar .button.plus"),
-	minus_button: $(".toolbar .button.minus"),
-	areas_links: $("#picture-objects a, #picture-themes a"),
-    });
-
-    $.highlightFade.defaults.speed = 3000;
-
-    $('.toolbar a.dropdown').each(function() {
-	$t = $(this);
-	$($t.attr('href')).hide().insertAfter(this);
-    });
-
-    function closeDD() {
-	$(this).removeClass('selected');
-	$($(this).attr('href')).slideUp('fast');
-	
-    }
-    $('.toolbar a.dropdown').click(function() {
-	if ($(this).hasClass('selected')) {
-	    closeDD.call(this);
-	} else {
-	    $(this).addClass('selected');
-	    $($(this).attr('href')).slideDown('fast');
-	    $(this).parent().siblings(".button:has(.dropdown)").children(".dropdown").each(closeDD);
+  $.widget('wl.pictureviewer', {
+    
+    options: {
+      step: 20, // step in % of initial image
+      plus_button: undefined,
+      minus_button: undefined,
+    },
+    ORIGINAL_LOADING: 0, 
+    ORIGINAL_AVAILABLE: 1, 
+    ORIGINAL_SHOWN: 2,
+
+    _create: function() {
+      var self = this;
+      self.initial_size = [ 
+	self.element.data('width'),
+	self.element.data('height') 
+      ];
+      self.original_size = [
+	self.element.data('original-width'),
+	self.element.data('original-height')
+      ];
+      self._zoom = 0;
+      self._ratio = 1.0;
+
+      self.original = $('<img src="'+ self.element.attr('data-original-url') +'">');
+      
+      self._original_avaialble = self.ORIGINAL_LOADING;
+      function original_loaded() {
+	self._original_avaialble = self.ORIGINAL_AVAILABLE;
+	self.options.plus_button.removeClass('inactive');
+	self.options.minus_button.removeClass('inactive');
+	console.log("Original image available, sizes initial: " + self.initial_size + ", original: " + self.original_size);
+      };
+      self.original.load(original_loaded);
+
+      self.element.width(self.initial_size[0]);
+      self.element.height(self.initial_size[1]);
+
+      if (self.options.plus_button)
+	self.options.plus_button.click(
+	  function(ev) { self.zoom(1); });
+      if (self.options.minus_button)
+	self.options.minus_button.click(
+	  function(ev) { self.zoom(-1); });
+
+      self._initial_mark = null;
+      function clean_initial_mark() {
+	if (self._initial_mark) {
+	  self._initial_mark.remove();
+	  self._initial_mark = null;
 	}
-    });
-
+      }
+      var initial_hash = window.location.hash;
+      if (initial_hash) {
+	var mk = null;
+	if (initial_hash.startsWith('#object-')) {
+	  $("[href=#picture-objects]").trigger('click');
+	} else if (initial_hash.startsWith('#theme-')) {
+	  $("[href=#picutre-themes]").trigger('click');
+	}
+	mk = $("[href=" + initial_hash + "]").eq(0);
+	self._initial_mark = self.createMark({
+	  label: mk.text(),
+	  coords: mk.data('coords')
+	});
+      }      
+
+
+      self.options.areas_links.hover(function() {
+	clean_initial_mark();
+	$this = $(this);
+	var coords = $this.data("coords");
+	this._picture_mark = self.createMark({
+//	  label: $this.text(),
+	  coords: coords,
+	});
+      }, function() {
+	$(this._picture_mark).remove();
+	this._picture_mark = undefined;
+      }).click(function(ev) {
+	ev.preventDefault();
+	var $mark = self.element.find('.mark').eq(0);
+	var markPos = $mark.offset();
+	markPos = [markPos.left, markPos.top];
+	var markSize = [ $mark.width(), $mark.height() ]
+	var wSize = [ window.innerWidth, window.innerHeight ];
+	window.scrollTo(
+	  markPos[0] + markSize[0]/2 - wSize[0]/2,
+	  markPos[1] + markSize[1]/2 - wSize[1]/2	
+	);
+	
+      });
+
+      
+
+      return self;
+    },
+
+    currentSize: function() {
+      return [this.element.width(), this.element.height() ];
+    },
+
+    currentZoom: function() { return this._zoom; },
+
+    initOriginal: function() {
+      if (this._original_avaialble > this.ORIGINAL_LOADING && 
+	  this._original_avaialble < this.ORIGINAL_SHOWN) {
+	this.element.css({'background-image': 'url('+ this.original.attr('src')+')', 'background-size':  this.initial_size[0]+'px'});
+	this._original_avaialble = this.ORIGINAL_SHOWN;
+      };
+    },
+
+    zoom: function(steps) {
+      this.initOriginal();
+      var t = this._zoom + steps;
+      return this.zoomTo(t);
+    },
+
+    zoomForStep: function(step) {
+      // 0 => initial
+      // max_step-1 => max %
+      if (step < 0) step = 0;
+      var zoomperc = 100 + step * this.options.step;
+      if (zoomperc * this.initial_size[0] > this.original_size[0] * 100) {
+	zoomperc = this.original_size[0] * 100 / this.initial_size[0];
+      };
+      return zoomperc;
+    },
+
+    zoomTo: function(level) {
+      var ratio = this.zoomForStep(level) / 100;
+      var new_width  = ratio * this.initial_size[0];
+      var new_height = ratio * this.initial_size[1];
+      var cs = this.currentSize();
+      if (new_width == cs[0]) 
+	return;
+
+      var target = {
+	'width': new_width + 'px',
+	'height': new_height + 'px',
+	'background-size': new_width + 'px',
+      };
+
+      this._zoom = level;
+      this._ratio = ratio;
+
+      this.element.css(target);
+      if (this._initial_mark) {
+	this._initial_mark = this.redrawMark(this._initial_mark);
+      }
+
+    },
+
+    allowedPosition: function(off) {
+      var x = undefined, fix_x = undefined;
+      var y = undefined, fix_y = undefined;
+      var w = this.element.width();
+      var h = this.element.height();
+      var cw = $(window).width();
+      var ch = $(window).height();
+      var off = off || this.element.offset();
+
+      if (w <= cw) {
+	var x = off.left;
+	if (x < 0) 
+	  fix_x = 0;
+	if (x + w > cw)
+	  fix_x = cw - w;
+      } else {
+	if (x > 0)
+	  fix_x = 0;
+	if (x + w < cw)
+	  fix_x = cw - w;
+      }
+
+      if (h <= ch) {
+	var y = off.top;
+	if (y < 0)
+	  fix_y = 0;
+	if (y + h > ch)
+	  fix_y = ch - h;
+      } else {
+	if (y > 0)
+	  fix_y = 0;
+	if (y + h < ch)
+	  fix_y = ch - h;
+      }
+      if (fix_x !== undefined || fix_y !== undefined)
+	return { top: fix_y, left: fix_x };
+      return undefined;
+
+    },
+    redrawMark: function(mark) {
+      var $mark = $(mark);
+      var $newmark = this.createMark($mark.data('mark'));
+      $mark.remove();
+      return $newmark;
+    },
+    // mark
+    // {
+    //  label: "...",
+    //  coords: [x, y, w, h]
+    // }
+    createMark: function(mark) {
+      if (mark.label === undefined)
+	mark.label = '';
+      var $mark = $('<div class="mark"><div class="label">' + 
+		    mark.label + '</div></div>');
+      var cs = this.currentSize()
+      var ratio = cs[0] / this.original_size[0];
+      var scale = function (v) { 
+	return v * ratio; 
+      }
+      if (mark.coords[1][0] < 0 || mark.coords[1][1] < 0) { // whole
+	var s = this.original_size;
+	if (mark.coords[1][0] < 0) mark.coords[1][0] = s[0];
+	if (mark.coords[1][1] < 0) mark.coords[1][1] = s[1];
+      }
+
+      var coords = [[scale(mark.coords[0][0]), scale(mark.coords[0][1])],
+		    [scale(mark.coords[1][0]), scale(mark.coords[1][1])]];
+      this.element.append($mark);
+      $mark.width(coords[1][0] - coords[0][0]);
+      $mark.height(coords[1][1] - coords[0][1]);
+      $mark.css({left: coords[0][0], top: coords[0][1]});
+
+      $mark.data('mark', mark);
+      return $mark.get(0);
+    },
+  });
+
+
+$(document).ready(function() {
+  $.highlightFade.defaults.speed = 3000;
+
+  $('#menu .dropdown').each(function() {
+    $t = $(this);
+    $($t.attr('href')).hide().insertAfter(this);
+  });
+
+  $(".picture-wrap").pictureviewer({
+    plus_button: $(".button.plus"),
+    minus_button: $(".button.minus"),
+    areas_links: $("#picture-objects a, #picture-themes a"),
+  });
 
 });
 
+}(jQuery));