resources @poster & @preview for play-resources.js via HTML5 dataset

This commit is contained in:
Astro 2010-11-15 02:39:28 +01:00
parent 20f780992e
commit 6fce8748fd
7 changed files with 217 additions and 8 deletions

View File

@ -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
/// <http://orangesoda.net/license.html>. 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);

View File

@ -1,5 +1,22 @@
function addButton(container, res) {
var button = $('<a class="play">▶ Play</a>');
var button = $('<a class="play" title="Play this"></a>');
if (res.poster) {
var img = $('<img class="poster"/>');
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) {

View File

@ -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;
}

View File

@ -29,6 +29,8 @@
hide (yes|no) #IMPLIED
title CDATA #IMPLIED
url %URI; #REQUIRED
poster %URI; #IMPLIED
preview %URI; #IMPLIED
>
<!ELEMENT alternative EMPTY>

View File

@ -64,6 +64,8 @@
<xs:attribute name="hide" type="xs:string" use="optional"/>
<xs:attribute name="title" type="xs:string" use="optional"/>
<xs:attribute name="url" type="xs:anyURI" use="required"/>
<xs:attribute name="poster" type="xs:anyURI" use="optional"/>
<xs:attribute name="preview" type="xs:anyURI" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="alternative">

View File

@ -45,6 +45,9 @@
<xsl:call-template name="make-script-tag">
<xsl:with-param name="name" select="'jquery-1.4.2.min'"/>
</xsl:call-template>
<xsl:call-template name="make-script-tag">
<xsl:with-param name="name" select="'jquery.dataset'"/>
</xsl:call-template>
<xsl:call-template name="make-script-tag">
<xsl:with-param name="name" select="'pentamedia-comments'"/>
</xsl:call-template>

View File

@ -392,7 +392,19 @@
<!-- @class = "resource" | "alternative" -->
<li class="{name(.)}">
<!-- MIME-Type ist nützlich z.B. für ftp:// URLs -->
<!-- HTML5 dataset hints for play-resources.js poster -->
<xsl:if test="@poster">
<xsl:attribute name="data-poster">
<xsl:value-of select="@poster"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="@preview">
<xsl:attribute name="data-preview">
<xsl:value-of select="@preview"/>
</xsl:attribute>
</xsl:if>
<!-- MIME type hinting works even in the browser -->
<a href="{$href}" type="{@type}" class="mime" rel="enclosure">
<xsl:choose>
<xsl:when test="string-length(string($title))"><xsl:value-of select="$title"/></xsl:when>