diff --git a/.bowerrc b/.bowerrc
new file mode 100644
index 0000000..44491d3
--- /dev/null
+++ b/.bowerrc
@@ -0,0 +1,3 @@
+{
+ "directory": "bower_components"
+}
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..c308ed0
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,13 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/.gitignore b/.gitignore
index 07be4ff..35aab8b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@
.idea
*.iml
atlassian-ide-plugin.xml
-
+/node_modules/
+/bower_components/
diff --git a/.jshintrc b/.jshintrc
index 9a3a0c1..d285383 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -6,15 +6,9 @@
// Predefined globals whom JSHint will ignore.
"browser" : true, // Standard browser globals e.g. `window`, `document`.
-
+ "node" : true,
"jquery" : true,
- "predef" : [
- "suite",
- "test"
- ],
-
-
// Development.
"debug" : false, // Allow debugger statements e.g. browser breakpoints.
"devel" : true, // Allow developments statements e.g. `console.log();`.
@@ -25,7 +19,7 @@
// The Good Parts.
"asi" : false, // Tolerate Automatic Semicolon Insertion (no semicolons).
- "laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
+ "laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
"bitwise" : true, // Prohibit bitwise operators (&, |, ^, etc.).
"boss" : false, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments.
"curly" : true, // Require {} for every new block or scope.
@@ -53,6 +47,6 @@
"plusplus" : false, // Prohibit use of `++` & `--`.
"sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`.
"trailing" : true, // Prohibit trailing whitespaces.
- "white" : false, // Check against strict whitespace and indentation rules.
+ "white" : true, // Check against strict whitespace and indentation rules.
"indent" : 0 // Specify indentation spacing
-}
\ No newline at end of file
+}
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..b64d15e
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,181 @@
+module.exports = function (grunt) {
+ 'use strict';
+ // Load all grunt tasks
+ require('load-grunt-tasks')(grunt);
+ // Show elapsed time at the end
+ require('time-grunt')(grunt);
+
+ // Project configuration.
+ grunt.initConfig({
+ // Metadata.
+ pkg: grunt.file.readJSON('package.json'),
+ banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
+ '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
+ '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
+ '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
+ ' Licensed <%= pkg.licenses[0].type %> */\n',
+ // Task configuration.
+ clean: {
+ files: ['dist']
+ },
+ concat: {
+ options: {
+ banner: '<%= banner %>',
+ stripBanners: true
+ },
+ libs: {
+ src: [
+ 'bower_components/jquery/dist/jquery.js',
+ 'bower_components/jquery-ui/ui/core.js',
+ 'bower_components/jquery-ui/ui/widget.js',
+ 'bower_components/jquery-cookie/jquery.cookie.js'
+ ],
+ dest: 'dist/libs.js'
+ },
+ dist: {
+ src: ['src/uhr.js', 'src/uhr-*.js'],
+ dest: 'dist/jquery.<%= pkg.name %>.complete.js'
+ },
+ main: {
+ src: ['src/uhr.js'],
+ dest: 'dist/jquery.<%= pkg.name %>.main.js'
+ },
+ base: {
+ src: ['src/uhr.js', 'src/uhr-de_CH.js'],
+ dest: 'dist/jquery.<%= pkg.name %>.base.js'
+ },
+ baselangs: {
+ src: ['src/uhr-*.js'],
+ exclude: ['src/uhr-de_CH.js'],
+ dest: 'dist/jquery.<%= pkg.name %>.baselangs.js'
+ },
+ langs: {
+ src: ['src/uhr-*.js'],
+ dest: 'dist/jquery.<%= pkg.name %>.langs.js'
+ }
+ },
+ uglify: {
+ options: {
+ banner: '<%= banner %>'
+ },
+ libs: {
+ src: '<%= concat.libs.dest %>',
+ dest: 'dist/libs.min.js'
+ },
+ dist: {
+ src: '<%= concat.dist.dest %>',
+ dest: 'dist/jquery.<%= pkg.name %>.complete.min.js'
+ },
+ main: {
+ src: '<%= concat.main.dest %>',
+ dest: 'dist/jquery.<%= pkg.name %>.main.min.js'
+ },
+ base: {
+ src: '<%= concat.base.dest %>',
+ dest: 'dist/jquery.<%= pkg.name %>.base.min.js'
+ },
+ baselangs: {
+ src: '<%= concat.baselangs.dest %>',
+ dest: 'dist/jquery.<%= pkg.name %>.baselangs.min.js'
+ },
+ langs: {
+ src: '<%= concat.langs.dest %>',
+ dest: 'dist/jquery.<%= pkg.name %>.langs.min.js'
+ }
+ },
+ cssmin: {
+ allcss: {
+ files: [{
+ expand: true,
+ cwd: 'css',
+ src: ['*.css'],
+ dest: 'dist',
+ ext: '.min.css'
+ }]
+ }
+ },
+ mocha_phantomjs: {
+ all: {
+ options: {
+ urls: ['http://localhost:9000/test/test.html']
+ }
+ }
+ },
+ jshint: {
+ options: {
+ reporter: require('jshint-stylish')
+ },
+ gruntfile: {
+ options: {
+ jshintrc: '.jshintrc'
+ },
+ src: 'Gruntfile.js'
+ },
+ src: {
+ options: {
+ jshintrc: '.jshintrc'
+ },
+ src: ['src/**/*.js']
+ },
+ test: {
+ options: {
+ jshintrc: 'test/.jshintrc'
+ },
+ src: ['test/*.js']
+ }
+ },
+ watch: {
+ gruntfile: {
+ files: '<%= jshint.gruntfile.src %>',
+ tasks: ['jshint:gruntfile']
+ },
+ src: {
+ files: '<%= jshint.src.src %>',
+ tasks: ['jshint:src', 'mocha_phantomjs']
+ },
+ test: {
+ files: ['test/test.html', '<%= jshint.test.src %>'],
+ tasks: ['jshint:test', 'mocha_phantomjs']
+ }
+ },
+ connect: {
+ server: {
+ options: {
+ hostname: '*',
+ port: 9000
+ }
+ }
+ },
+ version: {
+ VERSION: {
+ options: {
+ prefix: ''
+ },
+ src: ['VERSION']
+ },
+ bower: {
+ src: ['bower.json']
+ },
+ manifest: {
+ options: {
+ prefix: 'Version\\s+'
+ },
+ src: ['manifest.appcache']
+ }
+ }
+ });
+
+ grunt.loadNpmTasks('grunt-mocha-phantomjs');
+ grunt.loadNpmTasks('grunt-contrib-cssmin');
+ grunt.loadNpmTasks('grunt-version');
+
+ // Default task.
+ grunt.registerTask('default', ['jshint', 'clean', 'version', 'concat', 'connect', 'mocha_phantomjs', 'uglify', 'cssmin']);
+ grunt.registerTask('buildonly', ['clean', 'version', 'concat', 'uglify', 'cssmin']);
+ grunt.registerTask('server', function () {
+ grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
+ grunt.task.run(['serve']);
+ });
+ grunt.registerTask('serve', ['connect', 'watch']);
+ grunt.registerTask('test', ['jshint', 'connect', 'mocha_phantomjs']);
+};
diff --git a/README.md b/README.md
index b54f2fa..1c3d12b 100644
--- a/README.md
+++ b/README.md
@@ -6,38 +6,46 @@ Du willst Bärneruhr auf deiner Website verwenden? Dank des jQuery-Plugins geht
1. Benötigte Dateien einbinden
------------------------------
* Binde folgende CSS-Datei im HTML-Dokument ein:
- * uhr.css
+ * dist/uhr.min.css
* Binde zusätzlich mindestens eine der folgenden CSS-Dateien im HTML ein, je nach dem, welche Farben deine Uhr unterstützen soll:
- * uhr-black.css
- * uhr-white.css
- * uhr-red.css
- * uhr-yellow.css
- * uhr-green.css
- * uhr-blue.css
- * uhr-pink.css
+ * dist/uhr-black.min.css
+ * dist/uhr-white.min.css
+ * dist/uhr-red.min.css
+ * dist/uhr-yellow.min.css
+ * dist/uhr-green.min.css
+ * dist/uhr-blue.min.css
+ * dist/uhr-pink.min.css
Beim Einbinden muss das attribut `data-class` angegeben werden, welches die CSS-Klasse des Themes definiert. Optional kann mit `data-name` ein im Dropdown anzuzeigender Name angegeben werden. Beispiel:
-
+
* Binde nach den CSS-Dateien (wichtig!) folgende Javascript-Dateien im HTML-Dokument ein:
- * jquery-2.1.0.min.js (Falls nicht bereits vorhanden)
- * jquery-ui-1.10.4.custom.min.js (Falls nicht bereits vorhanden)
+ * dist/libs.min.js: Dies enthält die minifizierten Versionen von jQuery, jQuery-UI (mit den Komponenten `code` und `widget`) und jQuery-Cookie.
+Alternativ kannst Du auch direkt die benötigten Bibliotheken einbinden:
+ * jquery (getestet mit Version 2.1.0)
+ * jquery-ui (getestet mit Version 1.10.4)
* Von jquery-ui werden die Komponenten 'core' und 'widget' benötigt.
- * jquery-cookie-1.4.0.js (Falls nicht bereits vorhanden)
- * uhr.js
-* Binde mindestens eine der folgenden Javascript-Dateien im HTML nach uhr.js ein, je nach dem, welche Sprachen deine Uhr unterstützen soll:
- * uhr-de_CH.js (Berndeutsch)
- * uhr-de_CH_genau.js (Berndeutsch, siehe unten)
- * uhr-de.js (Deutsch)
- * uhr-dk.js (Dänisch)
- * uhr-en.js (Englisch)
- * uhr-es.js (Spanisch)
- * uhr-fr.js (Französisch)
- * uhr-it.js (Italienisch)
- * uhr-nl.js (Niederländisch)
+ * jquery-cookie (getestet mit Version 1.4.0)
+Je nach dem, in welchen Sprachen du die Uhr verwenden willst, noch eine der folgenden Dateien:
+ * dist/jquery.uhr.complete.min.js: Enthält die Hauptdatei sowie alle unterstützden Sprachdateien
+ * dist/jquery.uhr.base.min.js: Enthält die Hauptdatei sowie Bärndütsch (de_CH)
+ * dist/jquery.uhr.main.min.js: Enthält ausschliesslich die Hauptdatei. Zusätzlich muss noch mindestens eine Sprachdatei eingebunden werden (siehe unten).
-`uhr-de_CH_genau.js` ist eine Variante von Berndeutsch, bei der zur vollen Stunde zusätzlich das Wort "genau" angezeigt wird (also z.B. um 15:00 Uhr "ES ISCH GENAU DRÜ").
+* Je nach dem, welche der obigen Dateien du eingebunden hast, kannst du noch individuelle Sprachdateien einbinden. Im Einstellungsfenster der Uhr werden diese Sprachen dann in der Reihenfolge zur Auswahl angeboten, in welcher du sie eingebunden hast.
+ * dist/jquery.uhr.langs.min.js: Enthält alle Sprachen
+ * dist/jquery.uhr.baselangs.min.js: Enthält alle Sprachen bis auf Bärndütsch (de_CH), welche bereits in dist/jquery.uhr.base.min.js enthalten ist.
+ * src/uhr-de_CH.js (Bärndütsch)
+ * src/uhr-de_CH_genau.js (Bärndütsch, siehe unten)
+ * src/uhr-de.js (Deutsch)
+ * src/uhr-dk.js (Dänisch)
+ * src/uhr-en.js (Englisch)
+ * src/uhr-es.js (Spanisch)
+ * src/uhr-fr.js (Französisch)
+ * src/uhr-it.js (Italienisch)
+ * src/uhr-nl.js (Niederländisch)
+
+`src/uhr-de_CH_genau.js` ist eine Variante von Bärndütsch, bei der zur vollen Stunde zusätzlich das Wort "genau" angezeigt wird (also z.B. um 15:00 Uhr "ES ISCH GENAU DRÜ" anstelle von "ES ISCH DRÜ").
2. Uhr-Element im HTML-Dokument einfügen
----------------------------------------
@@ -63,7 +71,7 @@ Damit wird eine Uhr in der Standardkonfiguration erzeugt. Das heisst:
Mit den Bedienelementen kannst du die Uhr ein- und ausschalten, zwischen Stunden/Minuten- oder Sekundenanzeige wechseln sowie Sprache und Farbe einstellen.
-Wie du diese Optionen ändern kannst, verrät der nächste Abschnitt.
+Wie du diese Optionen bereits in der Konfiguration ändern kannst, verrät der nächste Abschnitt.
Es kann natürlich auch eine Collection von Elementen übergeben werden. Mit
@@ -76,18 +84,19 @@ würde also jedes `
`-Element der Seite in eine Uhr umgewandelt.
Der uhr()-Methode kann ein Options-Objekt mitgegeben werden:
jQuery('#uhrcontainer').uhr({
- status: 'on', // 'on' (default) oder 'off'
- theme: 'black', // 'black' (default), 'white', 'red', 'yellow', 'green', 'blue' oder 'pink' (je nach eingebundenen Theme-Stylesheets)
- language: 'de_CH', // 'de_CH' (default), 'de_CH_genau', 'de', 'dk', 'en', 'es', 'fr', 'it' oder 'nl' (je nach eingebundenen Sprachdateien)
- mode: 'normal', // 'normal' (default): Die Uhr zeigt die aktuelle Zeit (Stunden und Minuten) in Worten an
- // 'seconds': Die Uhr zeigt die aktuellen Sekunden als grosse Ziffern an
- width: '100%', // eine CSS-Grössenangabe (default: 100%)
- force: false, // false (default): Falls ein Cookie im Browser besteht, werden dessen Konfigurationswerte übernommen;
- // true: immer die angegebene Konfiguration verwenden
- controls: true, // true (default): Die Bedienelemente (Ein-/Ausschalter, Theme-, Zeitmodus- und Sprachwähler) werden angezeigt
- // false: Die Bedienelemente werden nicht angezeigt
- autoresize: true // true (default): Die Uhr passt ihre Grösse dynamisch an
- // false: Die Uhr behält ihre anfängliche Grösse
+ status: 'on', // 'on' (default) oder 'off'
+ theme: 'black', // 'black' (default), 'white', 'red', 'yellow', 'green', 'blue' oder 'pink' (je nach eingebundenen Theme-Stylesheets)
+ language: 'de_CH', // 'de_CH' (default), 'de_CH_genau', 'de', 'dk', 'en', 'es', 'fr', 'it' oder 'nl' (je nach eingebundenen Sprachdateien)
+ mode: 'normal', // 'normal' (default): Die Uhr zeigt die aktuelle Zeit (Stunden und Minuten) in Worten an
+ // 'seconds': Die Uhr zeigt die aktuellen Sekunden als grosse Ziffern an
+ width: '100%', // eine CSS-Grössenangabe (default: 100%)
+ force: false, // false (default): Falls ein Cookie im Browser besteht, werden dessen Konfigurationswerte übernommen;
+ // true: immer die angegebene Konfiguration verwenden
+ controls: true, // true (default): Die Bedienelemente (Ein-/Ausschalter, Theme-, Zeitmodus- und Sprachwähler) werden angezeigt
+ // false: Die Bedienelemente werden nicht angezeigt
+ autoresize: true, // true (default): Die Uhr passt ihre Grösse dynamisch an
+ // false: Die Uhr behält ihre anfängliche Grösse
+ cookiePath: undefined // Gibt den Cookie-Pfad an. Ist normalerweise nicht definiert; in diesem Fall wird der Pfad der Datei benutzt, welche die Uhr anzeigt. Kann für spezielle Zwecke aber explizit gesetzt werden.
});
5. Sonderfunktionen
@@ -103,6 +112,39 @@ Die Zeit kann auch über einen Methodenaufruf dynamisch eingestellt werden:
jQuery('#uhrcontainer').uhr("time", new Date());
+6. Konfiguration über die URL
+-----------------------------
+Es ist möglich, die Uhr durch den Aufruf mit URL-Parameters zu konfigurieren. Dies übersteuert auch allfällig bereits in einem Cookie gespeicherte Einstellungen. Die Einstellungen werden für alle Uhr-Elemente übernommen, welche sich auf der Seite befinden. Folgende Parameter werden unterstützt, wenn du sie mit einem Hash (`#`) an die URL anhängst:
+ * `l` oder `language`: Bestimmt die Sprache. Der Wert ist der Sprach-Code (abhängig von den eingebundenen Sprachdateien):
+ * de_CH: Bärndütsch
+ * de_CH_genau: Bärndütsch (mit "genau")
+ * de: Deutsch
+ * dk: Dänisch
+ * en: Englisch
+ * es: Spanisch
+ * fr: Französisch
+ * it: Italienisch
+ * nl: Niederländisch
+ * `t` oder `theme`: Bestimmt die Farbe der Uhr. Der Wert ist der Farb-Code (abhängig von den eingebundenen CSS-Dateien):
+ * black: Schwarz
+ * white: Weiss
+ * red: Rot
+ * yellow: Gelb
+ * green: Grün
+ * blue: Blau
+ * pink: Pink
+ * `m` oder `mode`: Bestimmt den Modus der Uhr. Mögliche Werte sind:
+ * normal: Die Uhr zeit Stunde und Minute an
+ * seconds: Die Uhr zeigt die Sekunden an
+ * `s` oder `status`: Bestimmt den anfänglichen Zustand der Uhr.
+ * on: Die Uhr ist eingeschaltet
+ * off: Die Uhr ist ausgeschaltet
+Eine URL kann also beispielweise so aussehen:
+
+ http://example.com/uhr.html#l=fr&t=red&m=seconds&s=on
+
+Dies zeigt dann die Uhr auf Französisch in Rot, im Sekunden-Modus und eingeschaltet.
+
Viel Spass!
A. Lizenzbestimmungen
diff --git a/VERSION b/VERSION
index cc9b20e..77e13e6 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-7.0-next
+8.0.1-dev.0
diff --git a/bower.json b/bower.json
new file mode 100644
index 0000000..6ca3063
--- /dev/null
+++ b/bower.json
@@ -0,0 +1,13 @@
+{
+ "name": "uhr",
+ "version": "8.0.1-dev.0",
+ "dependencies": {
+ "jquery": "~2.1.3",
+ "jquery-ui": "~1.11.2",
+ "jquery-cookie": "~1.4.1"
+ },
+ "devDependencies": {
+ "mocha": "~2.1.0",
+ "chai": "~1.10.0"
+ }
+}
diff --git a/dist/jquery.uhr.base.js b/dist/jquery.uhr.base.js
new file mode 100644
index 0000000..82dad82
--- /dev/null
+++ b/dist/jquery.uhr.base.js
@@ -0,0 +1,870 @@
+/*! uhr - v8.0.1-dev.0 - 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('
');
+ }
+ });
+ if (typeof beforeshow === 'function') {
+ beforeshow();
+ }
+ renderarea.fadeIn('fast');
+ });
+ };
+ }
+
+ function UhrRendererV2Delegate(layout) {
+ var vorne0 = {
+ 3: [2, 3, 4],
+ 4: [1, 5],
+ 5: [1, 4, 5],
+ 6: [1, 3, 5],
+ 7: [1, 2, 5],
+ 8: [1, 5],
+ 9: [2, 3, 4]
+ };
+ var hinten0 = {
+ 3: [8, 9, 10],
+ 4: [7, 11],
+ 5: [7, 10, 11],
+ 6: [7, 9, 11],
+ 7: [7, 8, 11],
+ 8: [7, 11],
+ 9: [8, 9, 10]
+ };
+ var vorne1 = {
+ 3: [3],
+ 4: [2, 3],
+ 5: [3],
+ 6: [3],
+ 7: [3],
+ 8: [3],
+ 9: [2, 3, 4]
+ };
+ var hinten1 = {
+ 3: [9],
+ 4: [8, 9],
+ 5: [9],
+ 6: [9],
+ 7: [9],
+ 8: [9],
+ 9: [8, 9, 10]
+ };
+ var vorne2 = {
+ 3: [2, 3, 4],
+ 4: [1, 5],
+ 5: [5],
+ 6: [4],
+ 7: [3],
+ 8: [2],
+ 9: [1, 2, 3, 4, 5]
+ };
+ var hinten2 = {
+ 3: [8, 9, 10],
+ 4: [7, 11],
+ 5: [11],
+ 6: [10],
+ 7: [9],
+ 8: [8],
+ 9: [7, 8, 9, 10, 11]
+ };
+ var vorne3 = {
+ 3: [1, 2, 3, 4, 5],
+ 4: [4],
+ 5: [3],
+ 6: [4],
+ 7: [5],
+ 8: [1, 5],
+ 9: [2, 3, 4]
+ };
+ var hinten3 = {
+ 3: [7, 8, 9, 10, 11],
+ 4: [10],
+ 5: [9],
+ 6: [10],
+ 7: [11],
+ 8: [7, 11],
+ 9: [8, 9, 10]
+ };
+ var vorne4 = {
+ 3: [4],
+ 4: [3, 4],
+ 5: [2, 4],
+ 6: [1, 4],
+ 7: [1, 2, 3, 4, 5],
+ 8: [4],
+ 9: [4]
+ };
+ var hinten4 = {
+ 3: [10],
+ 4: [9, 10],
+ 5: [8, 10],
+ 6: [7, 10],
+ 7: [7, 8, 9, 10, 11],
+ 8: [10],
+ 9: [10]
+ };
+ var vorne5 = {
+ 3: [1, 2, 3, 4, 5],
+ 4: [1],
+ 5: [1, 2, 3, 4],
+ 6: [5],
+ 7: [5],
+ 8: [1, 5],
+ 9: [2, 3, 4]
+ };
+ var hinten5 = {
+ 3: [7, 8, 9, 10, 11],
+ 4: [7],
+ 5: [7, 8, 9, 10],
+ 6: [11],
+ 7: [11],
+ 8: [7, 11],
+ 9: [8, 9, 10]
+ };
+ var hinten6 = {
+ 3: [9, 10],
+ 4: [8],
+ 5: [7],
+ 6: [7, 8, 9, 10],
+ 7: [7, 11],
+ 8: [7, 11],
+ 9: [8, 9, 10]
+ };
+ var hinten7 = {
+ 3: [7, 8, 9, 10, 11],
+ 4: [11],
+ 5: [10],
+ 6: [9],
+ 7: [8],
+ 8: [8],
+ 9: [8]
+ };
+ var hinten8 = {
+ 3: [8, 9, 10],
+ 4: [7, 11],
+ 5: [7, 11],
+ 6: [8, 9, 10],
+ 7: [7, 11],
+ 8: [7, 11],
+ 9: [8, 9, 10]
+ };
+ var hinten9 = {
+ 3: [8, 9, 10],
+ 4: [7, 11],
+ 5: [7, 11],
+ 6: [8, 9, 10, 11],
+ 7: [11],
+ 8: [10],
+ 9: [8, 9]
+ };
+ var seconds= {
+ "0": [vorne0, hinten0],
+ "1": [vorne0, hinten1],
+ "2": [vorne0, hinten2],
+ "3": [vorne0, hinten3],
+ "4": [vorne0, hinten4],
+ "5": [vorne0, hinten5],
+ "6": [vorne0, hinten6],
+ "7": [vorne0, hinten7],
+ "8": [vorne0, hinten8],
+ "9": [vorne0, hinten9],
+ "10": [vorne1, hinten0],
+ "11": [vorne1, hinten1],
+ "12": [vorne1, hinten2],
+ "13": [vorne1, hinten3],
+ "14": [vorne1, hinten4],
+ "15": [vorne1, hinten5],
+ "16": [vorne1, hinten6],
+ "17": [vorne1, hinten7],
+ "18": [vorne1, hinten8],
+ "19": [vorne1, hinten9],
+ "20": [vorne2, hinten0],
+ "21": [vorne2, hinten1],
+ "22": [vorne2, hinten2],
+ "23": [vorne2, hinten3],
+ "24": [vorne2, hinten4],
+ "25": [vorne2, hinten5],
+ "26": [vorne2, hinten6],
+ "27": [vorne2, hinten7],
+ "28": [vorne2, hinten8],
+ "29": [vorne2, hinten9],
+ "30": [vorne3, hinten0],
+ "31": [vorne3, hinten1],
+ "32": [vorne3, hinten2],
+ "33": [vorne3, hinten3],
+ "34": [vorne3, hinten4],
+ "35": [vorne3, hinten5],
+ "36": [vorne3, hinten6],
+ "37": [vorne3, hinten7],
+ "38": [vorne3, hinten8],
+ "39": [vorne3, hinten9],
+ "40": [vorne4, hinten0],
+ "41": [vorne4, hinten1],
+ "42": [vorne4, hinten2],
+ "43": [vorne4, hinten3],
+ "44": [vorne4, hinten4],
+ "45": [vorne4, hinten5],
+ "46": [vorne4, hinten6],
+ "47": [vorne4, hinten7],
+ "48": [vorne4, hinten8],
+ "49": [vorne4, hinten9],
+ "50": [vorne5, hinten0],
+ "51": [vorne5, hinten1],
+ "52": [vorne5, hinten2],
+ "53": [vorne5, hinten3],
+ "54": [vorne5, hinten4],
+ "55": [vorne5, hinten5],
+ "56": [vorne5, hinten6],
+ "57": [vorne5, hinten7],
+ "58": [vorne5, hinten8],
+ "59": [vorne5, hinten9]
+ };
+
+ function parseArrayOrObject(letters, styleClass, input) {
+ if (typeof input !== 'undefined' && input !== null) {
+ if (Array.isArray(input)) {
+ input.forEach(function(item) {
+ parseObject(letters, styleClass, item);
+ });
+ } else {
+ parseObject(letters, styleClass, input);
+ }
+ }
+ }
+
+ function parseObject(letters, styleClass, object) {
+ if (typeof object !== 'undefined' && object !== null) {
+ 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) {
+ if (typeof definition !== 'undefined' && definition !== null) {
+ 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);
+ if (typeof layout.seconds !== 'undefined' && layout.seconds !== null) {
+ parseTimeDefinition(letters, 'second', layout.seconds);
+ } else {
+ parseTimeDefinition(letters, 'second', seconds);
+ }
+ 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);
+
+(function($) {
+ 'use strict';
+// hilfsvariablen
+ var es_isch = {1: [1, 2, 4, 5, 6, 7]};
+ var ab = {4: [1, 2]};
+ var vor = {3: [9, 10, 11]};
+ var haubi = {4: [4, 5, 6, 7, 8]};
+ var fuef = {1: [9, 10, 11]};
+ var zae = {2: [9, 10, 11]};
+ var viertu = {2: [1, 2, 3, 4, 5, 6]};
+ var zwaenzg = {3: [1, 2, 3, 4, 5, 6]};
+ var layout = {
+ // version: zur Zeit immer 2 (Pflichtattribut)
+ "version": 2,
+ // Sprechender Name der Sprache
+ "language": 'Bärndütsch',
+ // Buchstabenfeld als Array von Strings.
+ "letters": [
+ 'ESKISCHAFÜF',
+ 'VIERTUBFZÄÄ',
+ 'ZWÄNZGSIVOR',
+ 'ABOHAUBIEGE',
+ 'EISZWÖISDRÜ',
+ 'VIERIFÜFIQT',
+ 'SÄCHSISIBNI',
+ 'ACHTINÜNIEL',
+ 'ZÄNIERBEUFI',
+ 'ZWÖUFINAUHR'
+ ],
+ // Permanent aktive Buchstaben.
, vgl. ausführliche Beschreibung bei "minutes".
+ "permanent": es_isch,
+ /*
+ * Minuten: Objekt im folgenden Format:
+ * {
+ * : ,
+ * ...
+ * }
+ * : String von Komma-separierten Minutenwerten, zu welchem die in angegebenen Buchstaben aktiv sein sollen
+ * : [