diff --git a/css/style.css b/css/style.css index 1e09bb5..77a575b 100644 --- a/css/style.css +++ b/css/style.css @@ -6,127 +6,126 @@ padding: 0px; font-family: Arial, sans-serif; width: 100%; - height: 100%; + height: 100%; } html body{ - background: #FFF; - width: 100%; - height: 100%; + background: #FFF; + width: 100%; + height: 100%; } /* ************** LAYOUT **************************************** *****************************************************************/ #wrapper { - width: 100%; - height: 100%; - background:linear-gradient(to bottom, rgba(0,0,0,0) 80%,rgba(0,0,0,0.65) 100%); + width: 100%; + height: 100%; + background:linear-gradient(to bottom, rgba(0,0,0,0) 80%,rgba(0,0,0,0.65) 100%); } #mlibheader{ - width: 100%; - height: 20%; - max-height: 100px; - min-height: 50px; - line-height: 100px; - float: left; - text-align: center; - font-size: 48px; - font-weight: 500; - color: #FFF; - background: linear-gradient(to right, rgba(207,231,250,1) 0%,rgba(99,147,193,1) 100%); + width: 100%; + height: 20%; + max-height: 100px; + min-height: 50px; + line-height: 100px; + float: left; + text-align: center; + font-size: 48px; + font-weight: 500; + color: #FFF; + background: linear-gradient(to right, rgba(207,231,250,1) 0%,rgba(99,147,193,1) 100%); } #breadcrumb{ - height:10%; - width: 100%; - max-height:30px; - min-height: 10px; - float:left; - border-top: 1px solid #ccc; - border-bottom: 1px solid #ccc; - background: rgba(155,155,155,1); - } - + height:10%; + width: 100%; + max-height:30px; + min-height: 10px; + float:left; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; + background: rgba(155,155,155,1); +} + #contentwrapper { - padding-top: 1%; - width: 100%; - height:50%; - float:left; + padding-top: 1%; + width: 100%; + height:50%; + float:left; } #sidenav { - width: 29%; - float:left; - height:49%; - } - + width: 29%; + float:left; + height:49%; +} + #playersec { - width: 40%; - float:left; - margin-left: 1%; - margin-right : 1%; - margin-bottom: auto; - background: linear-gradient(to bottom, rgba(155,155,155,1) 0%,rgba(14,14,14,1) 100%); - vertical-align: bottom; - } + width: 40%; + float:left; + margin-left: 1%; + margin-right : 1%; + margin-bottom: auto; + background: linear-gradient(to bottom, rgba(155,155,155,1) 0%,rgba(14,14,14,1) 100%); + vertical-align: bottom; +} #timeline { - height: 90%; - } - #player { - height: 10%; - } + height: 90%; +} +#player { + height: 10%; +} #playerlistsec { - width: 29%; - float:left; - } + width: 29%; + float:left; +} footer{ - height: 20%; - width: 100%; - float:left; + height: 20%; + width: 100%; + float:left; } - /* ************** NAV **************************************** +/* ************** NAV **************************************** *****************************************************************/ #playerlistsec.menu { - list-style-type: none; - width: 97%; - } + list-style-type: none; + width: 97%; +} #playerlistsec .menu li { - height: 5%; - min-height: 50px; - line-height: 50px; - list-style-type: none; - text-align: center; - vertical-align: middle; - margin-bottom: 1%; - background: linear-gradient(to bottom, rgba(207,231,250,1) 0%,rgba(99,147,193,1) 100%); - cursor: pointer; - float: left; - - } + height: 5%; + min-height: 50px; + line-height: 50px; + list-style-type: none; + text-align: center; + vertical-align: middle; + margin-bottom: 1%; + background: linear-gradient(to bottom, rgba(207,231,250,1) 0%,rgba(99,147,193,1) 100%); + cursor: pointer; + float: left; + +} #playerlistsec .menu li.subli{ - width: auto; - height: 3%; - min-height: 30px; - line-height: 30px; - margin: 1%; - padding-left: 5px; - padding-right: 5px; - float: left; - background: linear-gradient(to left, rgba(207,231,250,1) 0%,rgba(99,147,193,1) 100%); + width: auto; + height: 3%; + min-height: 30px; + line-height: 30px; + margin: 1%; + padding-left: 5px; + padding-right: 5px; + float: left; + background: linear-gradient(to left, rgba(207,231,250,1) 0%,rgba(99,147,193,1) 100%); } #sidenav li { - height: 50px; - width: 100px; - - } - #sidenav ul { - margin-left: 50px; - } - \ No newline at end of file + height: 50px; + width: 100px; + +} +#sidenav ul { + margin-left: 50px; +} diff --git a/index.html b/index.html index e684620..f70666f 100644 --- a/index.html +++ b/index.html @@ -1,80 +1,49 @@ - - Mlib5 - - - + + Mlib5 + + + + + + + + +
+
+ mlib5 +
+ +
+ - - - -
-
- mlib5 -
- -
- - -
+
test
- -
+ +
-
-
-
- - + +
+ +
- + + + diff --git a/js/cheapter.js b/js/chapter.js similarity index 100% rename from js/cheapter.js rename to js/chapter.js diff --git a/js/json_sans_eval.js b/js/json_sans_eval.js new file mode 100644 index 0000000..cb79cce --- /dev/null +++ b/js/json_sans_eval.js @@ -0,0 +1,238 @@ +// This source code is free for use in the public domain. +// NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + +// http://code.google.com/p/json-sans-eval/ + +/** + * Parses a string of well-formed JSON text. + * + * If the input is not well-formed, then behavior is undefined, but it is + * deterministic and is guaranteed not to modify any object other than its + * return value. + * + * This does not use `eval` so is less likely to have obscure security bugs than + * json2.js. + * It is optimized for speed, so is much faster than json_parse.js. + * + * This library should be used whenever security is a concern (when JSON may + * come from an untrusted source), speed is a concern, and erroring on malformed + * JSON is *not* a concern. + * + * Pros Cons + * +-----------------------+-----------------------+ + * json_sans_eval.js | Fast, secure | Not validating | + * +-----------------------+-----------------------+ + * json_parse.js | Validating, secure | Slow | + * +-----------------------+-----------------------+ + * json2.js | Fast, some validation | Potentially insecure | + * +-----------------------+-----------------------+ + * + * json2.js is very fast, but potentially insecure since it calls `eval` to + * parse JSON data, so an attacker might be able to supply strange JS that + * looks like JSON, but that executes arbitrary javascript. + * If you do have to use json2.js with untrusted data, make sure you keep + * your version of json2.js up to date so that you get patches as they're + * released. + * + * @param {string} json per RFC 4627 + * @param {function (this:Object, string, *):*} opt_reviver optional function + * that reworks JSON objects post-parse per Chapter 15.12 of EcmaScript3.1. + * If supplied, the function is called with a string key, and a value. + * The value is the property of 'this'. The reviver should return + * the value to use in its place. So if dates were serialized as + * {@code { "type": "Date", "time": 1234 }}, then a reviver might look like + * {@code + * function (key, value) { + * if (value && typeof value === 'object' && 'Date' === value.type) { + * return new Date(value.time); + * } else { + * return value; + * } + * }}. + * If the reviver returns {@code undefined} then the property named by key + * will be deleted from its container. + * {@code this} is bound to the object containing the specified property. + * @return {Object|Array} + * @author Mike Samuel + */ +var jsonParse = (function () { + var number + = '(?:-?\\b(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?(?:[eE][+-]?[0-9]+)?\\b)'; + var oneChar = '(?:[^\\0-\\x08\\x0a-\\x1f\"\\\\]' + + '|\\\\(?:[\"/\\\\bfnrt]|u[0-9A-Fa-f]{4}))'; + var string = '(?:\"' + oneChar + '*\")'; + + // Will match a value in a well-formed JSON file. + // If the input is not well-formed, may match strangely, but not in an unsafe + // way. + // Since this only matches value tokens, it does not match whitespace, colons, + // or commas. + var jsonToken = new RegExp( + '(?:false|true|null|[\\{\\}\\[\\]]' + + '|' + number + + '|' + string + + ')', 'g'); + + // Matches escape sequences in a string literal + var escapeSequence = new RegExp('\\\\(?:([^u])|u(.{4}))', 'g'); + + // Decodes escape sequences in object literals + var escapes = { + '"': '"', + '/': '/', + '\\': '\\', + 'b': '\b', + 'f': '\f', + 'n': '\n', + 'r': '\r', + 't': '\t' + }; + function unescapeOne(_, ch, hex) { + return ch ? escapes[ch] : String.fromCharCode(parseInt(hex, 16)); + } + + // A non-falsy value that coerces to the empty string when used as a key. + var EMPTY_STRING = new String(''); + var SLASH = '\\'; + + // Constructor to use based on an open token. + var firstTokenCtors = { '{': Object, '[': Array }; + + var hop = Object.hasOwnProperty; + + return function (json, opt_reviver) { + // Split into tokens + var toks = json.match(jsonToken); + // Construct the object to return + var result; + var tok = toks[0]; + var topLevelPrimitive = false; + if ('{' === tok) { + result = {}; + } else if ('[' === tok) { + result = []; + } else { + // The RFC only allows arrays or objects at the top level, but the JSON.parse + // defined by the EcmaScript 5 draft does allow strings, booleans, numbers, and null + // at the top level. + result = []; + topLevelPrimitive = true; + } + + // If undefined, the key in an object key/value record to use for the next + // value parsed. + var key; + // Loop over remaining tokens maintaining a stack of uncompleted objects and + // arrays. + var stack = [result]; + for (var i = 1 - topLevelPrimitive, n = toks.length; i < n; ++i) { + tok = toks[i]; + + var cont; + switch (tok.charCodeAt(0)) { + default: // sign or digit + cont = stack[0]; + cont[key || cont.length] = +(tok); + key = void 0; + break; + case 0x22: // '"' + tok = tok.substring(1, tok.length - 1); + if (tok.indexOf(SLASH) !== -1) { + tok = tok.replace(escapeSequence, unescapeOne); + } + cont = stack[0]; + if (!key) { + if (cont instanceof Array) { + key = cont.length; + } else { + key = tok || EMPTY_STRING; // Use as key for next value seen. + break; + } + } + cont[key] = tok; + key = void 0; + break; + case 0x5b: // '[' + cont = stack[0]; + stack.unshift(cont[key || cont.length] = []); + key = void 0; + break; + case 0x5d: // ']' + stack.shift(); + break; + case 0x66: // 'f' + cont = stack[0]; + cont[key || cont.length] = false; + key = void 0; + break; + case 0x6e: // 'n' + cont = stack[0]; + cont[key || cont.length] = null; + key = void 0; + break; + case 0x74: // 't' + cont = stack[0]; + cont[key || cont.length] = true; + key = void 0; + break; + case 0x7b: // '{' + cont = stack[0]; + stack.unshift(cont[key || cont.length] = {}); + key = void 0; + break; + case 0x7d: // '}' + stack.shift(); + break; + } + } + // Fail if we've got an uncompleted object. + if (topLevelPrimitive) { + if (stack.length !== 1) { throw new Error(); } + result = result[0]; + } else { + if (stack.length) { throw new Error(); } + } + + if (opt_reviver) { + // Based on walk as implemented in http://www.json.org/json2.js + var walk = function (holder, key) { + var value = holder[key]; + if (value && typeof value === 'object') { + var toDelete = null; + for (var k in value) { + if (hop.call(value, k) && value !== holder) { + // Recurse to properties first. This has the effect of causing + // the reviver to be called on the object graph depth-first. + + // Since 'this' is bound to the holder of the property, the + // reviver can access sibling properties of k including ones + // that have not yet been revived. + + // The value returned by the reviver is used in place of the + // current value of property k. + // If it returns undefined then the property is deleted. + var v = walk(value, k); + if (v !== void 0) { + value[k] = v; + } else { + // Deleting properties inside the loop has vaguely defined + // semantics in ES3 and ES3.1. + if (!toDelete) { toDelete = []; } + toDelete.push(k); + } + } + } + if (toDelete) { + for (var i = toDelete.length; --i >= 0;) { + delete value[toDelete[i]]; + } + } + } + return opt_reviver.call(holder, key, value); + }; + result = walk({ '': result }, ''); + } + + return result; + }; +})(); diff --git a/js/mlib.js b/js/mlib.js new file mode 100644 index 0000000..5ab338d --- /dev/null +++ b/js/mlib.js @@ -0,0 +1,90 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +function pageLoad() { + bread = document.getElementById('breadcrumb'); + player = document.getElementById('player'); + mediaSource = document.getElementById('playersource'); + + player.addEventListener('timeupdate', timeUpdate); + player.addEventListener('ended', trackEnded); + + var episodeHTML = document.getElementById('episode'); + var episodeJson = episodeHTML.contentDocument.body.firstChild.innerHTML; + episodeObj = jsonParse(episodeJson); + actTitle = episodeObj.title; + actTrack = 0; + actChapter = 0; + createPlayList(); + jumpById(actTrack, actChapter); +} + +function createPlayList() { + var playList = document.getElementById('playList'); + var entryNumber = 1; + var listEntries = ""; + for (var track in episodeObj.tracks) { + var trackObj = episodeObj.tracks[track]; + if (trackObj.chapters) { + for (var chapter in trackObj.chapters) { + var chapterObj = trackObj.chapters[chapter]; + listEntries = listEntries + "
  • " + entryNumber++ + ": " + chapterObj.title + "
  • "; + } + } else { + listEntries = listEntries + "
  • " + entryNumber++ + ": " + trackObj.title + "
  • "; + } + } + playList.innerHTML = listEntries; +} + +function jumpById(trackId, chapterId) { + if (!episodeObj.tracks || trackId >= episodeObj.tracks.length) { + return; + } + var trackObj = episodeObj.tracks[trackId]; + var trackSrc = trackObj.src; + var trackTime = 0; + + if (trackObj.chapters && chapterId < trackObj.chapters.length) { + var chapterObj = trackObj.chapters[chapterId]; + trackTime = chapterObj.time; + } + actTrack = trackId; + actChapter = chapterId; + mediaSource.src = trackSrc + "#t=" + trackTime; + player.load(); +} + +function timeUpdate() { + actChapter = calcChapterId(actTrack, player.currentTime); + bread.innerHTML = createBreadCrumb(actTrack,actChapter); +} + +function createBreadCrumb(trackId, chapterId) { + var trackObj = episodeObj.tracks[trackId]; + + var actNewTitle = episodeObj.title + " -> " + trackObj.title; + if (trackObj.chapters && chapterId < trackObj.chapters.length) { + var chapterObj = trackObj.chapters[chapterId]; + actNewTitle = actNewTitle + " -> "+chapterObj.title; + } + return actNewTitle; +} +function calcChapterId(trackId, time) { + var trackObj = episodeObj.tracks[trackId]; + var newChapId = 0; + for (var chapter in trackObj.chapters) { + var chapterObj = trackObj.chapters[chapter]; + if (chapterObj.time <= time) { + newChapId = chapter; + } else { + return newChapId; + } + } + return newChapId; +} + +function trackEnded() { + jumpById(actTrack+1, 0); +} \ No newline at end of file diff --git a/js/newjson.json b/js/newjson.json deleted file mode 100644 index 8f28aaa..0000000 --- a/js/newjson.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "user" -} diff --git a/js/test.json b/js/test.json new file mode 100644 index 0000000..6ac62c1 --- /dev/null +++ b/js/test.json @@ -0,0 +1,34 @@ +{ + "title": "Testepisode", + "info": "this is a testepisode", + "tracks": [ + { + "title": "testtrack1", + "info": "this the testtrack1", + "src": "audio.ogg", + "chapters": [ + { + "title": "testtrackcheapter1", + "info": "this the cheapter1", + "time": "0" + }, + { + "title": "testtrackcheapter2", + "info": "this the cheapter2", + "time": "3000" + }, + { + "title": "testtrackcheapter3", + "info": "this the cheapter3", + "time": "9000" + } + ] + }, + { + "title": "testtrack2", + "info": "this the testtrack2", + "src": "audio2.ogg", + "cheapter": null + } + ] +} \ No newline at end of file