2013-01-24 02:58:13 +04:00
|
|
|
/**********************************************************************
|
2013-01-24 03:12:01 +04:00
|
|
|
* JavaScript Lib
|
|
|
|
|
* at this point this is just a place I put most of the generic stuff I
|
|
|
|
|
* use.
|
|
|
|
|
*
|
|
|
|
|
* P.S. the name "jli" just stands for Java script LIb, like how it
|
|
|
|
|
* looks...
|
2013-01-24 02:58:13 +04:00
|
|
|
**********************************************************************/
|
|
|
|
|
|
2013-01-26 22:48:59 +04:00
|
|
|
//var DEBUG = DEBUG != null ? DEBUG : true
|
2013-01-24 02:58:13 +04:00
|
|
|
|
|
|
|
|
|
2013-02-20 23:29:22 +04:00
|
|
|
|
2013-01-24 02:58:13 +04:00
|
|
|
/*********************************************************************/
|
|
|
|
|
|
2013-02-26 19:05:29 +04:00
|
|
|
// This will create a function that will cycle through a class_list on elem
|
2013-01-24 02:58:13 +04:00
|
|
|
// calling the optional callbacks before and/or after.
|
2013-02-26 19:05:29 +04:00
|
|
|
// If class_list is given as a string, then this will create a toggler that
|
2013-02-09 07:17:40 +04:00
|
|
|
// will turn the given class on the element on and off.
|
2013-01-24 02:58:13 +04:00
|
|
|
//
|
2013-02-26 19:05:29 +04:00
|
|
|
// Elem is a jquery compatible object; default use-case: a css selector.
|
2013-01-24 02:58:13 +04:00
|
|
|
//
|
2013-02-26 19:05:29 +04:00
|
|
|
// If class_list is a string, the resulting function understands the
|
2013-02-09 07:17:40 +04:00
|
|
|
// folowing arguments:
|
|
|
|
|
// - <index> : 0 for 'off' and 1 for 'on' (see below)
|
2013-02-09 16:26:17 +04:00
|
|
|
// - 'on' : switch mode on -- add class
|
|
|
|
|
// - 'off' : switch mode off -- remove class
|
2013-01-24 02:58:13 +04:00
|
|
|
// - '?' : return current state ('on'|'off')
|
|
|
|
|
// - no arguments : toggle the state
|
|
|
|
|
//
|
2013-02-26 19:05:29 +04:00
|
|
|
// Otherwise, if class_list is a list of strings:
|
2013-02-09 07:17:40 +04:00
|
|
|
// - <index> : explicitly set the state to index in class_list
|
|
|
|
|
// - <class-name> : explicitly set a class from the list
|
|
|
|
|
// - '?' : return current state ('on'|'off')
|
|
|
|
|
// - no arguments : set next state in cycle
|
|
|
|
|
//
|
2013-02-09 16:26:17 +04:00
|
|
|
// NOTE: a special class name 'none' means no class is set, if it is present
|
|
|
|
|
// in the class_list then that state will be with all other state
|
|
|
|
|
// classes removed.
|
2013-02-09 07:17:40 +04:00
|
|
|
// NOTE: <class-name> must be an exact match to a string given in class_list
|
2013-01-24 02:58:13 +04:00
|
|
|
// NOTE: of only one callback is given then it will be called after the
|
2013-02-09 16:26:17 +04:00
|
|
|
// class change...
|
|
|
|
|
// a way around this is to pass an empty function as callback_b
|
2013-02-26 18:55:20 +04:00
|
|
|
// NOTE: due to several times I've repeated the same mistake of forgetting
|
|
|
|
|
// to write the classes without leading dots, this now will normalize
|
|
|
|
|
// the class list, so now this will correctly treat both dotted
|
|
|
|
|
// and non-dotted class names...
|
2013-02-26 19:05:29 +04:00
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
// This also takes one or two callbacks. If only one is given then it is
|
|
|
|
|
// called after (post) the change is made. If two are given then the first
|
|
|
|
|
// is called before the change and the second after the change.
|
|
|
|
|
// The callbacks are passed the current action.
|
|
|
|
|
//
|
|
|
|
|
// NOTE: the pre-callback will get the "intent" action, i.e. the state the
|
|
|
|
|
// we are changing into but the changes are not yet made.
|
|
|
|
|
// NOTE: if the pre-callback explicitly returns false, then the change will
|
|
|
|
|
// not be made.
|
2013-02-09 01:47:04 +04:00
|
|
|
function createCSSClassToggler(elem, class_list, callback_a, callback_b){
|
|
|
|
|
var bool_action = false
|
|
|
|
|
if(typeof(class_list) == typeof('')){
|
|
|
|
|
class_list = ['none', class_list]
|
|
|
|
|
bool_action = true
|
|
|
|
|
}
|
2013-02-26 18:55:20 +04:00
|
|
|
// Normalize classes -- remove the dot from class names...
|
|
|
|
|
// NOTE: this is here because I've made the error of including a
|
|
|
|
|
// leading "." almost every time I use this after I forget
|
|
|
|
|
// the UI...
|
2013-02-26 19:05:29 +04:00
|
|
|
class_list = $(class_list).map(function(_, e){
|
|
|
|
|
return $(e.split(' ')).map(function(_, c){
|
2013-02-26 18:55:20 +04:00
|
|
|
c = c.trim()
|
|
|
|
|
return c[0] == '.' ? c.slice(1) : c
|
|
|
|
|
}).toArray().join(' ')
|
|
|
|
|
}).toArray()
|
|
|
|
|
// normalize the callbacks...
|
2013-01-24 02:58:13 +04:00
|
|
|
if(callback_b == null){
|
|
|
|
|
var callback_pre = null
|
|
|
|
|
var callback_post = callback_a
|
|
|
|
|
} else {
|
|
|
|
|
var callback_pre = callback_a
|
|
|
|
|
var callback_post = callback_b
|
|
|
|
|
}
|
2013-02-09 01:47:04 +04:00
|
|
|
|
|
|
|
|
// XXX make this generic...
|
2013-01-24 02:58:13 +04:00
|
|
|
var func = function(action){
|
2013-02-09 01:47:04 +04:00
|
|
|
elem = $(elem)
|
|
|
|
|
// option number...
|
|
|
|
|
if(typeof(action) == typeof(1)){
|
|
|
|
|
// range check...
|
|
|
|
|
if(action < 0 || action >= class_list.length){
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
if(bool_action){
|
|
|
|
|
action = action == 0 ? 'off' : 'on'
|
|
|
|
|
} else {
|
|
|
|
|
action = class_list[action]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// we need to get the current state...
|
2013-01-24 02:58:13 +04:00
|
|
|
if(action == null || action == '?'){
|
|
|
|
|
// get current state...
|
2013-02-09 01:47:04 +04:00
|
|
|
var cur = 'none'
|
|
|
|
|
for(var i=0; i < class_list.length; i++){
|
|
|
|
|
if(elem.hasClass(class_list[i])){
|
|
|
|
|
cur = class_list[i]
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// just asking for info...
|
|
|
|
|
if(action == '?'){
|
|
|
|
|
return bool_action ? (cur == 'none' ? 'off' : 'on') : cur
|
2013-01-24 02:58:13 +04:00
|
|
|
}
|
2013-02-09 01:47:04 +04:00
|
|
|
|
|
|
|
|
// invalid action...
|
|
|
|
|
} else if((bool_action && ['on', 'off'].indexOf(action) == -1)
|
|
|
|
|
|| (!bool_action && class_list.indexOf(action) == -1)){
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var cls = bool_action ? class_list[1] : action
|
|
|
|
|
// get the right class...
|
|
|
|
|
if(action == null){
|
|
|
|
|
var i = class_list.indexOf(cur)+1
|
|
|
|
|
i = i == -1 ? 0 : i
|
|
|
|
|
i = i == class_list.length ? 0 : i
|
|
|
|
|
cls = class_list[i]
|
|
|
|
|
|
|
|
|
|
if(bool_action){
|
|
|
|
|
action = cls == 'none' ? 'off' : 'on'
|
|
|
|
|
} else {
|
|
|
|
|
action = cls
|
2013-01-24 02:58:13 +04:00
|
|
|
}
|
|
|
|
|
}
|
2013-02-09 01:47:04 +04:00
|
|
|
|
|
|
|
|
// pre callback...
|
2013-02-26 19:05:29 +04:00
|
|
|
if(callback_pre != null){
|
2013-02-26 19:08:09 +04:00
|
|
|
if(callback_pre(action) === false){
|
2013-02-26 19:05:29 +04:00
|
|
|
return
|
|
|
|
|
}
|
2013-01-24 02:58:13 +04:00
|
|
|
}
|
2013-02-09 01:47:04 +04:00
|
|
|
// update the element...
|
|
|
|
|
elem.removeClass(class_list.join(' '))
|
|
|
|
|
if(cls != 'none' && action != 'off'){
|
|
|
|
|
elem.addClass(cls)
|
2013-01-24 02:58:13 +04:00
|
|
|
}
|
2013-02-09 01:47:04 +04:00
|
|
|
// post callback...
|
2013-02-26 19:05:29 +04:00
|
|
|
if(callback_post != null){
|
|
|
|
|
callback_post(action)
|
2013-01-24 02:58:13 +04:00
|
|
|
}
|
2013-02-09 01:47:04 +04:00
|
|
|
|
|
|
|
|
return action
|
2013-01-24 02:58:13 +04:00
|
|
|
}
|
2013-02-09 01:47:04 +04:00
|
|
|
|
|
|
|
|
func.class_list = class_list
|
|
|
|
|
if(bool_action){
|
|
|
|
|
func.doc = 'With no arguments this will toggle between "on" and '+
|
|
|
|
|
'"off".\n'+
|
|
|
|
|
'If either "on" or "off" are given then this will switch '+
|
|
|
|
|
'to that mode.\n'+
|
|
|
|
|
'If "?" is given, this will return either "on" or "off" '+
|
|
|
|
|
'depending on the current state.'
|
|
|
|
|
}else{
|
|
|
|
|
func.doc = 'With no arguments this will toggle between '+
|
|
|
|
|
class_list +' in cycle.\n' +
|
|
|
|
|
'if any of the state names or its number is given then that '+
|
|
|
|
|
'state is switched on.'+
|
|
|
|
|
'If "?" is given, this will return the current state.'
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-24 02:58:13 +04:00
|
|
|
return func
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-02-09 01:47:04 +04:00
|
|
|
|
2013-02-26 01:52:57 +04:00
|
|
|
/*
|
2013-01-24 02:58:13 +04:00
|
|
|
// show a jQuary opject in viewer overlay...
|
|
|
|
|
// XXX need to set .scrollTop(0) when showing different UI...
|
|
|
|
|
// ...and not set it when the UI is the same
|
|
|
|
|
// XXX this must create it's own overlay...
|
|
|
|
|
function showInOverlay(obj){
|
|
|
|
|
obj.click(function(){ return false })
|
|
|
|
|
// XXX
|
|
|
|
|
$('.viewer').addClass('overlay-mode')
|
|
|
|
|
// clean things up...
|
|
|
|
|
$('.overlay .content').children().remove()
|
|
|
|
|
// put it in the overlay...
|
|
|
|
|
$('.overlay .content').append(obj)
|
|
|
|
|
// prepare the overlay...
|
|
|
|
|
$('.overlay')
|
|
|
|
|
.one('click', function(){
|
|
|
|
|
$('.overlay')
|
|
|
|
|
.fadeOut(function(){
|
|
|
|
|
$('.overlay .content')
|
|
|
|
|
.children()
|
|
|
|
|
.remove()
|
|
|
|
|
$('.overlay-mode').removeClass('overlay-mode')
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
.fadeIn()
|
|
|
|
|
return obj
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function overlayMessage(text){
|
|
|
|
|
return showInOverlay($('<div class="overlay-message">' +text+ '</div>'))
|
|
|
|
|
}
|
2013-02-26 01:52:57 +04:00
|
|
|
*/
|
2013-01-24 02:58:13 +04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function unanimated(obj, func, time){
|
|
|
|
|
return function(){
|
|
|
|
|
if(time == null){
|
|
|
|
|
time = 5
|
|
|
|
|
}
|
2013-02-13 17:27:04 +04:00
|
|
|
obj = $(obj)
|
2013-01-24 02:58:13 +04:00
|
|
|
obj.addClass('unanimated')
|
|
|
|
|
var res = func.apply(func, arguments)
|
|
|
|
|
setTimeout(function(){obj.removeClass('unanimated')}, time)
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-26 21:55:38 +04:00
|
|
|
|
2013-02-25 23:37:28 +04:00
|
|
|
// NOTE: this will only use the first element in a set.
|
|
|
|
|
// NOTE: if no element is given this will return null.
|
|
|
|
|
function makeCSSVendorAttrGetter(attr, dfl, callback){
|
|
|
|
|
return function(elem){
|
|
|
|
|
elem = $(elem)
|
|
|
|
|
if(elem.length == 0){
|
|
|
|
|
return null
|
|
|
|
|
}
|
|
|
|
|
// using the attr...
|
|
|
|
|
var vendors = ['O', 'Moz', 'ms', 'webkit']
|
|
|
|
|
var data = elem[0].style[attr]
|
|
|
|
|
|
|
|
|
|
// go through vendor prefixes... (hate this!)
|
|
|
|
|
if(!data || data == 'none'){
|
|
|
|
|
for(var i in vendors){
|
|
|
|
|
data = elem[0].style[vendors[i] + attr.capitalize()]
|
|
|
|
|
if(data && data != 'none'){
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// no data is set...
|
|
|
|
|
if(!data || data == 'none'){
|
|
|
|
|
return dfl
|
|
|
|
|
}
|
|
|
|
|
return callback(data)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Return a scale value for the given element(s).
|
|
|
|
|
// NOTE: this will only return a single scale value...
|
|
|
|
|
var getElementScale = makeCSSVendorAttrGetter(
|
|
|
|
|
'transform',
|
|
|
|
|
1,
|
|
|
|
|
function(data){
|
|
|
|
|
return parseFloat((/(scale|matrix)\(([^),]*)\)/).exec(data)[2])
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
var getElementShift = makeCSSVendorAttrGetter(
|
|
|
|
|
'transform',
|
|
|
|
|
{left: 0, top: 0},
|
|
|
|
|
function(data){
|
|
|
|
|
res = /(translate\(|matrix\([^,]*,[^,]*,[^,]*,[^,]*,)([^,]*),([^\)]*)\)/.exec(data)
|
|
|
|
|
return {
|
|
|
|
|
left: parseFloat(res[2]),
|
|
|
|
|
top: parseFloat(res[3])
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2013-02-26 01:52:57 +04:00
|
|
|
|
2013-02-25 23:37:28 +04:00
|
|
|
var DEFAULT_TRANSITION_DURATION = 200
|
|
|
|
|
|
|
|
|
|
var getElementTransitionDuration = makeCSSVendorAttrGetter(
|
|
|
|
|
'transitionDuration',
|
|
|
|
|
DEFAULT_TRANSITION_DURATION,
|
|
|
|
|
parseInt)
|
|
|
|
|
|
|
|
|
|
|
2013-01-26 21:55:38 +04:00
|
|
|
|
2013-02-22 19:56:06 +04:00
|
|
|
var USE_3D_TRANSFORM = true
|
2013-02-22 18:44:11 +04:00
|
|
|
|
2013-02-19 19:34:03 +04:00
|
|
|
// NOTE: at this point this works only on the X axis...
|
2013-02-25 18:02:18 +04:00
|
|
|
function setElementTransform(elem, offset, scale, duration){
|
2013-02-20 04:37:47 +04:00
|
|
|
elem = $(elem)
|
2013-02-22 18:44:11 +04:00
|
|
|
var t3d = USE_3D_TRANSFORM ? 'translateZ(0px)' : ''
|
2013-02-25 18:02:18 +04:00
|
|
|
|
2013-02-19 19:34:03 +04:00
|
|
|
if(offset == null){
|
2013-02-20 04:37:47 +04:00
|
|
|
offset = getElementShift(elem)
|
|
|
|
|
// number -- only the x coord...
|
|
|
|
|
} else if(typeof(offset) == typeof(1)){
|
|
|
|
|
offset = {
|
|
|
|
|
left: offset,
|
|
|
|
|
top: 0
|
|
|
|
|
}
|
|
|
|
|
// array...
|
|
|
|
|
} else if(offset.indexOf){
|
|
|
|
|
offset = {
|
|
|
|
|
left: offset[0] ? offset[0] : 0,
|
|
|
|
|
top: offset[1] ? offset[1] : 0
|
|
|
|
|
}
|
2013-02-19 19:34:03 +04:00
|
|
|
}
|
|
|
|
|
if(scale == null){
|
|
|
|
|
var scale = getElementScale(elem)
|
|
|
|
|
}
|
|
|
|
|
if(USE_TRANSFORM){
|
2013-02-26 22:50:52 +04:00
|
|
|
var transform = 'translate('+
|
|
|
|
|
Math.round(offset.left) +'px, '+
|
|
|
|
|
Math.round(offset.top) +'px) scale('+ scale +') ' + t3d
|
2013-02-19 19:34:03 +04:00
|
|
|
elem.css({
|
2013-02-23 01:51:36 +04:00
|
|
|
'-ms-transform' : transform,
|
2013-02-19 19:34:03 +04:00
|
|
|
'-webkit-transform' : transform,
|
2013-02-23 01:51:36 +04:00
|
|
|
'-moz-transform' : transform,
|
|
|
|
|
'-o-transform' : transform,
|
|
|
|
|
'transform' : transform,
|
2013-02-19 19:34:03 +04:00
|
|
|
|
|
|
|
|
// XXX can we avoid this here??
|
2013-02-20 04:37:47 +04:00
|
|
|
left: 0,
|
|
|
|
|
// XXX is this correct???
|
|
|
|
|
top: ''
|
2013-02-25 18:02:18 +04:00
|
|
|
}, duration)
|
2013-02-19 19:34:03 +04:00
|
|
|
} else {
|
2013-02-22 18:44:11 +04:00
|
|
|
var transform = 'translate(0px, 0px) scale('+ scale +') ' + t3d
|
2013-02-19 19:34:03 +04:00
|
|
|
elem.css({
|
|
|
|
|
// NOTE: this will be wrong during a transition, that's why we
|
|
|
|
|
// can pass the pre-calculated offset as an argument...
|
2013-02-23 01:51:36 +04:00
|
|
|
left: Math.round(offset.left),
|
|
|
|
|
top: Math.round(offset.top),
|
2013-02-19 19:34:03 +04:00
|
|
|
|
|
|
|
|
// XXX can we avoid this here??
|
2013-02-23 01:51:36 +04:00
|
|
|
'-ms-transform' : transform,
|
2013-02-19 19:34:03 +04:00
|
|
|
'-webkit-transform' : transform,
|
2013-02-23 01:51:36 +04:00
|
|
|
'-moz-transform' : transform,
|
|
|
|
|
'-o-transform' : transform,
|
|
|
|
|
'transform' : transform,
|
2013-02-25 18:02:18 +04:00
|
|
|
}, duration)
|
2013-02-19 19:34:03 +04:00
|
|
|
}
|
|
|
|
|
return elem
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-26 01:35:59 +04:00
|
|
|
|
|
|
|
|
// XXX this affects only the innertial part, not setCurrentPage...
|
|
|
|
|
var USE_TRANSITIONS_FOR_ANIMATION = false
|
|
|
|
|
|
|
|
|
|
// XXX make this a drop-in replacement for setElementTransform...
|
|
|
|
|
// XXX cleanup, still flacky...
|
2013-02-26 22:50:52 +04:00
|
|
|
function animateElementTo(elem, to, duration, easing, speed, use_transitions){
|
2013-02-26 01:35:59 +04:00
|
|
|
// stop all ongoing animations on the current elem...
|
|
|
|
|
stopAnimation(elem)
|
2013-02-26 22:50:52 +04:00
|
|
|
use_transitions = use_transitions != null ?
|
|
|
|
|
use_transitions
|
|
|
|
|
: USE_TRANSITIONS_FOR_ANIMATION
|
2013-02-26 01:35:59 +04:00
|
|
|
// use transition for animation...
|
2013-02-26 22:50:52 +04:00
|
|
|
if(use_transitions){
|
2013-02-26 01:35:59 +04:00
|
|
|
setTransitionEasing(elem, easing)
|
|
|
|
|
duration == null && setTransitionDuration(elem, duration)
|
|
|
|
|
setElementTransform(elem, to)
|
|
|
|
|
|
|
|
|
|
// manually animate...
|
|
|
|
|
} else {
|
|
|
|
|
if(typeof(to) == typeof(1)){
|
|
|
|
|
to = {
|
|
|
|
|
left: to,
|
|
|
|
|
top: 0,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(typeof(speed) == typeof(2)){
|
|
|
|
|
speed = {
|
|
|
|
|
x: speed,
|
|
|
|
|
y: 0,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(duration == null){
|
|
|
|
|
duration = getElementTransitionDuration(elem)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setTransitionDuration(elem, 0)
|
|
|
|
|
|
|
|
|
|
var start = Date.now()
|
|
|
|
|
var then = start + duration
|
|
|
|
|
var from = getElementShift(elem)
|
|
|
|
|
var cur = {
|
|
|
|
|
top: from.top,
|
|
|
|
|
left: from.left
|
|
|
|
|
}
|
|
|
|
|
var dist = {
|
|
|
|
|
top: to.top - from.top,
|
|
|
|
|
left: to.left - from.left,
|
|
|
|
|
}
|
|
|
|
|
elem.animating = true
|
|
|
|
|
|
|
|
|
|
function animate(){
|
|
|
|
|
var t = Date.now()
|
|
|
|
|
// end of the animation...
|
|
|
|
|
if(t >= then){
|
|
|
|
|
setElementTransform(elem, to)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if(!elem.animating){
|
|
|
|
|
// XXX jittery...
|
|
|
|
|
setElementTransform(elem, cur)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// do an intermediate step...
|
|
|
|
|
// XXX do propper easing...
|
|
|
|
|
// XXX sometimes results in jumping around...
|
|
|
|
|
// ...result of jumping over the to position...
|
|
|
|
|
if(speed != null){
|
|
|
|
|
|
|
|
|
|
// XXX the folowing two blocks are the same...
|
|
|
|
|
// XXX looks a bit too complex, revise...
|
|
|
|
|
if(Math.abs(dist.top) >= 1){
|
|
|
|
|
dy = ((t - start) * speed.y)
|
|
|
|
|
if(Math.abs(dist.top) > Math.abs(dy)){
|
|
|
|
|
dist.top -= dy
|
|
|
|
|
cur.top = Math.round(cur.top + dy)
|
|
|
|
|
// normalize...
|
|
|
|
|
cur.top = Math.abs(dist.top) <= 1 ? to.top : cur.top
|
|
|
|
|
// calc speed for next step...
|
|
|
|
|
speed.y = dist.top / (duration - (t - start))
|
|
|
|
|
} else {
|
|
|
|
|
cur.top = to.top
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// XXX looks a bit too complex, revise...
|
|
|
|
|
if(Math.abs(dist.left) >= 1){
|
|
|
|
|
dx = ((t - start) * speed.x)
|
|
|
|
|
if(Math.abs(dist.left) > Math.abs(dx)){
|
|
|
|
|
dist.left -= dx
|
|
|
|
|
cur.left = Math.round(cur.left + dx)
|
|
|
|
|
// normalize...
|
|
|
|
|
cur.left = Math.abs(dist.left) <= 1 ? to.left : cur.left
|
|
|
|
|
// calc speed for next step...
|
|
|
|
|
speed.x = dist.left / (duration - (t - start))
|
|
|
|
|
} else {
|
|
|
|
|
cur.left = to.left
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// XXX this is a staright forward linear function...
|
|
|
|
|
} else {
|
|
|
|
|
var r = (t - start) / duration
|
|
|
|
|
cur.top = Math.round(from.top + (dist.top * r))
|
|
|
|
|
cur.left = Math.round(from.left + (dist.left * r))
|
|
|
|
|
}
|
|
|
|
|
setElementTransform(elem, cur)
|
|
|
|
|
// sched next frame...
|
|
|
|
|
elem.next_frame = getAnimationFrame(animate)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
animate()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function stopAnimation(elem){
|
|
|
|
|
if(elem.next_frame){
|
|
|
|
|
cancelAnimationFrame(elem.next_frame)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-02-19 19:34:03 +04:00
|
|
|
// XXX account for other transitions...
|
2013-01-24 02:58:13 +04:00
|
|
|
function setElementScale(elem, scale){
|
2013-02-19 19:34:03 +04:00
|
|
|
return setElementTransform(elem, null, scale)
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-20 18:04:56 +04:00
|
|
|
function setTransitionEasing(elem, ease){
|
|
|
|
|
if(typeof(ms) == typeof(0)){
|
|
|
|
|
ms = ms + 'ms'
|
|
|
|
|
}
|
|
|
|
|
return elem.css({
|
2013-02-23 01:51:36 +04:00
|
|
|
'transition-timing-function': ease,
|
|
|
|
|
'-moz-transition-timing-function': ease,
|
|
|
|
|
'-o-transition-timing-function': ease,
|
|
|
|
|
'-ms-transition-timing-function': ease,
|
2013-02-20 18:04:56 +04:00
|
|
|
'-webkit-transition-timing-function': ease
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-07 03:24:57 +04:00
|
|
|
function setTransitionDuration(elem, ms){
|
|
|
|
|
if(typeof(ms) == typeof(0)){
|
|
|
|
|
ms = ms + 'ms'
|
|
|
|
|
}
|
|
|
|
|
return elem.css({
|
2013-02-23 01:51:36 +04:00
|
|
|
'transition-duration': ms,
|
|
|
|
|
'-moz-transition-duration': ms,
|
|
|
|
|
'-o-transition-duration': ms,
|
|
|
|
|
'-ms-transition-duration': ms,
|
2013-02-07 03:24:57 +04:00
|
|
|
'-webkit-transition-duration': ms
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-01-27 22:41:06 +04:00
|
|
|
|
2013-02-20 05:02:09 +04:00
|
|
|
|
2013-01-24 03:12:01 +04:00
|
|
|
/************************************************ jQuery extensions **/
|
2013-01-24 02:58:13 +04:00
|
|
|
|
2013-01-24 03:12:01 +04:00
|
|
|
jQuery.fn.reverseChildren = function(){
|
|
|
|
|
return $(this).each(function(_, e){
|
|
|
|
|
return $(e).append($(e).children().detach().get().reverse())
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
jQuery.fn.sortChildren = function(func){
|
|
|
|
|
return $(this).each(function(_, e){
|
|
|
|
|
return $(e).append($(e).children().detach().get().sort(func))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-24 02:58:13 +04:00
|
|
|
|
2013-01-24 03:12:01 +04:00
|
|
|
|
2013-02-25 23:37:28 +04:00
|
|
|
/**************************************************** JS utilities ***/
|
|
|
|
|
|
|
|
|
|
String.prototype.capitalize = function(){
|
|
|
|
|
return this[0].toUpperCase() + this.slice(1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var getAnimationFrame = (window.requestAnimationFrame
|
|
|
|
|
|| window.webkitRequestAnimationFrame
|
|
|
|
|
|| window.mozRequestAnimationFrame
|
|
|
|
|
|| window.oRequestAnimationFrame
|
|
|
|
|
|| window.msRequestAnimationFrame
|
|
|
|
|
|| function(callback){
|
2013-02-26 22:50:52 +04:00
|
|
|
setTimeout(callback, 1000/60)
|
2013-02-25 23:37:28 +04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
var cancelAnimationFrame = (window.cancelRequestAnimationFrame
|
|
|
|
|
|| window.webkitCancelAnimationFrame
|
|
|
|
|
|| window.webkitCancelRequestAnimationFrame
|
|
|
|
|
|| window.mozCancelRequestAnimationFrame
|
|
|
|
|
|| window.oCancelRequestAnimationFrame
|
|
|
|
|
|| window.msCancelRequestAnimationFrame
|
|
|
|
|
|| clearTimeout)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-01-24 03:12:01 +04:00
|
|
|
/**********************************************************************
|
|
|
|
|
* vim:set ts=4 sw=4 : */
|