From d96d0cb3d2c7a21e2153a335d68852d388e0ba92 Mon Sep 17 00:00:00 2001 From: Tyler Sticka Date: Fri, 2 Aug 2013 14:21:22 -0700 Subject: [PATCH] theoretically successful History.js integration, still WIP (#5) --- index.html | 2 +- lib/simpleslideview.js | 56 ++++++++++++++++++-------------------- lib/simpleslideview.min.js | 2 +- src/simpleslideview.coffee | 38 ++++++++++++-------------- 4 files changed, 45 insertions(+), 53 deletions(-) diff --git a/index.html b/index.html index 6721cfb..659f73b 100644 --- a/index.html +++ b/index.html @@ -113,7 +113,7 @@

Where to get it

// the view container, any elements therein with a class of // 'view' will be a view, and the only default option we're // overriding is the duration of the animations. -$('.views').simpleSlideView({ duration: 250, useHistoryJS: true }); +$('.views').simpleSlideView({ duration: 250, useHistory: true }); diff --git a/lib/simpleslideview.js b/lib/simpleslideview.js index 231435b..50343b5 100644 --- a/lib/simpleslideview.js +++ b/lib/simpleslideview.js @@ -18,7 +18,6 @@ scrollOnStart: $.scrollTo != null ? 'scrollTo' : false, scrollToContainerTop: true, maintainViewportHeight: null, - useHistoryJS: false, dataAttrEvent: 'click', dataAttr: { push: 'pushview', @@ -37,7 +36,8 @@ deferred: 'slideViewDeferred', viewChangeStart: 'viewChangeStart', viewChangeEnd: 'viewChangeEnd' - } + }, + useHistory: null }; resetStyles = function(el, styles) { @@ -81,13 +81,6 @@ this.$views = typeof this.options.views === 'string' ? this.$container.find(this.options.views) : $(this.options.views); this.$activeView = this.options.activeView != null ? $(this.options.activeView) : this.$views.first(); this.isActive = false; - this.activeId = 0; - if (this.options.useHistoryJS) { - History.pushState({ - id: this.activeId, - index: this.$views.index(this.$activeView) - }, '', ''); - } if (this.options.deferOn) { this.$container.trigger(this.options.eventNames.deferred); } else { @@ -135,17 +128,17 @@ } }); } - if (this.options.useHistoryJS) { + if (this.options.useHistory) { + this.historyID = 0; + History.replaceState({ + id: this.historyID, + viewIndex: this.$views.index(this.$activeView) + }, null, ''); $(window).on('statechange', function() { - var action, state; - console.log('statechange'); + var state; state = History.getState(); - if (state.data.id !== _this.activeId) { - console.log(state.data.index); - action = state.data.id > _this.activeId ? 'push' : 'pop'; - _this.activeId = state.data.id; - return _this.changeView(_this.$views.get(state.data.index), action, false); - } + _this.changeView(_this.$views.get(state.data.viewIndex), (state.data.id > _this.historyID ? 'push' : 'pop'), false); + return _this.historyID = state.data.id; }); } return this.$container.trigger(this.options.eventNames.on); @@ -180,18 +173,21 @@ return this.off(); }; - SimpleSlideView.prototype.changeView = function(targetView, action, pushState) { + SimpleSlideView.prototype.changeView = function(targetView, action, useHistory) { var $bothViews, $targetView, animateHeight, animateHeightCallback, containerWidth, eventArgs, inAnimProps, outAnimProps, resetProps, top, transformProp, translateAfter, translateBefore, _this = this; if (action == null) { action = 'push'; } - if (pushState == null) { - pushState = true; + if (useHistory == null) { + useHistory = this.options.useHistory; } eventArgs = [targetView, action]; - this.$container.trigger(this.options.eventNames.viewChangeStart, eventArgs); $targetView = $(targetView); + if ($targetView[0] === this.$activeView[0]) { + return; + } + this.$container.trigger(this.options.eventNames.viewChangeStart, eventArgs); $bothViews = this.$activeView.add($targetView); containerWidth = outerWidth(this.$container); outAnimProps = {}; @@ -233,13 +229,6 @@ } animateHeightCallback = function() { resetStyles(_this.$container, ['height', 'overflow', 'position', 'width']); - if (_this.options.useHistoryJS && pushState) { - _this.activeId += 1; - History.pushState({ - id: _this.activeId, - index: _this.$views.index($targetView) - }, '', ''); - } return _this.$container.trigger(_this.options.eventNames.viewChangeEnd, eventArgs); }; animateHeight = function() { @@ -270,7 +259,14 @@ } this.$activeView.removeClass(this.options.classNames.activeView); $targetView.addClass(this.options.classNames.activeView); - return this.$activeView = $targetView; + this.$activeView = $targetView; + if (useHistory) { + this.historyID += 1; + return History.pushState({ + id: this.historyID, + viewIndex: this.$views.index(this.$activeView) + }, null, ''); + } }; SimpleSlideView.prototype.pushView = function(targetView) { diff --git a/lib/simpleslideview.min.js b/lib/simpleslideview.min.js index 71d1f75..c94f529 100644 --- a/lib/simpleslideview.min.js +++ b/lib/simpleslideview.min.js @@ -1 +1 @@ -!function(){var a,b,c,d,e,f;a="undefined"!=typeof jQuery&&null!==jQuery?jQuery:Zepto,c={views:".view",activeView:null,deferOn:!1,duration:a.fx.speeds._default,easing:"undefined"!=typeof Zepto&&null!==Zepto?"ease-out":"swing",useTransformProps:"undefined"!=typeof Zepto&&null!==Zepto,use3D:"undefined"!=typeof Modernizr&&null!==Modernizr&&Modernizr.csstransforms3d,cssPrefix:null!=a.fx.cssPrefix?a.fx.cssPrefix:"",resizeHeight:!0,heightDuration:null,deferHeightChange:"undefined"!=typeof Zepto&&null!==Zepto,scrollOnStart:null!=a.scrollTo?"scrollTo":!1,scrollToContainerTop:!0,maintainViewportHeight:null,useHistoryJS:!1,dataAttrEvent:"click",dataAttr:{push:"pushview",pop:"popview"},classNames:{container:"SimpleSlideView-container",view:"SimpleSlideView-view",activeView:"SimpleSlideView-view-active"},eventNames:{on:"slideViewOn",off:"slideViewOff",beforeOn:"slideViewBeforeOn",beforeOff:"slideViewBeforeOff",deferred:"slideViewDeferred",viewChangeStart:"viewChangeStart",viewChangeEnd:"viewChangeEnd"}},f=function(b,c){var d,e,f,g,h;for(d=a(b),e={},g=0,h=c.length;h>g;g++)f=c[g],e[f]="";return d.css(e)},d=function(b){return null!=a.fn.outerHeight?a(b).outerHeight():a(b).height()},e=function(b){return null!=a.fn.outerWidth?a(b).outerWidth():a(b).width()},b=function(){function b(b,d){this.options=a.extend(!0,{},c,d),null==this.options.heightDuration&&(this.options.heightDuration=this.options.duration),null==this.options.maintainViewportHeight&&(this.options.maintainViewportHeight=this.options.resizeHeight&&this.options.scrollOnStart),null==window.innerHeight&&(this.options.maintainViewportHeight=!1),this.$container=a(b),this.$views="string"==typeof this.options.views?this.$container.find(this.options.views):a(this.options.views),this.$activeView=null!=this.options.activeView?a(this.options.activeView):this.$views.first(),this.isActive=!1,this.activeId=0,this.options.useHistoryJS&&History.pushState({id:this.activeId,index:this.$views.index(this.$activeView)},"",""),this.options.deferOn?this.$container.trigger(this.options.eventNames.deferred):this.on()}return b.prototype.on=function(){var b=this;if(!this.isActive)return this.$container.trigger(this.options.eventNames.beforeOn),this.isActive=!0,this.$container.addClass(this.options.classNames.container),this.$views.addClass(this.options.classNames.view),this.$activeView.addClass(this.options.classNames.activeView),this.$views.not(this.$activeView).css("display","none"),this.options.maintainViewportHeight&&(this.lastViewportHeight=window.innerHeight),null!=this.options.dataAttrEvent&&(this.$container.on(this.options.dataAttrEvent,"[data-"+this.options.dataAttr.push+"]",function(c){var d,e;return d=a(c.currentTarget),e=d.data(b.options.dataAttr.push),e.length||(e=d.attr("href")),e.length?(c.preventDefault(),b.pushView(e)):void 0}),this.$container.on(this.options.dataAttrEvent,"[data-"+this.options.dataAttr.pop+"]",function(c){var d,e;return d=a(c.currentTarget),e=d.data(b.options.dataAttr.pop),e.length||(e=d.attr("href")),e.length?(c.preventDefault(),b.popView(e)):void 0})),this.options.useHistoryJS&&a(window).on("statechange",function(){var a,c;return console.log("statechange"),c=History.getState(),c.data.id!==b.activeId?(console.log(c.data.index),a=c.data.id>b.activeId?"push":"pop",b.activeId=c.data.id,b.changeView(b.$views.get(c.data.index),a,!1)):void 0}),this.$container.trigger(this.options.eventNames.on)},b.prototype.off=function(){return this.isActive?(this.$container.trigger(this.options.eventNames.beforeOff),this.isActive=!1,this.$container.removeClass(this.options.classNames.container),this.$views.removeClass(this.options.classNames.view+" "+this.options.classNames.activeView),this.$views.css("display",""),this.options.maintainViewportHeight&&a("html").css("min-height",""),null!=this.options.dataAttrEvent&&(this.$container.off(this.options.dataAttrEvent,"[data-"+this.options.dataAttr.push+"]"),this.$container.off(this.options.dataAttrEvent,"[data-"+this.options.dataAttr.pop+"]")),this.$container.trigger(this.options.eventNames.off)):void 0},b.prototype.toggle=function(a){return null==a&&(a=!this.isActive),a?this.on():this.off()},b.prototype.changeView=function(b,c,g){var h,i,j,k,l,m,n,o,p,q,r,s,t,u=this;return null==c&&(c="push"),null==g&&(g=!0),m=[b,c],this.$container.trigger(this.options.eventNames.viewChangeStart,m),i=a(b),h=this.$activeView.add(i),l=e(this.$container),o={},n={},p=["left","position","top","width"],q=this.options.scrollOnStart&&this.options.scrollToContainerTop?this.$container.position().top:0,this.options.scrollOnStart&&a(window).scrollTop()>q&&("string"==typeof this.options.scrollOnStart&&null!=a[this.options.scrollOnStart]?a[this.options.scrollOnStart](q,this.options.duration):window.scrollTo(0,q)),this.$container.css({height:d(this.$container),overflow:"hidden",position:"relative",width:"100%"}),h.css({position:"absolute",top:0,width:l}),this.options.useTransformProps?(r=this.options.cssPrefix+"transform",t=this.options.use3D?"translate3d(":"translateX(",s=this.options.use3D?", 0, 0)":")",p.push(r),h.css("left",0),i.css(r,t+("push"===c?100:-100)+"%"+s),o[r]=t+("push"===c?-100:100)+"%"+s,n[r]=t+"0"+s):(this.$activeView.css("left",0),i.css("left","push"===c?l:-1*l),o.left="push"===c?-1*l:l,n.left=0),k=function(){return f(u.$container,["height","overflow","position","width"]),u.options.useHistoryJS&&g&&(u.activeId+=1,History.pushState({id:u.activeId,index:u.$views.index(i)},"","")),u.$container.trigger(u.options.eventNames.viewChangeEnd,m)},j=function(){return u.options.resizeHeight?(u.options.maintainViewportHeight&&window.innerHeight>u.lastViewportHeight&&(u.lastViewportHeight=window.innerHeight,a("html").css("min-height",u.lastViewportHeight+q+"px")),u.$container.animate({height:d(i)},u.options.heightDuration,u.options.easing,k)):k()},i.show(),this.$activeView.animate(o,this.options.duration,this.options.easing,function(){return f(this,p).hide()}),i.animate(n,this.options.duration,this.options.easing,function(){return f(i,p),u.options.deferHeightChange?j():void 0}),this.options.deferHeightChange||j(),this.$activeView.removeClass(this.options.classNames.activeView),i.addClass(this.options.classNames.activeView),this.$activeView=i},b.prototype.pushView=function(a){return this.changeView(a,"push")},b.prototype.popView=function(a){return this.changeView(a,"pop")},b}(),a.fn.simpleSlideView=function(c,d){return null==c&&(c={}),"object"!=typeof c&&(c={views:c}),"object"==typeof d&&a.extend(c,d),new b(this,c)}}.call(this); \ No newline at end of file +!function(){var a,b,c,d,e,f;a="undefined"!=typeof jQuery&&null!==jQuery?jQuery:Zepto,c={views:".view",activeView:null,deferOn:!1,duration:a.fx.speeds._default,easing:"undefined"!=typeof Zepto&&null!==Zepto?"ease-out":"swing",useTransformProps:"undefined"!=typeof Zepto&&null!==Zepto,use3D:"undefined"!=typeof Modernizr&&null!==Modernizr&&Modernizr.csstransforms3d,cssPrefix:null!=a.fx.cssPrefix?a.fx.cssPrefix:"",resizeHeight:!0,heightDuration:null,deferHeightChange:"undefined"!=typeof Zepto&&null!==Zepto,scrollOnStart:null!=a.scrollTo?"scrollTo":!1,scrollToContainerTop:!0,maintainViewportHeight:null,dataAttrEvent:"click",dataAttr:{push:"pushview",pop:"popview"},classNames:{container:"SimpleSlideView-container",view:"SimpleSlideView-view",activeView:"SimpleSlideView-view-active"},eventNames:{on:"slideViewOn",off:"slideViewOff",beforeOn:"slideViewBeforeOn",beforeOff:"slideViewBeforeOff",deferred:"slideViewDeferred",viewChangeStart:"viewChangeStart",viewChangeEnd:"viewChangeEnd"},useHistory:null},f=function(b,c){var d,e,f,g,h;for(d=a(b),e={},g=0,h=c.length;h>g;g++)f=c[g],e[f]="";return d.css(e)},d=function(b){return null!=a.fn.outerHeight?a(b).outerHeight():a(b).height()},e=function(b){return null!=a.fn.outerWidth?a(b).outerWidth():a(b).width()},b=function(){function b(b,d){this.options=a.extend(!0,{},c,d),null==this.options.heightDuration&&(this.options.heightDuration=this.options.duration),null==this.options.maintainViewportHeight&&(this.options.maintainViewportHeight=this.options.resizeHeight&&this.options.scrollOnStart),null==window.innerHeight&&(this.options.maintainViewportHeight=!1),this.$container=a(b),this.$views="string"==typeof this.options.views?this.$container.find(this.options.views):a(this.options.views),this.$activeView=null!=this.options.activeView?a(this.options.activeView):this.$views.first(),this.isActive=!1,this.options.deferOn?this.$container.trigger(this.options.eventNames.deferred):this.on()}return b.prototype.on=function(){var b=this;if(!this.isActive)return this.$container.trigger(this.options.eventNames.beforeOn),this.isActive=!0,this.$container.addClass(this.options.classNames.container),this.$views.addClass(this.options.classNames.view),this.$activeView.addClass(this.options.classNames.activeView),this.$views.not(this.$activeView).css("display","none"),this.options.maintainViewportHeight&&(this.lastViewportHeight=window.innerHeight),null!=this.options.dataAttrEvent&&(this.$container.on(this.options.dataAttrEvent,"[data-"+this.options.dataAttr.push+"]",function(c){var d,e;return d=a(c.currentTarget),e=d.data(b.options.dataAttr.push),e.length||(e=d.attr("href")),e.length?(c.preventDefault(),b.pushView(e)):void 0}),this.$container.on(this.options.dataAttrEvent,"[data-"+this.options.dataAttr.pop+"]",function(c){var d,e;return d=a(c.currentTarget),e=d.data(b.options.dataAttr.pop),e.length||(e=d.attr("href")),e.length?(c.preventDefault(),b.popView(e)):void 0})),this.options.useHistory&&(this.historyID=0,History.replaceState({id:this.historyID,viewIndex:this.$views.index(this.$activeView)},null,""),a(window).on("statechange",function(){var a;return a=History.getState(),b.changeView(b.$views.get(a.data.viewIndex),a.data.id>b.historyID?"push":"pop",!1),b.historyID=a.data.id})),this.$container.trigger(this.options.eventNames.on)},b.prototype.off=function(){return this.isActive?(this.$container.trigger(this.options.eventNames.beforeOff),this.isActive=!1,this.$container.removeClass(this.options.classNames.container),this.$views.removeClass(this.options.classNames.view+" "+this.options.classNames.activeView),this.$views.css("display",""),this.options.maintainViewportHeight&&a("html").css("min-height",""),null!=this.options.dataAttrEvent&&(this.$container.off(this.options.dataAttrEvent,"[data-"+this.options.dataAttr.push+"]"),this.$container.off(this.options.dataAttrEvent,"[data-"+this.options.dataAttr.pop+"]")),this.$container.trigger(this.options.eventNames.off)):void 0},b.prototype.toggle=function(a){return null==a&&(a=!this.isActive),a?this.on():this.off()},b.prototype.changeView=function(b,c,g){var h,i,j,k,l,m,n,o,p,q,r,s,t,u=this;return null==c&&(c="push"),null==g&&(g=this.options.useHistory),m=[b,c],i=a(b),i[0]!==this.$activeView[0]?(this.$container.trigger(this.options.eventNames.viewChangeStart,m),h=this.$activeView.add(i),l=e(this.$container),o={},n={},p=["left","position","top","width"],q=this.options.scrollOnStart&&this.options.scrollToContainerTop?this.$container.position().top:0,this.options.scrollOnStart&&a(window).scrollTop()>q&&("string"==typeof this.options.scrollOnStart&&null!=a[this.options.scrollOnStart]?a[this.options.scrollOnStart](q,this.options.duration):window.scrollTo(0,q)),this.$container.css({height:d(this.$container),overflow:"hidden",position:"relative",width:"100%"}),h.css({position:"absolute",top:0,width:l}),this.options.useTransformProps?(r=this.options.cssPrefix+"transform",t=this.options.use3D?"translate3d(":"translateX(",s=this.options.use3D?", 0, 0)":")",p.push(r),h.css("left",0),i.css(r,t+("push"===c?100:-100)+"%"+s),o[r]=t+("push"===c?-100:100)+"%"+s,n[r]=t+"0"+s):(this.$activeView.css("left",0),i.css("left","push"===c?l:-1*l),o.left="push"===c?-1*l:l,n.left=0),k=function(){return f(u.$container,["height","overflow","position","width"]),u.$container.trigger(u.options.eventNames.viewChangeEnd,m)},j=function(){return u.options.resizeHeight?(u.options.maintainViewportHeight&&window.innerHeight>u.lastViewportHeight&&(u.lastViewportHeight=window.innerHeight,a("html").css("min-height",u.lastViewportHeight+q+"px")),u.$container.animate({height:d(i)},u.options.heightDuration,u.options.easing,k)):k()},i.show(),this.$activeView.animate(o,this.options.duration,this.options.easing,function(){return f(this,p).hide()}),i.animate(n,this.options.duration,this.options.easing,function(){return f(i,p),u.options.deferHeightChange?j():void 0}),this.options.deferHeightChange||j(),this.$activeView.removeClass(this.options.classNames.activeView),i.addClass(this.options.classNames.activeView),this.$activeView=i,g?(this.historyID+=1,History.pushState({id:this.historyID,viewIndex:this.$views.index(this.$activeView)},null,"")):void 0):void 0},b.prototype.pushView=function(a){return this.changeView(a,"push")},b.prototype.popView=function(a){return this.changeView(a,"pop")},b}(),a.fn.simpleSlideView=function(c,d){return null==c&&(c={}),"object"!=typeof c&&(c={views:c}),"object"==typeof d&&a.extend(c,d),new b(this,c)}}.call(this); \ No newline at end of file diff --git a/src/simpleslideview.coffee b/src/simpleslideview.coffee index 317db59..3debac7 100644 --- a/src/simpleslideview.coffee +++ b/src/simpleslideview.coffee @@ -74,9 +74,6 @@ defaults = # iOS Safari. maintainViewportHeight: null - # WIP! - useHistoryJS: false - # The event that the magic data-attribute events will # be bound to. If 'false', no events will be bound. dataAttrEvent: 'click' @@ -106,6 +103,9 @@ defaults = viewChangeStart: 'viewChangeStart' viewChangeEnd: 'viewChangeEnd' + # WIP! + useHistory: null + resetStyles = (el, styles) -> $el = $(el) reset = {} @@ -130,9 +130,6 @@ class SimpleSlideView @$views = if typeof @options.views is 'string' then @$container.find(@options.views) else $(@options.views) @$activeView = if @options.activeView? then $(@options.activeView) else @$views.first() @isActive = false - @activeId = 0 - if @options.useHistoryJS - History.pushState { id: @activeId, index: @$views.index(@$activeView) }, '', '' if @options.deferOn @$container.trigger @options.eventNames.deferred else @@ -163,18 +160,13 @@ class SimpleSlideView if target.length event.preventDefault() @popView target - if @options.useHistoryJS + if @options.useHistory + @historyID = 0 + History.replaceState { id: @historyID, viewIndex: @$views.index(@$activeView) }, null, '' $(window).on 'statechange', () => - console.log 'statechange' state = History.getState() - if state.data.id isnt @activeId - console.log state.data.index - action = if state.data.id > @activeId then 'push' else 'pop' - @activeId = state.data.id - @changeView @$views.get(state.data.index), action, false - # $(window).on 'popstate', () -> - # console.log 'popstate' - # console.log History.getState() + @changeView @$views.get(state.data.viewIndex), (if state.data.id > @historyID then 'push' else 'pop'), false + @historyID = state.data.id @$container.trigger @options.eventNames.on off: () -> @@ -195,10 +187,11 @@ class SimpleSlideView return @on() if activate return @off() - changeView: (targetView, action = 'push', pushState = true) -> + changeView: (targetView, action = 'push', useHistory = @options.useHistory) -> eventArgs = [targetView, action] - @$container.trigger @options.eventNames.viewChangeStart, eventArgs $targetView = $ targetView + return if $targetView[0] is @$activeView[0] + @$container.trigger @options.eventNames.viewChangeStart, eventArgs $bothViews = @$activeView.add $targetView containerWidth = outerWidth @$container outAnimProps = {} @@ -240,9 +233,9 @@ class SimpleSlideView animateHeightCallback = () => resetStyles @$container, ['height', 'overflow', 'position', 'width'] - if @options.useHistoryJS and pushState - @activeId += 1 - History.pushState { id: @activeId, index: @$views.index($targetView) }, '', '' + # if @options.useHistoryJS and pushState + # @activeId += 1 + # History.pushState { id: @activeId, index: @$views.index($targetView) }, '', '' @$container.trigger @options.eventNames.viewChangeEnd, eventArgs animateHeight = () => @@ -272,6 +265,9 @@ class SimpleSlideView @$activeView.removeClass @options.classNames.activeView $targetView.addClass @options.classNames.activeView @$activeView = $targetView + if useHistory + @historyID += 1 + History.pushState { id: @historyID, viewIndex: @$views.index(@$activeView) }, null, '' pushView: (targetView) -> @changeView targetView, 'push' popView: (targetView) -> @changeView targetView, 'pop'