1
0

Merge branch 'master' into talmdal

This commit is contained in:
Tim Almdal 2010-09-22 22:12:08 -07:00
commit 206073f76b
22 changed files with 1657 additions and 173 deletions

View File

@ -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

View File

@ -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 <ul id="mycarousel" class="jcarousel-skin-name"><li>First item</li><li>Second item</li></ul>
* @result
*
* <div class="jcarousel-skin-name">
* <div class="jcarousel-container">
* <div class="jcarousel-clip">
* <ul class="jcarousel-list">
* <li class="jcarousel-item-1">First item</li>
* <li class="jcarousel-item-2">Second item</li>
* </ul>
* </div>
* <div disabled="disabled" class="jcarousel-prev jcarousel-prev-disabled"></div>
* <div class="jcarousel-next"></div>
* </div>
* </div>
*
* @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: '<div></div>',
buttonPrevHTML: '<div></div>',
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('<div></div>');
this.container = this.container.parent();
} else if (!this.container.hasClass('jcarousel-container'))
this.container = this.list.wrap('<div></div>').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('<div class=" '+ skin + '"></div>');
this.clip = this.list.parent();
if (!this.clip.length || !this.clip.hasClass('jcarousel-clip'))
this.clip = this.list.wrap('<div></div>').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('<li></li>', 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);

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
name = "Navigation Carousel"
description = "Adds a navigation carousel under the photo."
version = 4.2
version = 4

View File

@ -0,0 +1,150 @@
<?php defined("SYSPATH") or die("No direct script access.");
/**
* Gallery - a web based photo album viewer and editor
* Copyright (C) 2000-2010 Bharat Mediratta
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* This is the API for handling movies.
*
* Note: by design, this class does not do any permission checking.
*/
include MODPATH . "noffmpeg/libraries/MP4Info.php";
class movie_Core {
static function get_edit_form($movie) {
$form = new Forge("movies/update/$movie->id", "", "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);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -0,0 +1,194 @@
<?php
/**
* FLVMetaData - This tiny class is provided to parse FLV file header and
* get the most common metadata like the width, height, framerate, duration and etc.
* for more information see http://www.adobe.com/devnet/flv/
*
* Note: Metadata fileds might be dependent upon the software used to create the FLV.
*
* -----------------------------------------------------------------------------
* LICENSE:
*
* FLVMetaData is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FLVMetaData is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FLVMetaData. If not, see <http://www.gnu.org/licenses/>.
*
* @author Amin Saeedi, <amin.w3dev@gmail.com>
* @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.<br />";
return false;
}
if(!is_readable($this->fileName)){
echo "Error! Could not read the file. Check the file permissions.<br />";
return false;
}
$f = @fopen($this->fileName,"rb");
if(!$f){
echo "Unknown Error! Could not read the file.<br />";
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;
}
}
?>

View File

@ -0,0 +1,3 @@
name = "NoFFMPEG"
description = "Allow video uploads on systems without FFMPEG."
version = 1

View File

@ -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"))

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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();
}
}
}

View File

@ -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;
}
}
}

View File

@ -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");
}
}
}
}

View File

@ -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) {

View File

@ -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

View File

@ -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 = $('<div class="image-annotate-canvas g-thumbnail"><div class="image-annotate-view"></div><div class="image-annotate-edit"><div class="image-annotate-edit-area"></div></div></div>');
this.canvas = $('<div class="image-annotate-canvas g-thumbnail"><div class="image-annotate-view"><div id="photoannotation-fullsize" class="image-annotate-note"></div></div><div class="image-annotate-edit"><div class="image-annotate-edit-area"></div></div></div>');
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) {
/// <summary>
/// Creates a Save button on the editable note.
/// </summary>
var ok = $('<a class="image-annotate-edit-ok g-button ui-corner-all ui-icon-left ui-state-default ' + rtlsupport + '">' + labels[8] + '</a>');
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 = '<div id="image-annotate-error-dialog">' + labels[13] + '<div />';
$('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 = '<div id="image-annotate-error-dialog">' + data.message + '<div />';
$('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 = '<a href="' + data.url + '">';
anchor_close = '</a>';
}
legendid = "photoannotation-legend-" + data.notetype;
$("#" + legendid).show();
$("#" + legendid).append('<span id="' + legendid + '-' + data.noteid + '">' + anchor_open + data.text + anchor_close + ' </span>');
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 = $('<div id="image-annotate-edit-form" class="ui-dialog-content ui-widget-content ' + rtlsupport + '"><form id="photoannotation-form" action="' + saveUrl + '" method="post"><input type="hidden" name="csrf" value="' + csrf + '" /><input type="hidden" name="noteid" value="' + this.note.noteid + '" /><input type="hidden" name="notetype" value="' + this.note.notetype + '" /><fieldset><legend>' + labels[12] + '</legend><label for="photoannotation-user-list">' + labels[10] + '</label><input id="photoannotation-user-list" class="textbox ui-corner-left ui-corner-right" type="text" name="userlist" style="width: 210px;" value="' + username + '" /><div style="text-align: center"><strong>' + labels[4] + '</strong></div><label for="image-annotate-tag-text">' + labels[0] + '</label><input id="image-annotate-tag-text" class="textbox ui-corner-left ui-corner-right" type="text" name="tagsList" style="width: 210px;" value="' + selectedtag + '" /><div style="text-align: center"><strong>' + labels[4] + '</strong></div><label for="image-annotate-text">' + labels[1] + '</label><input id="image-annotate-text" class="textbox ui-corner-left ui-corner-right" type="text" name="text" style="width: 210px;" value="' + notetitle + '" /></fieldset><fieldset><legend>' + labels[2] + '</legend><textarea id="image-annotate-desc" name="desc" rows="3" style="width: 210px;">' + this.note.description + '</textarea></fieldset</form></div>');
var form = $('<div id="image-annotate-edit-form" class="ui-dialog-content ui-widget-content ' + rtlsupport + '"><form id="photoannotation-form" action="' + saveUrl + '" method="post"><input id="photoannotation-csrf" type="hidden" name="csrf" value="' + csrf + '" /><input id="photoannotation-noteid" type="hidden" name="noteid" value="' + this.note.noteid + '" /><input id="photoannotation-notetype" type="hidden" name="notetype" value="' + this.note.notetype + '" /><fieldset><legend>' + labels[12] + '</legend><label for="photoannotation-user-list">' + labels[10] + '</label><input id="photoannotation-user-list" class="textbox ui-corner-left ui-corner-right" type="text" name="userlist" style="width: 210px;" value="' + username + '" /><div style="text-align: center"><strong>' + labels[4] + '</strong></div><label for="image-annotate-tag-text">' + labels[0] + '</label><input id="image-annotate-tag-text" class="textbox ui-corner-left ui-corner-right" type="text" name="tagsList" style="width: 210px;" value="' + selectedtag + '" /><div style="text-align: center"><strong>' + labels[4] + '</strong></div><label for="image-annotate-text">' + labels[1] + '</label><input id="image-annotate-text" class="textbox ui-corner-left ui-corner-right" type="text" name="text" style="width: 210px;" value="' + notetitle + '" /></fieldset><fieldset><legend>' + labels[2] + '</legend><textarea id="image-annotate-desc" name="desc" rows="3" style="width: 210px;">' + this.note.description + '</textarea></fieldset></form></div>');
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 = $('<div class="image-annotate-area photoannotation-del-button"><div><form id="photoannotation-del-' + this.note.noteid + '" class="photoannotation-del-form" method="post" action="' + deleteUrl + '"><input type="hidden" name="notetype" value="' + this.note.notetype + '" /><input type="hidden" name="noteid" value="' + this.note.noteid + '" /><input type="hidden" name="csrf" value="' + csrf + '" /></form></div></div>');
this.editarea = $('<div id="photoannotation-edit-' + this.note.noteid + '" class="image-annotate-area photoannotation-edit-button"><div></div></div>');
this.delarea = $('<div id="photoannotation-area-' + this.note.notetype + "-" + this.note.noteid + '-delete" class="image-annotate-area photoannotation-del-button" rel="photoannotation-area-' + this.note.notetype + "-" + this.note.noteid + '"><div><form id="photoannotation-area-' + this.note.notetype + "-" + this.note.noteid + '-del-form" class="photoannotation-del-form" method="post" action="' + deleteUrl + '"><input type="hidden" name="notetype" value="' + this.note.notetype + '" /><input type="hidden" name="noteid" value="' + this.note.noteid + '" /><input type="hidden" name="csrf" value="' + csrf + '" /></form></div></div>');
this.editarea = $('<div id="photoannotation-area-' + this.note.notetype + "-" + this.note.noteid + '-edit" class="image-annotate-area photoannotation-edit-button"><div></div></div>');
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 = '<div id="image-annotate-conf-dialog" rel="' + $(this).find('form.photoannotation-del-form').attr('id') + '">' + labels[3] + '<div />';
var confdialog = '<div id="image-annotate-conf-dialog" rel="' + $(this).attr('rel') + '">' + labels[3] + '<div />';
$('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 = '<div id="image-annotate-error-dialog">' + labels[15] + '<div />';
$('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 = "<br />" + note.description;
}
this.form = $('<div class="image-annotate-note">' + note.text + notedescription + '</div>');
this.form = $('<div id="photoannotation-area-' + this.note.notetype + "-" + this.note.noteid + '-note" class="image-annotate-note">' + note.text + notedescription + '</div>');
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) {
/// <summary>
/// Appends the annotations coordinates to the given form that is posted to the server.
/// </summary>
var areaFields = $('<input type="hidden" value="' + editable.area.height() + '" name="height"/>' +
'<input type="hidden" value="' + editable.area.width() + '" name="width"/>' +
'<input type="hidden" value="' + editable.area.position().top + '" name="top"/>' +
'<input type="hidden" value="' + editable.area.position().left + '" name="left"/>' +
'<input type="hidden" value="' + editable.note.id + '" name="id"/>');
form.append(areaFields);
};
$.fn.annotateView.prototype.resetPosition = function(editable, text) {
/// <summary>
/// Sets the position of an annotation.
@ -571,4 +679,16 @@
this.editable = true;
};
$.fn.annotateImage.appendPosition = function(form, editable) {
/// <summary>
/// Appends the annotations coordinates to the given form that is posted to the server.
/// </summary>
var areaFields = $('<input type="hidden" value="' + editable.area.height() + '" name="height"/>' +
'<input type="hidden" value="' + editable.area.width() + '" name="width"/>' +
'<input type="hidden" value="' + editable.area.position().top + '" name="top"/>' +
'<input type="hidden" value="' + editable.area.position().left + '" name="left"/>' +
'<input type="hidden" value="' + editable.note.id + '" name="id"/>');
form.append(areaFields);
};
})(jQuery);

File diff suppressed because one or more lines are too long

View File

@ -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 .= "<span id=\"photoannotation-legend-user-". $oneUser->id . "\"><a href=\"". user_profile::url($oneUser->user_id) ."\">". html::clean($user_text) ."</a></span>, ";
$legend_users .= "<span id=\"photoannotation-legend-user-". $oneUser->id . "\"><a href=\"". user_profile::url($oneUser->user_id) ."\">". html::clean($user_text) ."</a></span> ";
}
$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("<span id=\"photoannotation-legend-user\" style=\"display: ". $display ."\">People on this photo: ") . $legend_users ."</span>";
foreach ($existingFaces as $oneFace) {
$oneTag = ORM::factory("tag", $oneFace->tag_id);
if ($oneTag->loaded()) {
if ($showfaces) {
$legend_faces .= "<span id=\"photoannotation-legend-face-". $oneFace->id . "\"><a href=\"". $oneTag->url() ."\">". html::clean($oneTag->name) ."</a></span>, ";
$legend_faces .= "<span id=\"photoannotation-legend-face-". $oneFace->id . "\"><a href=\"". $oneTag->url() ."\">". html::clean($oneTag->name) ."</a></span> ";
}
$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("<span id=\"photoannotation-legend-face\" style=\"display: ". $display ."\">Faces on this photo: ") . $legend_faces ."</span>";
foreach ($existingNotes as $oneNote) {
if ($shownotes) {
$legend_notes .= "<span id=\"photoannotation-legend-note-". $oneNote->id . "\">". html::clean($oneNote->title) ."</span>, ";
$legend_notes .= "<span id=\"photoannotation-legend-note-". $oneNote->id . "\">". html::clean($oneNote->title) ."</span> ";
}
$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("<span id=\"photoannotation-legend-note\" style=\"display: ". $display ."\">Notes on this photo: ") . $legend_notes ."</span>";
}
$legend_display = "";
if ($legend_users != "" || $legend_faces != "" || $legend_notes != "") {
$legend_display = $legend_users . "<br />" . $legend_faces . "<br />" . $legend_notes;
$legend_display = str_replace("<br /><br />", "<br />", $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") ."' ],";
?>
<script type="text/javascript">
$(document).ready(function() {
@ -133,6 +133,4 @@
});
});
</script>
<? if ($legend_display != ""): ?>
<?= "<div style=\"text-align: center\">". $legend_display ."</div>" ?>
<? endif ?>
<?= "<div id=\"photoannotation-legend\" class=\"g-breadcrumbs\" style=\"text-align: center\">". $legend_display ."</div>" ?>

View File

@ -16,7 +16,7 @@
<?= $search_form ?>
<? if (count($users)): ?>
<div class="g-message photoannotation-user-search">
<?= t("%count users found for <b>%term</b>", array("count" => $count, "term" => $q)) ?>
<?= t("%count people found for <b>%term</b>", array("count" => $count, "term" => $q)) ?>
</div>
<? foreach ($users as $user): ?>
<? $profile_link = "<a href=\"". user_profile::url($user->id) ."\">" ?>
@ -52,4 +52,4 @@
<?= t("No users found for <b>%term</b>", array("term" => $q)) ?>
</div>
<? endif; ?>
</div>
</div>

View File

@ -0,0 +1,53 @@
<?php
class user_rest_Core {
static function get($request) {
$user = rest::resolve($request->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;
}
}
}
?>

View File

@ -0,0 +1,3 @@
name = "REST User Resource"
description = "Provides access to user names via the RESTful API"
version = 1.1