Improve scrolling title, uses css animations
authorymh <ymh.work@gmail.com>
Tue, 22 Nov 2016 14:04:03 +0100
changeset 431 3e0a4a322f9e
parent 430 46b4d1971fee
child 432 44569a7f8db0
Improve scrolling title, uses css animations
cms/app-client/app/components/autoscroll-component.js
cms/app-client/app/components/player-component.js
cms/app-client/app/services/constants.js
cms/app-client/app/styles/app.scss
cms/app-client/app/styles/components/autoscroll-component.scss
cms/app-client/app/styles/components/player-component.scss
cms/app-client/app/templates/components/autoscroll-component.hbs
cms/app-client/app/templates/components/player-component.hbs
cms/app-client/tests/integration/components/autoscroll-component-test.js
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/components/autoscroll-component.js	Tue Nov 22 14:04:03 2016 +0100
@@ -0,0 +1,68 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+  constants: Ember.inject.service(),
+
+  classNames: ['autoscroll-component'],
+  tagName: "span",
+  attributeBindings: ['title'],
+
+  title: Ember.computed.oneWay('text'),
+
+  text: null,
+  textWidth: null,
+  doScroll: false,
+  keyFrameStyleDef: null,
+  scrollRate: null,
+
+  willDestroyElement() {
+    const keyFrameStyleDef = this.get('keyFrameStyleDef');
+    if(keyFrameStyleDef !== null) {
+        Ember.run(() => {
+          Ember.$(keyFrameStyleDef).remove();
+        });
+        this.set('keyFrameStyleDef', null);
+    }
+  },
+
+  didRender() {
+    const textWidth = this.$('span').width();
+    if(textWidth === this.get('textWidth')) {
+      return;
+    }
+    this.set('textWidth', textWidth);
+    const outerWidth = this.$().width();
+    const doScroll = (textWidth > outerWidth);
+    const id = this.elementId;
+
+    Ember.run(() => {
+      if(this.get('keyFrameStyleDef') !== null) {
+        Ember.$(this.get('keyFrameStyleDef')).remove();
+      }
+      if(doScroll) {
+        const scrollRate = this.get('scrollRate') || this.get('constants').AUTOSCROLL_RATE;
+        const duration = Math.ceil((textWidth + 30) / scrollRate) + 1;
+        const firstFramePercent = Math.ceil((1/duration)*100);
+
+        var keyframesDef = '';
+        ['-webkit-', '-moz-', ''].forEach(function(p) {
+          keyframesDef += `@${p}keyframes marquee-${id} { 0% { left: 0; } ${firstFramePercent}% { left: 0; } 100% { left: -${textWidth + 30 }px; } }\n`;
+        });
+        this.set(
+          'keyFrameStyleDef',
+          Ember.$("<style>")
+            .prop('id', 'scroll-style-'+id)
+            .prop("type", "text/css")
+            .text(keyframesDef)
+            .appendTo("head")
+        );
+        this.$('div').css('animation', `marquee-${id} ${duration}s linear infinite`);
+        this.$('span:last-child').removeClass('hidden-double');
+      } else {
+        this.$('span:last-child').addClass('hidden-double');
+        this.$('div').css('animation', '');
+      }
+    });
+
+  }
+});
--- a/cms/app-client/app/components/player-component.js	Tue Nov 22 13:53:52 2016 +0100
+++ b/cms/app-client/app/components/player-component.js	Tue Nov 22 14:04:03 2016 +0100
@@ -62,31 +62,6 @@
                 this.send('toggle');
             }
         }));
-
-        setTimeout(Ember.run.bind(this, function() {
-            this.textAutoscroll(Ember.$('#' + this.elementId).find('.title'));
-            this.textAutoscroll(Ember.$('#' + this.elementId).find('.author'));
-        }), 500);
-    },
-
-    textAutoscroll: function(jElement) {
-        var text = jElement.find('span');
-        text.stop(true);
-        text.css('text-indent', '0px');
-        if(text.width() > jElement.width()) {
-            var duration = ( ( text.width() - jElement.width() ) * 8 / 100 ) * 1000;
-            var animate = function() {
-                text.delay(4000)
-                    .animate({
-                        'text-indent': -( text.width() - jElement.width() ) + 'px'
-                    }, duration, 'linear', function() {
-                        text.stop(true);
-                        text.css('text-indent', '0px');
-                        window.setTimeout(function() { animate(); }, 1);
-                    });
-            };
-            animate();
-        }
     },
 
     onUpdate: function() {
--- a/cms/app-client/app/services/constants.js	Tue Nov 22 13:53:52 2016 +0100
+++ b/cms/app-client/app/services/constants.js	Tue Nov 22 14:04:03 2016 +0100
@@ -314,6 +314,8 @@
  ]
 };
 
+const AUTOSCROLL_RATE = 35; // 35px/s
+
 export default Ember.Service.extend({
   OLAC_ROLES: OLAC_ROLES,
   DISCOURSE_CATEGORY_KEYS: DISCOURSE_CATEGORY_KEYS,
@@ -323,5 +325,6 @@
   VIAF_BASE_URL: "http://viaf.org/viaf/",
   LEXVO_BASE_URL: "http://lexvo.org/id/iso639-3/",
   LANGUAGES_TREEMAP: LANGUAGES_TREEMAP,
-  DOCUMENTS_PAGINATION_PERPAGE : DOCUMENTS_PAGINATION_PERPAGE
+  DOCUMENTS_PAGINATION_PERPAGE : DOCUMENTS_PAGINATION_PERPAGE,
+  AUTOSCROLL_RATE: AUTOSCROLL_RATE
 });
--- a/cms/app-client/app/styles/app.scss	Tue Nov 22 13:53:52 2016 +0100
+++ b/cms/app-client/app/styles/app.scss	Tue Nov 22 14:04:03 2016 +0100
@@ -62,6 +62,7 @@
 @import 'components/notice-component';
 @import 'components/transcript-component';
 @import 'components/color-gradient';
+@import 'components/autoscroll-component';
 
 
 h1, h2, h3, h4, h5, h6 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/styles/components/autoscroll-component.scss	Tue Nov 22 14:04:03 2016 +0100
@@ -0,0 +1,18 @@
+.autoscroll-component {
+  > div {
+    display: block;
+    position: absolute;
+    white-space: nowrap;
+    float:left;
+  }
+
+  span {
+    margin-right: 30px;
+    display: inline;
+  }
+
+  span.hidden-double {
+    display: none;
+  }
+
+}
--- a/cms/app-client/app/styles/components/player-component.scss	Tue Nov 22 13:53:52 2016 +0100
+++ b/cms/app-client/app/styles/components/player-component.scss	Tue Nov 22 14:04:03 2016 +0100
@@ -157,11 +157,6 @@
     display: block;
 }
 
-.player-component #audio .meta .language,
-.player-component #audio .meta .date {
-
-}
-
 .player-component #audio .meta .language a {
     text-transform: capitalize;
     text-decoration: none;
@@ -177,13 +172,6 @@
     text-overflow: clip;
 }
 
-.player-component #audio .meta .title span,
-.player-component #audio .meta .author span {
-    position: absolute;
-    overflow: auto;
-    text-overflow: initial;
-}
-
 .player-component #audio .meta .title {
     font-weight: bold;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/app/templates/components/autoscroll-component.hbs	Tue Nov 22 14:04:03 2016 +0100
@@ -0,0 +1,1 @@
+<div class="inner"><span>{{ text }}</span><span class="hidden-double">{{ text }}</span></div>
--- a/cms/app-client/app/templates/components/player-component.hbs	Tue Nov 22 13:53:52 2016 +0100
+++ b/cms/app-client/app/templates/components/player-component.hbs	Tue Nov 22 14:04:03 2016 +0100
@@ -27,13 +27,13 @@
   </div>
   <div class="meta">
     <p>
-      <span title="{{ item.title }}" class="title"><span>{{ item.title }}</span></span>
+      {{ autoscroll-component text=item.title class='title' }}
       <div class="player-language-list">
           {{#each item.languages as |lang index|}}{{if index ", "}}{{doc-language url=lang class="language"}}{{/each}}
       </div>
     </p>
     <p>
-      <span title="{{item.publishers_disp}}" class="author"><span>{{item.publishers_disp}}</span></span>
+      {{ autoscroll-component text=item.publishers_disp class='author' }}
       <span class="date">{{short-date item.issued}}</span>
     </p>
   </div>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cms/app-client/tests/integration/components/autoscroll-component-test.js	Tue Nov 22 14:04:03 2016 +0100
@@ -0,0 +1,24 @@
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('autoscroll-component', 'Integration | Component | autoscroll component', {
+  integration: true
+});
+
+test('it renders', function(assert) {
+  // Set any properties with this.set('myProperty', 'value');
+  // Handle any actions with this.on('myAction', function(val) { ... });
+
+  this.render(hbs`{{autoscroll-component}}`);
+
+  assert.equal(this.$().text().trim(), '');
+
+  // Template block usage:
+  this.render(hbs`
+    {{#autoscroll-component}}
+      template block text
+    {{/autoscroll-component}}
+  `);
+
+  assert.equal(this.$().text().trim(), 'template block text');
+});