From 6fce8748fd3aba7e8947df96f0b263c298088289 Mon Sep 17 00:00:00 2001 From: Astro Date: Mon, 15 Nov 2010 02:39:28 +0100 Subject: [PATCH] resources @poster & @preview for play-resources.js via HTML5 dataset --- content/static/script/jquery.dataset.js | 167 ++++++++++++++++++++++++ content/static/script/play-resources.js | 25 +++- content/static/style/default.css | 12 +- dtd/c3d2web.dtd | 2 + xsd/c3d2web.xsd | 2 + xsl/header.xsl | 3 + xsl/xhtml5.xsl | 14 +- 7 files changed, 217 insertions(+), 8 deletions(-) create mode 100644 content/static/script/jquery.dataset.js diff --git a/content/static/script/jquery.dataset.js b/content/static/script/jquery.dataset.js new file mode 100644 index 000000000..7b87359de --- /dev/null +++ b/content/static/script/jquery.dataset.js @@ -0,0 +1,167 @@ +/// jquery.dataset v0.1.0 -- HTML5 dataset jQuery plugin +/// http://orangesoda.net/jquery.dataset.html + +/// Copyright (c) 2009, Ben Weaver. All rights reserved. +/// This software is issued "as is" under a BSD license +/// . All warrenties disclaimed. + +/// The HTML5 specification allows elements to have custom data +/// attributes that are prefixed with `data-'. They may be +/// conveniently accessed through an element's `dataset' property. +/// This plugin provides similar functionality. +/// +/// The methods in the plugin are designed to be similar to the +/// built-in `attr' and `data' methods. All names are without the +/// `data-' prefix. +// +/// These methods are defined: +/// +/// dataset() +/// Return an object with all custom attribute (name, value) items. +/// +/// dataset(name) +/// Return the value of the attribute `data-NAME'. +/// +/// dataset(name, value) +/// Set the value of attribtue `data-NAME' to VALUE. +/// +/// dataset({...}) +/// Set many custom attributes at once. +/// +/// removeDataset(name) +/// Remove the attribute `data-NAME'. +/// +/// removeDataset([n1, n2, ...]) +/// Remove the attributes `data-N1', `data-N2', ... + +(function($) { + var PREFIX = 'data-', + PATTERN = /^data\-(.*)$/; + + function dataset(name, value) { + if (value !== undefined) { + // dataset(name, value): set the NAME attribute to VALUE. + return this.attr(PREFIX + name, value); + } + + switch (typeof name) { + case 'string': + // dataset(name): get the value of the NAME attribute. + return this.attr(PREFIX + name); + + case 'object': + // dataset(items): set the values of all (name, value) items. + return set_items.call(this, name); + + case 'undefined': + // dataset(): return a mapping of (name, value) items for the + // first element. + return get_items.call(this); + + default: + throw 'dataset: invalid argument ' + name; + } + } + + function get_items() { + return this.foldAttr(function(index, attr, result) { + var match = PATTERN.exec(this.name); + if (match) result[match[1]] = this.value; + }); + } + + function set_items(items) { + for (var key in items) { + this.attr(PREFIX + key, items[key]); + } + return this; + } + + function remove(name) { + if (typeof name == 'string') { + // Remove a single attribute; + return this.removeAttr(PREFIX + name); + } + return remove_names(name); + } + + function remove_names(obj) { + var idx, length = obj && obj.length; + + // For any object, remove attributes named by the keys. + if (length === undefined) { + for (idx in obj) { + this.removeAttr(PREFIX + idx); + } + } + // For an array, remove attributes named by the values. + else { + for (idx = 0; idx < length; idx++) { + this.removeAttr(PREFIX + obj[idx]); + } + } + + return this; + } + + $.fn.dataset = dataset; + $.fn.removeDataset = remove_names; + +})(jQuery); + +(function($) { + + function each_attr(proc) { + if (this.length > 0) { + $.each(this[0].attributes, proc); + } + return this; + } + + function fold_attr(proc, acc) { + return fold((this.length > 0) && this[0].attributes, proc, acc); + } + + /* + * A left-fold operator. The behavior is the same as $.each(), + * but the callback is called with the accumulator as the third + * argument. The default accumulator is an empty object. + */ + function fold(object, proc, acc) { + var length = object && object.length; + + // The default accumulator is an empty object. + if (acc === undefined) acc = {}; + + // Returning an empty accumulator when OBJECT is "false" + // makes FOLD more composable. + if (!object) return acc; + + // Check to see if OBJECT is an array. + if (length !== undefined) { + for (var i = 0, value = object[i]; + (i < length) && (proc.call(value, i, value, acc) !== false); + value = object[++i]) + { } + } + // Object is a map of (name, value) items. + else { + for (var name in object) { + if (proc.call(object[name], name, object[name], acc) === false) break; + } + } + + return acc; + } + + function fold_jquery(proc, acc) { + if (acc === undefined) acc = []; + return fold(this, proc, acc); + } + + $.fn.eachAttr = each_attr; + $.fn.foldAttr = fold_attr; + $.fn.fold = fold_jquery; + $.fold = fold; + +})(jQuery); diff --git a/content/static/script/play-resources.js b/content/static/script/play-resources.js index 823c88b72..1fd0ecea8 100644 --- a/content/static/script/play-resources.js +++ b/content/static/script/play-resources.js @@ -1,5 +1,22 @@ function addButton(container, res) { - var button = $('▶ Play'); + var button = $(''); + if (res.poster) { + var img = $(''); + img.attr('src', res.poster); + if (res.preview) { + button.mouseover(function() { + img.attr('src', res.preview); + }); + button.mouseout(function() { + img.attr('src', res.poster); + }); + } + button.append(img); + } else { + /* No poster */ + button.text('▶ Play'); + } + button.click(function() { button.remove(); @@ -71,6 +88,8 @@ $(document).ready(function() { $('.resource').each(function() { var resource = { href: $(this).find('a').attr('href'), type: $(this).find('a').attr('type') }; + var poster = $(this).dataset('poster'); + var preview = $(this).dataset('preview'); /* Get all associated alternatives */ var alternativeEls = $(this).nextUntil('.resource'); @@ -82,6 +101,10 @@ $(document).ready(function() { toArray(); var res = [resource].concat(alternatives); + if (poster) + res.poster = poster; + if (preview) + res.preview = preview; /* Check playability */ if (res.map(function(res) { diff --git a/content/static/style/default.css b/content/static/style/default.css index 0eb7bd8bd..587026f20 100644 --- a/content/static/style/default.css +++ b/content/static/style/default.css @@ -576,7 +576,7 @@ a[href$="calendar.html"]:before { padding-right: 0.3em; } -li audio, li video { +li audio, li video, li .poster { max-width: 100%; margin: 0; padding: 0; @@ -584,6 +584,11 @@ li audio, li video { background-color: white; } +.play { + cursor: pointer; + font-weight: bold; +} + /* -- Search Engine -- */ div.search div.estform { margin: 0.8em 1.0em; padding: 0em 1.0em; @@ -765,8 +770,3 @@ a.flattr:hover { text-decoration: none; border-bottom: none; } - -.play { - cursor: pointer; - font-weight: bold; -} diff --git a/dtd/c3d2web.dtd b/dtd/c3d2web.dtd index 7baaa3b90..98dae6eb9 100644 --- a/dtd/c3d2web.dtd +++ b/dtd/c3d2web.dtd @@ -29,6 +29,8 @@ hide (yes|no) #IMPLIED title CDATA #IMPLIED url %URI; #REQUIRED + poster %URI; #IMPLIED + preview %URI; #IMPLIED > diff --git a/xsd/c3d2web.xsd b/xsd/c3d2web.xsd index d3e9f52e2..95efd86ef 100644 --- a/xsd/c3d2web.xsd +++ b/xsd/c3d2web.xsd @@ -64,6 +64,8 @@ + + diff --git a/xsl/header.xsl b/xsl/header.xsl index fd2521b5f..9b228120e 100644 --- a/xsl/header.xsl +++ b/xsl/header.xsl @@ -45,6 +45,9 @@ + + + diff --git a/xsl/xhtml5.xsl b/xsl/xhtml5.xsl index b3c35efc4..511cca24a 100644 --- a/xsl/xhtml5.xsl +++ b/xsl/xhtml5.xsl @@ -392,7 +392,19 @@
  • - + + + + + + + + + + + + +