Last active
December 12, 2015 00:48
-
-
Save iwyg/4686181 to your computer and use it in GitHub Desktop.
simple Backbone Slideview
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (define, Modernizr, undefined) { | |
define(['underscore', 'modules/mod_sequence', 'plugins/bgpos'], function (_, sequence) { | |
if ($.browser.opera) { | |
Modernizr.csstransitions = false; | |
Modernizr.csstransforms = false; | |
$('html').removeClass('csstransitions csstransforms').addClass('no-csstransitions no-csstransforms'); | |
} | |
var slice = Array.prototype.slice, | |
hasTransition = Modernizr.csstransitions, | |
isOldOpera = ($.browser.opera && $.browser.version < 12) ? true : false, | |
hasTransforms = Modernizr.csstransforms, | |
has3dTransforms = Modernizr.csstransforms3d, | |
translateOpen = has3dTransforms ? 'translate3d(' : 'translate(', | |
translateClose = has3dTransforms ? ', 0)' : ')', | |
cubicOpen = 'cubic-bezier(', | |
cubicClose = ')', | |
hasOpacity = $.support.opacity, | |
transform = Modernizr.prefixed('transform'), | |
transition = Modernizr.prefixed('transition'), | |
transitionEnd = $.browser.webkit ? 'webkitTransitionEnd' : $.browser.msie ? 'msTransitionEnd' : $.browser.opera ? 'oTransitionEnd' : $.browser.mozilla ? 'transitionend' : 'transitionend', | |
cssTransform = (function () { | |
var l = 'transform'.length, | |
trans; | |
if (transform.length > l) { | |
return '-' + transform.toLowerCase().split('transform')[0] + '-transform'; | |
} | |
else { | |
return 'transform'; | |
} | |
}()), | |
clearTransition = (function () { | |
var props = 'Property Duration TimingFunction Delay'.split(' '), | |
l = props.length, i = 0, exports = {}; | |
for (; i < l; ++i) { | |
exports[transition + props[i]] = ''; | |
} | |
return exports; | |
}()); | |
$.wait = function (time) { | |
var dfr = $.Deferred(); | |
setTimeout(dfr.resolve, time); | |
return dfr.promise(); | |
}; | |
var killTimers = []; | |
var transM = { | |
transform: function (coords) { | |
return translateOpen + coords.join(', ') + translateClose; | |
}, | |
scale: function (coords) { | |
return 'scale(' + coords.join(', ') + ')'; | |
} | |
} | |
function removeFilter() { | |
this.style.removeAttribute('filter'); | |
} | |
function getCssProperty(prop) { | |
prop = prop.toLowerCase(); | |
var p = Modernizr.prefixed(prop), l = p.length; | |
if (prop.length < l) { | |
return '-' + p.toLowerCase().split(prop)[0] + '-' + prop; | |
} else { | |
return prop; | |
} | |
} | |
function setTiming(coords) { | |
return cubicOpen + coords.join(', ') + cubicClose; | |
} | |
function setTransform(coords) { | |
return translateOpen + coords.join(', ') + translateClose; | |
} | |
// param property = { | |
// property: position | |
// } | |
// param timing = { | |
// duration: seconds, | |
// delay: seconds, | |
// easing: timing | |
// } | |
function setTransition(property, timing) { | |
var prop = Object.keys(property), | |
//val = property[prop], | |
idx = prop.indexOf('type'), | |
p = {}; | |
idx >= 0 && prop.splice(idx, 1); | |
//p[transition] = [prop.join(', '), timing.duration + 's', setTiming(timing.easing), timing.delay && timing.delay + 's' || ''].join(' '); | |
p[transition + 'Property'] = prop.join(', '); | |
p[transition + 'Duration'] = timing.duration + 's'; | |
p[transition + 'TimingFunction'] = setTiming(timing.easing); | |
p[transition + 'Delay'] = timing.delay && timing.delay + 's' || 'initial'; | |
this.css(p); | |
} | |
function handleCallback(elem) { | |
var elem = evt.data.element, ki; | |
if (evt.target !== elem[0]) { | |
return; | |
} | |
elem.off(transitionEnd, handleCallback); | |
elem.css(clearTransition); | |
if ($.isFunction(this)) { | |
this.call(elem, {prop: cssTransform}); | |
} | |
} | |
var cbStore = {}; | |
function EventObj(elem, id, cb) { | |
this.elem = elem; | |
this.id = id; | |
this.callback = cb; | |
} | |
function _fxq(id, callback) { | |
cbStore[id] = callback; | |
} | |
function doAnimation(prop, val, callback, id) { | |
var el = this; | |
setTransition.apply(this, arguments); | |
el[0].addEventListener(transitionEnd, new EventObj(el, id, callback)); | |
$.wait(35).then(function () { | |
var trans = prop[cssTransform]; | |
if (prop.type && trans) { | |
prop[transform] = transM[prop.type](trans); | |
// getting DOM property forces a reflow; | |
// forcing a reflow ensures all browsers will apply transition (I'm looking at you, FF) | |
el.height(); | |
//p[transform] = $.isArray(value) ? transM[prop.type](value) : value; | |
} | |
delete prop[cssTransform]; | |
delete prop.type; | |
el.css(prop); | |
}); | |
} | |
EventObj.prototype = { | |
handleEvent : function (evt) { | |
if (evt.target !== this.elem[0]) { | |
return; | |
} | |
this.elem[0].removeEventListener(transitionEnd, this); | |
this.elem.css(clearTransition); | |
if ($.isFunction(this.callback)) { | |
this.callback.call(this.elem, {prop: cssTransform}); | |
delete cbStore[this.id]; | |
} | |
} | |
}; | |
function animate(elem, prop, val, callback, q) { | |
q = typeof q === 'boolean' ? q : true; | |
var animID = 'anim' + _.uniqueId(); | |
//_fxq.apply(elem, [animID, prop, val, callback, q]); | |
_fxq.call(elem, animID, callback); | |
doAnimation.apply(elem, [prop, val, callback, animID]); | |
return this; | |
} | |
/* | |
if (typeof navigator.platform === 'string' && navigator.platform.toLowerCase().match(/mac/)) { | |
if (/chrome/.test(navigator.userAgent.toLowerCase())) { | |
hasTransforms = false; | |
hasTransition = false; | |
} | |
} | |
*/ | |
if (hasTransforms && hasTransition && !isOldOpera) { | |
return { | |
cssAnimation: true, | |
getCssProperty: getCssProperty, | |
slideVertical: function (elem, props, timing, callback) { | |
var p = {}; | |
props[cssTransform] = [0, props.to]; | |
props.type = 'transform'; | |
delete props.to; | |
delete props.direction; | |
if (timing.duration === 0) { | |
elem.css(props); | |
return this; | |
} | |
animate(elem, props, timing, callback); | |
return this; | |
}, | |
slideHorizontal: function (elem, props, timing, callback) { | |
var p = {}; | |
props[cssTransform] = [props.to, 0]; | |
props.type = 'transform'; | |
delete props.to; | |
delete props.direction; | |
if (timing.duration === 0) { | |
elem.css(props); | |
return this; | |
} | |
animate(elem, props, timing, callback); | |
return this; | |
}, | |
fadeOut: function (elem, timing, callback, q) { | |
var p = {opacity: 0}; | |
animate(elem, p, timing, function () { | |
elem.css({display: 'none'}); | |
$.isFunction(callback) && callback(); | |
}, q); | |
return this; | |
}, | |
fadeIn: function (elem, timing, callback, q) { | |
var p = {opacity: 1}; | |
elem.css({display: 'block', opacity: 0}); | |
animate(elem, p, timing, function () { | |
$.isFunction(callback) && callback(); | |
}, q); | |
return this; | |
}, | |
fadeTo: function (elem, props, timing, callback, q) { | |
var p = {opacity: props.to}; | |
animate(elem, p, timing, callback, q); | |
return this; | |
}, | |
fadeToSeq: function (elem, props, timing, callback) { | |
var that = this, | |
elems = elem, l = elems.length; | |
$.when.apply($, sequence(timing.steps || elems.length, elems.length, timing.seqDuration || 4050, function (i, delay, dfr) { | |
timing.delay = Math.round(delay) / 1000; | |
that.fadeTo($(elems[i]), props, timing, dfr.resolve, false); | |
})).done($.isFunction(callback) && callback); | |
return this; | |
}, | |
animate: animate | |
}; | |
} else { | |
function handle(callback, prop) { | |
var elem = $(this); | |
/*if (!hasOpacity) { | |
if (prop && (prop.prop && (prop.prop === 'opacity'))) { | |
//removeFilter.call(this); | |
} | |
}*/ | |
if ($.isFunction(callback)) { | |
callback.call(elem, prop); | |
} | |
} | |
return { | |
cssAnimation: false, | |
getCssProperty: function () { | |
return false; | |
}, | |
slideVertical : function (elem, props, timing, callback) { | |
var dir = props.direction; | |
if (dir) { | |
props[dir] = props.to; | |
} else { | |
props.top = props.to; | |
} | |
delete props.to; | |
delete props.direction; | |
elem.animate(props, timing.duration * 1000, $.bez(timing.easing), function () { | |
handle.call(this, callback, {prop: dir || 'top'}); | |
}); | |
return this; | |
}, | |
slideHorizontal: function (elem, props, timing, callback) { | |
var dir = props.direction; | |
if (dir) { | |
props[dir] = props.to; | |
} else { | |
props.left = props.to; | |
} | |
delete props.to; | |
delete props.direction; | |
elem.animate(props, timing.duration * 1000, $.bez(timing.easing), function () { | |
handle.call(this, callback, {prop: dir || 'left'}); | |
}); | |
return this; | |
}, | |
fadeIn: function (elem, timing, callback) { | |
var p = {opacity: 1}; | |
elem.css({opacity: 0, display: 'block'}); | |
elem.animate(p, timing.duration * 1000, $.bez(timing.easing), function () { | |
handle.call(this, callback, {prop: 'opacity'}); | |
}); | |
return this; | |
}, | |
fadeOut: function (elem, timing, callback) { | |
var p = {opacity: 0}; | |
elem.animate(p, timing.duration * 1000, $.bez(timing.easing), function () { | |
handle.call(this, callback); | |
elem.css({display: 'none'}); | |
}); | |
return this; | |
}, | |
fadeTo: function (elem, props, timing, callback) { | |
var p = {opacity: props.to}, pp = props.to === 1 ? {prop: 'opacity'} : undefined; | |
elem.delay(timing.delay).animate(p, timing.duration * 1000, $.bez(timing.easing), function () { | |
handle.call(this, callback, pp); | |
}); | |
return this; | |
}, | |
fadeToSeq: function (elem, props, timing, callback) { | |
var that = this, | |
elems = elem, l = elems.length; | |
$.when.apply($, sequence(timing.steps || elems.length, elems.length, timing.seqDuration || 450, function (i, delay, dfr) { | |
timing.delay = delay; | |
that.fadeTo($(elems[i]), props, timing, function () { | |
dfr.resolve(); | |
handle.call(this); | |
}); | |
})).done(callback && callback); | |
return this; | |
}, | |
animate: function (elem, props, timing, callback) { | |
var t = props.backgroundPosition || props['background-position'], tt; | |
if (t) { | |
tt = t.split(' '); | |
props.backgroundPositionX = tt[0] || 0; | |
props.backgroundPositionY = tt[1] || 0; | |
delete props.backgroundPosition; | |
delete props['background-position']; | |
} | |
elem.animate(props, timing.duration * 1000, $.bez(timing.easing), function () { | |
handle.call(this, callback); | |
}); | |
return this; | |
} | |
}; | |
} | |
}); | |
}(this.define, this.Modernizr)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (define) { | |
define(['jquery', 'underscore', 'modules/mod_rotator', 'templates/templates'], function ($, _, Rotator, templates) { | |
var cachedItems = {}, Slider; | |
Slider = Rotator.extend({ | |
initialize: function () { | |
this._constructOrigin.apply(this, arguments); | |
this.render = _.once(this.render); | |
}, | |
render: function () { | |
var cached = this.getItems(), view = this, list = this.addItem(this.model), items; | |
this.$el.html(list); | |
items = _.map(this.$el.children(), function (item) { | |
return $(item); | |
}); | |
cached.push.apply(cached, items); | |
this.trigger('ready.' + this.cid, this); | |
}, | |
renderItem: function (model) { | |
var template = templates.gallery_image; | |
return template(model.toJSON()); | |
}, | |
addItem: function (model) { | |
var html = templates.gallery_image(model.toJSON()); | |
return html; | |
}, | |
getCurrentIndex: function () { | |
return this.model.get('displays'); | |
}, | |
setCurrentIndex: function (index) { | |
this.model.set('displays', index); | |
}, | |
getItemAt: function (index) { | |
return this.getItems()[index]; | |
}, | |
}); | |
return Slider; | |
}); | |
}(this.define)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (define) { | |
define(function (require) { | |
var $ = require('jquery'), | |
_ = require('underscore'), | |
Backbone = require('backbone'), | |
fx = require('modules/mod_animation'), | |
animators = {}, | |
slidelock = {}, | |
cachedItems = {}, | |
Rotator; | |
function slide(type, position, time, easing, callback) { | |
fx[type](this, {to: position}, {duration: time, easing: easing, delay: 0}, callback); | |
} | |
function ready() { | |
this.getItems()[this.getCurrentIndex()] | |
.removeClass('prev next') | |
.addClass('current') | |
.nextAll() | |
.addClass('next') | |
.end() | |
.prevAll() | |
.addClass('prev'); | |
this.trigger('ready'); | |
} | |
function setClasses(item) { | |
item.removeClass('next prev').addClass('current'); | |
item.prevAll() | |
.removeClass('current next') | |
.addClass('prev').end() | |
.nextAll().removeClass('current prev') | |
.addClass('next'); | |
} | |
Rotator = Backbone.View.extend({ | |
_constructOrigin: function () { | |
Rotator.prototype.initialize.apply(this, arguments); | |
}, | |
initialize: function (options) { | |
this.options = _.extend(_.clone(Rotator.defaults), options || {}); | |
this.el.id = this.cid; | |
this.el.className = this.options.type === 'slideHorizontal' ? 'slide-h' : this.options.type === 'slideVertical' ? 'slide-v' : ''; | |
this.setCurrentIndex(this.options.start || 0); | |
this.on('ready.' + this.cid, _.bind(ready, this)); | |
cachedItems[this.cid] = []; | |
}, | |
next: function () { | |
var current = this.getCurrentIndex(), | |
items = this.getItems(), | |
item = current + 1 === items.length ? (this.options.carousel ? 0 : false) : current + 1; | |
this.to(item); | |
return this; | |
}, | |
prev: function () { | |
var current = this.getCurrentIndex(), | |
items = this.getItems(), | |
item = current === 0 ? (this.options.carousel ? items.length - 1 : false) : current - 1; | |
this.to(item); | |
return this; | |
}, | |
to: function (i) { | |
var this_id = this.cid, current = this.getCurrentIndex(); | |
if ((i === false || i < 0) || !!slidelock[this_id] || i === current) { | |
return false; | |
} | |
slidelock[this_id] = true; | |
var item = this.getItems()[i], | |
currentItem = this.getItemAt(current).css({display: 'block'}), | |
nextItem = this.getItemAt(i).css({display: 'block'}), | |
that = this, to, | |
easing = this.options.easing, | |
oldZIndex = parseInt(currentItem.css('z-index'), 10), | |
zIndex = isNaN(oldZIndex) ? 2 : oldZIndex; | |
this.current = this.requested = i; | |
this.requested = i; | |
this.trigger('beforeSlide', i, nextItem, currentItem); | |
to = current < i ? '-100%' : '100%'; | |
this.setCurrentIndex(i); | |
nextItem.css({zIndex: zIndex}); | |
currentItem.css({zIndex: zIndex - 1}); | |
slide.call(currentItem, this.options.type, to, this.options.transitionTime || 1, this.calcEasing(easing), function (property) { | |
currentItem[0].style.display = 'none'; | |
property && currentItem.css(property.prop, ''); | |
}); | |
slide.call(nextItem, this.options.type, 0, this.options.transitionTime || 1, easing, function (property) { | |
setClasses(this); | |
//delete that.slidelock; | |
slidelock[this_id] = false; | |
that.trigger('afterSlide', current, nextItem, 'afterSlide', that.id, that.name); | |
}); | |
return this; | |
}, | |
getItems: function (easing) { | |
return cachedItems[this.cid]; | |
}, | |
getItemAt: function (index) { | |
return this.getItems()[index]; | |
}, | |
// @return the current index of item to be inserted | |
getPosition: function () { | |
throw ('Abstract method `getPosition` has not been declared'); | |
}, | |
getCurrentIndex: function () { | |
throw ('Abstract method `getCurrentIndex` has not been declared'); | |
}, | |
setCurrentIndex: function () { | |
throw ('Abstract method `setCurrentIndex` has not been declared'); | |
}, | |
calcEasing: function (easing) { | |
return [Math.min(easing[0] + 0.04, 1), Math.min(easing[1] - 0.18, 1), Math.min(easing[2] + 0.21, 1), Math.min(easing[3], 1)]; | |
} | |
}); | |
Rotator.defaults = { | |
transitionTime: 0.8, | |
carousel: true, | |
start: 0, | |
className: 'revolve', | |
type: 'slideHorizontal', | |
easing: [0.1, 0.6, 0, 1] | |
}; | |
return Rotator; | |
}); | |
}(this.define)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment