/*! uhr - v8.0.0-dev.1 - 2015-01-19 * http://bärneruhr.ch/ * Copyright (c) 2015 Manuel Friedli; Licensed GPLv3 */ (function($) { 'use strict'; var uhrGlobals = { "id": 0, "languages": [], "themes": [], registerLanguage: function registerLanguage(code, language) { var alreadyExists = uhrGlobals.languages.some(function(element) { if (code === element.code) { console.error("Error: Language code '" + code + "' cannot be registered for language '" + language.language + "' because it is already registered for language '" + element.language + "'!"); return true; } return false; }); if (!alreadyExists) { language.code = code; uhrGlobals.languages.push(language); } } }; // auto-detect themes $('link[rel=stylesheet]').each(function(index, item) { var styleSheet = $(item); var styleClass = styleSheet.attr('data-class'); if (styleClass !== undefined) { var name = styleSheet.attr('data-name'); if (name === undefined) { name = styleClass; } uhrGlobals.themes.push({'styleClass': styleClass, 'name': name}); } }); // fall-back if no theme was included if (uhrGlobals.themes.length === 0) { uhrGlobals.themes.push({}); } // public interface methods (exported later) var start = function start() { if (!isOn.bind(this)()) { this.timer = window.setInterval(function() { this.options.time = new Date(); update.bind(this)(); }.bind(this), 1000); update.bind(this)(); setCookie.bind(this)('uhr-status', 'on'); } }; var stop = function stop() { if (isOn.bind(this)()) { window.clearInterval(this.timer); this.timer = null; update.bind(this)(); setCookie.bind(this)('uhr-status', 'off'); } }; var toggle = function toggle() { if (isOn.bind(this)()) { this.stop(); } else { this.start(); } }; var setLanguage = function setLanguage(languageKey) { if (languageKey !== this.options.language) { this.options.language = languageKey; var renderer = new UhrRenderer(language.bind(this)(), this.element.find('.letterarea')); renderer.render.bind(this)(function() { this.currentMinute = -1; update.bind(this)(); }.bind(this)); setCookie.bind(this)('uhr-language', languageKey); update.bind(this)(); } }; var setTheme = function setTheme(theme) { if (theme !== this.options.theme) { this.element.removeClass(this.options.theme).addClass(theme); $('#uhr-onoffswitch' + this.id).removeClass(this.options.theme).addClass(theme); this.options.theme = theme; setCookie.bind(this)('uhr-theme', theme); } }; var setTime = function setTime(time) { this.currentMinute = -1; if (time === null) { this.options.time = new Date(); } else { if (this.timer !== null) { window.clearInterval(this.timer); } this.options.time = time; } update.bind(this)(); }; var setMode = function(mode) { this.options.mode = mode; this.currentMinute = -1; update.bind(this)(); setCookie.bind(this)('uhr-mode', mode); }; var setWidth = function setWidth(width) { var e = this.element; e.css('width', width); var realWidth = e.width(); e.width(realWidth); e.height(realWidth); e.css('font-size', (realWidth / 40) + 'px'); }; // private interface methods var create = function create() { this.id = uhrGlobals.id++; this.timer = null; this.currentMinute = -1; var userTime = this.options.time; var hash, params; if (this.options.time === undefined) { this.options.time = new Date(); } // parse the URL params hash = window.location.hash; if (hash !== undefined && typeof hash === 'string' && hash.charAt(0) === '#') { hash = hash.substring(1); hash = decodeURIComponent(hash); params = hash.split('&'); params.forEach(function (element) { var pair = element.split('='); var key = pair[0]; var value = pair[1]; switch (key) { case 'l': case 'language': this.options.language = value; this.options.force = true; break; case 't': case 'theme': this.options.theme = value; this.options.force = true; break; case 'm': case 'mode': this.options.mode = value; this.options.force = true; break; case 's': case 'status': this.options.status = value; this.options.force = true; break; } }.bind(this)); } // end parse the URL params setupHTML.bind(this)(); wireFunctionality.bind(this)(); if (userTime !== undefined) { this.time(userTime); } }; // private helper methods (not exported) var toggleConfigScreen = function toggleConfigScreen() { $('#uhr-controlpanel' + this.id).toggle('fast'); }; // set up var setupHTML = function setupHTML() { var e = this.element; // Base clock area e.addClass('uhr'); e.empty(); e.append(''); e.append(''); e.append(''); e.append(''); e.append('
'); e.append(''); setWidth.bind(this)(this.options.width); if (this.options.controls) { var controlpanel = $(''); var content = $(''); controlpanel.append(content); // on/off switch var toggleSwitch = $(''); toggleSwitch.append(''); toggleSwitch.append(''); content.append(toggleSwitch); // time mode switch var modeSwitch = $(''); modeSwitch.append(''); modeSwitch.append(''); content.append(modeSwitch); // language chooser if (uhrGlobals.languages.length > 1) { var languageChooser = $(''); uhrGlobals.languages.forEach(function(item) { languageChooser.append(''); }); content.append(languageChooser); } // theme chooser if (uhrGlobals.themes.length > 1) { var themeChooser = $(''); uhrGlobals.themes.forEach(function(item) { themeChooser.append(''); }); content.append(themeChooser); } var closebutton = $(''); closebutton.on('click', function() { $('#uhr-controlpanel' + this.id).hide('fast'); }.bind(this)); content.append(closebutton); e.after(controlpanel); controlpanel.hide(); var configlink = $(''); configlink.on('click', function() { toggleConfigScreen.bind(this)(); }.bind(this)); e.after(configlink); } }; var wireFunctionality = function wireFunctionality() { // on/off switch var toggleSwitch = $('#uhr-onoffswitch-checkbox' + this.id); toggleSwitch.on('click', function() { this.toggle(); }.bind(this)); var status = $.cookie('uhr-status' + this.id); if (status === undefined || this.options.force) { status = this.options.status; } toggleSwitch.prop('checked', status === 'on'); if (status === 'on') { this.start(); } else { this.stop(); } // time mode switch var modeSwitch = $('#uhr-modeswitch-checkbox' + this.id); modeSwitch.on('click', function() { if (this.options.mode === 'seconds') { setMode.bind(this)('normal'); } else { setMode.bind(this)('seconds'); } }.bind(this)); var mode = $.cookie('uhr-mode' + this.id); if (mode === undefined || this.options.force) { mode = this.options.mode; } modeSwitch.prop('checked', mode !== 'seconds'); if (mode === 'seconds') { setMode.bind(this)('seconds'); } else { setMode.bind(this)('normal'); } // language chooser var languageChooser = $('#uhr-languagechooser' + this.id); languageChooser.on('change', function() { var languageKey = $('#uhr-languagechooser' + this.id).val(); this.language(languageKey); }.bind(this)); var selectedLanguage = $.cookie('uhr-language' + this.id); if (selectedLanguage === undefined || this.options.force) { selectedLanguage = this.options.language; } var found = uhrGlobals.languages.some(function(item) { return selectedLanguage === item.code; }); if (!found) { var fallbackLanguage; if (uhrGlobals.languages.length > 0) { fallbackLanguage = uhrGlobals.languages[0].code; } else { fallbackLanguage = ''; } console.warn("Language '" + selectedLanguage + "' not found! Using fallback '" + fallbackLanguage + "'"); selectedLanguage = fallbackLanguage; } languageChooser.val(selectedLanguage); this.options.language = ""; this.language(selectedLanguage); // theme chooser var themeChooser = $('#uhr-themechooser' + this.id); themeChooser.on('change', function() { var themeKey = $('#uhr-themechooser' + this.id).val(); this.theme(themeKey); }.bind(this)); var selectedTheme = $.cookie('uhr-theme' + this.id); if (selectedTheme === undefined || this.options.force) { selectedTheme = this.options.theme; } found = uhrGlobals.themes.some(function(item) { return selectedTheme === item.styleClass; }); if (!found) { var fallbackTheme = uhrGlobals.themes[0].styleClass; console.warn("Theme '" + selectedTheme + "' not found! Using fallback '" + fallbackTheme + "'"); selectedTheme = fallbackTheme; } themeChooser.val(selectedTheme); this.options.theme = ""; this.theme(selectedTheme); if (this.options.autoresize) { $(window).on('resize', function() { var $e = this.element; var $parent = $e.parent(); var $window = $(window); var parentWidth = $parent.width(); var parentHeight = $parent.height(); var windowWidth = $window.width(); var windowHeight = $window.height(); var size = Math.min(parentWidth, parentHeight, windowWidth, windowHeight) + 'px'; setWidth.bind(this)(size); }.bind(this)); } }; var destroy = function destroy() { this.timer = null; $(this.element) .removeAttr('style') .removeAttr('class') .empty(); $('#uhr-configlink' + this.id).remove(); $('#uhr-controlpanel' + this.id).remove(); }; var setCookie = function setCookie(cookieName, cookieValue) { var options = {}; if (this.options.cookiePath !== undefined) { options = {expires: 365, path: this.options.cookiePath}; } else { options = {expires: 365}; } $.cookie(cookieName + this.id, cookieValue, options); }; // business logic var isOn = function isOn() { return this.timer !== null; }; var update = function update() { if (isOn.bind(this)()) { var time = this.options.time; if (!language.bind(this)().hasOwnProperty('seconds') && this.options.mode !== 'seconds') { if (time.getMinutes() === this.currentMinute) { return; } this.currentMinute = time.getMinutes(); } show.bind(this)(time); } else { clear.bind(this)(); this.currentMinute = -1; } }; var show = function show(time) { var second = getSecond.bind(this)(time); var dotMinute = getDotMinute.bind(this)(time); var hour = getHour.bind(this)(time); var coarseMinute = getCoarseMinute.bind(this)(time); clear.bind(this)(); if (this.options.mode === 'seconds') { highlight.bind(this)('second' + second); } else { highlight.bind(this)('on'); for (var i = 1; i <= dotMinute; i++) { highlight.bind(this)('dot' + i); } highlight.bind(this)('minute' + coarseMinute); highlight.bind(this)('hour' + hour); } }; var highlight = function highlight(itemClass) { this.element.find('.item.' + itemClass).addClass('active'); }; var clear = function clear() { this.element.find('.item').removeClass('active'); }; var getSecond = function getSecond(date) { if (typeof language.bind(this)().getSeconds === 'function') { return language.bind(this)().getSeconds(date); } return date.getSeconds(); }; var getDotMinute = function getDotMinute(date) { if (typeof language.bind(this)().getDotMinute === 'function') { return language.bind(this)().getDotMinute(date); } var minutes = date.getMinutes(); return minutes % 5; }; var getCoarseMinute = function getCoarseMinute(date) { if (typeof language.bind(this)().getCoarseMinute === 'function') { return language.bind(this)().getCoarseMinute(date); } return date.getMinutes(); }; var getHour = function getHour(date) { if (typeof language.bind(this)().getHour === 'function') { return language.bind(this)().getHour(date); } var hour = date.getHours(); if (date.getMinutes() >= 25) { return (hour + 1) % 24; } return hour; }; var language = function language() { var matchingLanguages = uhrGlobals.languages.filter(function(element) { return (element.code === this.options.language); }, this); if (matchingLanguages.length > 0) { return matchingLanguages[0]; } // fallback: return empty object return {}; }; $.widget("fritteli.uhr", { "options": { width: '100%', status: 'on', language: 'de_CH', theme: uhrGlobals.themes[0].styleClass, force: false, controls: true, cookiePath: undefined, autoresize: true, mode: 'normal' }, "start": start, "stop": stop, "toggle": toggle, "language": setLanguage, "theme": setTheme, "time": setTime, "mode": setMode, "width": setWidth, // constructor method "_create": create, // destructor method "_destroy": destroy }); $.fritteli.uhr.register = uhrGlobals.registerLanguage; /** * Hilfsklasse zum Rendern der Uhr. * @param layout Layout-Objekt, das gerendert werden soll. * @param renderarea Das jQuery-gewrappte HTML-Element, auf dem gerendert werden soll. */ function UhrRenderer(layout, renderarea) { this.render = function render(beforeshow) { if (layout.parsed === undefined) { switch (layout.version) { case 2: var delegate = new UhrRendererV2Delegate(layout); var parsedLayout = delegate.parse(); Object.defineProperty(layout, "parsed", {"value": parsedLayout, "writable": false, "configurable": false}); break; default: console.warn("Unknown layout version: '" + layout.version + "'"); return; } } var letters = layout.parsed; renderarea.fadeOut('fast', function() { renderarea.empty(); letters.forEach(function(line, index, array) { line.forEach(function(letter) { renderarea.append(letter.toString()); }); if (index < array.length - 1) { renderarea.append('