/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ (function ($) { 'use strict'; var uhrGlobals = { "id": 0, "languages": [], "themes": [], registerLanguage: function registerLanguage(code, language) { var alreadyExists = uhrGlobals.languages.reduce(function (exists, element) { if (exists) { return true; } 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; }, false); if (!alreadyExists) { language.code = code; uhrGlobals.languages.push(language); } } }; // auto-detect themes var styleSheets = $('link[rel=stylesheet]'); for (var i = 0; i < styleSheets.length; i++) { var styleSheet = $(styleSheets[i]); 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(this)) { var uhr = this; this.timer = window.setInterval(function uhrTimer() { uhr.options.time = new Date(); update(uhr); }, 1000); update(this); setCookie(this, 'uhr-status', 'on'); } }; var stop = function stop() { if (isOn(this)) { window.clearInterval(this.timer); this.timer = null; update(this); setCookie(this, 'uhr-status', 'off'); } }; var toggle = function toggle() { if (isOn(this)) { this.stop(); } else { this.start(); } }; var setLanguage = function setLanugage(languageKey) { if (languageKey !== this.options.language) { this.options.language = languageKey; var renderer = new UhrRenderer(language(this), this.element.find('.letterarea')); var uhr = this; renderer.render(this, function () { uhr.currentMinute = -1; update(uhr); }); setCookie(this, 'uhr-language', languageKey); update(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(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(this); }; // private interface methods var create = function create() { this.id = uhrGlobals.id++; this.timer = null; this.currentMinute = -1; var userTime = this.options.time; if (this.options.time === undefined) { this.options.time = new Date(); } setupHTML(this); wireFunctionality(this); if (userTime !== undefined) { this.time(userTime); } }; // private helper methods (not exported) // set up var setupHTML = function setupHTML(uhr) { var e = uhr.element; // Base clock area e.addClass('uhr'); e.empty(); e.append(''); e.append(''); e.append(''); e.append(''); e.append('
'); e.append('
'); e.css('width', uhr.options.width); var realWidth = e.width(); e.width(realWidth); e.height(realWidth); e.css('font-size', (realWidth / 40) + 'px'); if (uhr.options.controls) { // on/off switch var toggleSwitch = $('
'); toggleSwitch.append(''); toggleSwitch.append(''); e.after(toggleSwitch); // language chooser if (uhrGlobals.languages.length > 1) { var languageChooser = $(''); for (var i = 0; i < uhrGlobals.languages.length; i++) { var language = uhrGlobals.languages[i]; languageChooser.append(''); } e.after(languageChooser); } // theme chooser if (uhrGlobals.themes.length > 1) { var themeChooser = $(''); for (var i = 0; i < uhrGlobals.themes.length; i++) { var theme = uhrGlobals.themes[i]; themeChooser.append(''); } e.after(themeChooser); } } }; var wireFunctionality = function wireFunctionality(uhr) { // on/off switch var toggleSwitch = $('#uhr-onoffswitch-checkbox' + uhr.id); toggleSwitch.on('click', function () { uhr.toggle(); }); var status = $.cookie('uhr-status' + uhr.id); if (status === undefined || uhr.options.force) { status = uhr.options.status; } toggleSwitch.prop('checked', status === 'on'); if (status === 'on') { uhr.start(); } else { uhr.stop(); } // language chooser var languageChooser = $('#uhr-languagechooser' + uhr.id); languageChooser.on('change', function () { uhr.language(this.value); }); var selectedLanguage = $.cookie('uhr-language' + uhr.id); if (selectedLanguage === undefined || uhr.options.force) { selectedLanguage = uhr.options.language; } var found = false; for (var i = 0; i < uhrGlobals.languages.length; i++) { var code = uhrGlobals.languages[i].code; if (selectedLanguage === code) { found = true; break; } } if (!found) { var fallback; if (uhrGlobals.languages.length > 0) { fallback = uhrGlobals.languages[0].code; } else { fallback = ''; } console.warn("Language " + selectedLanguage + " not found! Using fallback: " + fallback); selectedLanguage = fallback; } languageChooser.val(selectedLanguage); uhr.options.language = ""; uhr.language(selectedLanguage); // theme chooser var themeChooser = $('#uhr-themechooser' + uhr.id); themeChooser.on('change', function () { uhr.theme(this.value); }); var selectedTheme = $.cookie('uhr-theme' + uhr.id); if (selectedTheme === undefined || uhr.options.force) { selectedTheme = uhr.options.theme; } found = false; for (var i = 0; i < uhrGlobals.themes.length; i++) { var styleClass = uhrGlobals.themes[i].styleClass; if (selectedTheme === styleClass) { found = true; break; } } if (!found) { var fallback = uhrGlobals.themes[0].styleClass; console.warn("Theme " + selectedTheme + " not found! Using fallback: " + fallback); selectedTheme = fallback; } themeChooser.val(selectedTheme); uhr.options.theme = ""; uhr.theme(selectedTheme); }; var setCookie = function setCookie(uhr, cookieName, cookieValue) { var options = {}; if (uhr.options.cookiePath !== undefined) { options = {expires: 365, path: uhr.options.cookiePath}; } else { options = {expires: 365}; } $.cookie(cookieName + uhr.id, cookieValue, options); }; // business logic var isOn = function isOn(uhr) { return uhr.timer !== null; }; var update = function update(uhr) { if (isOn(uhr)) { var time = uhr.options.time; if (time.getMinutes() === uhr.currentMinute) { return; } uhr.currentMinute = time.getMinutes(); show(uhr, time); } else { clear(uhr); uhr.currentMinute = -1; } }; var show = function show(uhr, time) { var dotMinute = getDotMinute(uhr, time); var hour = getHour(uhr, time); var coarseMinute = getCoarseMinute(uhr, time); clear(uhr); highlight(uhr, 'on'); for (var i = 1; i <= dotMinute; i++) { highlight(uhr, 'dot' + i); } highlight(uhr, 'minute' + coarseMinute); highlight(uhr, 'hour' + hour); }; var highlight = function highlight(uhr, itemClass) { uhr.element.find('.item.' + itemClass).addClass('active'); }; var clear = function clear(uhr) { uhr.element.find('.item').removeClass('active'); }; var getDotMinute = function getDotMinute(uhr, date) { if (typeof language(uhr).getDotMinute === 'function') { return language(uhr).getDotMinute(date); } var minutes = date.getMinutes(); return minutes % 5; }; var getCoarseMinute = function getCoarseMinute(uhr, date) { if (typeof language(uhr).getCoarseMinute === 'function') { return language(uhr).getCoarseMinute(date); } return date.getMinutes(); }; var getHour = function getHour(uhr, date) { if (typeof language(uhr).getHour === 'function') { return language(uhr).getHour(date); } var hour = date.getHours(); if (date.getMinutes() >= 25) { return (hour + 1) % 24; } return hour; }; var language = function language(uhr) { var matchingLanguages = uhrGlobals.languages.filter(function (element) { return (element.code === this.options.language) }, uhr); 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 }, "start": start, "stop": stop, "toggle": toggle, "language": setLanguage, "theme": setTheme, "time": setTime, // constructor method "_create": create }); $.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.layout = layout; this.renderarea = renderarea; } UhrRenderer.prototype.render = function (uhr, beforeshow) { var renderer = this; if (this.layout._parsed === undefined) { switch (this.layout.version) { case 2: var delegate = new _UhrRendererV2Delegate(this.layout); this.layout._parsed = delegate.parse(); break; default: console.warn("Unknown layout version: '" + this.layout.version + "'"); return; } } var letters = this.layout._parsed; this.renderarea.fadeOut('fast', function () { renderer.renderarea.empty(); for (var y = 0; y < letters.length; y++) { for (var x = 0; x < letters[y].length; x++) { var letter = letters[y][x]; renderer.renderarea.append(letter.toString()); } if (y < letters.length - 1) { renderer.renderarea.append('
'); } } if (typeof beforeshow === 'function') { beforeshow(); } renderer.renderarea.fadeIn('fast'); }); }; function _UhrRendererV2Delegate(layout) { this.layout = layout; this._parseArrayOrObject = function (letters, styleClass, input) { if (Array.isArray(input)) { for (var i = 0; i < input.length; i++) { this._parseObject(letters, styleClass, input[i]); } } else { this._parseObject(letters, styleClass, input); } } this._parseObject = function(letters, styleClass, object) { for (var line in object) { if (object.hasOwnProperty(line)) { var highlightLetters = object[line]; for (var i = 0; i < highlightLetters.length; i++) { var x = highlightLetters[i] - 1; letters[line - 1][x].addStyle(styleClass); } } } } this._parseTimeDefinition = function(letters, styleClass, definition) { for (var listString in definition) { if (definition.hasOwnProperty(listString)) { var array = listString.split(','); var highlightLetters = definition[listString]; for (var index = 0; index < array.length; index++) { this._parseArrayOrObject(letters, styleClass + array[index], highlightLetters); } } } } } _UhrRendererV2Delegate.prototype.parse = function() { var letters = []; for (var i = 0; i < this.layout.letters.length; i++) { var line = []; var string = this.layout.letters[i]; for (var c = 0; c < string.length; c++) { var character = new Letter(string[c]); line.push(character); } letters.push(line); } this._parseArrayOrObject(letters, 'on', this.layout.permanent); this._parseTimeDefinition(letters, 'minute', this.layout.minutes); this._parseTimeDefinition(letters, 'hour', this.layout.hours); return letters; }; /** * Ein Buchstabe. Hilfsklasse für den Renderer und Inhalt der Layout-Arrays. * @param value Der Buchstabe, der Dargestellt werden soll. * @param style Die CSS-Styleklassen des Buchstabens. */ function Letter(value, style) { var myValue = value; var myStyle = style || ''; this.addStyle = function(style) { if (myStyle == '') { myStyle = style; } else { myStyle += ' ' + style; } } this.toString = function () { return '' + myValue + ''; }; } })(jQuery);