[yelp-xsl/wip/html5] Use inline SVG icons for media controls



commit d8598cd77077d8d71b5f04d5d1c10030728bc3c4
Author: Shaun McCance <shaunm gnome org>
Date:   Fri Feb 12 16:48:05 2016 -0500

    Use inline SVG icons for media controls

 xslt/common/html.xsl                 |  193 +++++++++++++++++-----------------
 xslt/common/icons.xsl                |   35 ++++++
 xslt/docbook/html/db2html-media.xsl  |   10 ++-
 xslt/mallard/html/mal2html-media.xsl |   20 ++--
 4 files changed, 149 insertions(+), 109 deletions(-)
---
diff --git a/xslt/common/html.xsl b/xslt/common/html.xsl
index 931c756..b6473cb 100644
--- a/xslt/common/html.xsl
+++ b/xslt/common/html.xsl
@@ -1430,7 +1430,7 @@ span.var { font-style: italic; }
 span.media-audio, span.media-video { display: inline-block; }
 audio, video { display: block; margin: 0; }
 div.media > div.inner { display: inline-block; text-align: center; }
-div.media-controls {
+.media-controls {
   min-width: 24em;
   height: 24px;
   margin: 0; padding: 0;
@@ -1444,14 +1444,14 @@ div.media-controls {
   display: flex;
   align-items: center;
 }
-.media-audio div.media-controls {
+.media-audio .media-controls {
   border-top-left-radius: 4px;
   border-top-right-radius: 4px;
 }
-div.media-controls > * {
+.media-controls > * {
   flex: 0 1 auto;
 }
-div.media-controls > input.media-range {
+.media-controls > input.media-range {
   flex: 1 0 auto;
   background-color: </xsl:text><xsl:value-of select="$color.fg.dark"/><xsl:text>;
   margin: 0 10px;
@@ -1489,7 +1489,7 @@ input.media-range::-moz-range-thumb {
   border: solid 1px </xsl:text><xsl:value-of select="$color.fg.dark"/><xsl:text>;
   margin-top: -6px;
 }
-div.media-controls-audio {
+.media-controls-audio {
   border-top: solid 1px </xsl:text><xsl:value-of select="$color.fg"/><xsl:text>;;
   border-radius: 4px;
 }
@@ -1504,17 +1504,21 @@ button.media-play {
 button.media-play:hover, button.media-play:focus {
   background-color: </xsl:text><xsl:value-of select="$color.fg.blue"/><xsl:text>;
 }
-button.media-play canvas { margin: 0; }
-div.media-time {
+button.media-play .yelp-svg-fill { fill: </xsl:text>
+  <xsl:value-of select="$color.bg.gray"/><xsl:text>; }
+button.media-play .media-pause { display: none; }
+button.media-play-playing .media-play { display: none; }
+button.media-play-playing .media-pause { display: inline; }
+.media-time {
   margin: 0;
   font-size: 16px;
   height: 24px;
   line-height: 24px;
 }
-div.media-time > span {
+.media-time > span {
   padding-</xsl:text><xsl:value-of select="$right"/><xsl:text>: 8px;
 }
-span.media-duration {
+.media-duration {
   font-size: 12px;
   color: </xsl:text><xsl:value-of select="$color.bg.dark"/><xsl:text>;
   opacity: 0.8;
@@ -2188,84 +2192,60 @@ function yelp_media_init (media) {
       media.pause();
   }, false);
 
-  var controls = document.createElement('div');
-  controls.className = 'media-controls media-controls-' + media.nodeName;
-  media.parentNode.insertBefore(controls, media.nextSibling);
-
-  var playControl = document.createElement('button');
-  playControl.className = 'media-play';
-  playControl.setAttribute('data-play-label', media.getAttribute('data-play-label'));
-  playControl.setAttribute('data-pause-label', media.getAttribute('data-pause-label'));
-  playControl.setAttribute('value', media.getAttribute('data-play-label'));
-  controls.appendChild(playControl);
-
-  var playCanvas = document.createElement('canvas');
-  playCanvas.setAttribute('width', '20');
-  playCanvas.setAttribute('height', '20');
-  playControl.appendChild(playCanvas);
-
-  var rangeControl = document.createElement('input');
-  rangeControl.className = 'media-range'
-  rangeControl.setAttribute('type', 'range');
-  rangeControl.value = 0;
-  controls.appendChild(rangeControl);
-
-  var curSpan = document.createElement('span');
-  curSpan.className = 'media-current';
-  curSpan.textContent = '0:00';
-  var durSpan = document.createElement('span');
-  durSpan.className = 'media-duration';
-  durSpan.textContent = '-:--';
-  var timeDiv = document.createElement('div');
-  timeDiv.className = 'media-time';
-  timeDiv.appendChild(curSpan);
-  timeDiv.appendChild(durSpan);
-  controls.appendChild(timeDiv);
-
-  var playCanvasCtxt = playCanvas.getContext('2d');
-  var paintPlayButton = function () {
-    playCanvasCtxt.fillStyle = yelp_color_gray_background;
-    playCanvasCtxt.clearRect(0, 0, 20, 20);
-    playCanvasCtxt.beginPath();
-    playCanvasCtxt.moveTo(5, 5);   playCanvasCtxt.lineTo(5, 15);
-    playCanvasCtxt.lineTo(15, 10); playCanvasCtxt.lineTo(5, 5);
-    playCanvasCtxt.fill();
+  var controls = null;
+  for (var cur = media.nextSibling; cur instanceof Element; cur = cur.nextSibling) {
+    if (cur.classList.contains('media-controls')) {
+      controls = cur;
+      break;
+    }
   }
-  var paintPauseButton = function () {
-    playCanvasCtxt.fillStyle = yelp_color_gray_background;
-    playCanvasCtxt.clearRect(0, 0, 20, 20);
-    playCanvasCtxt.beginPath();
-    playCanvasCtxt.moveTo(5, 5);   playCanvasCtxt.lineTo(9, 5);
-    playCanvasCtxt.lineTo(9, 15);  playCanvasCtxt.lineTo(5, 15);
-    playCanvasCtxt.lineTo(5, 5);   playCanvasCtxt.fill();
-    playCanvasCtxt.beginPath();
-    playCanvasCtxt.moveTo(11, 5);  playCanvasCtxt.lineTo(15, 5);
-    playCanvasCtxt.lineTo(15, 15); playCanvasCtxt.lineTo(11, 15);
-    playCanvasCtxt.lineTo(11, 5);  playCanvasCtxt.fill();
+  if (controls == null) {
+    media.setAttribute('controls', 'controls');
+    return;
   }
-  paintPlayButton();
+  var playbutton = controls.querySelector('button.media-play');
+  playbutton.addEventListener('click', function () {
+    if (media.paused || media.ended)
+      media.play();
+    else
+      media.pause();
+  }, false);
 
-  var mediaChange = function () {
+  var mediachange = function () {
     if (media.ended)
       media.pause()
     if (media.paused) {
-      playControl.setAttribute('value', playControl.getAttribute('data-play-label'));
-      paintPlayButton();
+      playbutton.setAttribute('value', playbutton.getAttribute('data-play-label'));
+      playbutton.classList.remove('media-play-playing');
     }
     else {
-      playControl.setAttribute('value', playControl.getAttribute('data-pause-label'));
-      paintPauseButton();
+      playbutton.setAttribute('value', playbutton.getAttribute('data-pause-label'));
+      playbutton.classList.add('media-play-playing');
     }
   }
-  media.addEventListener('play', mediaChange, false);
-  media.addEventListener('pause', mediaChange, false);
-  media.addEventListener('ended', mediaChange, false);
-  playControl.addEventListener('click', function () {
-    if (media.paused || media.ended)
-      media.play();
-    else
-      media.pause();
+  media.addEventListener('play', mediachange, false);
+  media.addEventListener('pause', mediachange, false);
+  media.addEventListener('ended', mediachange, false);
+
+  var mediarange = controls.querySelector('input.media-range');
+  mediarange.addEventListener('input', function () {
+    var pct = this.value;
+    if (pct < 0)
+      pct = 0;
+    if (pct > 100)
+      pct = 100;
+    media.currentTime = (pct / 100.0) * media.duration;
   }, false);
+  var curspan = controls.querySelector('span.media-current');
+  var durspan = controls.querySelector('span.media-duration');
+  var durationUpdate = function () {
+    if (!isNaN(media.duration)) {
+      mins = parseInt(media.duration / 60);
+      secs = parseInt(media.duration - (60 * mins));
+      durspan.textContent = (mins + (secs < 10 ? ':0' : ':') + secs);
+    }
+  };
+  media.addEventListener('durationchange', durationUpdate, false);
 
   var ttmlDiv = null;
   var ttmlNodes = null;
@@ -2280,10 +2260,10 @@ function yelp_media_init (media) {
 
   var timeUpdate = function () {
     var pct = (media.currentTime / media.duration) * 100;
-    rangeControl.value = pct;
+    mediarange.value = pct;
     var mins = parseInt(media.currentTime / 60);
     var secs = parseInt(media.currentTime - (60 * mins))
-    curSpan.textContent = (mins + (secs < 10 ? ':0' : ':') + secs);
+    curspan.textContent = (mins + (secs < 10 ? ':0' : ':') + secs);
     if (ttmlNodes != null) {
       for (var i = 0; i < ttmlNodes.length; i++) {
         var ttml = ttmlNodes[i];
@@ -2302,23 +2282,6 @@ function yelp_media_init (media) {
     }
   };
   media.addEventListener('timeupdate', timeUpdate, false);
-  var durationUpdate = function () {
-    if (!isNaN(media.duration)) {
-      mins = parseInt(media.duration / 60);
-      secs = parseInt(media.duration - (60 * mins));
-      durSpan.textContent = (mins + (secs < 10 ? ':0' : ':') + secs);
-    }
-  };
-  media.addEventListener('durationchange', durationUpdate, false);
-
-  rangeControl.addEventListener('input', function () {
-    var pct = this.value;
-    if (pct < 0)
-      pct = 0;
-    if (pct > 100)
-      pct = 100;
-    media.currentTime = (pct / 100.0) * media.duration;
-  }, false);
 };
 document.addEventListener('DOMContentLoaded', function() {
   var matches = document.querySelectorAll('video, audio');
@@ -2527,4 +2490,44 @@ It should return a simple language identifier.
 -->
 <xsl:template mode="html.syntax.class.mode" match="*"/>
 
+
+<!--**==========================================================================
+html.media.controls
+Output media controls for a video or audio object.
+:Revision:version="3.20" date="2016-02-12" status="final"
+
+This template outputs HTML containing controls for a media play for audio or
+video HTML elements. To work with the built-in JavaScript binding code, it
+should be placed immediately after the #{audio} or #{video} element.
+-->
+<xsl:template name="html.media.controls">
+  <xsl:param name="type" select="'video'"/>
+  <span class="media-controls media-controls-{$type}">
+    <button class="media-play">
+      <xsl:attribute name="data-play-label">
+        <xsl:call-template name="l10n.gettext">
+          <xsl:with-param name="msgid" select="'Play'"/>
+        </xsl:call-template>
+      </xsl:attribute>
+      <xsl:attribute name="data-pause-label">
+        <xsl:call-template name="l10n.gettext">
+          <xsl:with-param name="msgid" select="'Pause'"/>
+        </xsl:call-template>
+      </xsl:attribute>
+      <xsl:attribute name="value">
+        <xsl:call-template name="l10n.gettext">
+          <xsl:with-param name="msgid" select="'Play'"/>
+        </xsl:call-template>
+      </xsl:attribute>
+      <xsl:call-template name="icons.svg.media.play"/>
+      <xsl:call-template name="icons.svg.media.pause"/>
+    </button>
+    <input type="range" class="media-range" value="0"/>
+    <span class="media-time">
+      <span class="media-current">0:00</span>
+      <span class="media-duration">-:--</span>
+    </span>
+  </span>
+</xsl:template>
+
 </xsl:stylesheet>
diff --git a/xslt/common/icons.xsl b/xslt/common/icons.xsl
index 88906a3..e118ee0 100644
--- a/xslt/common/icons.xsl
+++ b/xslt/common/icons.xsl
@@ -172,4 +172,39 @@ names.
   </svg:svg>
 </xsl:template>
 
+
+<!--**==========================================================================
+icons.svg.media.play
+Output an #{svg} element for a figure zoom-out icon.
+:Revision: version="3.20" date="2016-02-12" status="final"
+
+This template outputs an SVG #{svg} element with a play icon for media controls.
+
+SVG icons can use CSS class names to pick up colors from the !{colors} module.
+By default, this icon uses the #{yelp-svg-fill} class name.
+-->
+<xsl:template name="icons.svg.media.play">
+  <svg:svg width="20" height="20" class="media-play">
+    <svg:polygon points="5,4 5,16 15,10" class="yelp-svg-fill"/>
+  </svg:svg>
+</xsl:template>
+
+
+<!--**==========================================================================
+icons.svg.media.pause
+Output an #{svg} element for a figure zoom-out icon.
+:Revision: version="3.20" date="2016-02-12" status="final"
+
+This template outputs an SVG #{svg} element with a pause icon for media controls.
+
+SVG icons can use CSS class names to pick up colors from the !{colors} module.
+By default, this icon uses the #{yelp-svg-fill} class name.
+-->
+<xsl:template name="icons.svg.media.pause">
+  <svg:svg width="20" height="20" class="media-pause">
+    <svg:rect x="4" y="4" width="4" height="12" class="yelp-svg-fill"/>
+    <svg:rect x="12" y="4" width="4" height="12" class="yelp-svg-fill"/>
+  </svg:svg>
+</xsl:template>
+
 </xsl:stylesheet>
diff --git a/xslt/docbook/html/db2html-media.xsl b/xslt/docbook/html/db2html-media.xsl
index f1c96fd..3122123 100644
--- a/xslt/docbook/html/db2html-media.xsl
+++ b/xslt/docbook/html/db2html-media.xsl
@@ -50,7 +50,7 @@ calls *{db2html.mediaobject.fallback} for the contents of the #{audio} element.
                                       $node/ancestor::db:mediaobject[1] |
                                       $node/ancestor::db:inlinemediaobject[1]
                                      )[last()]"/>
-  <audio preload="auto" controls="controls">
+  <audio preload="auto">
     <xsl:attribute name="src">
       <xsl:choose>
         <xsl:when test="$node/@fileref">
@@ -75,6 +75,9 @@ calls *{db2html.mediaobject.fallback} for the contents of the #{audio} element.
       <xsl:with-param name="node" select="$media"/>
     </xsl:call-template>
   </audio>
+  <xsl:call-template name="html.media.controls">
+    <xsl:with-param name="type" select="'audio'"/>
+  </xsl:call-template>
 </xsl:template>
 
 
@@ -160,7 +163,7 @@ attribute on the HTML #{video} element. This template calls
                                       $node/ancestor::db:mediaobject[1] |
                                       $node/ancestor::db:inlinemediaobject[1]
                                      )[last()]"/>
-  <video preload="auto" controls="controls">
+  <video preload="auto">
     <xsl:attribute name="src">
       <xsl:choose>
         <xsl:when test="$node/@fileref">
@@ -210,6 +213,9 @@ attribute on the HTML #{video} element. This template calls
       <xsl:with-param name="node" select="$media"/>
     </xsl:call-template>
   </video>
+  <xsl:call-template name="html.media.controls">
+    <xsl:with-param name="type" select="'video'"/>
+  </xsl:call-template>
 </xsl:template>
 
 
diff --git a/xslt/mallard/html/mal2html-media.xsl b/xslt/mallard/html/mal2html-media.xsl
index 71c7a4c..cb643a0 100644
--- a/xslt/mallard/html/mal2html-media.xsl
+++ b/xslt/mallard/html/mal2html-media.xsl
@@ -108,7 +108,7 @@ HTML #{video} element.
 <xsl:template name="mal2html.media.video">
   <xsl:param name="node" select="."/>
   <xsl:param name="inline" select="false()"/>
-  <video src="{$node/@src}" preload="auto" controls="controls">
+  <video src="{$node/@src}" preload="auto">
     <xsl:attribute name="class">
       <xsl:text>media </xsl:text>
       <xsl:choose>
@@ -129,16 +129,6 @@ HTML #{video} element.
         <xsl:value-of select="$poster[1]/@src"/>
       </xsl:attribute>
     </xsl:if>
-    <xsl:attribute name="data-play-label">
-      <xsl:call-template name="l10n.gettext">
-        <xsl:with-param name="msgid" select="'Play'"/>
-      </xsl:call-template>
-    </xsl:attribute>
-    <xsl:attribute name="data-pause-label">
-      <xsl:call-template name="l10n.gettext">
-        <xsl:with-param name="msgid" select="'Pause'"/>
-      </xsl:call-template>
-    </xsl:attribute>
     <xsl:choose>
       <xsl:when test="$inline">
         <xsl:apply-templates mode="mal2html.inline.mode" select="$node/node()"/>
@@ -148,6 +138,9 @@ HTML #{video} element.
       </xsl:otherwise>
     </xsl:choose>
   </video>
+  <xsl:call-template name="html.media.controls">
+    <xsl:with-param name="type" select="'video'"/>
+  </xsl:call-template>
   <xsl:if test="not($inline)">
     <xsl:apply-templates mode="mal2html.ttml.mode" select="tt:tt[1]"/>
   </xsl:if>
@@ -169,7 +162,7 @@ in the source to the #{audio} element's fallback content. If ${inline} is
 <xsl:template name="mal2html.media.audio">
   <xsl:param name="node" select="."/>
   <xsl:param name="inline" select="false()"/>
-  <audio src="{$node/@src}" preload="auto" controls="controls">
+  <audio src="{$node/@src}" preload="auto">
     <xsl:attribute name="class">
       <xsl:text>media </xsl:text>
       <xsl:choose>
@@ -200,6 +193,9 @@ in the source to the #{audio} element's fallback content. If ${inline} is
       </xsl:otherwise>
     </xsl:choose>
   </audio>
+  <xsl:call-template name="html.media.controls">
+    <xsl:with-param name="type" select="'audio'"/>
+  </xsl:call-template>
   <xsl:if test="not($inline)">
     <xsl:apply-templates mode="mal2html.ttml.mode" select="tt:tt[1]"/>
   </xsl:if>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]