/* 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.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 setLanugage(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)(); }; // 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.bind(this)(); wireFunctionality.bind(this)(); if (userTime !== undefined) { this.time(userTime); } }; // private helper methods (not exported) var showConfigScreen = function showConfigScreen() { $('#uhr-controlpanel' + this.id).show(); }; // 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('
'); e.css('width', this.options.width); var realWidth = e.width(); e.width(realWidth); e.height(realWidth); e.css('font-size', (realWidth / 40) + 'px'); if (this.options.controls) { var configlink = $(''); configlink.on('click', function () { showConfigScreen.bind(this)(); }.bind(this)); e.after(configlink); var controlpanel = $('
'); var content = $('
'); controlpanel.append(content); // on/off switch var toggleSwitch = $('
'); toggleSwitch.append(''); toggleSwitch.append(''); content.append(toggleSwitch); // 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(); }.bind(this)); content.append(closebutton); e.after(controlpanel); controlpanel.hide(); } }; 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(); } // 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); }; 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 (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 dotMinute = getDotMinute.bind(this)(time); var hour = getHour.bind(this)(time); var coarseMinute = getCoarseMinute.bind(this)(time); clear.bind(this)(); 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 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 }, "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.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('
'); } }); if (typeof beforeshow === 'function') { beforeshow(); } renderarea.fadeIn('fast'); }); }; } function UhrRendererV2Delegate(layout) { function parseArrayOrObject(letters, styleClass, input) { if (Array.isArray(input)) { input.forEach(function (item) { parseObject(letters, styleClass, item); }); } else { parseObject(letters, styleClass, input); } } function parseObject(letters, styleClass, object) { Object.keys(object).forEach(function (y) { var highlightLetters = object[y]; highlightLetters.forEach(function (x) { letters[y - 1][x - 1].addStyle(styleClass); }); }); } function parseTimeDefinition(letters, styleClass, definition) { Object.keys(definition).forEach(function (listString) { var array = listString.split(','); var highlightLetters = definition[listString]; array.forEach(function (item) { parseArrayOrObject(letters, styleClass + item, highlightLetters); }); }); } this.parse = function parse() { var letters = []; layout.letters.forEach(function (string) { var line = []; for (var c = 0; c < string.length; c++) { var character = new Letter(string[c]); line.push(character); } letters.push(line); }); parseArrayOrObject(letters, 'on', layout.permanent); parseTimeDefinition(letters, 'minute', layout.minutes); parseTimeDefinition(letters, 'hour', 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);