From 364f0f481b9a809309bb4254610defc49b451308 Mon Sep 17 00:00:00 2001 From: ladmin Date: Mon, 24 Sep 2018 06:58:50 +0000 Subject: [PATCH] Decaffeinated and removed coffescript dependency --- animate.coffee | 13 ---- animate.js | 14 ++++ package.js | 7 +- transitions.coffee | 129 ---------------------------------- transitions.js | 168 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 185 insertions(+), 146 deletions(-) delete mode 100644 animate.coffee create mode 100644 animate.js delete mode 100644 transitions.coffee create mode 100644 transitions.js diff --git a/animate.coffee b/animate.coffee deleted file mode 100644 index a08a29b..0000000 --- a/animate.coffee +++ /dev/null @@ -1,13 +0,0 @@ -Template.animate.onRendered -> - self = @ - $node = @$('>').first() - animation = self.data?.type || 'bounce' - delay = self.data?.delay && parseInt(self.data.delay) || 200 - - animate = -> - $node.addClass("animated #{animation}") - - if delay - Meteor.setTimeout animate, delay - else - animate() diff --git a/animate.js b/animate.js new file mode 100644 index 0000000..d1b58e6 --- /dev/null +++ b/animate.js @@ -0,0 +1,14 @@ +Template.animate.onRendered(function() { + const self = this; + const $node = this.$('>').first(); + const animation = (self.data != null ? self.data.type : undefined) || 'bounce'; + const delay = ((self.data != null ? self.data.delay : undefined) && parseInt(self.data.delay)) || 200; + + const animate = () => $node.addClass(`animated ${animation}`); + + if (delay) { + return Meteor.setTimeout(animate, delay); + } else { + return animate(); + } +}); diff --git a/package.js b/package.js index 45411d0..e1fe826 100644 --- a/package.js +++ b/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'webtempest:animate', - version: '0.1.9', + version: '0.2.0', summary: 'Easily perform CSS animations and transitions in Meteor', git: 'https://github.com/webtempest/meteor-animate.git', documentation: 'README.md' @@ -8,13 +8,12 @@ Package.describe({ Package.onUse(function(api) { api.versionsFrom('1.1.0.3'); - api.use('coffeescript'); api.use('templating'); api.addFiles([ 'transition.html', - 'transitions.coffee', + 'transitions.js', 'animate.html', - 'animate.coffee', + 'animate.js', 'animate.css' ], 'client'); }); diff --git a/transitions.coffee b/transitions.coffee deleted file mode 100644 index 209e853..0000000 --- a/transitions.coffee +++ /dev/null @@ -1,129 +0,0 @@ -ENDTRANSITION = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd transitionEnd msTransitionEnd animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd animationEnd msAnimationEnd' - -class Transitions - constructor: (options) -> - defaults = - onScreenClass: '' - offScreenClass: '' - hiddenClass: 'out' - animateClass: "animated" - - @opt = _.defaults options, defaults - @opt.insertTimeout = @getInsertTimeout() - @opt.removeTimeout = @getRemoveTimeout() - @opt.parentNode._uihooks = @createHooks() - - self = @ - @setupStyles() - - # This for when the page first loads - _.each $(@opt.parentNode).find('.animated.out'), (item) -> - self.insertElement(item, null) - - setupStyles: -> - if @opt.inDuration or @opt.outDuration - - # For durations to be changed we need to inject CSS - randName = @opt.onScreenClass + _.random(0, 1000) - - styleInjection = $("") - $(@opt.parentNode).addClass(randName) - - if @opt.inDuration - styleInjection.append(".#{randName} .animated.#{@opt.onScreenClass} {-webkit-animation-duration: #{@opt.inDuration}ms;animation-duration: #{@opt.inDuration}ms;}") - - if @opt.outDuration - styleInjection.append(".#{randName} .animated.#{@opt.offScreenClass} {-webkit-animation-duration: #{@opt.outDuration}ms;animation-duration: #{@opt.outDuration}ms;}") - - $(@opt.parentNode).append(styleInjection) - - getInsertTimeout: -> - return parseInt(@opt.inDuration) if @opt.inDuration - switch @opt.onScreenClass - when 'hinge' then 2000 - when 'bounceIn' then 750 - else 1000 - - getRemoveTimeout: -> - return parseInt(@opt.outDuration) if @opt.outDuration - switch @opt.offScreenClass - when 'hinge' then 2000 - when 'bounceOut' then 750 - when 'flipOutX' then 750 - when 'flipOutY' then 750 - else 1000 - - insertElement: (node, next) -> - self = @ - $node = $(node) - $parent = $(self.opt.parentNode) - $node.addClass("#{self.opt.animateClass} #{self.opt.hiddenClass}") - $node.attr('hidden', true) - $(next).before($node) - - finish = (e) -> - $node.removeClass(self.opt.onScreenClass) - node.setAttribute('inserting', false) - - insert = -> - $node.width() - $node.attr('hidden', false) - $node.removeClass(self.opt.hiddenClass) - $node.addClass(self.opt.onScreenClass) - $node.one ENDTRANSITION, finish - - if self.removing - Meteor.setTimeout insert, self.opt.removeTimeout - else - insert() - - removeElement: (node) -> - $node = $(node) - - self = @ - $node.addClass(self.opt.animateClass) - remove = (e) -> - self.removing = false - $node.remove() - - if self.opt.offScreenClass - $node.addClass(self.opt.offScreenClass) - self.removing = true - $node.one ENDTRANSITION, remove - else - remove() - - createHooks: -> - opt: @opt - insertElement: @insertElement - removeElement: @removeElement - - -Template.transition.onRendered -> - transitionIn = @data?.in?.match(/^(.*)\:/)?[1] || @data?.in - transitionOut = @data?.out?.match(/^(.*)\:/)?[1] || @data?.out - - # Duration can be passed in like this: - # in="bounceIn:500" - # 500 means 500 milliseconds - inDuration = @data?.in?.match(/\:(\d*)/)?[1] - outDuration = @data?.out?.match(/\:(\d*)/)?[1] - - # If "wrap=true" is provided, then div.transition-wrapper will - # be the parent. Else just whatever is the parent above this template. - if @$('>').first().hasClass('transition-wrapper') - parentNode = @$('>').first()[0] - else - parentNode = @firstNode?.parentNode - - params = - onScreenClass: transitionIn - offScreenClass: transitionOut - inDuration: inDuration - outDuration: outDuration - parentNode: parentNode - - transitions = new Transitions(params) - -Template.transition.onDestroyed -> - @firstNode?.parentNode?._uihooks = null diff --git a/transitions.js b/transitions.js new file mode 100644 index 0000000..abe1385 --- /dev/null +++ b/transitions.js @@ -0,0 +1,168 @@ +/** + * Created by matt_000 on 24/09/2018. + */ +/* + * decaffeinate suggestions: + * DS102: Remove unnecessary code created because of implicit returns + * DS103: Rewrite code to no longer use __guard__ + * DS207: Consider shorter variations of null checks + * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md + */ +const ENDTRANSITION = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd transitionEnd msTransitionEnd animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd animationEnd msAnimationEnd'; + +class Transitions { + constructor(options) { + const defaults = { + onScreenClass: '', + offScreenClass: '', + hiddenClass: 'out', + animateClass: "animated" + }; + + this.opt = _.defaults(options, defaults); + this.opt.insertTimeout = this.getInsertTimeout(); + this.opt.removeTimeout = this.getRemoveTimeout(); + this.opt.parentNode._uihooks = this.createHooks(); + + const self = this; + this.setupStyles(); + + // This for when the page first loads + _.each($(this.opt.parentNode).find('.animated.out'), item => self.insertElement(item, null)); + } + + setupStyles() { + if (this.opt.inDuration || this.opt.outDuration) { + + // For durations to be changed we need to inject CSS + const randName = this.opt.onScreenClass + _.random(0, 1000); + + const styleInjection = $(""); + $(this.opt.parentNode).addClass(randName); + + if (this.opt.inDuration) { + styleInjection.append(`.${randName} .animated.${this.opt.onScreenClass} {-webkit-animation-duration: ${this.opt.inDuration}ms;animation-duration: ${this.opt.inDuration}ms;}`); + } + + if (this.opt.outDuration) { + styleInjection.append(`.${randName} .animated.${this.opt.offScreenClass} {-webkit-animation-duration: ${this.opt.outDuration}ms;animation-duration: ${this.opt.outDuration}ms;}`); + } + + return $(this.opt.parentNode).append(styleInjection); + } + } + + getInsertTimeout() { + if (this.opt.inDuration) { return parseInt(this.opt.inDuration); } + switch (this.opt.onScreenClass) { + case 'hinge': return 2000; + case 'bounceIn': return 750; + default: return 1000; + } + } + + getRemoveTimeout() { + if (this.opt.outDuration) { return parseInt(this.opt.outDuration); } + switch (this.opt.offScreenClass) { + case 'hinge': return 2000; + case 'bounceOut': return 750; + case 'flipOutX': return 750; + case 'flipOutY': return 750; + default: return 1000; + } + } + + insertElement(node, next) { + const self = this; + const $node = $(node); + const $parent = $(self.opt.parentNode); + $node.addClass(`${self.opt.animateClass} ${self.opt.hiddenClass}`); + $node.attr('hidden', true); + $(next).before($node); + + const finish = function(e) { + $node.removeClass(self.opt.onScreenClass); + return node.setAttribute('inserting', false); + }; + + const insert = function() { + $node.width(); + $node.attr('hidden', false); + $node.removeClass(self.opt.hiddenClass); + $node.addClass(self.opt.onScreenClass); + return $node.one(ENDTRANSITION, finish); + }; + + if (self.removing) { + return Meteor.setTimeout(insert, self.opt.removeTimeout); + } else { + return insert(); + } + } + + removeElement(node) { + const $node = $(node); + + const self = this; + $node.addClass(self.opt.animateClass); + const remove = function(e) { + self.removing = false; + return $node.remove(); + }; + + if (self.opt.offScreenClass) { + $node.addClass(self.opt.offScreenClass); + self.removing = true; + return $node.one(ENDTRANSITION, remove); + } else { + return remove(); + } + } + + createHooks() { + return { + opt: this.opt, + insertElement: this.insertElement, + removeElement: this.removeElement + }; + } +} + + +Template.transition.onRendered(function() { + let parentNode, transitions; + const transitionIn = __guard__(__guard__(this.data != null ? this.data.in : undefined, x1 => x1.match(/^(.*)\:/)), x => x[1]) || (this.data != null ? this.data.in : undefined); + const transitionOut = __guard__(__guard__(this.data != null ? this.data.out : undefined, x3 => x3.match(/^(.*)\:/)), x2 => x2[1]) || (this.data != null ? this.data.out : undefined); + + // Duration can be passed in like this: + // in="bounceIn:500" + // 500 means 500 milliseconds + const inDuration = __guard__(__guard__(this.data != null ? this.data.in : undefined, x5 => x5.match(/\:(\d*)/)), x4 => x4[1]); + const outDuration = __guard__(__guard__(this.data != null ? this.data.out : undefined, x7 => x7.match(/\:(\d*)/)), x6 => x6[1]); + + // If "wrap=true" is provided, then div.transition-wrapper will + // be the parent. Else just whatever is the parent above this template. + if (this.$('>').first().hasClass('transition-wrapper')) { + parentNode = this.$('>').first()[0]; + } else { + parentNode = this.firstNode != null ? this.firstNode.parentNode : undefined; + } + + const params = { + onScreenClass: transitionIn, + offScreenClass: transitionOut, + inDuration, + outDuration, + parentNode + }; + + return transitions = new Transitions(params); +}); + +Template.transition.onDestroyed(function() { + return __guard__(this.firstNode != null ? this.firstNode.parentNode : undefined, x => x._uihooks = null); +}); + +function __guard__(value, transform) { + return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined; +}