diff --git a/modules/navcarousel/helpers/navcarousel_theme.php b/modules/navcarousel/helpers/navcarousel_theme.php index 99853437..844af7f2 100644 --- a/modules/navcarousel/helpers/navcarousel_theme.php +++ b/modules/navcarousel/helpers/navcarousel_theme.php @@ -21,9 +21,9 @@ class navcarousel_theme_Core { static function head($theme) { if ($theme->page_type == "item") { if (locales::is_rtl()) { - $rtl_support = "horizontalDirection: 'rtl',\n"; + $rtl_support = "rtl: true,\n"; } else { - $rtl_support = ""; + $rtl_support = "rtl: false,\n"; } $carouselwidth = module::get_var("navcarousel", "carouselwidth", "600"); if ($carouselwidth == 0) { @@ -89,6 +89,7 @@ class navcarousel_theme_Core { jQuery(document).ready(function() {\n jQuery('#navcarousel').jcarousel({\n ". $ajaxhandler ." + itemFallbackDimension: ". ($thumbsize + 25) .",\n start: ". $itemoffset .",\n size: ". $childcount .",\n visible: ". $showelements .",\n diff --git a/modules/navcarousel/js/jquery.jcarousel.js b/modules/navcarousel/js/jquery.jcarousel.js new file mode 100644 index 00000000..90f2459e --- /dev/null +++ b/modules/navcarousel/js/jquery.jcarousel.js @@ -0,0 +1,917 @@ +/*! + * jCarousel - Riding carousels with jQuery + * http://sorgalla.com/jcarousel/ + * + * Copyright (c) 2006 Jan Sorgalla (http://sorgalla.com) + * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) + * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. + * + * Built on top of the jQuery library + * http://jquery.com + * + * Inspired by the "Carousel Component" by Bill Scott + * http://billwscott.com/carousel/ + */ + +(function($) { + /** + * Creates a carousel for all matched elements. + * + * @example $("#mycarousel").jcarousel(); + * @before + * @result + * + *
+ *
+ *
+ *
    + *
  • First item
  • + *
  • Second item
  • + *
+ *
+ *
+ *
+ *
+ *
+ * + * @method jcarousel + * @return jQuery + * @param o {Hash|String} A set of key/value pairs to set as configuration properties or a method name to call on a formerly created instance. + */ + $.fn.jcarousel = function(o) { + if (typeof o == 'string') { + var instance = $(this).data('jcarousel'), args = Array.prototype.slice.call(arguments, 1); + return instance[o].apply(instance, args); + } else + return this.each(function() { + $(this).data('jcarousel', new $jc(this, o)); + }); + }; + + // Default configuration properties. + var defaults = { + vertical: false, + rtl: false, + start: 1, + offset: 1, + size: null, + scroll: 3, + visible: null, + animation: 'normal', + easing: 'swing', + auto: 0, + wrap: null, + initCallback: null, + reloadCallback: null, + itemLoadCallback: null, + itemFirstInCallback: null, + itemFirstOutCallback: null, + itemLastInCallback: null, + itemLastOutCallback: null, + itemVisibleInCallback: null, + itemVisibleOutCallback: null, + buttonNextHTML: '
', + buttonPrevHTML: '
', + buttonNextEvent: 'click', + buttonPrevEvent: 'click', + buttonNextCallback: null, + buttonPrevCallback: null, + itemFallbackDimension: null + }, windowLoaded = false; + + $(window).bind('load.jcarousel', function() { windowLoaded = true; }) + + /** + * The jCarousel object. + * + * @constructor + * @class jcarousel + * @param e {HTMLElement} The element to create the carousel for. + * @param o {Object} A set of key/value pairs to set as configuration properties. + * @cat Plugins/jCarousel + */ + $.jcarousel = function(e, o) { + this.options = $.extend({}, defaults, o || {}); + + this.locked = false; + + this.container = null; + this.clip = null; + this.list = null; + this.buttonNext = null; + this.buttonPrev = null; + + // Only set if not explicitly passed as option + if (!o || o.rtl === undefined) + this.options.rtl = ($(e).attr('dir') || $('html').attr('dir') || '').toLowerCase() == 'rtl'; + + this.wh = !this.options.vertical ? 'width' : 'height'; + this.lt = !this.options.vertical ? (this.options.rtl ? 'right' : 'left') : 'top'; + + // Extract skin class + var skin = '', split = e.className.split(' '); + + for (var i = 0; i < split.length; i++) { + if (split[i].indexOf('jcarousel-skin') != -1) { + $(e).removeClass(split[i]); + skin = split[i]; + break; + } + } + + if (e.nodeName.toUpperCase() == 'UL' || e.nodeName.toUpperCase() == 'OL') { + this.list = $(e); + this.container = this.list.parent(); + + if (this.container.hasClass('jcarousel-clip')) { + if (!this.container.parent().hasClass('jcarousel-container')) + this.container = this.container.wrap('
'); + + this.container = this.container.parent(); + } else if (!this.container.hasClass('jcarousel-container')) + this.container = this.list.wrap('
').parent(); + } else { + this.container = $(e); + this.list = this.container.find('ul,ol').eq(0); + } + + if (skin != '' && this.container.parent()[0].className.indexOf('jcarousel-skin') == -1) + this.container.wrap('
'); + + this.clip = this.list.parent(); + + if (!this.clip.length || !this.clip.hasClass('jcarousel-clip')) + this.clip = this.list.wrap('
').parent(); + + this.buttonNext = $('.jcarousel-next', this.container); + + if (this.buttonNext.size() == 0 && this.options.buttonNextHTML != null) + this.buttonNext = this.clip.after(this.options.buttonNextHTML).next(); + + this.buttonNext.addClass(this.className('jcarousel-next')); + + this.buttonPrev = $('.jcarousel-prev', this.container); + + if (this.buttonPrev.size() == 0 && this.options.buttonPrevHTML != null) + this.buttonPrev = this.clip.after(this.options.buttonPrevHTML).next(); + + this.buttonPrev.addClass(this.className('jcarousel-prev')); + + this.clip.addClass(this.className('jcarousel-clip')).css({ + overflow: 'hidden', + position: 'relative' + }); + this.list.addClass(this.className('jcarousel-list')).css({ + overflow: 'hidden', + position: 'relative', + top: 0, + margin: 0, + padding: 0 + }).css((this.options.rtl ? 'right' : 'left'), 0); + this.container.addClass(this.className('jcarousel-container')).css({ + position: 'relative' + }); + if (!this.options.vertical && this.options.rtl) + this.container.addClass('jcarousel-direction-rtl').attr('dir', 'rtl'); + + var di = this.options.visible != null ? Math.ceil(this.clipping() / this.options.visible) : null; + var li = this.list.children('li'); + + var self = this; + + if (li.size() > 0) { + var wh = 0, i = this.options.offset; + li.each(function() { + self.format(this, i++); + wh += self.dimension(this, di); + }); + + this.list.css(this.wh, (wh + 100) + 'px'); + + // Only set if not explicitly passed as option + if (!o || o.size === undefined) + this.options.size = li.size(); + } + + // For whatever reason, .show() does not work in Safari... + this.container.css('display', 'block'); + this.buttonNext.css('display', 'block'); + this.buttonPrev.css('display', 'block'); + + this.funcNext = function() { self.next(); }; + this.funcPrev = function() { self.prev(); }; + this.funcResize = function() { self.reload(); }; + + if (this.options.initCallback != null) + this.options.initCallback(this, 'init'); + + if (!windowLoaded && $.browser.safari) { + this.buttons(false, false); + $(window).bind('load.jcarousel', function() { self.setup(); }); + } else + this.setup(); + }; + + // Create shortcut for internal use + var $jc = $.jcarousel; + + $jc.fn = $jc.prototype = { + jcarousel: '0.2.5' + }; + + $jc.fn.extend = $jc.extend = $.extend; + + $jc.fn.extend({ + /** + * Setups the carousel. + * + * @method setup + * @return undefined + */ + setup: function() { + this.first = null; + this.last = null; + this.prevFirst = null; + this.prevLast = null; + this.animating = false; + this.timer = null; + this.tail = null; + this.inTail = false; + + if (this.locked) + return; + + this.list.css(this.lt, this.pos(this.options.offset) + 'px'); + var p = this.pos(this.options.start); + this.prevFirst = this.prevLast = null; + this.animate(p, false); + + $(window).unbind('resize.jcarousel', this.funcResize).bind('resize.jcarousel', this.funcResize); + }, + + /** + * Clears the list and resets the carousel. + * + * @method reset + * @return undefined + */ + reset: function() { + this.list.empty(); + + this.list.css(this.lt, '0px'); + this.list.css(this.wh, '10px'); + + if (this.options.initCallback != null) + this.options.initCallback(this, 'reset'); + + this.setup(); + }, + + /** + * Reloads the carousel and adjusts positions. + * + * @method reload + * @return undefined + */ + reload: function() { + if (this.tail != null && this.inTail) + this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) + this.tail); + + this.tail = null; + this.inTail = false; + + if (this.options.reloadCallback != null) + this.options.reloadCallback(this); + + if (this.options.visible != null) { + var self = this; + var di = Math.ceil(this.clipping() / this.options.visible), wh = 0, lt = 0; + this.list.children('li').each(function(i) { + wh += self.dimension(this, di); + if (i + 1 < self.first) + lt = wh; + }); + + this.list.css(this.wh, wh + 'px'); + this.list.css(this.lt, -lt + 'px'); + } + + this.scroll(this.first, false); + }, + + /** + * Locks the carousel. + * + * @method lock + * @return undefined + */ + lock: function() { + this.locked = true; + this.buttons(); + }, + + /** + * Unlocks the carousel. + * + * @method unlock + * @return undefined + */ + unlock: function() { + this.locked = false; + this.buttons(); + }, + + /** + * Sets the size of the carousel. + * + * @method size + * @return undefined + * @param s {Number} The size of the carousel. + */ + size: function(s) { + if (s != undefined) { + this.options.size = s; + if (!this.locked) + this.buttons(); + } + + return this.options.size; + }, + + /** + * Checks whether a list element exists for the given index (or index range). + * + * @method get + * @return bool + * @param i {Number} The index of the (first) element. + * @param i2 {Number} The index of the last element. + */ + has: function(i, i2) { + if (i2 == undefined || !i2) + i2 = i; + + if (this.options.size !== null && i2 > this.options.size) + i2 = this.options.size; + + for (var j = i; j <= i2; j++) { + var e = this.get(j); + if (!e.length || e.hasClass('jcarousel-item-placeholder')) + return false; + } + + return true; + }, + + /** + * Returns a jQuery object with list element for the given index. + * + * @method get + * @return jQuery + * @param i {Number} The index of the element. + */ + get: function(i) { + return $('.jcarousel-item-' + i, this.list); + }, + + /** + * Adds an element for the given index to the list. + * If the element already exists, it updates the inner html. + * Returns the created element as jQuery object. + * + * @method add + * @return jQuery + * @param i {Number} The index of the element. + * @param s {String} The innerHTML of the element. + */ + add: function(i, s) { + var e = this.get(i), old = 0, n = $(s); + + if (e.length == 0) { + var c, e = this.create(i), j = $jc.intval(i); + while (c = this.get(--j)) { + if (j <= 0 || c.length) { + j <= 0 ? this.list.prepend(e) : c.after(e); + break; + } + } + } else + old = this.dimension(e); + + if (n.get(0).nodeName.toUpperCase() == 'LI') { + e.replaceWith(n); + e = n; + } else + e.empty().append(s); + + this.format(e.removeClass(this.className('jcarousel-item-placeholder')), i); + + var di = this.options.visible != null ? Math.ceil(this.clipping() / this.options.visible) : null; + var wh = this.dimension(e, di) - old; + + if (i > 0 && i < this.first) + this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) - wh + 'px'); + + this.list.css(this.wh, $jc.intval(this.list.css(this.wh)) + wh + 'px'); + + return e; + }, + + /** + * Removes an element for the given index from the list. + * + * @method remove + * @return undefined + * @param i {Number} The index of the element. + */ + remove: function(i) { + var e = this.get(i); + + // Check if item exists and is not currently visible + if (!e.length || (i >= this.first && i <= this.last)) + return; + + var d = this.dimension(e); + + if (i < this.first) + this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) + d + 'px'); + + e.remove(); + + this.list.css(this.wh, $jc.intval(this.list.css(this.wh)) - d + 'px'); + }, + + /** + * Moves the carousel forwards. + * + * @method next + * @return undefined + */ + next: function() { + this.stopAuto(); + + if (this.tail != null && !this.inTail) + this.scrollTail(false); + else + this.scroll(((this.options.wrap == 'both' || this.options.wrap == 'last') && this.options.size != null && this.last == this.options.size) ? 1 : this.first + this.options.scroll); + }, + + /** + * Moves the carousel backwards. + * + * @method prev + * @return undefined + */ + prev: function() { + this.stopAuto(); + + if (this.tail != null && this.inTail) + this.scrollTail(true); + else + this.scroll(((this.options.wrap == 'both' || this.options.wrap == 'first') && this.options.size != null && this.first == 1) ? this.options.size : this.first - this.options.scroll); + }, + + /** + * Scrolls the tail of the carousel. + * + * @method scrollTail + * @return undefined + * @param b {Boolean} Whether scroll the tail back or forward. + */ + scrollTail: function(b) { + if (this.locked || this.animating || !this.tail) + return; + + var pos = $jc.intval(this.list.css(this.lt)); + + !b ? pos -= this.tail : pos += this.tail; + this.inTail = !b; + + // Save for callbacks + this.prevFirst = this.first; + this.prevLast = this.last; + + this.animate(pos); + }, + + /** + * Scrolls the carousel to a certain position. + * + * @method scroll + * @return undefined + * @param i {Number} The index of the element to scoll to. + * @param a {Boolean} Flag indicating whether to perform animation. + */ + scroll: function(i, a) { + if (this.locked || this.animating) + return; + + this.animate(this.pos(i), a); + }, + + /** + * Prepares the carousel and return the position for a certian index. + * + * @method pos + * @return {Number} + * @param i {Number} The index of the element to scoll to. + */ + pos: function(i) { + var pos = $jc.intval(this.list.css(this.lt)); + + if (this.locked || this.animating) + return pos; + + if (this.options.wrap != 'circular') + i = i < 1 ? 1 : (this.options.size && i > this.options.size ? this.options.size : i); + + var back = this.first > i; + + // Create placeholders, new list width/height + // and new list position + var f = this.options.wrap != 'circular' && this.first <= 1 ? 1 : this.first; + var c = back ? this.get(f) : this.get(this.last); + var j = back ? f : f - 1; + var e = null, l = 0, p = false, d = 0, g; + + while (back ? --j >= i : ++j < i) { + e = this.get(j); + p = !e.length; + if (e.length == 0) { + e = this.create(j).addClass(this.className('jcarousel-item-placeholder')); + c[back ? 'before' : 'after' ](e); + + if (this.first != null && this.options.wrap == 'circular' && this.options.size !== null && (j <= 0 || j > this.options.size)) { + g = this.get(this.index(j)); + if (g.length) + e = this.add(j, g.clone(true)); + } + } + + c = e; + d = this.dimension(e); + + if (p) + l += d; + + if (this.first != null && (this.options.wrap == 'circular' || (j >= 1 && (this.options.size == null || j <= this.options.size)))) + pos = back ? pos + d : pos - d; + } + + // Calculate visible items + var clipping = this.clipping(); + var cache = []; + var visible = 0, j = i, v = 0; + var c = this.get(i - 1); + + while (++visible) { + e = this.get(j); + p = !e.length; + if (e.length == 0) { + e = this.create(j).addClass(this.className('jcarousel-item-placeholder')); + // This should only happen on a next scroll + c.length == 0 ? this.list.prepend(e) : c[back ? 'before' : 'after' ](e); + + if (this.first != null && this.options.wrap == 'circular' && this.options.size !== null && (j <= 0 || j > this.options.size)) { + g = this.get(this.index(j)); + if (g.length) + e = this.add(j, g.clone(true)); + } + } + + c = e; + var d = this.dimension(e); + if (d == 0) { + throw new Error('jCarousel: No width/height set for items. This will cause an infinite loop. Aborting...'); + } + + if (this.options.wrap != 'circular' && this.options.size !== null && j > this.options.size) + cache.push(e); + else if (p) + l += d; + + v += d; + + if (v >= clipping) + break; + + j++; + } + + // Remove out-of-range placeholders + for (var x = 0; x < cache.length; x++) + cache[x].remove(); + + // Resize list + if (l > 0) { + this.list.css(this.wh, this.dimension(this.list) + l + 'px'); + + if (back) { + pos -= l; + this.list.css(this.lt, $jc.intval(this.list.css(this.lt)) - l + 'px'); + } + } + + // Calculate first and last item + var last = i + visible - 1; + if (this.options.wrap != 'circular' && this.options.size && last > this.options.size) + last = this.options.size; + + if (j > last) { + visible = 0, j = last, v = 0; + while (++visible) { + var e = this.get(j--); + if (!e.length) + break; + v += this.dimension(e); + if (v >= clipping) + break; + } + } + + var first = last - visible + 1; + if (this.options.wrap != 'circular' && first < 1) + first = 1; + + if (this.inTail && back) { + pos += this.tail; + this.inTail = false; + } + + this.tail = null; + if (this.options.wrap != 'circular' && last == this.options.size && (last - visible + 1) >= 1) { + var m = $jc.margin(this.get(last), !this.options.vertical ? 'marginRight' : 'marginBottom'); + if ((v - m) > clipping) + this.tail = v - clipping - m; + } + + // Adjust position + while (i-- > first) + pos += this.dimension(this.get(i)); + + // Save visible item range + this.prevFirst = this.first; + this.prevLast = this.last; + this.first = first; + this.last = last; + + return pos; + }, + + /** + * Animates the carousel to a certain position. + * + * @method animate + * @return undefined + * @param p {Number} Position to scroll to. + * @param a {Boolean} Flag indicating whether to perform animation. + */ + animate: function(p, a) { + if (this.locked || this.animating) + return; + + this.animating = true; + + var self = this; + var scrolled = function() { + self.animating = false; + + if (p == 0) + self.list.css(self.lt, 0); + + if (self.options.wrap == 'circular' || self.options.wrap == 'both' || self.options.wrap == 'last' || self.options.size == null || self.last < self.options.size) + self.startAuto(); + + self.buttons(); + self.notify('onAfterAnimation'); + + // This function removes items which are appended automatically for circulation. + // This prevents the list from growing infinitely. + if (self.options.wrap == 'circular' && self.options.size !== null) + for (var i = self.prevFirst; i <= self.prevLast; i++) + if (i !== null && !(i >= self.first && i <= self.last) && (i < 1 || i > self.options.size)) + self.remove(i); + }; + + this.notify('onBeforeAnimation'); + + // Animate + if (!this.options.animation || a == false) { + this.list.css(this.lt, p + 'px'); + scrolled(); + } else { + var o = !this.options.vertical ? (this.options.rtl ? {'right': p} : {'left': p}) : {'top': p}; + this.list.animate(o, this.options.animation, this.options.easing, scrolled); + } + }, + + /** + * Starts autoscrolling. + * + * @method auto + * @return undefined + * @param s {Number} Seconds to periodically autoscroll the content. + */ + startAuto: function(s) { + if (s != undefined) + this.options.auto = s; + + if (this.options.auto == 0) + return this.stopAuto(); + + if (this.timer != null) + return; + + var self = this; + this.timer = setTimeout(function() { self.next(); }, this.options.auto * 1000); + }, + + /** + * Stops autoscrolling. + * + * @method stopAuto + * @return undefined + */ + stopAuto: function() { + if (this.timer == null) + return; + + clearTimeout(this.timer); + this.timer = null; + }, + + /** + * Sets the states of the prev/next buttons. + * + * @method buttons + * @return undefined + */ + buttons: function(n, p) { + if (n == undefined || n == null) { + var n = !this.locked && this.options.size !== 0 && ((this.options.wrap && this.options.wrap != 'first') || this.options.size == null || this.last < this.options.size); + if (!this.locked && (!this.options.wrap || this.options.wrap == 'first') && this.options.size != null && this.last >= this.options.size) + n = this.tail != null && !this.inTail; + } + + if (p == undefined || p == null) { + var p = !this.locked && this.options.size !== 0 && ((this.options.wrap && this.options.wrap != 'last') || this.first > 1); + if (!this.locked && (!this.options.wrap || this.options.wrap == 'last') && this.options.size != null && this.first == 1) + p = this.tail != null && this.inTail; + } + + var self = this; + + this.buttonNext[n ? 'bind' : 'unbind'](this.options.buttonNextEvent + '.jcarousel', this.funcNext)[n ? 'removeClass' : 'addClass'](this.className('jcarousel-next-disabled')).attr('disabled', n ? false : true); + this.buttonPrev[p ? 'bind' : 'unbind'](this.options.buttonPrevEvent + '.jcarousel', this.funcPrev)[p ? 'removeClass' : 'addClass'](this.className('jcarousel-prev-disabled')).attr('disabled', p ? false : true); + + if (this.options.buttonNextCallback != null && this.buttonNext.data('jcarouselstate') != n) { + this.buttonNext.each(function() { self.options.buttonNextCallback(self, this, n); }).data('jcarouselstate', n); + } + + if (this.options.buttonPrevCallback != null && (this.buttonPrev.data('jcarouselstate') != p)) { + this.buttonPrev.each(function() { self.options.buttonPrevCallback(self, this, p); }).data('jcarouselstate', p); + } + }, + + /** + * Notify callback of a specified event. + * + * @method notify + * @return undefined + * @param evt {String} The event name + */ + notify: function(evt) { + var state = this.prevFirst == null ? 'init' : (this.prevFirst < this.first ? 'next' : 'prev'); + + // Load items + this.callback('itemLoadCallback', evt, state); + + if (this.prevFirst !== this.first) { + this.callback('itemFirstInCallback', evt, state, this.first); + this.callback('itemFirstOutCallback', evt, state, this.prevFirst); + } + + if (this.prevLast !== this.last) { + this.callback('itemLastInCallback', evt, state, this.last); + this.callback('itemLastOutCallback', evt, state, this.prevLast); + } + + this.callback('itemVisibleInCallback', evt, state, this.first, this.last, this.prevFirst, this.prevLast); + this.callback('itemVisibleOutCallback', evt, state, this.prevFirst, this.prevLast, this.first, this.last); + }, + + callback: function(cb, evt, state, i1, i2, i3, i4) { + if (this.options[cb] == undefined || (typeof this.options[cb] != 'object' && evt != 'onAfterAnimation')) + return; + + var callback = typeof this.options[cb] == 'object' ? this.options[cb][evt] : this.options[cb]; + + if (!$.isFunction(callback)) + return; + + var self = this; + + if (i1 === undefined) + callback(self, state, evt); + else if (i2 === undefined) + this.get(i1).each(function() { callback(self, this, i1, state, evt); }); + else { + for (var i = i1; i <= i2; i++) + if (i !== null && !(i >= i3 && i <= i4)) + this.get(i).each(function() { callback(self, this, i, state, evt); }); + } + }, + + create: function(i) { + return this.format('
  • ', i); + }, + + format: function(e, i) { + var e = $(e), split = e.get(0).className.split(' '); + for (var j = 0; j < split.length; j++) { + if (split[j].indexOf('jcarousel-') != -1) { + e.removeClass(split[j]); + } + } + e.addClass(this.className('jcarousel-item')).addClass(this.className('jcarousel-item-' + i)).css({ + 'float': (this.options.rtl ? 'right' : 'left'), + 'list-style': 'none' + }).attr('jcarouselindex', i); + return e; + }, + + className: function(c) { + return c + ' ' + c + (!this.options.vertical ? '-horizontal' : '-vertical'); + }, + + dimension: function(e, d) { + var el = e.jquery != undefined ? e[0] : e; + + var old = !this.options.vertical ? + (el.offsetWidth || $jc.intval(this.options.itemFallbackDimension)) + $jc.margin(el, 'marginLeft') + $jc.margin(el, 'marginRight') : + (el.offsetHeight || $jc.intval(this.options.itemFallbackDimension)) + $jc.margin(el, 'marginTop') + $jc.margin(el, 'marginBottom'); + + if (d == undefined || old == d) + return old; + + var w = !this.options.vertical ? + d - $jc.margin(el, 'marginLeft') - $jc.margin(el, 'marginRight') : + d - $jc.margin(el, 'marginTop') - $jc.margin(el, 'marginBottom'); + + $(el).css(this.wh, w + 'px'); + + return this.dimension(el); + }, + + clipping: function() { + return !this.options.vertical ? + this.clip[0].offsetWidth - $jc.intval(this.clip.css('borderLeftWidth')) - $jc.intval(this.clip.css('borderRightWidth')) : + this.clip[0].offsetHeight - $jc.intval(this.clip.css('borderTopWidth')) - $jc.intval(this.clip.css('borderBottomWidth')); + }, + + index: function(i, s) { + if (s == undefined) + s = this.options.size; + + return Math.round((((i-1) / s) - Math.floor((i-1) / s)) * s) + 1; + } + }); + + $jc.extend({ + /** + * Gets/Sets the global default configuration properties. + * + * @method defaults + * @return {Object} + * @param d {Object} A set of key/value pairs to set as configuration properties. + */ + defaults: function(d) { + return $.extend(defaults, d || {}); + }, + + margin: function(e, p) { + if (!e) + return 0; + + var el = e.jquery != undefined ? e[0] : e; + + if (p == 'marginRight' && $.browser.safari) { + var old = {'display': 'block', 'float': 'none', 'width': 'auto'}, oWidth, oWidth2; + + $.swap(el, old, function() { oWidth = el.offsetWidth; }); + + old['marginRight'] = 0; + $.swap(el, old, function() { oWidth2 = el.offsetWidth; }); + + return oWidth2 - oWidth; + } + + return $jc.intval($.css(el, p)); + }, + + intval: function(v) { + v = parseInt(v); + return isNaN(v) ? 0 : v; + } + }); + +})(jQuery); diff --git a/modules/navcarousel/js/jquery.jcarousel.min.js b/modules/navcarousel/js/jquery.jcarousel.min.js index f7c76886..0b8313ad 100644 --- a/modules/navcarousel/js/jquery.jcarousel.min.js +++ b/modules/navcarousel/js/jquery.jcarousel.min.js @@ -11,8 +11,6 @@ * * Inspired by the "Carousel Component" by Bill Scott * http://billwscott.com/carousel/ - * - * RTLed by nightS @ RTL-This - * http://rtl-this.com/tutorial/rtling-jcarousel-jquery-plugin */ -(function($){$.fn.jcarousel=function(o){if(typeof o=='string'){var instance=$(this).data('jcarousel'),args=Array.prototype.slice.call(arguments,1);return instance[o].apply(instance,args)}else return this.each(function(){$(this).data('jcarousel',new $jc(this,o))})};var defaults={vertical:false,horizontalDirection:'ltr',start:1,offset:1,size:null,scroll:3,visible:null,animation:'normal',easing:'swing',auto:0,wrap:null,initCallback:null,reloadCallback:null,itemLoadCallback:null,itemFirstInCallback:null,itemFirstOutCallback:null,itemLastInCallback:null,itemLastOutCallback:null,itemVisibleInCallback:null,itemVisibleOutCallback:null,buttonNextHTML:'
    ',buttonPrevHTML:'
    ',buttonNextEvent:'click',buttonPrevEvent:'click',buttonNextCallback:null,buttonPrevCallback:null};$.jcarousel=function(e,o){this.options=$.extend({},defaults,o||{});this.locked=false;this.container=null;this.clip=null;this.list=null;this.buttonNext=null;this.buttonPrev=null;this.wh=!this.options.vertical?'width':'height';this.lt=!this.options.vertical?(this.options.horizontalDirection=='rtl'?'right':'left'):'top';var skin='',split=e.className.split(' ');for(var i=0;i');this.container=this.container.parent()}else if(!this.container.hasClass('jcarousel-container'))this.container=this.list.wrap('
    ').parent()}else{this.container=$(e);this.list=this.container.find('ul,ol').eq(0)}if(skin!=''&&this.container.parent()[0].className.indexOf('jcarousel-skin')==-1)this.container.wrap('
    ');this.clip=this.list.parent();if(!this.clip.length||!this.clip.hasClass('jcarousel-clip'))this.clip=this.list.wrap('
    ').parent();this.buttonNext=$('.jcarousel-next',this.container);if(this.buttonNext.size()==0&&this.options.buttonNextHTML!=null)this.buttonNext=this.clip.after(this.options.buttonNextHTML).next();this.buttonNext.addClass(this.className('jcarousel-next'));this.buttonPrev=$('.jcarousel-prev',this.container);if(this.buttonPrev.size()==0&&this.options.buttonPrevHTML!=null)this.buttonPrev=this.clip.after(this.options.buttonPrevHTML).next();this.buttonPrev.addClass(this.className('jcarousel-prev'));this.clip.addClass(this.className('jcarousel-clip')).css({overflow:'hidden',position:'relative'});this.list.addClass(this.className('jcarousel-list')).css({overflow:'hidden',position:'relative',top:0,left:0,margin:0,padding:0});this.container.addClass(this.className('jcarousel-container')).addClass(!this.options.vertical?'jcarousel-direction-'+this.options.horizontalDirection:'').css({position:'relative'});var di=this.options.visible!=null?Math.ceil(this.clipping()/this.options.visible):null;var li=this.list.children('li');var self=this;if(li.size()>0){var wh=0,i=this.options.offset;li.each(function(){self.format(this,i++);wh+=self.dimension(this,di)});this.list.css(this.wh,wh+'px');if(!o||o.size===undefined)this.options.size=li.size()}this.container.css('display','block');this.buttonNext.css('display','block');this.buttonPrev.css('display','block');this.funcNext=function(){self.next()};this.funcPrev=function(){self.prev()};this.funcResize=function(){self.reload()};if(this.options.initCallback!=null)this.options.initCallback(this,'init');if($.browser.safari){this.buttons(false,false);$(window).bind('load.jcarousel',function(){self.setup()})}else this.setup()};var $jc=$.jcarousel;$jc.fn=$jc.prototype={jcarousel:'0.2.4'};$jc.fn.extend=$jc.extend=$.extend;$jc.fn.extend({setup:function(){this.first=null;this.last=null;this.prevFirst=null;this.prevLast=null;this.animating=false;this.timer=null;this.tail=null;this.inTail=false;if(this.locked)return;this.list.css(this.lt,this.pos(this.options.offset)+'px');var p=this.pos(this.options.start);this.prevFirst=this.prevLast=null;this.animate(p,false);$(window).unbind('resize.jcarousel',this.funcResize).bind('resize.jcarousel',this.funcResize)},reset:function(){this.list.empty();this.list.css(this.lt,'0px');this.list.css(this.wh,'10px');if(this.options.initCallback!=null)this.options.initCallback(this,'reset');this.setup()},reload:function(){if(this.tail!=null&&this.inTail)this.list.css(this.lt,$jc.intval(this.list.css(this.lt))+this.tail);this.tail=null;this.inTail=false;if(this.options.reloadCallback!=null)this.options.reloadCallback(this);if(this.options.visible!=null){var self=this;var di=Math.ceil(this.clipping()/this.options.visible),wh=0,lt=0;$('li',this.list).each(function(i){wh+=self.dimension(this,di);if(i+1this.options.size)i2=this.options.size;for(var j=i;j<=i2;j++){var e=this.get(j);if(!e.length||e.hasClass('jcarousel-item-placeholder'))return false}return true},get:function(i){return $('.jcarousel-item-'+i,this.list)},add:function(i,s){var e=this.get(i),old=0,add=0;if(e.length==0){var c,e=this.create(i),j=$jc.intval(i);while(c=this.get(--j)){if(j<=0||c.length){j<=0?this.list.prepend(e):c.after(e);break}}}else old=this.dimension(e);e.removeClass(this.className('jcarousel-item-placeholder'));typeof s=='string'?e.html(s):e.empty().append(s);var di=this.options.visible!=null?Math.ceil(this.clipping()/this.options.visible):null;var wh=this.dimension(e,di)-old;if(i>0&&i=this.first&&i<=this.last))return;var d=this.dimension(e);if(ithis.options.size?this.options.size:i);var back=this.first>i;var f=this.options.wrap!='circular'&&this.first<=1?1:this.first;var c=back?this.get(f):this.get(this.last);var j=back?f:f-1;var e=null,l=0,p=false,d=0,g;while(back?--j>=i:++jthis.options.size)){g=this.get(this.index(j));if(g.length)this.add(j,g.children().clone(true))}}c=e;d=this.dimension(e);if(p)l+=d;if(this.first!=null&&(this.options.wrap=='circular'||(j>=1&&(this.options.size==null||j<=this.options.size))))pos=back?pos+d:pos-d}var clipping=this.clipping();var cache=[];var visible=0,j=i,v=0;var c=this.get(i-1);while(++visible){e=this.get(j);p=!e.length;if(e.length==0){e=this.create(j).addClass(this.className('jcarousel-item-placeholder'));c.length==0?this.list.prepend(e):c[back?'before':'after'](e);if(this.first!=null&&this.options.wrap=='circular'&&this.options.size!==null&&(j<=0||j>this.options.size)){g=this.get(this.index(j));if(g.length)this.add(j,g.find('>*').clone(true))}}c=e;var d=this.dimension(e);if(d==0){alert('jCarousel: No width/height set for items. This will cause an infinite loop. Aborting...');return 0}if(this.options.wrap!='circular'&&this.options.size!==null&&j>this.options.size)cache.push(e);else if(p)l+=d;v+=d;if(v>=clipping)break;j++}for(var x=0;x0){this.list.css(this.wh,this.dimension(this.list)+l+'px');if(back){pos-=l;this.list.css(this.lt,$jc.intval(this.list.css(this.lt))-l+'px')}}var last=i+visible-1;if(this.options.wrap!='circular'&&this.options.size&&last>this.options.size)last=this.options.size;if(j>last){visible=0,j=last,v=0;while(++visible){var e=this.get(j--);if(!e.length)break;v+=this.dimension(e);if(v>=clipping)break}}var first=last-visible+1;if(this.options.wrap!='circular'&&first<1)first=1;if(this.inTail&&back){pos+=this.tail;this.inTail=false}this.tail=null;if(this.options.wrap!='circular'&&last==this.options.size&&(last-visible+1)>=1){var m=$jc.margin(this.get(last),!this.options.vertical?'marginRight':'marginBottom');if((v-m)>clipping)this.tail=v-clipping-m}while(i-->first)pos+=this.dimension(this.get(i));this.prevFirst=this.first;this.prevLast=this.last;this.first=first;this.last=last;return pos},animate:function(p,a){if(this.locked||this.animating)return;this.animating=true;var self=this;var scrolled=function(){self.animating=false;if(p==0)self.list.css(self.lt,0);if(self.options.wrap=='circular'||self.options.wrap=='both'||self.options.wrap=='last'||self.options.size==null||self.last=this.options.size)n=this.tail!=null&&this.inTail}if(p==undefined||p==null){var p=!this.locked&&this.options.size!==0&&((this.options.wrap&&this.options.wrap!='last')||this.first>1);if(!this.locked&&(!this.options.wrap||this.options.wrap=='last')&&this.options.size!=null&&this.first==1)p=this.tail!=null&&this.inTail}var self=this;this.buttonNext[n?'bind':'unbind'](this.options.buttonNextEvent+'.jcarousel',this.funcNext)[n?'removeClass':'addClass'](this.className('jcarousel-next-disabled')).attr('disabled',n?false:true);this.buttonPrev[p?'bind':'unbind'](this.options.buttonPrevEvent+'.jcarousel',this.funcPrev)[p?'removeClass':'addClass'](this.className('jcarousel-prev-disabled')).attr('disabled',p?false:true);if(this.buttonNext.length>0&&(this.buttonNext[0].jcarouselstate==undefined||this.buttonNext[0].jcarouselstate!=n)&&this.options.buttonNextCallback!=null){this.buttonNext.each(function(){self.options.buttonNextCallback(self,this,n)});this.buttonNext[0].jcarouselstate=n}if(this.buttonPrev.length>0&&(this.buttonPrev[0].jcarouselstate==undefined||this.buttonPrev[0].jcarouselstate!=p)&&this.options.buttonPrevCallback!=null){this.buttonPrev.each(function(){self.options.buttonPrevCallback(self,this,p)});this.buttonPrev[0].jcarouselstate=p}},notify:function(evt){var state=this.prevFirst==null?'init':(this.prevFirst=i3&&i<=i4))this.get(i).each(function(){callback(self,this,i,state,evt)})}},create:function(i){return this.format('
  • ',i)},format:function(e,i){var $e=$(e).addClass(this.className('jcarousel-item')).addClass(this.className('jcarousel-item-'+i)).css({'float':(this.options.horizontalDirection=='rtl'?'right':'left'),'list-style':'none'});$e.attr('jcarouselindex',i);return $e},className:function(c){return c+' '+c+(!this.options.vertical?'-horizontal':'-vertical')},dimension:function(e,d){var el=e.jquery!=undefined?e[0]:e;var old=!this.options.vertical?el.offsetWidth+$jc.margin(el,'marginLeft')+$jc.margin(el,'marginRight'):el.offsetHeight+$jc.margin(el,'marginTop')+$jc.margin(el,'marginBottom');if(d==undefined||old==d)return old;var w=!this.options.vertical?d-$jc.margin(el,'marginLeft')-$jc.margin(el,'marginRight'):d-$jc.margin(el,'marginTop')-$jc.margin(el,'marginBottom');$(el).css(this.wh,w+'px');return this.dimension(el)},clipping:function(){return!this.options.vertical?this.clip[0].offsetWidth-$jc.intval(this.clip.css('borderLeftWidth'))-$jc.intval(this.clip.css('borderRightWidth')):this.clip[0].offsetHeight-$jc.intval(this.clip.css('borderTopWidth'))-$jc.intval(this.clip.css('borderBottomWidth'))},index:function(i,s){if(s==undefined)s=this.options.size;return Math.round((((i-1)/s)-Math.floor((i-1)/s))*s)+1}});$jc.extend({defaults:function(d){return $.extend(defaults,d||{})},margin:function(e,p){if(!e)return 0;var el=e.jquery!=undefined?e[0]:e;if(p=='marginRight'&&$.browser.safari){var old={'display':'block','float':'none','width':'auto'},oWidth,oWidth2;$.swap(el,old,function(){oWidth=el.offsetWidth});old['marginRight']=0;$.swap(el,old,function(){oWidth2=el.offsetWidth});return oWidth2-oWidth}return $jc.intval($.css(el,p))},intval:function(v){v=parseInt(v);return isNaN(v)?0:v}})})(jQuery); + +(function(i){i.fn.jcarousel=function(a){if(typeof a=="string"){var c=i(this).data("jcarousel"),b=Array.prototype.slice.call(arguments,1);return c[a].apply(c,b)}else return this.each(function(){i(this).data("jcarousel",new h(this,a))})};var p={vertical:false,rtl:false,start:1,offset:1,size:null,scroll:3,visible:null,animation:"normal",easing:"swing",auto:0,wrap:null,initCallback:null,reloadCallback:null,itemLoadCallback:null,itemFirstInCallback:null,itemFirstOutCallback:null,itemLastInCallback:null, itemLastOutCallback:null,itemVisibleInCallback:null,itemVisibleOutCallback:null,buttonNextHTML:"
    ",buttonPrevHTML:"
    ",buttonNextEvent:"click",buttonPrevEvent:"click",buttonNextCallback:null,buttonPrevCallback:null,itemFallbackDimension:null},q=false;i(window).bind("load.jcarousel",function(){q=true});i.jcarousel=function(a,c){this.options=i.extend({},p,c||{});this.locked=false;this.buttonPrev=this.buttonNext=this.list=this.clip=this.container=null;if(!c||c.rtl===undefined)this.options.rtl= (i(a).attr("dir")||i("html").attr("dir")||"").toLowerCase()=="rtl";this.wh=!this.options.vertical?"width":"height";this.lt=!this.options.vertical?this.options.rtl?"right":"left":"top";for(var b="",d=a.className.split(" "),e=0;e");this.container=this.container.parent()}else if(!this.container.hasClass("jcarousel-container"))this.container=this.list.wrap("
    ").parent()}else{this.container=i(a);this.list=this.container.find("ul,ol").eq(0)}b!=""&&this.container.parent()[0].className.indexOf("jcarousel-skin")==-1&&this.container.wrap('
    ');this.clip=this.list.parent();if(!this.clip.length||!this.clip.hasClass("jcarousel-clip"))this.clip=this.list.wrap("
    ").parent(); this.buttonNext=i(".jcarousel-next",this.container);if(this.buttonNext.size()==0&&this.options.buttonNextHTML!=null)this.buttonNext=this.clip.after(this.options.buttonNextHTML).next();this.buttonNext.addClass(this.className("jcarousel-next"));this.buttonPrev=i(".jcarousel-prev",this.container);if(this.buttonPrev.size()==0&&this.options.buttonPrevHTML!=null)this.buttonPrev=this.clip.after(this.options.buttonPrevHTML).next();this.buttonPrev.addClass(this.className("jcarousel-prev"));this.clip.addClass(this.className("jcarousel-clip")).css({overflow:"hidden", position:"relative"});this.list.addClass(this.className("jcarousel-list")).css({overflow:"hidden",position:"relative",top:0,margin:0,padding:0}).css(this.options.rtl?"right":"left",0);this.container.addClass(this.className("jcarousel-container")).css({position:"relative"});!this.options.vertical&&this.options.rtl&&this.container.addClass("jcarousel-direction-rtl").attr("dir","rtl");var f=this.options.visible!=null?Math.ceil(this.clipping()/this.options.visible):null;b=this.list.children("li");var g= this;if(b.size()>0){var j=0;e=this.options.offset;b.each(function(){g.format(this,e++);j+=g.dimension(this,f)});this.list.css(this.wh,j+100+"px");if(!c||c.size===undefined)this.options.size=b.size()}this.container.css("display","block");this.buttonNext.css("display","block");this.buttonPrev.css("display","block");this.funcNext=function(){g.next()};this.funcPrev=function(){g.prev()};this.funcResize=function(){g.reload()};this.options.initCallback!=null&&this.options.initCallback(this,"init");if(!q&& i.browser.safari){this.buttons(false,false);i(window).bind("load.jcarousel",function(){g.setup()})}else this.setup()};var h=i.jcarousel;h.fn=h.prototype={jcarousel:"0.2.5"};h.fn.extend=h.extend=i.extend;h.fn.extend({setup:function(){this.prevLast=this.prevFirst=this.last=this.first=null;this.animating=false;this.tail=this.timer=null;this.inTail=false;if(!this.locked){this.list.css(this.lt,this.pos(this.options.offset)+"px");var a=this.pos(this.options.start);this.prevFirst=this.prevLast=null;this.animate(a, false);i(window).unbind("resize.jcarousel",this.funcResize).bind("resize.jcarousel",this.funcResize)}},reset:function(){this.list.empty();this.list.css(this.lt,"0px");this.list.css(this.wh,"10px");this.options.initCallback!=null&&this.options.initCallback(this,"reset");this.setup()},reload:function(){this.tail!=null&&this.inTail&&this.list.css(this.lt,h.intval(this.list.css(this.lt))+this.tail);this.tail=null;this.inTail=false;this.options.reloadCallback!=null&&this.options.reloadCallback(this);if(this.options.visible!= null){var a=this,c=Math.ceil(this.clipping()/this.options.visible),b=0,d=0;this.list.children("li").each(function(e){b+=a.dimension(this,c);if(e+1this.options.size)c=this.options.size;for(var b=a;b<=c;b++){var d=this.get(b);if(!d.length||d.hasClass("jcarousel-item-placeholder"))return false}return true},get:function(a){return i(".jcarousel-item-"+a,this.list)},add:function(a,c){var b=this.get(a),d=0,e=i(c);if(b.length==0){var f;b=this.create(a);for(var g=h.intval(a);f=this.get(--g);)if(g<=0||f.length){g<=0?this.list.prepend(b):f.after(b);break}}else d=this.dimension(b);if(e.get(0).nodeName.toUpperCase()=="LI"){b.replaceWith(e); b=e}else b.empty().append(c);this.format(b.removeClass(this.className("jcarousel-item-placeholder")),a);e=this.options.visible!=null?Math.ceil(this.clipping()/this.options.visible):null;d=this.dimension(b,e)-d;a>0&&a=this.first&&a<=this.last)){var b=this.dimension(c);athis.options.size?this.options.size:a;for(var b=this.first>a,d=this.options.wrap!="circular"&&this.first<=1?1:this.first,e=b?this.get(d):this.get(this.last),f=b?d:d-1,g=null,j=0,l=false,k=0;b?--f>=a:++fthis.options.size)){e=this.get(this.index(f)); if(e.length)g=this.add(f,e.clone(true))}}e=g;k=this.dimension(g);if(l)j+=k;if(this.first!=null&&(this.options.wrap=="circular"||f>=1&&(this.options.size==null||f<=this.options.size)))c=b?c+k:c-k}d=this.clipping();var o=[],n=0;f=a;var m=0;for(e=this.get(a-1);++n;){g=this.get(f);l=!g.length;if(g.length==0){g=this.create(f).addClass(this.className("jcarousel-item-placeholder"));e.length==0?this.list.prepend(g):e[b?"before":"after"](g);if(this.first!=null&&this.options.wrap=="circular"&&this.options.size!== null&&(f<=0||f>this.options.size)){e=this.get(this.index(f));if(e.length)g=this.add(f,e.clone(true))}}e=g;k=this.dimension(g);if(k==0)throw Error("jCarousel: No width/height set for items. This will cause an infinite loop. Aborting...");if(this.options.wrap!="circular"&&this.options.size!==null&&f>this.options.size)o.push(g);else if(l)j+=k;m+=k;if(m>=d)break;f++}for(g=0;g0){this.list.css(this.wh,this.dimension(this.list)+j+"px");if(b){c-=j;this.list.css(this.lt,h.intval(this.list.css(this.lt))- j+"px")}}j=a+n-1;if(this.options.wrap!="circular"&&this.options.size&&j>this.options.size)j=this.options.size;if(f>j){n=0;f=j;for(m=0;++n;){g=this.get(f--);if(!g.length)break;m+=this.dimension(g);if(m>=d)break}}f=j-n+1;if(this.options.wrap!="circular"&&f<1)f=1;if(this.inTail&&b){c+=this.tail;this.inTail=false}this.tail=null;if(this.options.wrap!="circular"&&j==this.options.size&&j-n+1>=1){b=h.margin(this.get(j),!this.options.vertical?"marginRight":"marginBottom");if(m-b>d)this.tail=m-d-b}for(;a-- > f;)c+=this.dimension(this.get(a));this.prevFirst=this.first;this.prevLast=this.last;this.first=f;this.last=j;return c},animate:function(a,c){if(!(this.locked||this.animating)){this.animating=true;var b=this,d=function(){b.animating=false;a==0&&b.list.css(b.lt,0);if(b.options.wrap=="circular"||b.options.wrap=="both"||b.options.wrap=="last"||b.options.size==null||b.last=b.first&&e<=b.last)&&(e<1||e>b.options.size))b.remove(e)};this.notify("onBeforeAnimation");if(!this.options.animation||c==false){this.list.css(this.lt,a+"px");d()}else this.list.animate(!this.options.vertical?this.options.rtl?{right:a}:{left:a}:{top:a},this.options.animation,this.options.easing,d)}},startAuto:function(a){if(a!=undefined)this.options.auto=a;if(this.options.auto==0)return this.stopAuto();if(this.timer==null){var c=this;this.timer=setTimeout(function(){c.next()}, this.options.auto*1E3)}},stopAuto:function(){if(this.timer!=null){clearTimeout(this.timer);this.timer=null}},buttons:function(a,c){if(a==undefined||a==null){a=!this.locked&&this.options.size!==0&&(this.options.wrap&&this.options.wrap!="first"||this.options.size==null||this.last=this.options.size)a=this.tail!=null&&!this.inTail}if(c==undefined||c==null){c=!this.locked&&this.options.size!== 0&&(this.options.wrap&&this.options.wrap!="last"||this.first>1);if(!this.locked&&(!this.options.wrap||this.options.wrap=="last")&&this.options.size!=null&&this.first==1)c=this.tail!=null&&this.inTail}var b=this;this.buttonNext[a?"bind":"unbind"](this.options.buttonNextEvent+".jcarousel",this.funcNext)[a?"removeClass":"addClass"](this.className("jcarousel-next-disabled")).attr("disabled",a?false:true);this.buttonPrev[c?"bind":"unbind"](this.options.buttonPrevEvent+".jcarousel",this.funcPrev)[c?"removeClass": "addClass"](this.className("jcarousel-prev-disabled")).attr("disabled",c?false:true);this.options.buttonNextCallback!=null&&this.buttonNext.data("jcarouselstate")!=a&&this.buttonNext.each(function(){b.options.buttonNextCallback(b,this,a)}).data("jcarouselstate",a);this.options.buttonPrevCallback!=null&&this.buttonPrev.data("jcarouselstate")!=c&&this.buttonPrev.each(function(){b.options.buttonPrevCallback(b,this,c)}).data("jcarouselstate",c)},notify:function(a){var c=this.prevFirst==null?"init":this.prevFirst< this.first?"next":"prev";this.callback("itemLoadCallback",a,c);if(this.prevFirst!==this.first){this.callback("itemFirstInCallback",a,c,this.first);this.callback("itemFirstOutCallback",a,c,this.prevFirst)}if(this.prevLast!==this.last){this.callback("itemLastInCallback",a,c,this.last);this.callback("itemLastOutCallback",a,c,this.prevLast)}this.callback("itemVisibleInCallback",a,c,this.first,this.last,this.prevFirst,this.prevLast);this.callback("itemVisibleOutCallback",a,c,this.prevFirst,this.prevLast, this.first,this.last)},callback:function(a,c,b,d,e,f,g){if(!(this.options[a]==undefined||typeof this.options[a]!="object"&&c!="onAfterAnimation")){var j=typeof this.options[a]=="object"?this.options[a][c]:this.options[a];if(i.isFunction(j)){var l=this;if(d===undefined)j(l,b,c);else if(e===undefined)this.get(d).each(function(){j(l,this,d,b,c)});else for(var k=d;k<=e;k++)k!==null&&!(k>=f&&k<=g)&&this.get(k).each(function(){j(l,this,k,b,c)})}}},create:function(a){return this.format("
  • ",a)},format:function(a, c){a=i(a);for(var b=a.get(0).className.split(" "),d=0;did", "", "post", array("id" => "g-edit-movie-form")); + $form->hidden("from_id")->value($movie->id); + $group = $form->group("edit_item")->label(t("Edit Movie")); + $group->input("title")->label(t("Title"))->value($movie->title) + ->error_messages("required", t("You must provide a title")) + ->error_messages("length", t("Your title is too long")); + $group->textarea("description")->label(t("Description"))->value($movie->description); + $group->input("name")->label(t("Filename"))->value($movie->name) + ->error_messages( + "conflict", t("There is already a movie, photo or album with this name")) + ->error_messages("no_slashes", t("The movie name can't contain a \"/\"")) + ->error_messages("no_trailing_period", t("The movie name can't end in \".\"")) + ->error_messages("illegal_data_file_extension", t("You cannot change the movie file extension")) + ->error_messages("required", t("You must provide a movie file name")) + ->error_messages("length", t("Your movie file name is too long")); + $group->input("slug")->label(t("Internet Address"))->value($movie->slug) + ->error_messages( + "conflict", t("There is already a movie, photo or album with this internet address")) + ->error_messages( + "not_url_safe", + t("The internet address should contain only letters, numbers, hyphens and underscores")) + ->error_messages("required", t("You must provide an internet address")) + ->error_messages("length", t("Your internet address is too long")); + + module::event("item_edit_form", $movie, $form); + + $group = $form->group("buttons")->label(""); + $group->submit("")->value(t("Modify")); + + return $form; + } + + static function extract_frame($input_file, $output_file) { + $ffmpeg = self::find_ffmpeg(); + if (empty($ffmpeg)) { + // BEGIN rWatcher Edit. + copy(MODPATH . "noffmpeg/images/missing_movie.png", $output_file); + //throw new Exception("@todo MISSING_FFMPEG"); + // END rWatcher Edit. + } + + $cmd = escapeshellcmd($ffmpeg) . " -i " . escapeshellarg($input_file) . + " -an -ss 00:00:03 -an -r 1 -vframes 1" . + " -y -f mjpeg " . escapeshellarg($output_file) . " 2>&1"; + exec($cmd); + + clearstatcache(); // use $filename parameter when PHP_version is 5.3+ + if (filesize($output_file) == 0) { + // Maybe the movie is shorter, fall back to the first frame. + $cmd = escapeshellcmd($ffmpeg) . " -i " . escapeshellarg($input_file) . + " -an -an -r 1 -vframes 1" . + " -y -f mjpeg " . escapeshellarg($output_file) . " 2>&1"; + exec($cmd); + + clearstatcache(); + if (filesize($output_file) == 0) { + throw new Exception("@todo FFMPEG_FAILED"); + } + } + } + + static function find_ffmpeg() { + if (!($ffmpeg_path = module::get_var("gallery", "ffmpeg_path")) || !file_exists($ffmpeg_path)) { + $graphics_path = module::get_var("gallery", "graphics_toolkit_path", null); + + putenv("PATH=" . getenv("PATH") . (empty($graphics_path) ? "" : ":$graphics_path") . + ":/usr/local/bin:/opt/local/bin:/opt/bin"); + if (function_exists("exec")) { + $ffmpeg_path = exec("which ffmpeg"); + } + + module::set_var("gallery", "ffmpeg_path", $ffmpeg_path); + } + return $ffmpeg_path; + } + + + /** + * Return the width, height, mime_type and extension of the given movie file. + */ + static function get_file_metadata($file_path) { + $ffmpeg = self::find_ffmpeg(); + if (empty($ffmpeg)) { + // BEGIN rWatcher Edit. + $pi = pathinfo($file_path); + $extension = isset($pi["extension"]) ? $pi["extension"] : "flv"; // No extension? Assume FLV. + $mime_type = in_array(strtolower($extension), array("mp4", "m4v")) ? + "video/mp4" : "video/x-flv"; + $vid_width = 320; + $vid_height = 240; + if (strtolower($extension) == "flv") { + $flvinfo = new FLVMetaData($file_path); + $info = $flvinfo->getMetaData(); + if (($info["width"] != "") && ($info["height"] != "")) { + $vid_width = $info["width"]; + $vid_height = $info["height"]; + } + } + return array($vid_width, $vid_height, $mime_type, $extension); + //throw new Exception("@todo MISSING_FFMPEG"); + // END rWatcher Edit. + } + + $cmd = escapeshellcmd($ffmpeg) . " -i " . escapeshellarg($file_path) . " 2>&1"; + $result = `$cmd`; + if (preg_match("/Stream.*?Video:.*?(\d+)x(\d+)/", $result, $regs)) { + list ($width, $height) = array($regs[1], $regs[2]); + } else { + list ($width, $height) = array(0, 0); + } + + $pi = pathinfo($file_path); + $extension = isset($pi["extension"]) ? $pi["extension"] : "flv"; // No extension? Assume FLV. + $mime_type = in_array(strtolower($extension), array("mp4", "m4v")) ? + "video/mp4" : "video/x-flv"; + + return array($width, $height, $mime_type, $extension); + } + +} diff --git a/modules/noffmpeg/images/missing_movie.png b/modules/noffmpeg/images/missing_movie.png new file mode 100644 index 00000000..fdc97779 Binary files /dev/null and b/modules/noffmpeg/images/missing_movie.png differ diff --git a/modules/noffmpeg/libraries/FLVMetaData.php b/modules/noffmpeg/libraries/FLVMetaData.php new file mode 100644 index 00000000..bfd8e435 --- /dev/null +++ b/modules/noffmpeg/libraries/FLVMetaData.php @@ -0,0 +1,194 @@ +. + * + * @author Amin Saeedi, + * @copyright Copyright (c) 2009, Amin Saeedi + * @version 1.0 + * + */ +class FLVMetaData { + private $buffer; + private $metaData; + private $fileName; + private $typeFlagsAudio; + private $typeFlagsVideo; + + public $VCidMap = array( + 2=>"Sorenson H.263", + 3=>"Screen Video", + 4=>"VP6", + 5=>"VP6 with Alpha channel", + ); //Video Codec ID(s) + + public $ACidMap = array( + "Linear PCM, platform endian", + "ADPCM", + "MP3", + "Linear PCM, little endian", + "Nellymoser 16-kHz Mono", + "Nellymoser 8-kHz Mono", + "Nellymoser", + "G.711 A-law logarithmic PCM", + "G.711 mu-law logarithmic PCM", + "reserved", + "AAC", + "Speex", + 14=>"MP3 8-Khz", + 15=>"Device-specific sound" + ); //Audio Codec ID(s) + +/** + * CONSTRUCTOR : initialize class members + * + * @param string $flv : flv file path + */ + public function __construct($flv) { + $this->fileName = $flv; + $this->metaData = array( + "duration"=>null, + "size"=>null, + "framerate"=>null, + "width"=>null, + "height"=>null, + "videodatarate"=>null, + "audiodatarate"=>null, + "audiodelay"=>null, + "audiosamplesize"=>null, + "audiosamplerate"=>null, + "audiocodecid"=>null, + "videocodecid"=>null, + "version"=>null, + "headersize"=>0 + ); + } + +/** + * Gets metadata of FLV file + * + * @return array $this->metaData : matadata of FLV + */ + public function getMetaData(){ + if(!file_exists($this->fileName)){ + echo "Error! {$this->fileName} does not exist.
    "; + return false; + } + if(!is_readable($this->fileName)){ + echo "Error! Could not read the file. Check the file permissions.
    "; + return false; + } + $f = @fopen($this->fileName,"rb"); + if(!$f){ + echo "Unknown Error! Could not read the file.
    "; + return; + } + $signature = fread($f,3); + if($signature != "FLV"){ + echo "Error! Wrong file format."; + return false; + } + $this->metaData["version"] = ord(fread($f,1)); + $this->metaData["size"] = filesize($this->fileName); + + $flags = ord(fread($f,1)); + $flags = sprintf("%'04b", $flags); + $this->typeFlagsAudio = substr($flags, 1, 1); + $this->typeFlagsVideo = substr($flags, 3, 1); + + for ($i=0; $i < 4; $i++) { + $this->metaData["headersize"] += ord(fread($f,1)) ; + } + + $this->buffer = fread($f, 400); + fclose($f); + if(strpos($this->buffer, "onMetaData") === false){ + echo "Error! No MetaData Exists."; + return false; + } + + foreach($this->metaData as $k=>$v){ + $this->parseBuffer($k); + } + return $this->metaData; + } + +/** + * Takes a field name of metadata, retrieve it's value and set it in $this->metaData + * + * @param string $fieldName : matadata field name + */ + private function parseBuffer($fieldName){ + $fieldPos = strpos($this->buffer, $fieldName); //get the field position + if($fieldPos !== false){ + $pos = $fieldPos + strlen($fieldName) + 1; + $buffer = substr($this->buffer,$pos); + + $d = ""; + for($i=0; $i < 8;$i++){ + $d .= sprintf("%08b", ord(substr($buffer,$i,1))); + } + + $total = self::bin2Double($d); + $this->metaData[$fieldName] = $total; + } + } + +/** + * Calculates double-precision value of given binary string + * (IEEE Standard 754 - Floating Point Numbers) + * + * @param string binary data $strBin + * @return Float calculated double-precision number + */ + public static function bin2Double($strBin){ + $sb = substr($strBin, 0, 1); // first bit is sign bit + $exponent = substr($strBin, 1, 11); // 11 bits exponent + $fraction = "1".substr($strBin, 12, 52); //52 bits fraction (1.F) + + $s = pow(-1, bindec($sb)); + $dec = pow(2, (bindec($exponent) - 1023)); //Decode exponent + + if($dec == 2047){ + if($fraction == 0){ + if($s==0){ + echo "Infinity"; + }else{ + echo "-Infinity"; + } + }else{ + echo "NaN"; + } + } + + if($dec > 0 && $dec < 2047){ + $t = 1; + for($i=1 ; $i <= 53; $i++){ + $t += ((int)substr($fraction, $i, 1)) * pow(2, -$i); //decode significand + } + $total = $s * $t * $dec ; + return $total; + } + return false; + } +} +?> diff --git a/modules/noffmpeg/module.info b/modules/noffmpeg/module.info new file mode 100644 index 00000000..c11f0853 --- /dev/null +++ b/modules/noffmpeg/module.info @@ -0,0 +1,3 @@ +name = "NoFFMPEG" +description = "Allow video uploads on systems without FFMPEG." +version = 1 diff --git a/modules/photoannotation/controllers/admin_photoannotation.php b/modules/photoannotation/controllers/admin_photoannotation.php index bdcd71be..dc7436f6 100755 --- a/modules/photoannotation/controllers/admin_photoannotation.php +++ b/modules/photoannotation/controllers/admin_photoannotation.php @@ -43,7 +43,7 @@ class Admin_Photoannotation_Controller extends Admin_Controller { //Load the target user $targetuser = ORM::factory("user", $form->targetuser->value); if (!$targetuser->loaded()) { - message::error(t("The specified user could not be found")); + message::error(t("The specified person could not be found")); url::redirect("admin/photoannotation/converter"); } //Load all existing tag annotations @@ -280,12 +280,12 @@ class Admin_Photoannotation_Controller extends Admin_Controller { ->checked(module::get_var("photoannotation", "shownotes", false)); $group->checkbox("fullname")->label(t("Show full name of a user instead of the username on annotations (username will be dispayed for users without a full name).")) ->checked(module::get_var("photoannotation", "fullname", false)); - $group = $form->group("notifications")->label(t("Notification and user cloud settings")); + $group = $form->group("notifications")->label(t("Notification and people cloud settings")); $group->checkbox("nonotifications")->label(t("Disable user notifications.")) ->checked(module::get_var("photoannotation", "nonotifications", false)); $group->checkbox("notificationoptout")->label(t("Notify users by default (only applies to new users and user who have not saved their profile after installing this module).")) ->checked(module::get_var("photoannotation", "notificationoptout", false)); - $group->checkbox("allowguestsearch")->label(t("Show user cloud and allow user search for guests.")) + $group->checkbox("allowguestsearch")->label(t("Show people cloud and allow people search for guests.")) ->checked(module::get_var("photoannotation", "allowguestsearch", false)); $group = $form->group("newtagmail")->label(t("Customize the mail sent to users when a user annotation is created")); $group->input("newtagsubject")->label(t("Subject")) diff --git a/modules/photoannotation/controllers/photoannotation.php b/modules/photoannotation/controllers/photoannotation.php index 1431a311..eb25f189 100644 --- a/modules/photoannotation/controllers/photoannotation.php +++ b/modules/photoannotation/controllers/photoannotation.php @@ -20,7 +20,7 @@ class photoannotation_Controller extends Controller { public function showuser() { if (identity::active_user()->guest && !module::get_var("photoannotation", "allowguestsearch", false)) { - message::error(t("You have to log in to perform a user search.")); + message::error(t("You have to log in to perform a people search.")); url::redirect(url::site()); return; } @@ -83,18 +83,17 @@ class photoannotation_Controller extends Controller { $user_id = ""; $user_id = $_POST["userlist"]; $description = $_POST["desc"]; + $error_noselection = t("Please select a person or tag or specify a title."); $redir_uri = url::abs_site("{$item->type}s/{$item->id}"); //If this is a user then get the id if ($user_id != "") { $getuser = photoannotation::getuser($user_id); if (!$getuser->found) { - message::error(t("Could not find user %user.", array("user" => $user_id))); - url::redirect($redir_uri); + json::reply(array("result" => "error", "message" => (string)t("Could not find anyone with the name %user.", array("user" => $user_id)))); return; } if ($getuser->isguest) { - message::error(t("You cannot create an annotation for the guest user.")); - url::redirect($redir_uri); + json::reply(array("result" => "error", "message" => (string)t("You cannot create an annotation for the guest user."))); return; } $user_id = $getuser->user->id; @@ -112,19 +111,22 @@ class photoannotation_Controller extends Controller { $tag->save(); $tag_data = $tag->id; } else { - $tag_data = -1; + $tag_data = ""; } //Save annotation if ($annotate_id == "new") { //This is a new annotation - if ($user_id > -1) { //Save user - photoannotation::saveuser($user_id, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); - } elseif ($tag_data > -1) { //Conversion user -> face - photoannotation::saveface($tag_data, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); - } elseif ($item_title != "") { //Conversion user -> note - photoannotation::savenote($item_title, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); - } else { //Somethings wrong - message::error(t("Please select a User or Tag or specify a Title.")); - url::redirect($redir_uri); + $annotate_id = -1; + if ($user_id != "") { //Save user + $new_id = photoannotation::saveuser($user_id, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + $dest_type = "user"; + } elseif ($tag_data != "") { //Save face + $new_id = photoannotation::saveface($tag_data, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + $dest_type = "face"; + } elseif ($item_title != "") { //Save note + $new_id = photoannotation::savenote($item_title, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + $dest_type = "note"; + } else { //Something's wrong + json::reply(array("result" => "error", "message" => (string)$error_noselection)); return; } } else { //This is an update to an existing annotation @@ -133,17 +135,19 @@ class photoannotation_Controller extends Controller { $updateduser = ORM::factory("items_user") //load the existing user ->where("id", "=", $annotate_id) ->find(); - if ($user_id > -1) { //Conversion user -> user - photoannotation::saveuser($user_id, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); - } elseif ($tag_data > -1) { //Conversion user -> face - photoannotation::saveface($tag_data, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + if ($user_id != "") { //Conversion user -> user + $new_id = photoannotation::saveuser($user_id, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + $dest_type = "user"; + } elseif ($tag_data != "") { //Conversion user -> face + $new_id = photoannotation::saveface($tag_data, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + $dest_type = "face"; $updateduser->delete(); //delete old user } elseif ($item_title != "") { //Conversion user -> note - photoannotation::savenote($item_title, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + $new_id = photoannotation::savenote($item_title, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + $dest_type = "note"; $updateduser->delete(); //delete old user } else { //Somethings wrong - message::error(t("Please select a User or Tag or specify a Title.")); - url::redirect($redir_uri); + json::reply(array("result" => "error", "message" => (string)$error_noselection)); return; } break; @@ -151,17 +155,19 @@ class photoannotation_Controller extends Controller { $updatedface = ORM::factory("items_face") //load the existing user ->where("id", "=", $annotate_id) ->find(); - if ($user_id > -1) { //Conversion face -> user - photoannotation::saveuser($user_id, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + if ($user_id != "") { //Conversion face -> user + $new_id = photoannotation::saveuser($user_id, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + $dest_type = "user"; $updatedface->delete(); //delete old face - } elseif ($tag_data > -1) { //Conversion face -> face - photoannotation::saveface($tag_data, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description, $annotate_id); + } elseif ($tag_data != "") { //Conversion face -> face + $new_id = photoannotation::saveface($tag_data, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description, $annotate_id); + $dest_type = "face"; } elseif ($item_title != "") { //Conversion face -> note - photoannotation::savenote($item_title, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + $new_id = photoannotation::savenote($item_title, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + $dest_type = "note"; $updatedface->delete(); //delete old face } else { //Somethings wrong - message::error(t("Please select a User or Tag or specify a Title.")); - url::redirect($redir_uri); + json::reply(array("result" => "error", "message" => (string)$error_noselection)); return; } break; @@ -169,29 +175,70 @@ class photoannotation_Controller extends Controller { $updatednote = ORM::factory("items_note") //load the existing user ->where("id", "=", $annotate_id) ->find(); - if ($user_id > -1) { //Conversion note -> user - photoannotation::saveuser($user_id, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + if ($user_id != "") { //Conversion note -> user + $new_id = photoannotation::saveuser($user_id, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + $dest_type = "user"; $updatednote->delete(); //delete old note - } elseif ($tag_data > -1) { //Conversion note -> face - photoannotation::saveface($tag_data, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + } elseif ($tag_data != "") { //Conversion note -> face + $new_id = photoannotation::saveface($tag_data, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description); + $dest_type = "face"; $updatednote->delete(); //delete old note } elseif ($item_title != "") { //Conversion note -> note - photoannotation::savenote($item_title, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description, $annotate_id); + $new_id = photoannotation::savenote($item_title, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description, $annotate_id); + $dest_type = "note"; } else { //Somethings wrong - message::error(t("Please select a User or Tag or specify a Title.")); - url::redirect($redir_uri); + json::reply(array("result" => "error", "message" => (string)$error_noselection)); return; } break; default: - message::error(t("Please select a User or Tag or specify a Title.")); - url::redirect($redir_uri); + json::reply(array("result" => "error", "message" => (string)$error_noselection)); return; } } - message::success(t("Annotation saved.")); - url::redirect($redir_uri); - return; + $int_text = ""; + $editable = true; + switch ($dest_type) { + case "user": + $fullname = module::get_var("photoannotation", "fullname", false); + $int_text = $getuser->user->display_name() ." (". $getuser->user->name .")"; + if ($fullname) { + $note_text = $getuser->user->display_name(); + } else { + $note_text = $getuser->user->name; + } + $note_url = user_profile::url($getuser->user->id); + break; + case "face": + $note_text = $tag->name; + $note_url = $tag->url(); + break; + case "note": + $note_text = $item_title; + $note_url = ""; + $editable = false; + } + if ($annotate_id == -1) { + $annotation_id = ""; + } else { + $annotation_id = "photoannotation-area-". $notetype ."-". $annotate_id; + } + $reply = array("result" => "success", + "notetype" => (string)$dest_type, + "description" => (string)$description, + "height" => (integer)$_POST["height"], + "internaltext" => (string)$int_text, + "left" => (integer)$str_x1, + "noteid" => (integer)$new_id, + "text" => (string)$note_text, + "top" => (integer)$str_y1, + "url" => (string)$note_url, + "width" => (integer)$_POST["width"], + "editable" => (boolean)$editable, + "annotationid" => (string)$annotation_id, + "oldid" => (string)$annotate_id, + "oldtype" => (string)$notetype); + json::reply($reply); } public function delete($item_data) { @@ -224,25 +271,27 @@ class photoannotation_Controller extends Controller { url::redirect($redir_uri); return; } - message::success(t("Annotation deleted.")); - url::redirect($redir_uri); + json::reply(array("result" => "success", "notetype" => (string)$notetype, "noteid" => (string)$noteid)); } public function autocomplete() { - $users = array(); - $user_parts = explode(",", Input::instance()->get("q")); - $limit = Input::instance()->get("limit"); - $user_part = ltrim(end($user_parts)); - $user_list = ORM::factory("user") - ->where("name", "LIKE", "{$user_part}%") - ->order_by("name", "ASC") - ->limit($limit) - ->find_all(); - foreach ($user_list as $user) { - if ($user->name != "guest") { - $users[] = $user->display_name() ." (". $user->name .")"; + if (!identity::active_user()->guest || module::get_var("photoannotation", "allowguestsearch", false)) { + $users = array(); + $user_parts = explode(",", Input::instance()->get("q")); + $limit = Input::instance()->get("limit"); + $user_part = ltrim(end($user_parts)); + $user_list = ORM::factory("user") + ->where("name", "LIKE", "{$user_part}%") + ->or_where("full_name", "LIKE", "{$user_part}%") + ->order_by("full_name", "ASC") + ->limit($limit) + ->find_all(); + foreach ($user_list as $user) { + if ($user->name != "guest") { + $users[] = $user->display_name() ." (". $user->name .")"; + } } + print implode("\n", $users); } - print implode("\n", $users); } } diff --git a/modules/photoannotation/css/photoannotation.css b/modules/photoannotation/css/photoannotation.css index 90d7026b..696ae734 100644 --- a/modules/photoannotation/css/photoannotation.css +++ b/modules/photoannotation/css/photoannotation.css @@ -69,7 +69,6 @@ color: #f30; text-decoration: underline; } - .image-annotate-canvas { background-position: left top; background-repeat: no-repeat; @@ -96,7 +95,7 @@ color: #FFFFFF; display: none; font-family: Verdana, Sans-Serif; - font-size: 1.4em; + font-size: 0.9em; max-width: 200px; padding: 3px 7px; position: absolute; diff --git a/modules/photoannotation/helpers/photoannotation.php b/modules/photoannotation/helpers/photoannotation.php index 13ec4078..696056e5 100644 --- a/modules/photoannotation/helpers/photoannotation.php +++ b/modules/photoannotation/helpers/photoannotation.php @@ -32,7 +32,7 @@ class photoannotation_Core { "SELECT SQL_CALC_FOUND_ROWS {users}.*, " . " MATCH({users}.`name`) AGAINST ('$q' IN BOOLEAN MODE) AS `score` " . "FROM {users} " . - "WHERE MATCH({users}.`name`) AGAINST ('$q' IN BOOLEAN MODE) " . + "WHERE MATCH({users}.`name`, {users}.`full_name`) AGAINST ('$q' IN BOOLEAN MODE) " . "ORDER BY `score` DESC " . "LIMIT $page_size OFFSET $offset"; $data = $db->query($query); @@ -42,10 +42,10 @@ class photoannotation_Core { } static function get_user_search_form($form_id) { - $form = new Forge("photoannotation/showuser/{$item->id}", "", "post", array("id" => $form_id, "class" => "g-short-form")); - $label = t("Type user name"); + $form = new Forge("photoannotation/showuser", "", "post", array("id" => $form_id, "class" => "g-short-form")); + $label = t("Search for a person"); - $group = $form->group("showuser")->label("Search for a user"); + $group = $form->group("showuser")->label("Search for a person"); $group->input("name")->label($label)->id("name"); $group->submit("")->value(t("Search")); return $form; @@ -99,6 +99,7 @@ class photoannotation_Core { $item_user->y2 = $str_y2; $item_user->description = $description; $item_user->save(); + return $item_user->id; } public static function saveface($tag_id, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description, $annotate_id = "") { @@ -117,6 +118,7 @@ class photoannotation_Core { $item_face->y2 = $str_y2; $item_face->description = $description; $item_face->save(); + return $item_face->id; } public static function savenote($item_title, $item_id, $str_x1, $str_y1, $str_x2, $str_y2, $description, $annotate_id = "") { @@ -135,6 +137,7 @@ class photoannotation_Core { $item_note->title = $item_title; $item_note->description = $description; $item_note->save(); + return $item_note->id; } public static function send_notifications($recipient_id, $item_id, $mailtype) { @@ -230,17 +233,6 @@ class photoannotation_Core { } return $notification_settings; } - - public static function get_user_cloud() { - $users = ORM::factory("user")->order_by("name", "ASC")->find_all(); - foreach ($users as $user) { - $items_users_count = ORM::factory("items_user")->where("user_id", "=", $user->id)->count_all(); - if ($items_users_count > 0) { - $user_array[] = $user->display_name(); - } - } - return $user_array; - } static function cloud($count) { $users = ORM::factory("user")->order_by("name", "ASC")->find_all(); @@ -262,12 +254,13 @@ class photoannotation_Core { $user_array[$user->name]->url = user_profile::url($user->id); } } - $cloud->users = array_slice($user_array, 0, $count); - $cloud->max_count = $maxcount; - if (!$cloud->max_count) { - return; + if (isset($user_array)) { + $cloud->users = array_slice($user_array, 0, $count); + $cloud->max_count = $maxcount; + return $cloud; + } else { + return ""; } - return $cloud; } } @@ -282,4 +275,4 @@ class photoannotation_Core { static function annotation_count($user_id) { return ORM::factory("items_user")->where("user_id", "=", $user_id)->count_all(); } -} \ No newline at end of file +} diff --git a/modules/photoannotation/helpers/photoannotation_block.php b/modules/photoannotation/helpers/photoannotation_block.php index 6facc671..d0e89e0a 100644 --- a/modules/photoannotation/helpers/photoannotation_block.php +++ b/modules/photoannotation/helpers/photoannotation_block.php @@ -29,7 +29,7 @@ class photoannotation_block_Core { case "photoannotation": $block = new Block(); $block->css_id = "g-photoannotation"; - $block->title = t("Users"); + $block->title = t("People"); $block->content = new View("photoannotation_block.html"); $block->content->cloud = photoannotation::cloud(30); $block->content->form = photoannotation::get_user_search_form("g-user-cloud-form"); @@ -37,4 +37,4 @@ class photoannotation_block_Core { } return $block; } -} \ No newline at end of file +} diff --git a/modules/photoannotation/helpers/photoannotation_event.php b/modules/photoannotation/helpers/photoannotation_event.php index 2d58af53..1db486b8 100644 --- a/modules/photoannotation/helpers/photoannotation_event.php +++ b/modules/photoannotation/helpers/photoannotation_event.php @@ -223,7 +223,10 @@ class photoannotation_event_Core { $item_users = ORM::factory("items_user")->where("item_id", "=", $comment->item_id)->find_all(); if (count($item_users) > 0) { foreach ($item_users as $item_user) { - photoannotation::send_notifications($item_user->user_id, $comment->item_id, "newcomment"); + //Don't send if the commenter is the user to be notified + if ($comment->author_id != $item_user->user_id && module::is_active("notification")) { + photoannotation::send_notifications($item_user->user_id, $comment->item_id, "newcomment"); + } } } } @@ -233,7 +236,10 @@ class photoannotation_event_Core { $item_users = ORM::factory("items_user")->where("item_id", "=", $comment->item_id)->find_all(); if (count($item_users) > 0) { foreach ($item_users as $item_user) { - photoannotation::send_notifications($item_user->user_id, $comment->item_id, "updatedcomment"); + //Don't send if the commenter is the user to be notified + if ($comment->author_id != $item_user->user_id && module::is_active("notification")) { + photoannotation::send_notifications($item_user->user_id, $comment->item_id, "updatedcomment"); + } } } } diff --git a/modules/photoannotation/helpers/photoannotation_installer.php b/modules/photoannotation/helpers/photoannotation_installer.php index 8ea36ecf..a0a881a9 100644 --- a/modules/photoannotation/helpers/photoannotation_installer.php +++ b/modules/photoannotation/helpers/photoannotation_installer.php @@ -66,7 +66,7 @@ class photoannotation_installer { DEFAULT CHARSET=utf8;"); // Set the module's version number. - module::set_version("photoannotation", 3); + module::set_version("photoannotation", 4); } static function upgrade($version) { diff --git a/modules/photoannotation/helpers/photoannotation_theme.php b/modules/photoannotation/helpers/photoannotation_theme.php index e255b883..15f584f8 100644 --- a/modules/photoannotation/helpers/photoannotation_theme.php +++ b/modules/photoannotation/helpers/photoannotation_theme.php @@ -38,7 +38,7 @@ class photoannotation_theme_Core { } else { $border_thickness = "1px"; } - if (!$noborder || !$noeditablehover || !$nohover) { + if (!$noborder || !$noclickablehover || !$nohover) { if (!$noborder) { $v .= ".image-annotate-area {\n border: 1px solid ". $bordercolor .";\n diff --git a/modules/photoannotation/js/jquery.annotate.js b/modules/photoannotation/js/jquery.annotate.js index 4125bbc0..a483bb4f 100644 --- a/modules/photoannotation/js/jquery.annotate.js +++ b/modules/photoannotation/js/jquery.annotate.js @@ -26,12 +26,13 @@ this.cssaclass = opts.cssaclass; this.rtlsupport = opts.rtlsupport; this.users = opts.users; + anchor = $('.g-fullsize-link'); // Add the canvas - this.canvas = $('
    '); + this.canvas = $('
    '); this.canvas.children('.image-annotate-edit').hide(); this.canvas.children('.image-annotate-view').hide(); - this.image.after(this.canvas); + $('#g-photo').after(this.canvas); // Give the canvas and the container their size and background this.canvas.height(this.height()); @@ -44,10 +45,12 @@ this.canvas.hover(function() { if ($(this).children('.image-annotate-edit').css('display') == 'none') { $(this).children('.image-annotate-view').show(); + $("#photoannotation-fullsize").show(); } }, function() { $(this).children('.image-annotate-view').hide(); $(this).children('.image-annotate-note').hide(); + $("#photoannotation-fullsize").hide(); }); this.canvas.children('.image-annotate-view').hover(function() { @@ -75,7 +78,12 @@ // Hide the original this.hide(); - + $('#g-photo').hide(); + $('.image-annotate-canvas').show(); + $(".g-resize").remove(); + $("#photoannotation-fullsize").append($('.g-fullsize-link:first')); + $('.g-fullsize-link').append($('.g-fullsize-link:first').attr('title')); + $('.image-annotate-canvas').after($('#photoannotation-legend')); return this; }; @@ -142,28 +150,114 @@ // Create/prepare the editable note elements var editable = new $.fn.annotateEdit(image, null, tags, labels, saveUrl, csrf, rtlsupport, users); - $.fn.annotateImage.createSaveButton(editable, image, null, rtlsupport, labels); + var okbut = new $.fn.annotateImage.createSaveButton(editable, image, null, rtlsupport, labels, saveUrl); + + editable.form.append(okbut); + $.fn.annotateImage.createCancelButton(editable, image, rtlsupport, labels); } }; - $.fn.annotateImage.createSaveButton = function(editable, image, note, rtlsupport, labels) { + $.fn.annotateImage.createSaveButton = function(editable, image, note, rtlsupport, labels, saveUrl) { /// /// Creates a Save button on the editable note. /// var ok = $('' + labels[8] + ''); - ok.click(function() { - var form = $('#image-annotate-edit-form form'); - var text = $('#image-annotate-text').val(); - $.fn.annotateImage.appendPosition(form, editable); - image.mode = 'view'; + var form = $('#image-annotate-edit-form form'); + $.fn.annotateImage.appendPosition(form, editable); + $.ajax({ + url: saveUrl, + type: 'POST', + data: form.serialize(), + error: function(e) { + var errordialog = '
    ' + labels[13] + '
    '; + $('body').append(errordialog); + var btns = {}; + if (rtlsupport == "") { + diagclass = "inmage-annotate-dialog"; + } else { + diagclass = "inmage-annotate-dialog-rtl"; + } + btns[labels[14]] = function(){ + $('#image-annotate-error-dialog').remove(); + }; + $('#image-annotate-error-dialog').dialog({ + modal: true, + resizable: false, + dialogClass: diagclass, + title: labels[13], + close: function(event, ui) { $('#image-annotate-error-dialog').remove(); }, + width: 450, + buttons: btns + }); + }, + success: function(data) { + if (data.result == "error") { + var errordialog = '
    ' + data.message + '
    '; + $('body').append(errordialog); + var btns = {}; + if (rtlsupport == "") { + diagclass = "inmage-annotate-dialog"; + } else { + diagclass = "inmage-annotate-dialog-rtl"; + } + btns[labels[14]] = function(){ + $('#image-annotate-error-dialog').remove(); + }; + $('#image-annotate-error-dialog').dialog({ + modal: true, + resizable: false, + dialogClass: diagclass, + title: labels[13], + close: function(event, ui) { $('#image-annotate-error-dialog').remove(); }, + width: 450, + buttons: btns + }); + } else { + if (data.annotationid != "") { + var legendid = "photoannotation-legend-" + data.oldtype; + $("#" + legendid + "-" + data.oldid).remove(); + if ($("#" + legendid + " > span").size() == 0) { + $("#" + legendid).hide(); + } + $("#" + data.annotationid).remove(); + $("#" + data.annotationid + "-edit").remove(); + $("#" + data.annotationid + "-delete").remove(); + $("#" + data.annotationid + "-note").remove(); + } + editable.description = data.description; + editable.editable = data.editable; + editable.height = data.height; + editable.internaltext = data.internaltext; + editable.left = data.left; + editable.noteid = data.noteid; + editable.notetype = data.notetype; + editable.text = data.text; + editable.top = data.top; + editable.url = data.url; + editable.width = data.width; + + var anchor_open = ""; + var anchor_close = ""; + if (data.url != "") { + anchor_open = ''; + anchor_close = ''; + } + legendid = "photoannotation-legend-" + data.notetype; + $("#" + legendid).show(); + $("#" + legendid).append('' + anchor_open + data.text + anchor_close + ' '); + note = new $.fn.annotateView(image, editable, image.tags, image.labels, image.editable, image.csrf, image.deleteUrl, image.saveUrl, image.cssaclass, image.rtlsupport, image.users); + } + }, + dataType: "json" + }); + image.mode = 'view'; - form.submit(); - - editable.destroy(); + editable.destroy(); + }); - editable.form.append(ok); + editable.form.append(ok); }; $.fn.annotateImage.createCancelButton = function(editable, image, rtlsupport, labels) { @@ -174,7 +268,6 @@ cancel.click(function() { editable.destroy(); image.mode = 'view'; - location.reload(); }); editable.form.append(cancel); }; @@ -209,8 +302,8 @@ newNote.noteid = "new"; newNote.top = 30; newNote.left = 30; - newNote.width = 30; - newNote.height = 30; + newNote.width = 60; + newNote.height = 60; newNote.text = ""; newNote.description = ""; newNote.notetype = ""; @@ -242,7 +335,7 @@ } else { notetitle = this.note.text; } - var form = $('
    ' + labels[12] + '
    ' + labels[4] + '
    ' + labels[4] + '
    ' + labels[2] + '
    '); + var form = $('
    ' + labels[12] + '
    ' + labels[4] + '
    ' + labels[4] + '
    ' + labels[2] + '
    '); this.form = form; $('body').append(this.form); $("#photoannotation-form").ready(function() { @@ -267,30 +360,24 @@ if ($("input#image-annotate-tag-text").val() != "") { $("input#image-annotate-text").html(""); $("input#image-annotate-text").val(""); - $("input#image-annotate-text").text(""); $("input#photoannotation-user-list").html(""); $("input#photoannotation-user-list").val(""); - $("input#photoannotation-user-list").text(""); } }); $("input#image-annotate-text").keyup(function() { if ($("input#image-annotate-text").val() != "") { $("input#image-annotate-tag-text").html(""); $("input#image-annotate-tag-text").val(""); - $("input#image-annotate-tag-text").text(""); $("input#photoannotation-user-list").html(""); $("input#photoannotation-user-list").val(""); - $("input#photoannotation-user-list").text(""); } }); $("input#photoannotation-user-list").keyup(function() { if ($("select#photoannotation-user-list").val() != "-1") { $("input#image-annotate-tag-text").html(""); $("input#image-annotate-tag-text").val(""); - $("input#image-annotate-tag-text").text(""); $("input#image-annotate-text").html(""); $("input#image-annotate-text").val(""); - $("input#image-annotate-text").text(""); } }); this.form.css('left', this.area.offset().left + 'px'); @@ -351,16 +438,12 @@ image.canvas.children('.image-annotate-view').prepend(this.area); if (editable) { - this.delarea = $('
    '); - this.editarea = $('
    '); + this.delarea = $('
    '); + this.editarea = $('
    '); image.canvas.children('.image-annotate-view').prepend(this.delarea); image.canvas.children('.image-annotate-view').prepend(this.editarea); this.delarea.bind('click',function () { - var alink = $(cssaclass); - alink.unbind(); - alink.attr ('href', '#'); - alink.removeAttr ('rel'); - var confdialog = '
    ' + labels[3] + '
    '; + var confdialog = '
    ' + labels[3] + '
    '; $('body').append(confdialog); var btns = {}; if (rtlsupport == "") { @@ -368,23 +451,64 @@ } else { diagclass = "inmage-annotate-dialog-rtl"; } - btns[labels[5]] = function(){ var delform = $(this).attr("rel"); $("form#" + delform).submit(); }; - btns[labels[6]] = function(){ location.reload(); }; + btns[labels[5]] = function(){ + var delform = $("#" + $(this).attr("rel") + "-del-form"); + $.ajax({ + url: deleteUrl, + type: 'POST', + data: delform.serialize(), + error: function(e) { + var errordialog = '
    ' + labels[15] + '
    '; + $('body').append(errordialog); + var btns = {}; + if (rtlsupport == "") { + diagclass = "inmage-annotate-dialog"; + } else { + diagclass = "inmage-annotate-dialog-rtl"; + } + btns[labels[14]] = function(){ + $('#image-annotate-error-dialog').remove(); + }; + $('#image-annotate-error-dialog').dialog({ + modal: true, + resizable: false, + dialogClass: diagclass, + title: labels[13], + close: function(event, ui) { $('#image-annotate-error-dialog').remove(); }, + width: 450, + buttons: btns + }); + }, + success: function(data) { + if (data.result == "success") { + var annotationid = "photoannotation-area-" + data.notetype + "-" + data.noteid; + var legendid = "photoannotation-legend-" + data.notetype; + $("#" + legendid + "-" + data.noteid).remove(); + if ($("#" + legendid + " > span").size() == 0) { + $("#" + legendid).hide(); + } + $("#" + annotationid).remove(); + $("#" + annotationid + "-edit").remove(); + $("#" + annotationid + "-delete").remove(); + $("#" + annotationid + "-note").remove(); + } + }, + dataType: "json" + }); + $('#image-annotate-conf-dialog').remove(); + }; + btns[labels[6]] = function(){ $('#image-annotate-conf-dialog').remove(); }; $('#image-annotate-conf-dialog').dialog({ modal: true, resizable: false, dialogClass: diagclass, title: labels[7], - close: function(event, ui) { location.reload(); }, + close: function(event, ui) { $('#image-annotate-conf-dialog').remove(); }, buttons: btns }); }); var form = this; this.editarea.bind('click',function () { - var alink = $(cssaclass); - alink.unbind(); - alink.attr ('href', '#'); - alink.removeAttr ('rel'); form.edit(tags, labels, saveUrl, csrf, rtlsupport, users); }); this.delarea.hide(); @@ -396,7 +520,7 @@ if (note.description != "") { notedescription = "
    " + note.description; } - this.form = $('
    ' + note.text + notedescription + '
    '); + this.form = $('
    ' + note.text + notedescription + '
    '); this.form.hide(); image.canvas.children('.image-annotate-view').append(this.form); this.form.children('span.actions').hide(); @@ -453,10 +577,6 @@ // Edit a note feature if (note.url != "" && note.url != null) { this.area.bind('click',function () { - var alink = $(cssaclass); - alink.unbind(); - alink.attr ('href', '#'); - alink.removeAttr ('rel'); window.location = note.url; }); } @@ -479,6 +599,7 @@ this.delarea.css('top', (this.note.top) + 'px'); this.editarea.children('div').height('14px'); this.editarea.children('div').width('14px'); + this.editarea.css('top', (this.note.top + 16) + 'px'); if (rtlsupport == '') { this.delarea.css('left', (this.note.left + parseInt(this.note.width)) + 'px'); this.editarea.css('left', (this.note.left + parseInt(this.note.width)) + 'px'); @@ -486,7 +607,6 @@ this.delarea.css('left', (this.note.left - 16) + 'px'); this.editarea.css('left', (this.note.left - 16) + 'px'); } - this.editarea.css('top', (this.note.top + 16) + 'px'); } }; @@ -529,23 +649,11 @@ // Create/prepare the editable note elements var editable = new $.fn.annotateEdit(this.image, this.note, tags, labels, saveUrl, csrf, rtlsupport, users); - $.fn.annotateImage.createSaveButton(editable, this.image, annotation, rtlsupport, labels); + $.fn.annotateImage.createSaveButton(editable, this.image, annotation, rtlsupport, labels, saveUrl); $.fn.annotateImage.createCancelButton(editable, this.image, rtlsupport, labels); } }; - $.fn.annotateImage.appendPosition = function(form, editable) { - /// - /// Appends the annotations coordinates to the given form that is posted to the server. - /// - var areaFields = $('' + - '' + - '' + - '' + - ''); - form.append(areaFields); - }; - $.fn.annotateView.prototype.resetPosition = function(editable, text) { /// /// Sets the position of an annotation. @@ -571,4 +679,16 @@ this.editable = true; }; + $.fn.annotateImage.appendPosition = function(form, editable) { + /// + /// Appends the annotations coordinates to the given form that is posted to the server. + /// + var areaFields = $('' + + '' + + '' + + '' + + ''); + form.append(areaFields); + }; + })(jQuery); diff --git a/modules/photoannotation/js/jquery.annotate.min.js b/modules/photoannotation/js/jquery.annotate.min.js index 9c9cdd6b..9d15d8e5 100644 --- a/modules/photoannotation/js/jquery.annotate.min.js +++ b/modules/photoannotation/js/jquery.annotate.min.js @@ -1 +1 @@ -(function($){$.fn.annotateImage=function(options){var opts=$.extend({},$.fn.annotateImage.defaults,options);var image=this;this.image=this;this.mode='view';this.getUrl=opts.getUrl;this.saveUrl=opts.saveUrl;this.deleteUrl=opts.deleteUrl;this.deleteUrl=opts.deleteUrl;this.editable=opts.editable;this.useAjax=opts.useAjax;this.tags=opts.tags;this.notes=opts.notes;this.labels=opts.labels;this.csrf=opts.csrf;this.cssaclass=opts.cssaclass;this.rtlsupport=opts.rtlsupport;this.users=opts.users;this.canvas=$('
    ');this.canvas.children('.image-annotate-edit').hide();this.canvas.children('.image-annotate-view').hide();this.image.after(this.canvas);this.canvas.height(this.height());this.canvas.width(this.width());this.canvas.css('background-image','url("'+this.attr('src')+'")');this.canvas.children('.image-annotate-view, .image-annotate-edit').height(this.height());this.canvas.children('.image-annotate-view, .image-annotate-edit').width(this.width());this.canvas.hover(function(){if($(this).children('.image-annotate-edit').css('display')=='none'){$(this).children('.image-annotate-view').show()}},function(){$(this).children('.image-annotate-view').hide();$(this).children('.image-annotate-note').hide()});this.canvas.children('.image-annotate-view').hover(function(){$(this).show()},function(){$(this).hide();$(this).children('.image-annotate-note').hide()});if(this.useAjax){$.fn.annotateImage.ajaxLoad(this)}else{$.fn.annotateImage.load(this,this.labels,this.editable,this.csrf,this.deleteUrl,this.tags,this.saveUrl,this.cssaclass,this.rtlsupport,this.users)}if($('#g-photoannotation-link').length!==0){this.button=$('#g-photoannotation-link');this.button.click(function(){$.fn.annotateImage.add(image,opts.tags,opts.labels,opts.saveUrl,opts.csrf,opts.rtlsupport,opts.users)})}this.hide();return this};$.fn.annotateImage.defaults={getUrl:'your-get.rails',saveUrl:'your-save.rails',deleteUrl:'your-delete.rails',editable:true,useAjax:true,tags:new Array(),notes:new Array()};$.fn.annotateImage.clear=function(image){for(var i=0;i'+labels[8]+'');ok.click(function(){var form=$('#image-annotate-edit-form form');var text=$('#image-annotate-text').val();$.fn.annotateImage.appendPosition(form,editable);image.mode='view';form.submit();editable.destroy()});editable.form.append(ok)};$.fn.annotateImage.createCancelButton=function(editable,image,rtlsupport,labels){var cancel=$(''+labels[9]+'');cancel.click(function(){editable.destroy();image.mode='view';location.reload()});editable.form.append(cancel)};$.fn.annotateImage.saveAsHtml=function(image,target){var element=$(target);var html="";for(var i=0;i'};$.fn.annotateEdit=function(image,note,tags,labels,saveUrl,csrf,rtlsupport,users){this.image=image;if(note){this.note=note}else{var newNote=new Object();newNote.noteid="new";newNote.top=30;newNote.left=30;newNote.width=30;newNote.height=30;newNote.text="";newNote.description="";newNote.notetype="";newNote.internaltext="";this.note=newNote}var area=image.canvas.children('.image-annotate-edit').children('.image-annotate-edit-area');this.area=area;this.area.css('height',this.note.height+'px');this.area.css('width',this.note.width+'px');this.area.css('left',this.note.left+'px');this.area.css('top',this.note.top+'px');image.canvas.children('.image-annotate-view').hide();image.canvas.children('.image-annotate-edit').show();var selectedtag="";var notetitle="";var username="";var selecteduser="";if(this.note.notetype=="face"){selectedtag=this.note.text}else if(this.note.notetype=="user"){username=this.note.internaltext}else{notetitle=this.note.text}var form=$('
    '+labels[12]+'
    '+labels[4]+'
    '+labels[4]+'
    '+labels[2]+'
    ');this.form=form;$('body').append(this.form);$("#photoannotation-form").ready(function(){var url=tags;$("input#image-annotate-tag-text").autocomplete(url,{max:30,multiple:false,cacheLength:1});var urlusers=users;$("input#photoannotation-user-list").autocomplete(urlusers,{max:30,multiple:false,cacheLength:1})});$("input#image-annotate-tag-text").keyup(function(){if($("input#image-annotate-tag-text").val()!=""){$("input#image-annotate-text").html("");$("input#image-annotate-text").val("");$("input#image-annotate-text").text("");$("input#photoannotation-user-list").html("");$("input#photoannotation-user-list").val("");$("input#photoannotation-user-list").text("")}});$("input#image-annotate-text").keyup(function(){if($("input#image-annotate-text").val()!=""){$("input#image-annotate-tag-text").html("");$("input#image-annotate-tag-text").val("");$("input#image-annotate-tag-text").text("");$("input#photoannotation-user-list").html("");$("input#photoannotation-user-list").val("");$("input#photoannotation-user-list").text("")}});$("input#photoannotation-user-list").keyup(function(){if($("select#photoannotation-user-list").val()!="-1"){$("input#image-annotate-tag-text").html("");$("input#image-annotate-tag-text").val("");$("input#image-annotate-tag-text").text("");$("input#image-annotate-text").html("");$("input#image-annotate-text").val("");$("input#image-annotate-text").text("")}});this.form.css('left',this.area.offset().left+'px');this.form.css('top',(parseInt(this.area.offset().top)+parseInt(this.area.height())+7)+'px');area.resizable({handles:'all',start:function(e,ui){form.hide()},stop:function(e,ui){form.css('left',area.offset().left+'px');form.css('top',(parseInt(area.offset().top)+parseInt(area.height())+7)+'px');form.show()}}).draggable({containment:image.canvas,drag:function(e,ui){form.hide()},stop:function(e,ui){form.css('left',area.offset().left+'px');form.css('top',(parseInt(area.offset().top)+parseInt(area.height())+7)+'px');form.show()}});return this};$.fn.annotateEdit.prototype.destroy=function(){this.image.canvas.children('.image-annotate-edit').hide();this.area.resizable('destroy');this.area.draggable('destroy');this.area.css('height','');this.area.css('width','');this.area.css('left','');this.area.css('top','');this.form.remove()};$.fn.annotateView=function(image,note,tags,labels,editable,csrf,deleteUrl,saveUrl,cssaclass,rtlsupport,users){this.image=image;this.note=note;this.area=$('
    ');image.canvas.children('.image-annotate-view').prepend(this.area);if(editable){this.delarea=$('
    ');this.editarea=$('
    ');image.canvas.children('.image-annotate-view').prepend(this.delarea);image.canvas.children('.image-annotate-view').prepend(this.editarea);this.delarea.bind('click',function(){var alink=$(cssaclass);alink.unbind();alink.attr('href','#');alink.removeAttr('rel');var confdialog='
    '+labels[3]+'
    ';$('body').append(confdialog);var btns={};if(rtlsupport==""){diagclass="inmage-annotate-dialog"}else{diagclass="inmage-annotate-dialog-rtl"}btns[labels[5]]=function(){var delform=$(this).attr("rel");$("form#"+delform).submit()};btns[labels[6]]=function(){location.reload()};$('#image-annotate-conf-dialog').dialog({modal:true,resizable:false,dialogClass:diagclass,title:labels[7],close:function(event,ui){location.reload()},buttons:btns})});var form=this;this.editarea.bind('click',function(){var alink=$(cssaclass);alink.unbind();alink.attr('href','#');alink.removeAttr('rel');form.edit(tags,labels,saveUrl,csrf,rtlsupport,users)});this.delarea.hide();this.editarea.hide()}var notedescription="";if(note.description!=""){notedescription="
    "+note.description}this.form=$('
    '+note.text+notedescription+'
    ');this.form.hide();image.canvas.children('.image-annotate-view').append(this.form);this.form.children('span.actions').hide();this.setPosition(rtlsupport);var annotation=this;this.area.hover(function(){annotation.show();if(annotation.delarea!=undefined){annotation.delarea.show();annotation.editarea.show()}},function(){annotation.hide();if(annotation.delarea!=undefined){annotation.delarea.hide();annotation.editarea.hide()}});var legendspan="#photoannotation-legend-"+this.note.notetype+"-"+this.note.noteid;if($(legendspan).length>0){$(legendspan).hover(function(){var legendsarea="#photoannotation-area-"+note.notetype+"-"+note.noteid;$(legendsarea).children('.image-annotate-view').show();$(".image-annotate-view").show();$(legendsarea).show();annotation.show()},function(){var legendsarea="#photoannotation-area-"+note.notetype+"-"+note.noteid;annotation.hide();$(legendsarea).children('.image-annotate-view').hide();$(".image-annotate-view").hide()})}if(editable){this.delarea.hover(function(){annotation.delarea.show();annotation.editarea.show()},function(){annotation.delarea.hide();annotation.editarea.hide()});this.editarea.hover(function(){annotation.delarea.show();annotation.editarea.show()},function(){annotation.delarea.hide();annotation.editarea.hide()})}if(note.url!=""&¬e.url!=null){this.area.bind('click',function(){var alink=$(cssaclass);alink.unbind();alink.attr('href','#');alink.removeAttr('rel');window.location=note.url})}};$.fn.annotateView.prototype.setPosition=function(rtlsupport){this.area.children('div').height((parseInt(this.note.height)-2)+'px');this.area.children('div').width((parseInt(this.note.width)-2)+'px');this.area.css('left',(this.note.left)+'px');this.area.css('top',(this.note.top)+'px');this.form.css('left',(this.note.left)+'px');this.form.css('top',(parseInt(this.note.top)+parseInt(this.note.height)+7)+'px');if(this.delarea!=undefined){this.delarea.children('div').height('14px');this.delarea.children('div').width('14px');this.delarea.css('top',(this.note.top)+'px');this.editarea.children('div').height('14px');this.editarea.children('div').width('14px');if(rtlsupport==''){this.delarea.css('left',(this.note.left+parseInt(this.note.width))+'px');this.editarea.css('left',(this.note.left+parseInt(this.note.width))+'px')}else{this.delarea.css('left',(this.note.left-16)+'px');this.editarea.css('left',(this.note.left-16)+'px')}this.editarea.css('top',(this.note.top+16)+'px')}};$.fn.annotateView.prototype.show=function(){this.form.fadeIn(250);if(!this.note.editable){this.area.addClass('image-annotate-area-hover')}else{this.area.addClass('image-annotate-area-editable-hover')}};$.fn.annotateView.prototype.hide=function(){this.form.fadeOut(250);this.area.removeClass('image-annotate-area-hover');this.area.removeClass('image-annotate-area-editable-hover')};$.fn.annotateView.prototype.destroy=function(){this.area.remove();this.form.remove()};$.fn.annotateView.prototype.edit=function(tags,labels,saveUrl,csrf,rtlsupport,users){if(this.image.mode=='view'){this.image.mode='edit';var annotation=this;var editable=new $.fn.annotateEdit(this.image,this.note,tags,labels,saveUrl,csrf,rtlsupport,users);$.fn.annotateImage.createSaveButton(editable,this.image,annotation,rtlsupport,labels);$.fn.annotateImage.createCancelButton(editable,this.image,rtlsupport,labels)}};$.fn.annotateImage.appendPosition=function(form,editable){var areaFields=$(''+''+''+''+'');form.append(areaFields)};$.fn.annotateView.prototype.resetPosition=function(editable,text){this.form.html(text);this.form.hide();this.area.children('div').height(editable.area.height()+'px');this.area.children('div').width((editable.area.width()-2)+'px');this.area.css('left',(editable.area.position().left)+'px');this.area.css('top',(editable.area.position().top)+'px');this.form.css('left',(editable.area.position().left)+'px');this.form.css('top',(parseInt(editable.area.position().top)+parseInt(editable.area.height())+7)+'px');this.note.top=editable.area.position().top;this.note.left=editable.area.position().left;this.note.height=editable.area.height();this.note.width=editable.area.width();this.note.text=text;this.note.id=editable.note.id;this.editable=true}})(jQuery); +(function($){$.fn.annotateImage=function(options){var opts=$.extend({},$.fn.annotateImage.defaults,options);var image=this;this.image=this;this.mode='view';this.getUrl=opts.getUrl;this.saveUrl=opts.saveUrl;this.deleteUrl=opts.deleteUrl;this.deleteUrl=opts.deleteUrl;this.editable=opts.editable;this.useAjax=opts.useAjax;this.tags=opts.tags;this.notes=opts.notes;this.labels=opts.labels;this.csrf=opts.csrf;this.cssaclass=opts.cssaclass;this.rtlsupport=opts.rtlsupport;this.users=opts.users;anchor=$('.g-fullsize-link');this.canvas=$('
    ');this.canvas.children('.image-annotate-edit').hide();this.canvas.children('.image-annotate-view').hide();$('#g-photo').after(this.canvas);this.canvas.height(this.height());this.canvas.width(this.width());this.canvas.css('background-image','url("'+this.attr('src')+'")');this.canvas.children('.image-annotate-view, .image-annotate-edit').height(this.height());this.canvas.children('.image-annotate-view, .image-annotate-edit').width(this.width());this.canvas.hover(function(){if($(this).children('.image-annotate-edit').css('display')=='none'){$(this).children('.image-annotate-view').show();$("#photoannotation-fullsize").show()}},function(){$(this).children('.image-annotate-view').hide();$(this).children('.image-annotate-note').hide();$("#photoannotation-fullsize").hide()});this.canvas.children('.image-annotate-view').hover(function(){$(this).show()},function(){$(this).hide();$(this).children('.image-annotate-note').hide()});if(this.useAjax){$.fn.annotateImage.ajaxLoad(this)}else{$.fn.annotateImage.load(this,this.labels,this.editable,this.csrf,this.deleteUrl,this.tags,this.saveUrl,this.cssaclass,this.rtlsupport,this.users)}if($('#g-photoannotation-link').length!==0){this.button=$('#g-photoannotation-link');this.button.click(function(){$.fn.annotateImage.add(image,opts.tags,opts.labels,opts.saveUrl,opts.csrf,opts.rtlsupport,opts.users)})}this.hide();$('#g-photo').hide();$('.image-annotate-canvas').show();$(".g-resize").remove();$("#photoannotation-fullsize").append($('.g-fullsize-link:first'));$('.g-fullsize-link').append($('.g-fullsize-link:first').attr('title'));$('.image-annotate-canvas').after($('#photoannotation-legend'));return this};$.fn.annotateImage.defaults={getUrl:'your-get.rails',saveUrl:'your-save.rails',deleteUrl:'your-delete.rails',editable:true,useAjax:true,tags:new Array(),notes:new Array()};$.fn.annotateImage.clear=function(image){for(var i=0;i'+labels[8]+'');ok.click(function(){var form=$('#image-annotate-edit-form form');$.fn.annotateImage.appendPosition(form,editable);$.ajax({url:saveUrl,type:'POST',data:form.serialize(),error:function(e){var errordialog='
    '+labels[13]+'
    ';$('body').append(errordialog);var btns={};if(rtlsupport==""){diagclass="inmage-annotate-dialog"}else{diagclass="inmage-annotate-dialog-rtl"}btns[labels[14]]=function(){$('#image-annotate-error-dialog').remove()};$('#image-annotate-error-dialog').dialog({modal:true,resizable:false,dialogClass:diagclass,title:labels[13],close:function(event,ui){$('#image-annotate-error-dialog').remove()},width:450,buttons:btns})},success:function(data){if(data.result=="error"){var errordialog='
    '+data.message+'
    ';$('body').append(errordialog);var btns={};if(rtlsupport==""){diagclass="inmage-annotate-dialog"}else{diagclass="inmage-annotate-dialog-rtl"}btns[labels[14]]=function(){$('#image-annotate-error-dialog').remove()};$('#image-annotate-error-dialog').dialog({modal:true,resizable:false,dialogClass:diagclass,title:labels[13],close:function(event,ui){$('#image-annotate-error-dialog').remove()},width:450,buttons:btns})}else{if(data.annotationid!=""){var legendid="photoannotation-legend-"+data.oldtype;$("#"+legendid+"-"+data.oldid).remove();if($("#"+legendid+" > span").size()==0){$("#"+legendid).hide()}$("#"+data.annotationid).remove();$("#"+data.annotationid+"-edit").remove();$("#"+data.annotationid+"-delete").remove();$("#"+data.annotationid+"-note").remove()}editable.description=data.description;editable.editable=data.editable;editable.height=data.height;editable.internaltext=data.internaltext;editable.left=data.left;editable.noteid=data.noteid;editable.notetype=data.notetype;editable.text=data.text;editable.top=data.top;editable.url=data.url;editable.width=data.width;var anchor_open="";var anchor_close="";if(data.url!=""){anchor_open='';anchor_close=''}legendid="photoannotation-legend-"+data.notetype;$("#"+legendid).show();$("#"+legendid).append(''+anchor_open+data.text+anchor_close+' ');note=new $.fn.annotateView(image,editable,image.tags,image.labels,image.editable,image.csrf,image.deleteUrl,image.saveUrl,image.cssaclass,image.rtlsupport,image.users)}},dataType:"json"});image.mode='view';editable.destroy()});editable.form.append(ok)};$.fn.annotateImage.createCancelButton=function(editable,image,rtlsupport,labels){var cancel=$(''+labels[9]+'');cancel.click(function(){editable.destroy();image.mode='view'});editable.form.append(cancel)};$.fn.annotateImage.saveAsHtml=function(image,target){var element=$(target);var html="";for(var i=0;i'};$.fn.annotateEdit=function(image,note,tags,labels,saveUrl,csrf,rtlsupport,users){this.image=image;if(note){this.note=note}else{var newNote=new Object();newNote.noteid="new";newNote.top=30;newNote.left=30;newNote.width=60;newNote.height=60;newNote.text="";newNote.description="";newNote.notetype="";newNote.internaltext="";this.note=newNote}var area=image.canvas.children('.image-annotate-edit').children('.image-annotate-edit-area');this.area=area;this.area.css('height',this.note.height+'px');this.area.css('width',this.note.width+'px');this.area.css('left',this.note.left+'px');this.area.css('top',this.note.top+'px');image.canvas.children('.image-annotate-view').hide();image.canvas.children('.image-annotate-edit').show();var selectedtag="";var notetitle="";var username="";var selecteduser="";if(this.note.notetype=="face"){selectedtag=this.note.text}else if(this.note.notetype=="user"){username=this.note.internaltext}else{notetitle=this.note.text}var form=$('
    '+labels[12]+'
    '+labels[4]+'
    '+labels[4]+'
    '+labels[2]+'
    ');this.form=form;$('body').append(this.form);$("#photoannotation-form").ready(function(){var url=tags;$("input#image-annotate-tag-text").autocomplete(url,{max:30,multiple:false,cacheLength:1});var urlusers=users;$("input#photoannotation-user-list").autocomplete(urlusers,{max:30,multiple:false,cacheLength:1})});$("input#image-annotate-tag-text").keyup(function(){if($("input#image-annotate-tag-text").val()!=""){$("input#image-annotate-text").html("");$("input#image-annotate-text").val("");$("input#photoannotation-user-list").html("");$("input#photoannotation-user-list").val("")}});$("input#image-annotate-text").keyup(function(){if($("input#image-annotate-text").val()!=""){$("input#image-annotate-tag-text").html("");$("input#image-annotate-tag-text").val("");$("input#photoannotation-user-list").html("");$("input#photoannotation-user-list").val("")}});$("input#photoannotation-user-list").keyup(function(){if($("select#photoannotation-user-list").val()!="-1"){$("input#image-annotate-tag-text").html("");$("input#image-annotate-tag-text").val("");$("input#image-annotate-text").html("");$("input#image-annotate-text").val("")}});this.form.css('left',this.area.offset().left+'px');this.form.css('top',(parseInt(this.area.offset().top)+parseInt(this.area.height())+7)+'px');area.resizable({handles:'all',start:function(e,ui){form.hide()},stop:function(e,ui){form.css('left',area.offset().left+'px');form.css('top',(parseInt(area.offset().top)+parseInt(area.height())+7)+'px');form.show()}}).draggable({containment:image.canvas,drag:function(e,ui){form.hide()},stop:function(e,ui){form.css('left',area.offset().left+'px');form.css('top',(parseInt(area.offset().top)+parseInt(area.height())+7)+'px');form.show()}});return this};$.fn.annotateEdit.prototype.destroy=function(){this.image.canvas.children('.image-annotate-edit').hide();this.area.resizable('destroy');this.area.draggable('destroy');this.area.css('height','');this.area.css('width','');this.area.css('left','');this.area.css('top','');this.form.remove()};$.fn.annotateView=function(image,note,tags,labels,editable,csrf,deleteUrl,saveUrl,cssaclass,rtlsupport,users){this.image=image;this.note=note;this.area=$('
    ');image.canvas.children('.image-annotate-view').prepend(this.area);if(editable){this.delarea=$('
    ');this.editarea=$('
    ');image.canvas.children('.image-annotate-view').prepend(this.delarea);image.canvas.children('.image-annotate-view').prepend(this.editarea);this.delarea.bind('click',function(){var confdialog='
    '+labels[3]+'
    ';$('body').append(confdialog);var btns={};if(rtlsupport==""){diagclass="inmage-annotate-dialog"}else{diagclass="inmage-annotate-dialog-rtl"}btns[labels[5]]=function(){var delform=$("#"+$(this).attr("rel")+"-del-form");$.ajax({url:deleteUrl,type:'POST',data:delform.serialize(),error:function(e){var errordialog='
    '+labels[15]+'
    ';$('body').append(errordialog);var btns={};if(rtlsupport==""){diagclass="inmage-annotate-dialog"}else{diagclass="inmage-annotate-dialog-rtl"}btns[labels[14]]=function(){$('#image-annotate-error-dialog').remove()};$('#image-annotate-error-dialog').dialog({modal:true,resizable:false,dialogClass:diagclass,title:labels[13],close:function(event,ui){$('#image-annotate-error-dialog').remove()},width:450,buttons:btns})},success:function(data){if(data.result=="success"){var annotationid="photoannotation-area-"+data.notetype+"-"+data.noteid;var legendid="photoannotation-legend-"+data.notetype;$("#"+legendid+"-"+data.noteid).remove();if($("#"+legendid+" > span").size()==0){$("#"+legendid).hide()}$("#"+annotationid).remove();$("#"+annotationid+"-edit").remove();$("#"+annotationid+"-delete").remove();$("#"+annotationid+"-note").remove()}},dataType:"json"});$('#image-annotate-conf-dialog').remove()};btns[labels[6]]=function(){$('#image-annotate-conf-dialog').remove()};$('#image-annotate-conf-dialog').dialog({modal:true,resizable:false,dialogClass:diagclass,title:labels[7],close:function(event,ui){$('#image-annotate-conf-dialog').remove()},buttons:btns})});var form=this;this.editarea.bind('click',function(){form.edit(tags,labels,saveUrl,csrf,rtlsupport,users)});this.delarea.hide();this.editarea.hide()}var notedescription="";if(note.description!=""){notedescription="
    "+note.description}this.form=$('
    '+note.text+notedescription+'
    ');this.form.hide();image.canvas.children('.image-annotate-view').append(this.form);this.form.children('span.actions').hide();this.setPosition(rtlsupport);var annotation=this;this.area.hover(function(){annotation.show();if(annotation.delarea!=undefined){annotation.delarea.show();annotation.editarea.show()}},function(){annotation.hide();if(annotation.delarea!=undefined){annotation.delarea.hide();annotation.editarea.hide()}});var legendspan="#photoannotation-legend-"+this.note.notetype+"-"+this.note.noteid;if($(legendspan).length>0){$(legendspan).hover(function(){var legendsarea="#photoannotation-area-"+note.notetype+"-"+note.noteid;$(legendsarea).children('.image-annotate-view').show();$(".image-annotate-view").show();$(legendsarea).show();annotation.show()},function(){var legendsarea="#photoannotation-area-"+note.notetype+"-"+note.noteid;annotation.hide();$(legendsarea).children('.image-annotate-view').hide();$(".image-annotate-view").hide()})}if(editable){this.delarea.hover(function(){annotation.delarea.show();annotation.editarea.show()},function(){annotation.delarea.hide();annotation.editarea.hide()});this.editarea.hover(function(){annotation.delarea.show();annotation.editarea.show()},function(){annotation.delarea.hide();annotation.editarea.hide()})}if(note.url!=""&¬e.url!=null){this.area.bind('click',function(){window.location=note.url})}};$.fn.annotateView.prototype.setPosition=function(rtlsupport){this.area.children('div').height((parseInt(this.note.height)-2)+'px');this.area.children('div').width((parseInt(this.note.width)-2)+'px');this.area.css('left',(this.note.left)+'px');this.area.css('top',(this.note.top)+'px');this.form.css('left',(this.note.left)+'px');this.form.css('top',(parseInt(this.note.top)+parseInt(this.note.height)+7)+'px');if(this.delarea!=undefined){this.delarea.children('div').height('14px');this.delarea.children('div').width('14px');this.delarea.css('top',(this.note.top)+'px');this.editarea.children('div').height('14px');this.editarea.children('div').width('14px');this.editarea.css('top',(this.note.top+16)+'px');if(rtlsupport==''){this.delarea.css('left',(this.note.left+parseInt(this.note.width))+'px');this.editarea.css('left',(this.note.left+parseInt(this.note.width))+'px')}else{this.delarea.css('left',(this.note.left-16)+'px');this.editarea.css('left',(this.note.left-16)+'px')}}};$.fn.annotateView.prototype.show=function(){this.form.fadeIn(250);if(!this.note.editable){this.area.addClass('image-annotate-area-hover')}else{this.area.addClass('image-annotate-area-editable-hover')}};$.fn.annotateView.prototype.hide=function(){this.form.fadeOut(250);this.area.removeClass('image-annotate-area-hover');this.area.removeClass('image-annotate-area-editable-hover')};$.fn.annotateView.prototype.destroy=function(){this.area.remove();this.form.remove()};$.fn.annotateView.prototype.edit=function(tags,labels,saveUrl,csrf,rtlsupport,users){if(this.image.mode=='view'){this.image.mode='edit';var annotation=this;var editable=new $.fn.annotateEdit(this.image,this.note,tags,labels,saveUrl,csrf,rtlsupport,users);$.fn.annotateImage.createSaveButton(editable,this.image,annotation,rtlsupport,labels,saveUrl);$.fn.annotateImage.createCancelButton(editable,this.image,rtlsupport,labels)}};$.fn.annotateView.prototype.resetPosition=function(editable,text){this.form.html(text);this.form.hide();this.area.children('div').height(editable.area.height()+'px');this.area.children('div').width((editable.area.width()-2)+'px');this.area.css('left',(editable.area.position().left)+'px');this.area.css('top',(editable.area.position().top)+'px');this.form.css('left',(editable.area.position().left)+'px');this.form.css('top',(parseInt(editable.area.position().top)+parseInt(editable.area.height())+7)+'px');this.note.top=editable.area.position().top;this.note.left=editable.area.position().left;this.note.height=editable.area.height();this.note.width=editable.area.width();this.note.text=text;this.note.id=editable.note.id;this.editable=true};$.fn.annotateImage.appendPosition=function(form,editable){var areaFields=$(''+''+''+''+'');form.append(areaFields)}})(jQuery); diff --git a/modules/photoannotation/views/photoannotation_highlight_block.html.php b/modules/photoannotation/views/photoannotation_highlight_block.html.php index 6e7b48e9..9241e5b9 100644 --- a/modules/photoannotation/views/photoannotation_highlight_block.html.php +++ b/modules/photoannotation/views/photoannotation_highlight_block.html.php @@ -22,6 +22,7 @@ $jscode = ""; $legend_faces = ""; $legend_notes = ""; + $legend_users = ""; if (module::get_var("gallery", "active_site_theme") == "greydragon") { $css_item_id = "#g-photo-id-". $item->id; $css_a_class = ".g-sb-preview"; @@ -42,7 +43,7 @@ $user_text = $oneTag->name; } if ($showusers) { - $legend_users .= "id . "\">user_id) ."\">". html::clean($user_text) .", "; + $legend_users .= "id . "\">user_id) ."\">". html::clean($user_text) ." "; } $jscode .= "{ \"top\": ". $oneUser->y1 .",\n"; $jscode .= "\"left\": ". $oneUser->x1 .",\n"; @@ -57,15 +58,16 @@ $jscode .= "\"url\": \"". user_profile::url($oneUser->user_id) ."\" },\n"; } } + $display = "none"; if ($legend_users != "") { - $legend_users = trim($legend_users, ", "); - $legend_users = t("Users on this photo: ") . $legend_users; + $display = "block"; } + $legend_users = t("People on this photo: ") . $legend_users .""; foreach ($existingFaces as $oneFace) { $oneTag = ORM::factory("tag", $oneFace->tag_id); if ($oneTag->loaded()) { if ($showfaces) { - $legend_faces .= "id . "\">url() ."\">". html::clean($oneTag->name) .", "; + $legend_faces .= "id . "\">url() ."\">". html::clean($oneTag->name) ." "; } $jscode .= "{ \"top\": ". $oneFace->y1 .",\n"; $jscode .= "\"left\": ". $oneFace->x1 .",\n"; @@ -79,13 +81,14 @@ $jscode .= "\"url\": \"". $oneTag->url() ."\" },\n"; } } + $display = "none"; if ($legend_faces != "") { - $legend_faces = trim($legend_faces, ", "); - $legend_faces = t("Faces on this photo: ") . $legend_faces; + $display = "block"; } + $legend_faces = t("Faces on this photo: ") . $legend_faces .""; foreach ($existingNotes as $oneNote) { if ($shownotes) { - $legend_notes .= "id . "\">". html::clean($oneNote->title) .", "; + $legend_notes .= "id . "\">". html::clean($oneNote->title) ." "; } $jscode .= "{ \"top\": ". $oneNote->y1 .",\n"; $jscode .= "\"left\": ". $oneNote->x1 .",\n"; @@ -100,17 +103,14 @@ } $jscode = trim($jscode, ",\n"); $jscode .= " ],"; + $display = "none"; if ($legend_notes != "") { - $legend_notes = trim($legend_notes, ", "); - $legend_notes = t("Notes on this photo: ") . $legend_notes; + $display = "block"; } + $legend_notes = t("Notes on this photo: ") . $legend_notes .""; } - $legend_display = ""; - if ($legend_users != "" || $legend_faces != "" || $legend_notes != "") { - $legend_display = $legend_users . "
    " . $legend_faces . "
    " . $legend_notes; - $legend_display = str_replace("

    ", "
    ", $legend_display); - } - $labels_arraystring = "labels: [ '". t("Tag:") ."','". t("Note Title:") ."','". t("Description (optional)") ."','". t("Are you sure you want to delete this annotation?") ."','". t("or") ."','". t("Yes") ."','". t("No") ."','". t("Confirm deletion") ."','". t("Save") ."','". t("Cancel") ."','". t("User:") ."','". t("No user selected") ."','". t("Select one of the following") ."' ],"; + $legend_display = $legend_users . $legend_faces . $legend_notes; + $labels_arraystring = "labels: [ '". t("Tag:") ."','". t("Note Title:") ."','". t("Description (optional)") ."','". t("Are you sure you want to delete this annotation?") ."','". t("or") ."','". t("Yes") ."','". t("No") ."','". t("Confirm deletion") ."','". t("Save") ."','". t("Cancel") ."','". t("Person:") ."','". t("No user selected") ."','". t("Select one of the following") ."','". t("An error ocurred while saving annotation") ."','". t("OK") ."','". t("An error ocurred while deleting annotation") ."','". t("View fullsize") ."' ],"; ?> - - ". $legend_display ."
    " ?> - + ". $legend_display ."
    " ?> diff --git a/modules/photoannotation/views/photoannotation_user_search.html.php b/modules/photoannotation/views/photoannotation_user_search.html.php index 42f32519..2182a324 100644 --- a/modules/photoannotation/views/photoannotation_user_search.html.php +++ b/modules/photoannotation/views/photoannotation_user_search.html.php @@ -16,7 +16,7 @@ id) ."\">" ?> @@ -52,4 +52,4 @@ %term", array("term" => $q)) ?>
    -
    \ No newline at end of file +
    diff --git a/modules/user_rest/helpers/user_rest.php b/modules/user_rest/helpers/user_rest.php new file mode 100644 index 00000000..4acd0d25 --- /dev/null +++ b/modules/user_rest/helpers/user_rest.php @@ -0,0 +1,53 @@ +url); + + return array( + "url" => $request->url, + "entity" => array( + "display_name" => $user->display_name() + ) + ); + } + + + static function resolve($id) { + $user = identity::lookup_user($id); + + if (!self::_can_view_profile_pages($user)) { + throw new Kohana_404_Exception(); + } + return $user; + } + + + static function _can_view_profile_pages($user) { + if (!$user->loaded()) { + return false; + } + + if ($user->id == identity::active_user()->id) { + // You can always view your own profile + return true; + } + + switch (module::get_var("gallery", "show_user_profiles_to")) { + case "admin_users": + return identity::active_user()->admin; + + case "registered_users": + return !identity::active_user()->guest; + + case "everybody": + return true; + + default: + // Fail in private mode on an invalid setting + return false; + } + } +} + + ?> \ No newline at end of file diff --git a/modules/user_rest/module.info b/modules/user_rest/module.info new file mode 100644 index 00000000..05b00468 --- /dev/null +++ b/modules/user_rest/module.info @@ -0,0 +1,3 @@ +name = "REST User Resource" +description = "Provides access to user names via the RESTful API" +version = 1.1