|
|
Строка 1: |
Строка 1: |
| /* Размещённый здесь код JavaScript будет загружаться пользователям при обращении к каждой странице */ | | /* Размещённый здесь код JavaScript будет загружаться пользователям при обращении к каждой странице */ |
− | /***************************************************
| |
− | * JavaScript-Framework für interaktive Lernaufgaben
| |
− | ****************************************************
| |
− | *
| |
− | * V 2.6 (2017/03/11)
| |
− | *
| |
− | * Dieses Script wandelt Teile einer Website
| |
− | * in interaktive Quiz-Aufgaben um. Dazu orientiert
| |
− | * es sich an CSS-Klassen einzelner HTML-Elemente.
| |
− | * Dadurch können interaktive Aufgaben auf Websiten
| |
− | * in einem einfachen WYSIWYG-Editor erstellt
| |
− | * werden. Die Interaktion geschieht dann mittels
| |
− | * dieses nachgeladenen Javascripts.
| |
− | *
| |
− | * SOFTWARE LICENSE: LGPL
| |
− | * (C) 2007 Felix Riesterer
| |
− | * This library is free software; you can redistribute it and/or
| |
− | * modify it under the terms of the GNU Lesser General Public
| |
− | * License as published by the Free Software Foundation; either
| |
− | * version 2.1 of the License, or (at your option) any later version.
| |
− | *
| |
− | * This library 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
| |
− | * Lesser General Public License for more details.
| |
− | *
| |
− | * You should have received a copy of the GNU Lesser General Public
| |
− | * License along with this library; if not, write to the Free Software
| |
− | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
| |
− | *
| |
− | * Felix Riesterer (Felix.Riesterer@gmx.net)
| |
− | */
| |
− |
| |
− | window.Quiz = {
| |
− |
| |
− | triggerClass : "-quiz", /* Variable, in der das Suffix der CSS-Klasse steht,
| |
− | auf die das Script reagiert, um eine Übung als solche zu erkennen und umzuwandeln.
| |
− | Es gibt derzeit folgende Übungen, deren Klassennamen wie folgt lauten:
| |
− | * Zuordnungsspiel
| |
− | -> class="zuordnungs-quiz"
| |
− | * Lückentext-Aufgabe
| |
− | -> class="lueckentext-quiz"
| |
− | * Memo
| |
− | -> class="memo-quiz"
| |
− | * Multiple Choice - Quiz
| |
− | -> class="multiplechoice-quiz"
| |
− | * Schüttelrätsel
| |
− | -> class="schuettel-quiz"
| |
− | * Kreuzworträtsel
| |
− | -> class="kreuzwort-quiz"
| |
− | */
| |
− |
| |
− | poolClass : "daten-pool", // CSS-Klasse für das Element, in welchem die zu ziehenden Felder liegen
| |
− | feldClass : "feld", // CSS-Klasse für Datenfelder
| |
− | fertigClass : "geloest", // CSS-Klasse für gelöstes Quiz
| |
− | bewertungsClass : "quiz-bewertung", // CSS-Klasse für den Textabsatz mit den Bewertungsergebnissen
| |
− | highlightClass : "anvisiert", // CSS-Klasse für das Ziel-Highlighting
| |
− | highlightElm : null, // hier steht später eine Referenz auf das HTML-Element, welches gerade als potenzielles Ziel anvisiert wird
| |
− | codeTabelle : false, // wird später durch ein nachgeladenes Script mit einem Objekt befüllt
| |
− | draggableClass : "quiz-beweglich", // CSS-Klasse, die ein Element für Drag&Drop freigibt, damit es beweglich wird.
| |
− | draggedClass : "quiz-gezogen", // CSS-Klasse, wenn ein Element gerade bewegt wird.
| |
− | dragMode : false, // entscheidet, ob ein Element bei onmousedown gezogen werden soll, oder nicht
| |
− | dragElm : null, // hier steht später eine Referenz auf das HTML-Element in dem der mousedown stattfand
| |
− | dragElmOldVisibility : "", // hier steht später der originale Wert des gezogenen Elements (wird für's Highlighten verändert)
| |
− |
| |
− | lastCoords : {
| |
− | // wird später mit den Mauskoordinaten überschrieben werden
| |
− | left : 0,
| |
− | top : 0
| |
− | },
| |
− |
| |
− | codeTabelle : codeTabelle = {
| |
− | A : new Array(
| |
− | '\u0041', // a
| |
− | '\u0061', // A
| |
− | '\u00c0', // À
| |
− | '\u00c1', // Á
| |
− | '\u00c2', // Â
| |
− | '\u00c3', // Ã
| |
− | '\u00c5', // Å
| |
− | '\u00e0', // à
| |
− | '\u00e1', // á
| |
− | '\u00e2', // â
| |
− | '\u00e3', // ã
| |
− | '\u00e5' // å
| |
− | ),
| |
− | AE : new Array(
| |
− | '\u00c4', // Ä
| |
− | '\u00c6', // Æ
| |
− | '\u00e4', // ä
| |
− | '\u00e6' // æ
| |
− | ),
| |
− | B : new Array(
| |
− | '\u0042', // B
| |
− | '\u0062' // b
| |
− | ),
| |
− | C : new Array(
| |
− | '\u0043', // C
| |
− | '\u0063', // c
| |
− | '\u00c7', // Ç
| |
− | '\u00e7' // ç
| |
− | ),
| |
− | D : new Array(
| |
− | '\u0044', // D
| |
− | '\u0064' // d
| |
− | ),
| |
− | E : new Array(
| |
− | '\u0045', // E
| |
− | '\u0065', // e
| |
− | '\u00c8', // È
| |
− | '\u00c9', // É
| |
− | '\u00ca', // Ê
| |
− | '\u00cb', // Ë
| |
− | '\u00e8', // è
| |
− | '\u00e9', // é
| |
− | '\u00ea', // ê
| |
− | '\u00eb' // ë
| |
− | ),
| |
− | F : new Array(
| |
− | '\u0046', // F
| |
− | '\u0066' // f
| |
− | ),
| |
− | G : new Array(
| |
− | '\u0047', // G
| |
− | '\u0067' // g
| |
− | ),
| |
− | H : new Array(
| |
− | '\u0048', // H
| |
− | '\u0068' // h
| |
− | ),
| |
− | I : new Array(
| |
− | '\u0049', // I
| |
− | '\u0069', // i
| |
− | '\u00cc', // Ì
| |
− | '\u00cd', // Í
| |
− | '\u00ce', // Î
| |
− | '\u00cf', // Ï
| |
− | '\u00ec', // ì
| |
− | '\u00ed', // í
| |
− | '\u00ee', // î
| |
− | '\u00ef' // ï
| |
− | ),
| |
− | J : new Array(
| |
− | '\u004a', // J
| |
− | '\u006a' // j
| |
− | ),
| |
− | K : new Array(
| |
− | '\u004b', // K
| |
− | '\u006b' // k
| |
− | ),
| |
− | L : new Array(
| |
− | '\u004c', // L
| |
− | '\u006c' // l
| |
− | ),
| |
− | M : new Array(
| |
− | '\u004d', // M
| |
− | '\u006d' // m
| |
− | ),
| |
− | N : new Array(
| |
− | '\u004e', // N
| |
− | '\u006e', // n
| |
− | '\u00d1', // Ñ
| |
− | '\u00f1' // ñ
| |
− | ),
| |
− | O : new Array(
| |
− | '\u004f', // O
| |
− | '\u006f', // o
| |
− | '\u00d2', // Ò
| |
− | '\u00d3', // Ó
| |
− | '\u00d4', // Ô
| |
− | '\u00d5', // Õ
| |
− | '\u00f2', // ò
| |
− | '\u00f3', // ó
| |
− | '\u00f4', // ô
| |
− | '\u00f5' // õ
| |
− | ),
| |
− | OE : new Array(
| |
− | '\u00d6', // Ö
| |
− | '\u00f6' // ö
| |
− | ),
| |
− | P : new Array(
| |
− | '\u0050', // P
| |
− | '\u0070' // p
| |
− | ),
| |
− | Q : new Array(
| |
− | '\u0051', // Q
| |
− | '\u0071' // q
| |
− | ),
| |
− | R : new Array(
| |
− | '\u0052', // R
| |
− | '\u0072' // r
| |
− | ),
| |
− | S : new Array(
| |
− | '\u0053', // S
| |
− | '\u0073' // s
| |
− | ),
| |
− | SS : new Array(
| |
− | '\u00df' // ß
| |
− | ),
| |
− | T : new Array(
| |
− | '\u0054', // T
| |
− | '\u0074' // t
| |
− | ),
| |
− | U : new Array(
| |
− | '\u0055', // U
| |
− | '\u0075', // u
| |
− | '\u00d9', // Ù
| |
− | '\u00da', // Ú
| |
− | '\u00db', // Û
| |
− | '\u00f9', // ù
| |
− | '\u00fa', // ú
| |
− | '\u00fb' // û
| |
− | ),
| |
− | UE : new Array(
| |
− | '\u00dc', // Ü
| |
− | '\u00fc' // ü
| |
− | ),
| |
− | V : new Array(
| |
− | '\u0056', // V
| |
− | '\u0076' // v
| |
− | ),
| |
− | W : new Array(
| |
− | '\u0057', // W
| |
− | '\u0077' // w
| |
− | ),
| |
− | X : new Array(
| |
− | '\u0058', // X
| |
− | '\u0078' // x
| |
− | ),
| |
− | Y : new Array(
| |
− | '\u0059', // Y
| |
− | '\u0079', // y
| |
− | '\u00dd', // Ý
| |
− | '\u00fd' // ý
| |
− | ),
| |
− | Z : new Array(
| |
− | '\u005a', // Z
| |
− | '\u007a' // z
| |
− | )
| |
− | },
| |
− |
| |
− | meldungen : {
| |
− | // deutsche Meldungen (Voreinstellung)
| |
− | de : {
| |
− | pruefen : 'pr\u00fcfen!',
| |
− | lob1 : 'Ausgezeichnet!',
| |
− | lob2 : 'Gut gemacht!',
| |
− | lob3 : 'Das war nicht schlecht!',
| |
− | ergebnis1 : 'Die Aufgabe wurde gleich beim ersten Versuch erfolgreich gel\u00f6st!',
| |
− | ergebnis2 : 'Die Aufgabe wurde nach nur zwei Versuchen erfolgreich gel\u00f6st!',
| |
− | ergebnis3 : 'Die Aufgabe wurde nach %n Versuchen erfolgreich gel\u00f6st!',
| |
− | // memo-quiz - Es können auch Triplets, Quartette und mehr gefunden werden müssen
| |
− | alleGefunden : 'Alle Sets gefunden!',
| |
− | erneut : 'Wie w\u00e4r\'s mit einer neuen Runde?',
| |
− | // Multiple-Choice-Quiz
| |
− | ergebnisProzent : 'Die Antworten sind zu %n% richtig.',
| |
− | // Kreuzworträtsel
| |
− | senkrecht : 'Senkrecht',
| |
− | waagrecht : 'Waagrecht',
| |
− | eintragen : 'eintragen',
| |
− | eingabehinweis : 'Benutzen Sie zur Eingabe die Tastatur. Eventuell m\u00fcssen sie zuerst ein Eingabefeld durch Anklicken aktivieren.',
| |
− | // Buchstabenraten-Quiz
| |
− | eingabehinweis_buchstabenraten : 'Benutzen Sie die Tastatur zur Eingabe! Eventuell m\u00fcssen Sie erst in das Quiz klicken, um es zu aktivieren.',
| |
− | quizStarten : 'Quiz starten.',
| |
− | gerateneBuchstaben : 'Bereits geratene Buchstaben',
| |
− | erkannteWoerter : 'Erkannte W\u00f6rter',
| |
− | quizEnde : 'Quiz ist zuende.'
| |
− | },
| |
− |
| |
− | // englische Meldungen
| |
− | en : {
| |
− | pruefen : 'check it!',
| |
− | lob1 : 'Brilliant!',
| |
− | lob2 : 'Well done!',
| |
− | lob3 : 'That was nice!',
| |
− | ergebnis1 : 'You solved everything on your first try!',
| |
− | ergebnis2 : 'You solved everything with only two tries!',
| |
− | ergebnis3 : 'You solved everything after trying %n times!',
| |
− | // memo-quiz - Es können auch Triplets, Quartette und mehr gefunden werden müssen
| |
− | alleGefunden : 'You\'ve found all sets!',
| |
− | erneut : 'How about another round?',
| |
− | // Multiple-Choice-Quiz
| |
− | ergebnisProzent : 'The answers are %n% correct.',
| |
− | // Kreuzworträtsel
| |
− | senkrecht : 'Vertical',
| |
− | waagrecht : 'Horizontal',
| |
− | eintragen : 'fill in',
| |
− | eingabehinweis : 'Use the keyboard to enter letters. You may need to first activate a box by clicking it.',
| |
− | // Buchstabenraten-Quiz
| |
− | eingabehinweis_buchstabenraten : 'Use the keyboard to enter letters. You may need to first click somewhere into this quiz in oder to activate it.',
| |
− | quizStarten : 'Start quiz.',
| |
− | gerateneBuchstaben : 'Already Guessed Characters',
| |
− | erkannteWoerter : 'Found Words',
| |
− | quizEnde : 'Quiz is over.'
| |
− | },
| |
− |
| |
− | // spanische Meldungen; mit dankenswerter Unterstützung von Frau Ulrike Weinmann
| |
− | es : {
| |
− | pruefen : '\u00a1Chequear!',
| |
− | lob1 : '\u00a1Muy bien hecho!',
| |
− | lob2 : '\u00a1Bien hecho!',
| |
− | lob3 : '\u00a1Correcto!',
| |
− | ergebnis1 : '\u00a1Resolviste el ejercicio al primer intento!',
| |
− | ergebnis2 : '\u00a1Resolviste el ejercicio al segundo intento!',
| |
− | ergebnis3 : 'Intentaste resolver el ejercicio %n veces y \u00a1lo lograste!',
| |
− | // memo-quiz - Es können auch Triplets, Quartette und mehr gefunden werden müssen
| |
− | alleGefunden : '\u00a1Encontraste todos los juegos!',
| |
− | erneut : '\u00bfOtra vez?',
| |
− | // Multiple-Choice-Quiz
| |
− | ergebnisProzent : 'Porcentaje de respuestas correctas: %n%.',
| |
− | // Kreuzworträtsel
| |
− | senkrecht : 'Vertical',
| |
− | waagrecht : 'Horizontal',
| |
− | eintragen : 'llenar',
| |
− | eingabehinweis : 'Usa el teclado para entrar letras. Quiz\u00e1s tienes que hacer clic en una caja primero para activ\u00e1rla.',
| |
− | // Buchstabenraten-Quiz
| |
− | eingabehinweis_buchstabenraten : 'Usa el teclado para entrar letras. Quiz\u00e1s tienes que hacer clic en el quiz primero para activ\u00e1rla.',
| |
− | quizStarten : 'Empezar quiz.',
| |
− | gerateneBuchstaben : 'Letras ya probadas',
| |
− | erkannteWoerter : 'Palabras encontradas',
| |
− | quizEnde : 'Fin de juego'
| |
− | },
| |
− |
| |
− | // französische Meldungen; mit dankenswerter Unterstützung von Herrn Otto Ebert
| |
− | fr : {
| |
− | pruefen : 'verifier!',
| |
− | lob1 : 'Excellent! Super!',
| |
− | lob2 : 'Bien fait!',
| |
− | lob3 : 'Ce n\'\u00e9tait pas mal',
| |
− | ergebnis1 : 'Ton essai \u00e9tait tout de suite un succ\u00e8s.',
| |
− | ergebnis2 : 'Tu as r\u00e9soulu le devoir apr\u00e8s deux tentatives seulement!',
| |
− | ergebnis3 : 'Tu as r\u00e9soulu le devoir apr\u00e8s %n tentatives.',
| |
− | // memo-quiz - Es können auch Triplets, Quartette und mehr gefunden werden müssen
| |
− | alleGefunden : 'Tu as trouv\u00e9 tous les "sets".',
| |
− | erneut : 'Alors tu veux recommencer?',
| |
− | // Multiple-Choice-Quiz
| |
− | ergebnisProzent : 'Les r\u00e9ponses sont %n% correctes.',
| |
− | // Kreuzworträtsel
| |
− | senkrecht : 'V\u00e9rtical',
| |
− | waagrecht : 'Horizontal',
| |
− | eintragen : 'inscrire',
| |
− | eingabehinweis : 'Utilisez le clavier pour inscrire des lettres. Vous devez probablement d\'abord activer une bo\u00eete en le claquant.',
| |
− | // Buchstabenraten-Quiz
| |
− | eingabehinweis_buchstabenraten : 'Utilisez le clavier pour inscrire des lettres. Vous devez probablement d\'abord activer le quiz en le claquant.',
| |
− | quizStarten : 'Commencer le quiz.',
| |
− | gerateneBuchstaben : 'Lettres d\u00e9j\u00e0 essay\u00e9es',
| |
− | erkannteWoerter : 'Mots trouv\u00e9s',
| |
− | quizEnde : 'Quiz est finis.'
| |
− | },
| |
− |
| |
− | // lateinische Meldungen; mit dankenswerter Unterstützung von Herrn Ralf Altgeld und Frau Ulrike Weinmann
| |
− | la : {
| |
− | pruefen : 'probare',
| |
− | lob1 : 'optime!',
| |
− | lob2 : 'bene!',
| |
− | lob3 : 'Id non male fecisti.',
| |
− | ergebnis1 : 'Pensum statim in primo conatu feliciter absolutum est!',
| |
− | ergebnis2 : 'Pensum cam post duos conatus feliciter absolutum est.',
| |
− | ergebnis3 : 'Pensum cam post %n conatus feliciter absolutum est.',
| |
− | // memo-quiz - Es können auch Triplets, Quartette und mehr gefunden werden müssen
| |
− | alleGefunden : 'Omnes partes repperisti.',
| |
− | erneut : 'Ludum novum vis?',
| |
− | // Multiple-Choice-Quiz
| |
− | ergebnisProzent : '%n% centesimae responsorum rectae sunt.',
| |
− | // Kreuzworträtsel
| |
− | senkrecht : 'perpendiculariter',
| |
− | waagrecht : 'directe',
| |
− | eintragen : 'complere',
| |
− | eingabehinweis : 'Utere clavibus ad verba scribenda. Fortasse tibi capsa eligenda est.',
| |
− | // Buchstabenraten-Quiz
| |
− | eingabehinweis_buchstabenraten : 'Utere clavibus ad verba scribenda. Fortasse tibi aenigma eligendum est.',
| |
− | quizStarten : 'Incipere aenigma.',
| |
− | gerateneBuchstaben : 'Litterae iam temptatae',
| |
− | erkannteWoerter : 'Verba iam reperta',
| |
− | quizEnde : 'Factum est.'
| |
− | },
| |
− |
| |
− | // italienische Meldungen; mit dankenswerter Unterstützung von Herrn Ihor Bilaniuk
| |
− | it : {
| |
− | pruefen : 'controllare!',
| |
− | lob1 : 'Ottimo!',
| |
− | lob2 : 'Benissimo!',
| |
− | lob3 : 'Bene!',
| |
− | ergebnis1 : 'Il compito \u00e8 stato risolto al primo passo!',
| |
− | ergebnis2 : 'Il compito \u00e8 stato risolto dopo la seconda prova!',
| |
− | ergebnis3 : 'Il compito \u00e8 stato risolto dopo %n prove.',
| |
− | // memo-quiz - Es können auch Triplets, Quartette und mehr gefunden werden müssen
| |
− | alleGefunden : 'Tutti i sets sono stati risolti!',
| |
− | erneut : 'Ancora una volta?',
| |
− | // Multiple-Choice-Quiz
| |
− | ergebnisProzent : 'Le tue risposte sono il %n per cento giuste.',
| |
− | // Kreuzworträtsel
| |
− | senkrecht : 'Verticale',
| |
− | waagrecht : 'Orizontale',
| |
− | eintragen : 'inserire',
| |
− | eingabehinweis : 'Utilizzi la tastiera per entrare nelle lettere. Potete avere bisogno di in primo luogo di attivare una scatola scattandola.',
| |
− | // Buchstabenraten-Quiz
| |
− | eingabehinweis_buchstabenraten : 'Utilizzi la tastiera per entrare nelle lettere. Potete avere bisogno di in primo luogo di scattarti in qualche luogo in questo quiz per attivarlo.',
| |
− | quizStarten : 'Inizi il quiz.',
| |
− | gerateneBuchstaben : 'Lettere gi\u00e0 indovinate',
| |
− | erkannteWoerter : 'Parole trovate ',
| |
− | quizEnde : 'Il quiz \u00e8 sopra .'
| |
− | },
| |
− |
| |
− | // polnische Meldungen von Pitr Wójs www.merula.pl
| |
− | pl : {
| |
− | pruefen : 'Sprawdź!',
| |
− | lob1 : 'Celująco!',
| |
− | lob2 : 'Bardzo dobrze!',
| |
− | lob3 : 'Nieźle!',
| |
− | ergebnis1 : 'Zadanie rozwiązałaś/łeś poprawnie za pierwszym razem!',
| |
− | ergebnis2 : 'Zadanie rozwiązałaś/łeś poprawnie za drugim razem!',
| |
− | ergebnis3 : 'Zadanie zostało rozwiązane poprawnie po %n próbach !',
| |
− | // memo-quiz - Es können auch Triplets, Quartette und mehr gefunden werden müssen
| |
− | alleGefunden : 'Znalazłaś/łeś wszystkie pary!',
| |
− | erneut : 'Co powiesz na drugą rundę? Spróbuj jeszcze raz!',
| |
− | // Multiple-Choice-Quiz
| |
− | ergebnisProzent : 'Odpowiedzi są poprawne w %n procentach.',
| |
− | // Kreuzworträtsel
| |
− | senkrecht : 'Pionowo',
| |
− | waagrecht : 'Poziomo',
| |
− | eintragen : 'Wpisz',
| |
− | eingabehinweis : 'Aby wpisać rozwiązanie użyj klawiatury. Kliknij pole, aby wprowadzić text!',
| |
− | // Buchstabenraten-Quiz
| |
− | eingabehinweis_buchstabenraten : 'Aby wpisać rozwiązanie użyj klawiatury. Kliknij pole, aby wprowadzić text!',
| |
− | quizStarten : 'Start quizu.',
| |
− | gerateneBuchstaben : 'Odgadnięte litery',
| |
− | erkannteWoerter : 'Rozpoznane słówka',
| |
− | quizEnde : 'Koniec quizu.'
| |
− | }
| |
− | },
| |
− |
| |
− | // Anzahl mouseover-Events, nach denen das Drag-Element unsichtbar geschaltet wird (reduziert das Flimmern beim Draggen)
| |
− | visibilityCountDefault : 5,
| |
− |
| |
− | // Hier findet später der Countdown statt, um das Drag-Element nicht bei jedem mouseover-Event unsichtbar zu schalten
| |
− | visibilityCount : 0,
| |
− |
| |
− | // Platzhalter für Eventhandler
| |
− | oldDocOnMouseMove : "leer",
| |
− | oldDocOnMouseOver : "leer",
| |
− | oldDocOnMouseUp : "leer",
| |
− | oldDocOnKeyUp : "leer",
| |
− |
| |
− | // Alle Quizze auf einer Seite werden hier beim Initialisieren abgespeichert
| |
− | alleQuizze : new Object(),
| |
− |
| |
− | // Das gerade benutze Quiz
| |
− | aktivesQuiz : null,
| |
− |
| |
− | domCreate : function (params) {
| |
− | var el, p;
| |
− | /* "params" ist ein Objekt mit folgender Struktur:
| |
− | { tagName : "p", // z.B. für <p>
| |
− | text : "einfach ein Text" // als Kind-Textknoten des Elements
| |
− | ... // weitere (native) Eigenschaften (wie id, className etc.)
| |
− | } */
| |
− | if (params.tagName && params.tagName.match(/[a-z]/)) {
| |
− | el = document.createElement(params.tagName);
| |
− |
| |
− | for (p in params) {
| |
− | if (p.match(/^text/i)) {
| |
− | el.appendChild(document.createTextNode(params[p]));
| |
− | } else {
| |
− | if (!p.match(/^tagname$/i)) {
| |
− | el[p] = params[p];
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | return el;
| |
− | },
| |
− |
| |
− | domSelect : null, // Hier steht später eine Referenz auf die Sizzle-Engine
| |
− |
| |
− | each : function(o, cb, s) {
| |
− | // Die each-Methode wurde aus dem TinyMCE-Projekt (von Moxiecode.com) entnommen.
| |
− | var n, l;
| |
− |
| |
− | if (!o)
| |
− | return 0;
| |
− |
| |
− | s = s || o;
| |
− |
| |
− | if (o.length !== undefined) {
| |
− | // Indexed arrays, needed for Safari
| |
− | for (n=0, l = o.length; n < l; n++) {
| |
− | if (cb.call(s, o[n], n, o) === false)
| |
− | return 0;
| |
− | }
| |
− | } else {
| |
− | // Hashtables
| |
− | for (n in o) {
| |
− | if (o.hasOwnProperty(n)) {
| |
− | if (cb.call(s, o[n], n, o) === false)
| |
− | return 0;
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | return 1;
| |
− | },
| |
− |
| |
− | init : function () {
| |
− | // baseURL herausfinden
| |
− | var q = this;
| |
− |
| |
− | document.addEventListener("DOMContentLoaded", function () { q.initQuizze(); });
| |
− |
| |
− | q.each(document.getElementsByTagName("script"), function (s) {
| |
− |
| |
− | if (s.src && s.src.match(/\/quiz.js$/)) {
| |
− | q.baseURL = s.src.substr(0, s.src.lastIndexOf("/") + 1);
| |
− | }
| |
− | });
| |
− |
| |
− | /* Die Initialisierung könnte mehrfach benötigt werden, die folgenden Umleitungen
| |
− | dürfen aber nur einmal gemacht werden! */
| |
− | if (q.oldDocOnMouseMove == "leer") {
| |
− | q.oldDocOnMouseMove = document.onmousemove;
| |
− |
| |
− | document.onmousemove = function (e) {
| |
− | if (typeof(q.oldDocOnMouseMove) == "function") {
| |
− | q.oldDocOnMouseMove(e);
| |
− | }
| |
− |
| |
− | q.whileMove(e);
| |
− | }
| |
− | document.addEventListener("touchstart",function(e){q.touchStart(e)});
| |
− | document.addEventListener("touchmove",function(e){q.whileMove(e)});
| |
− | }
| |
− |
| |
− | // OnMouseOver-Handler nur einmal eintragen
| |
− | if (q.oldDocOnMouseOver == "leer") {
| |
− | q.oldDocOnMouseOver = document.onmouseover;
| |
− |
| |
− | document.onmouseover = function (e) {
| |
− | if (typeof(q.oldDocOnMouseOver) == "function") {
| |
− | q.oldDocOnMouseOver(e);
| |
− | }
| |
− |
| |
− | q.einBlender(e);
| |
− | }
| |
− | }
| |
− |
| |
− | // OnMouseUp-Handler nur einmal eintragen
| |
− | if (q.oldDocOnMouseUp == "leer") {
| |
− | q.oldDocOnMouseUp = document.onmouseup;
| |
− |
| |
− | document.onmouseup = function (e) {
| |
− | if (typeof(q.oldDocOnMouseUp) == "function") {
| |
− | q.oldDocOnMouseUp(e);
| |
− | }
| |
− |
| |
− | q.each(q.alleQuizze, function (a) {
| |
− | if (a.element.onmouseup) {
| |
− | a.element.onmouseup(e);
| |
− | }
| |
− | });
| |
− | }
| |
− | }
| |
− |
| |
− | // OnKeyUp-Handler nur einmal eintragen
| |
− | if (q.oldDocOnKeyUp == "leer") {
| |
− | q.oldDocOnKeyUp = document.onkeyup;
| |
− |
| |
− | document.onkeyup = function (e) {
| |
− | if (typeof(q.oldDocOnKeyUp) == "function") {
| |
− | q.oldDocOnKeyUp(e);
| |
− | }
| |
− |
| |
− | q.each(q.alleQuizze, function (a) {
| |
− | if (a.element.onkeyup) {
| |
− | a.element.onkeyup(e);
| |
− | }
| |
− | });
| |
− | }
| |
− | }
| |
− |
| |
− | // Erweiterung für das native String-Objekt in JavaScript: trim()-Methode (wie in PHP verfügbar)
| |
− | if (typeof(new String().quizTrim) != "function") {
| |
− | String.prototype.quizTrim = function () {
| |
− | var l = new RegExp(
| |
− | "^[" + String.fromCharCode(32) + String.fromCharCode(160) + "\t\r\n]+",
| |
− | "g"
| |
− | );
| |
− | var r = new RegExp(
| |
− | "[" + String.fromCharCode(32) + String.fromCharCode(160) + "\t\r\n]+$",
| |
− | "g"
| |
− | );
| |
− |
| |
− | return this.replace(l, "").replace(r, "");
| |
− | };
| |
− | }
| |
− |
| |
− | // Erweiterung für das native Array-Objekt: contains()-Methode
| |
− | if (![].contains) {
| |
− | Array.prototype.contains = function (el, strict) {
| |
− | var i;
| |
− |
| |
− | for (i = 0; i < this.length; i++) {
| |
− | if (this[i] === el) {
| |
− | return true;
| |
− | }
| |
− | }
| |
− |
| |
− | return false;
| |
− | };
| |
− | }
| |
− |
| |
− | // Erweiterung für das native Array-Objekt: shuffle()-Methode
| |
− | if (typeof(new Array().shuffle) != "function") {
| |
− | Array.prototype.shuffle = function () {
| |
− | var ar = [], zufall, i;
| |
− |
| |
− | while (this.length > 0) {
| |
− | zufall = Math.floor(Math.random() * this.length);
| |
− |
| |
− | ar.push(this[zufall]);
| |
− |
| |
− | this.splice(zufall, 1); // Element entfernen
| |
− | }
| |
− |
| |
− | for (i = 0; i < ar.length; i++) {
| |
− | this[i] = ar[i];
| |
− | }
| |
− |
| |
− | return this;
| |
− | };
| |
− | }
| |
− | },
| |
− | removeAllListeners : function(t) {
| |
− | // Eventhandler entfernen
| |
− | t.element.removeEventListener("mousedown", this.startDrag);
| |
− | t.element.removeEventListener("mouseup", this.stopDrag);
| |
− | // touch devices
| |
− | t.element.removeEventListener("touchstart", this.startDrag);
| |
− | t.element.removeEventListener("touchend", this.stopDrag);
| |
− | t.element.removeEventListener("touchcancel", this.stopDrag);
| |
− | },
| |
− | addAllListeners : function(t) {
| |
− | // Eventhandler für bewegliche Felder einrichten
| |
− | t.element.addEventListener("mousedown", this.startDrag);
| |
− | t.element.addEventListener("mouseup", this.stopDrag);
| |
− | // touch devices
| |
− | t.element.addEventListener("touchstart", this.startDrag);
| |
− | t.element.addEventListener("touchend", this.stopDrag);
| |
− | t.element.addEventListener("touchcancel", this.stopDrag);
| |
− | },
| |
− |
| |
− | /*
| |
− | =================
| |
− | Quiz - Funktionen
| |
− | =================
| |
− | */
| |
− |
| |
− |
| |
− | /* Diese Funktion erzeugt ein Zuordnungs-Quiz. Dazu braucht sie eine Tabelle innerhalb eines
| |
− | Elternelements mit dem CSS-Klassen-Präfix "matching", z.B. "matching-quiz", wenn "-quiz"
| |
− | das Suffix der Quiz.triggerClass ist.
| |
− | Die Tabelle mit den Daten enthält Spalten (ohne <th>!), in denen die Werte stehen. */
| |
− |
| |
− | zuordnungsQuiz : function (div) {
| |
− | var q = this,
| |
− | i, tabelle;
| |
− |
| |
− | var quiz = {
| |
− | // Objekt-Gestalt eines Zuordnungs-Quizzes
| |
− | name : "Quiz-x", // Platzhalter - hier steht später etwas anderes.
| |
− | typ : "Zuordnungs-Quiz",
| |
− | spielModus : "paarweise", // entweder paarweise oder gruppenweise Zuordnungen
| |
− | loesungsClass : "loesungs-paar",
| |
− | element : div, // Referenz auf das DIV-Element, in welchem sich das Quiz befindet
| |
− | daten : new Array(), // Hier stehen später Wertegruppen (in Arrays).
| |
− | felder : new Array(), // Hier stehen später Referenzen auf SPAN-Elemente
| |
− | pool : q.domCreate({
| |
− | tagName : "p",
| |
− | className : q.poolClass
| |
− | }),
| |
− | auswertungsButton : null, // Hier steht später das HTML-Element des Auswertungs-Buttons.
| |
− | versuche : 0, // Speichert die Anzahl Versuche, die für die Lösung gebraucht wurden.
| |
− | sprache : (div.lang && div.lang != "") ? div.lang : "de", // deutsche Meldungen als Voreinstellung
| |
− |
| |
− | // Funktion zum Auswerten der Drag&Drop-Aktionen des Benutzers
| |
− | dragNDropAuswerten : function (element, ziel) {
| |
− | var t = this,
| |
− | vorgaenger, test;
| |
− |
| |
− | // Element einpflanzen
| |
− | element.parentNode.removeChild(element);
| |
− | ziel.appendChild(element);
| |
− | test = q.domSelect("."+q.draggableClass, ziel);
| |
− |
| |
− | // bei paarweise: War bereits ein Element hier eingefügt? -> Zurück in den Pool damit!
| |
− | if (t.spielModus == "paarweise" && test.length > 1) {
| |
− | vorgaenger = ziel.removeChild(test[0]);
| |
− | t.pool.appendChild(vorgaenger);
| |
− | }
| |
− |
| |
− | // Auswertungsbutton entfernen, falls vorhanden
| |
− | if (t.auswertungsButton.parentNode) {
| |
− | t.auswertungsButton.parentNode.removeChild(t.auswertungsButton);
| |
− | }
| |
− |
| |
− | // letztes Element verwendet -> Auswertungs-Button anbieten
| |
− | if (q.domSelect("."+q.draggableClass, t.pool).length < 1) {
| |
− | t.pool.appendChild(t.auswertungsButton);
| |
− | }
| |
− | },
| |
− |
| |
− | // Funktion zum Auswerten der Zuordnungen
| |
− | auswerten : function () {
| |
− | var t = this,
| |
− | loesungen = q.domSelect("."+t.loesungsClass, t.element),
| |
− | test;
| |
− |
| |
− | // Anzahl Lösungsversuche um eins erhöhen
| |
− | t.versuche++;
| |
− |
| |
− | // Zuordnungen einzeln überprüfen
| |
− | q.each(loesungen, function (l) {
| |
− | var gruppe = l.getElementsByTagName("span"),
| |
− | test = new RegExp(
| |
− | "^" + gruppe[0].id.substring(0, gruppe[0].id.lastIndexOf("_"))
| |
− | );
| |
− |
| |
− | // Stimmen die IDs bis auf ihre letzte Zahl überein?
| |
− | q.each(gruppe, function (g) {
| |
− | if (g && !g.id.match(test)) {
| |
− | // Nein! Element zurück in den Pool!
| |
− | t.pool.appendChild(g);
| |
− | }
| |
− | });
| |
− | });
| |
− |
| |
− | // Auswertungsbutton entfernen, falls vorhanden
| |
− | if (t.auswertungsButton.parentNode) {
| |
− | t.auswertungsButton.parentNode.removeChild(t.auswertungsButton);
| |
− | }
| |
− |
| |
− | // Sind keine Felder mehr im Pool? -> Quiz erfolgreich gelöst!
| |
− | if (q.domSelect("span", t.pool).length < 1) {
| |
− | q.removeAllListeners(t);
| |
− |
| |
− | t.solved = true;
| |
− | t.element.className += " "+q.fertigClass;
| |
− | t.pool.parentNode.removeChild(t.pool);
| |
− |
| |
− | // Bewegungscursor entfernen
| |
− | loesungen = q.domSelect("."+q.draggableClass, t.element);
| |
− | test = new RegExp(" ?" + q.draggableClass);
| |
− |
| |
− | q.each(loesungen, function (l) {
| |
− | l.className = l.className.replace(test, "");
| |
− | l.style.cursor = "";
| |
− | });
| |
− |
| |
− | // Erfolgsmeldung ausgeben
| |
− | t.element.appendChild(q.domCreate({
| |
− | tagName : "p",
| |
− | className : q.bewertungsClass,
| |
− | text : q.meldungen[t.sprache]["lob" + (t.versuche > 2 ? 3 : t.versuche)]
| |
− | + " "
| |
− | + q.meldungen[t.sprache][
| |
− | "ergebnis" + (t.versuche > 2 ? 3 : t.versuche)
| |
− | ].replace(/%n/i, t.versuche)
| |
− | }));
| |
− | }
| |
− | },
| |
− | // Funktion zum Mischen und Austeilen der Wörter
| |
− | init : function () {
| |
− | var t = this,
| |
− | loesung, feld, i, j, gruppe, benutzte, zufall, gemischte;
| |
− |
| |
− | // Spracheinstellungen auf deutsch zurück korrigieren, falls entsprechende Sprachdaten fehlen
| |
− | if (!q.meldungen[t.sprache]) {
| |
− | t.sprache = "de";
| |
− | }
| |
− |
| |
− | /* Jeder Wert aus den Werten der Daten wird zu einem SPAN-Element ("Feld") und erhält eine ID.
| |
− | Die ID eines solchen Feldes enthält den Namen des Quizes, die laufende Nummer der Wertegruppe, der er entstammt
| |
− | und anschließend die laufende Nummer innerhalb der Wertegruppe. Dadurch kann später die Zuordnung ausgewertet werden,
| |
− | da die ID bis auf die letzte Nummer übereinstimmen muss, wenn die Zuordnung stimmen soll. */
| |
− |
| |
− | t.element.appendChild(t.pool); // ins Dokument einfügen
| |
− |
| |
− | // Wertegruppen durchgehen, Felder erzeugen
| |
− | for (i = 0; i < t.daten.length; i++) {
| |
− | // Jedes Datum besteht aus einem Array, das mindestens zwei Felder besitzt.
| |
− | if (t.daten[i].length > 2) {
| |
− | t.spielModus = "gruppenweise";
| |
− | }
| |
− |
| |
− | for (j = 0; j < t.daten[i].length; j++) {
| |
− | t.felder.push(q.domCreate({
| |
− | tagName : "span",
| |
− | id : t.name + "_" + i + "_" + j,
| |
− | className : q.feldClass,
| |
− | innerHTML : t.daten[i][j]
| |
− | }));
| |
− | }
| |
− | }
| |
− |
| |
− | // Felder mischen und verteilen!
| |
− | benutzte = new Array(); // Hier werden bereits benutzte Gruppen markiert
| |
− | gemischte = new Array(); // Felder einer Gruppe die in den Pool sollen, hier eintragen
| |
− |
| |
− | for (j = 0; j < t.daten.length; j++) {
| |
− | // Lösungs-Absatz erzeugen
| |
− | loesung = q.domCreate({
| |
− | tagName: "p",
| |
− | className : t.loesungsClass
| |
− | });
| |
− |
| |
− | // Gruppe auswählen
| |
− | gruppe = true; // Wertegruppe schon verwendet?
| |
− | while (gruppe) {
| |
− | zufall = Math.floor(Math.random() * t.daten.length);
| |
− | gruppe = benutzte[zufall]; // prüfen auf "bereits verwendet"
| |
− | }
| |
− |
| |
− | benutzte[zufall] = true; // Gruppe jetzt als verwendet eintragen.
| |
− |
| |
− | /*
| |
− | Je nach Spiel-Modus ("paarweise" oder "gruppenweise") darf die inhaltliche Vorbelegung des
| |
− | Lösungsabsatzes nicht zufällig belegt werden. Bei paarweisen Zuordnungen ist immer "logisch",
| |
− | welches Feld aus dem Pool dem bereits im Lösungsabsatz stehenden zugeordnet werden muss. Bei
| |
− | gruppenweisen Zuordnungen muss dort aber eine Art Oberbegriff stehen, der dann der ersten
| |
− | Tabellenzelle der Vorgaben entspricht!
| |
− | */
| |
− |
| |
− | feld = 0; // erstes Feld einer Gruppe
| |
− | if (t.spielModus == "paarweise") {
| |
− | // Feld im Lösungsabsatz zufällig auswählen.
| |
− | feld = Math.floor(Math.random() * 2);
| |
− | }
| |
− |
| |
− | /* Feld aus der Liste der erstellten Felder ermitteln und in Lösungsabsatz schreiben.
| |
− | Restliche Felder der Gruppe in den Pool schreiben. */
| |
− | for (i = 0; i < t.felder.length; i++) {
| |
− | if (t.felder[i].id.match(new RegExp(t.name + "_" + zufall + "_"))) {
| |
− | // Feld aus dieser Gruppe ermittelt!
| |
− | if (t.felder[i].id.match(new RegExp(t.name + "_" + zufall + "_" + feld))) {
| |
− | // Feld in den Lösungsabsatz eintragen
| |
− | t.felder[i].style.cursor = "";
| |
− | loesung.appendChild(t.felder[i]);
| |
− | t.pool.parentNode.insertBefore(loesung, t.pool);
| |
− |
| |
− | } else {
| |
− | // Feld zu den gemischten einordnen
| |
− | gemischte.push(t.felder[i]);
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | // zuzuordnende Felder vermischt ausgeben
| |
− | gemischte.shuffle();
| |
− | q.each(gemischte, function (f) {
| |
− | t.pool.appendChild(f);
| |
− | f.className += " "+q.draggableClass;
| |
− | f.style.cursor = "move";
| |
− | });
| |
− |
| |
− | // ID für das umgebende DIV-Element vergeben
| |
− | t.element.id = t.name;
| |
− |
| |
− | q.addAllListeners(t);
| |
− | // Auswertungs-Button erzeugen
| |
− | t.auswertungsButton = q.domCreate({
| |
− | tagName : "span",
| |
− | className : "auswertungs-button",
| |
− | text : q.meldungen[t.sprache].pruefen,
| |
− | onclick : function (e) {
| |
− | t.auswerten();
| |
− | }
| |
− | });
| |
− | }
| |
− | };
| |
− |
| |
− | // Laufende Nummer ermitteln -> Quiz-Name wird "quiz" + laufende Nummer
| |
− | i = 0;
| |
− | q.each(q.alleQuizze, function() {
| |
− | i++;
| |
− | });
| |
− | quiz.name = "quiz" + i;
| |
− |
| |
− | // Gibt es Quiz-Daten?
| |
− | tabelle = q.domSelect("table", div);
| |
− |
| |
− | if (tabelle.length < 1) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Daten sind also vorhanden? -> Auswerten
| |
− | q.each(tabelle[0].getElementsByTagName("tr"), function (tr) {
| |
− | var gefunden = new Array(); // Eine Wertegruppe anlegen
| |
− |
| |
− | // Tabellenzeilen nach Daten durchforsten
| |
− | q.each(tr.getElementsByTagName("td"), function (td) {
| |
− | // Tabellenzellen nach Daten durchforsten
| |
− | var k = false; // normalisierter Zelleninhalt
| |
− |
| |
− | if (td.innerHTML && td.innerHTML != "") {
| |
− | k = td.innerHTML.replace(/ /, " ").quizTrim();
| |
− | }
| |
− |
| |
− | if (k && k != "") {
| |
− | gefunden.push(k);
| |
− | }
| |
− | });
| |
− |
| |
− | // Falls Wertegruppe mindestens ein Wertepaar enthält, dieses den Daten hinzufügen.
| |
− | if (gefunden.length > 1) {
| |
− | quiz.daten.push(gefunden);
| |
− | }
| |
− | });
| |
− |
| |
− | // Keine brauchbare Daten? -> Verwerfen!
| |
− | if (quiz.daten.length < 1) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Quiz in die Liste aufnehmen und initialisieren
| |
− | q.alleQuizze[quiz.name] = quiz;
| |
− | tabelle[0].parentNode.removeChild(tabelle[0]);
| |
− | quiz.element.quiz = quiz;
| |
− | quiz.init();
| |
− |
| |
− | return true;
| |
− | },
| |
− |
| |
− |
| |
− | /* Diese Funktion erzeugt ein Lückentext-Quiz. Dazu braucht sie ein Elternelement mit dem
| |
− | CSS-Klassen-Präfix "lueckentext", z.B. "lueckentext-quiz", wenn "-quiz" das Suffix der Quiz.triggerClass ist.
| |
− | Die mit <strong>, <em>, <b> oder <i> ausgezeichneten Textstellen werden durch Drag&Drop-Felder ersetzt. Sollten
| |
− | Lösungshinweise in Klammern stehen, so werden die Textstellen durch Eingabefelder ersetzt. */
| |
− |
| |
− | lueckentextQuiz : function (div) {
| |
− | var q = this,
| |
− | ids = 0,
| |
− | i, daten;
| |
− |
| |
− | var quiz = {
| |
− | // Objekt-Gestalt eines Lückentext-Quizzes
| |
− | name : "Quiz-x", // Platzhalter - hier steht später etwas anderes.
| |
− | typ : "Lückentext-Quiz",
| |
− | loesungsClass : "luecke", // Für die manuellen Texteingaben kommt noch "_i" hinzu!
| |
− | lueckenPlatzhalter : "", // Leerzeichen als Platzhalter für Lücken
| |
− | element : div, // Referenz auf das DIV-Element, in welchem sich das Quiz befindet
| |
− | felder : new Array(), // Hier stehen später Referenzen auf SPAN-Elemente
| |
− | pool : q.domCreate({
| |
− | tagName : "p",
| |
− | className: q.poolClass
| |
− | }),
| |
− | inputs : new Array(), // Hier stehen später Referenzen auf die Text-Eingabefelder und ihre Lösungen
| |
− | auswertungsButton : null, // Hier steht später das HTML-Element des Auswertungs-Buttons.
| |
− | versuche : 0, // Speichert die Anzahl Versuche, die für die Lösung gebraucht wurden.
| |
− | sprache : (div.lang && div.lang != "") ? div.lang : "de", // deutsche Meldungen als Voreinstellung
| |
− |
| |
− | // Funktion zum Auswerten der Drag&Drop-Aktionen des Benutzers
| |
− | dragNDropAuswerten : function (element, ziel) {
| |
− | var t = this,
| |
− | vorgaenger, test, ok, i;
| |
− |
| |
− | if (element && ziel) {
| |
− | // Element bewegen
| |
− | test = new RegExp(t.loesungsClass, "");
| |
− |
| |
− | // Zuerst überflüssige Leerzeichen im Ziel-Element entfernen?
| |
− | if (ziel.className.match(test)
| |
− | && q.domSelect("."+q.draggableClass, ziel).length < 1
| |
− | ) {
| |
− | ziel.innerHTML = ""; // Leerzeichen in einer Lücke zuvor entfernen
| |
− | }
| |
− |
| |
− | // Bewegliches Element einpflanzen
| |
− | vorgaenger = element.parentNode;
| |
− | ziel.appendChild(element);
| |
− |
| |
− | // Entleertes Element mit Leerzeichen auffüllen?
| |
− | if (vorgaenger.className.match(test)
| |
− | && q.domSelect("."+q.draggableClass, vorgaenger).length < 1
| |
− | ) {
| |
− | // Leerzeichen in einer Lücke als Platzhalter einfügen
| |
− | vorgaenger.innerHTML = t.lueckenPlatzhalter;
| |
− | }
| |
− |
| |
− | // War bereits ein Element hier eingefügt? -> Zurück in den Pool damit!
| |
− | test = q.domSelect("."+q.draggableClass, ziel);
| |
− |
| |
− | if (test.length > 1) {
| |
− | t.pool.appendChild(test[0]);
| |
− | }
| |
− | }
| |
− |
| |
− | // Auswertungsbutton entfernen, falls vorhanden
| |
− | if (t.auswertungsButton.parentNode) {
| |
− | t.auswertungsButton.parentNode.removeChild(t.auswertungsButton);
| |
− | }
| |
− |
| |
− | // Auswertungs-Button anbieten?
| |
− | if (q.domSelect("."+q.draggableClass, t.pool).length < 1) {
| |
− | // letztes Element verwendet -> Alle Eingabefelder ausgefüllt?
| |
− | ok = true; // Wir gehen jetzt einmal davon aus...
| |
− |
| |
− | q.each(t.element.getElementsByTagName("input"), function (i) {
| |
− | if (i.value == "") {
| |
− | ok = false; // Aha, ein Eingabefeld war leer!
| |
− | }
| |
− | });
| |
− |
| |
− | if (ok) {
| |
− | t.pool.appendChild(t.auswertungsButton);
| |
− | }
| |
− | }
| |
− | },
| |
− |
| |
− | // Funktion zum Auswerten der Lösungen
| |
− | auswerten : function () {
| |
− | var t = this,
| |
− | loesungen = new Array(),
| |
− | ok;
| |
− |
| |
− | // Anzahl Lösungsversuche um eins erhöhen
| |
− | t.versuche++;
| |
− |
| |
− | // Drag&Drop-Felder überprüfen
| |
− | loesungen = q.domSelect("."+t.loesungsClass, t.element);
| |
− |
| |
− | if (loesungen.length > 0) {
| |
− | // Es gibt Drag&Drop-Felder zu überprüfen...
| |
− | q.each(loesungen, function (l) {
| |
− | var test = new RegExp("^" + l.id.replace(/^([^_]+_\d+)\w+.*$/, "$1"), ""),
| |
− | element = q.domSelect("."+q.draggableClass, l)[0];
| |
− |
| |
− | if (!element.id.match(test)) {
| |
− | // Falsche Zuordnung! Zurück in den Pool damit!
| |
− | t.pool.appendChild(element);
| |
− | l.innerHTML = t.lueckenPlatzhalter;
| |
− | }
| |
− | });
| |
− | }
| |
− |
| |
− | // Eingabefelder überprüfen
| |
− | loesungen = q.domSelect("."+t.loesungsClass + "_i", t.element);
| |
− | ok = true; // Wir gehen einmal davon aus, dass alles richtig ist...
| |
− |
| |
− | q.each(loesungen, function (l) {
| |
− | q.each(t.inputs, function (i) {
| |
− | var element = q.domSelect("#"+l.id + "i")[0],
| |
− | richtig, test;
| |
− |
| |
− | if (element.id == q.domSelect("input", i.element)[0].id) {
| |
− | // Inhalt prüfen
| |
− | test = i.loesung.split("|");
| |
− | element.value = element.value.quizTrim();
| |
− |
| |
− | q.each(test, function (t) {
| |
− | if (element.value == t.quizTrim()) {
| |
− | richtig = true;
| |
− | }
| |
− | });
| |
− |
| |
− | if (!richtig) {
| |
− | ok = false; // Falsche Eingabe!
| |
− | element.value = "";
| |
− | }
| |
− | }
| |
− | });
| |
− | });
| |
− |
| |
− | // Auswertungsbutton entfernen
| |
− | t.auswertungsButton.parentNode.removeChild(t.auswertungsButton);
| |
− |
| |
− | // Sind alle Eingaben richtig und keine Felder mehr im Pool? -> Quiz erfolgreich gelöst!
| |
− | if (ok && q.domSelect("span", t.pool).length < 1) {
| |
− | // Eventhandler entfernen
| |
− | t.element.onmousedown = null;
| |
− | t.element.onmousemove = null;
| |
− | t.element.onmouseup = null;
| |
− | t.solved = true;
| |
− | t.element.className += " "+q.fertigClass;
| |
− | t.pool.parentNode.removeChild(t.pool);
| |
− |
| |
− | // Elementen die Beweglichkeit nehmen
| |
− | loesungen = q.domSelect("."+q.draggableClass, t.element);
| |
− | test = new RegExp(" ?" + q.draggableClass, "");
| |
− |
| |
− | q.each(loesungen, function (l) {
| |
− | l.className = l.className.replace(test);
| |
− | l.style.cursor = "";
| |
− | });
| |
− |
| |
− | // Eingabefelder durch gelöste Felder ersetzen
| |
− | loesungen = q.domSelect("."+t.loesungsClass + "_i", t.element);
| |
− |
| |
− | q.each(loesungen, function (l) {
| |
− | l.parentNode.insertBefore(q.domCreate({
| |
− | tagName : "span",
| |
− | className : t.loesungsClass,
| |
− | text : q.domSelect("#"+l.id+"i")[0].value
| |
− | }), l);
| |
− | l.parentNode.removeChild(l);
| |
− | });
| |
− |
| |
− | // Erfolgsmeldung ausgeben
| |
− | t.element.appendChild(q.domCreate({
| |
− | tagName : "p",
| |
− | className : q.bewertungsClass,
| |
− | text : q.meldungen[t.sprache]["lob" + (t.versuche > 2 ? 3 : t.versuche)]
| |
− | + " "
| |
− | + q.meldungen[t.sprache][
| |
− | "ergebnis" + (t.versuche > 2 ? 3 : t.versuche)
| |
− | ].replace(/%n/i, t.versuche)
| |
− | }));
| |
− | }
| |
− | },
| |
− |
| |
− | // Funktion zum Erstellen der Lücken, Mischen und Austeilen der beweglichen Wörter, bzw Umwandeln der Wörter zu Engabefeldern
| |
− | init : function () {
| |
− | var t = this,
| |
− | input, felder, benutzte, zufall, luecke, test, i;
| |
− |
| |
− | // Spracheinstellungen auf deutsch zurück korrigieren, falls entsprechende Sprachdaten fehlen
| |
− | if (!q.meldungen[t.sprache]) {
| |
− | t.sprache = "de";
| |
− | }
| |
− |
| |
− | /* Jeder markierte Textabschnitt (zum Markieren dienen die Elemente <i>, <b>, <em> und <strong>) wird zu entweder
| |
− | einem beweglichen SPAN-Element ("Feld"), oder (wenn eine öffnende Klammer für Hilfsangaben enthalten sind)
| |
− | einem Input-Feld. Das markierende Element (also das <i>, <b> etc.) wird ersetzt durch ein <span>-Element mit der
| |
− | CSS_Klasse, die in quiz.loesungsClass definiert wurde.
| |
− |
| |
− | Beispiel1: <p>Eine Henne legt ein <i>Ei</i>.</p>
| |
− | wird zu
| |
− | <p>Eine Henne legt ein <span class="luecke" id="......"> nbsp; nbsp; nbsp; </span>.</p>
| |
− | ->"Ei" wird zu <span id="quiz0_xb" class="beweglich">Ei</span> und landet im Pool.
| |
− |
| |
− | Beispiel2: <p>Eine Henne <b>legt (legen)</b> ein Ei.</p>
| |
− | wird zu
| |
− | <p>Eine Henne <span class="luecke"><input type="text" id="......" /></span> (legen) ein Ei.</p>
| |
− |
| |
− | Die ID eines solchen Feldes enthält den Namen des Quizes, die laufende Nummer des Wertepaares, dem er entstammt
| |
− | und entweder ein "a" oder ein "b". Dadurch kann später die Zuordnung ausgewertet werden, da die ID bis auf den
| |
− | letzten Buchstaben übereinstimmen muss, wenn die Zuordnung stimmen soll. */
| |
− |
| |
− | // Wenn es Drag&Drop-Felder gibt, dann wird ein Pool benötigt
| |
− | if (t.felder.length > 0 || t.inputs.length >0) {
| |
− | // Behälter für die beweglichen Teile ins Dokument einfügen
| |
− | t.element.appendChild(t.pool);
| |
− |
| |
− | // Felder vermischt im Pool ablegen und Lücken erzeugen
| |
− | t.felder.shuffle();
| |
− |
| |
− | q.each(t.felder, function (f) {
| |
− | t.pool.appendChild(f.element);
| |
− |
| |
− | luecke = q.domCreate({
| |
− | tagName: "span",
| |
− | text : t.lueckenPlatzhalter,
| |
− | id : f.element.id + "_" + t.loesungsClass,
| |
− | className : t.loesungsClass
| |
− | });
| |
− |
| |
− | // Lücke ins Dokument schreiben
| |
− | f.original.parentNode.insertBefore(luecke, f.original);
| |
− | f.original.parentNode.removeChild(f.original);
| |
− | });
| |
− |
| |
− | // Eventhandler für bewegliche Felder einrichten
| |
− | t.element.onmousedown = q.startDrag;
| |
− | t.element.onmouseover = q.highlight;
| |
− | t.element.onmouseup = q.stopDrag;
| |
− |
| |
− | q.each(q.domSelect("."+q.feldClass, t.pool), function (f) {
| |
− | f.className += " " + q.draggableClass;
| |
− | f.style.cursor = "move";
| |
− | });
| |
− | }
| |
− |
| |
− | // falls Eingabefelder vorhanden -> einbinden
| |
− | if (t.inputs.length > 0) {
| |
− | q.each(t.inputs, function (i) {
| |
− | if (typeof i != "function") {
| |
− | i.original.parentNode.insertBefore(i.element, i.original);
| |
− | i.original.parentNode.removeChild(i.original);
| |
− | }
| |
− | })
| |
− | }
| |
− |
| |
− | // ID für das umgebende DIV-Element vergeben
| |
− | t.element.id = t.name;
| |
− |
| |
− |
| |
− | q.addAllListeners(t);
| |
− |
| |
− | // Auswertungs-Button erzeugen
| |
− | t.auswertungsButton = q.domCreate({
| |
− | tagName : "span",
| |
− | className : "auswertungs-button",
| |
− | text : q.meldungen[t.sprache].pruefen,
| |
− | onclick : function (e) {
| |
− | t.auswerten();
| |
− | }
| |
− | });
| |
− | }
| |
− | };
| |
− |
| |
− | // Laufende Nummer ermitteln -> Quiz-Name wird "quiz" + laufende Nummer
| |
− | i = 0;
| |
− | q.each(q.alleQuizze, function () {
| |
− | i++;
| |
− | });
| |
− |
| |
− | quiz.name = "quiz" + i;
| |
− |
| |
− | // Gibt es Quiz-Daten?
| |
− | daten = {
| |
− | bolds : q.domSelect("b", div),
| |
− | italics : q.domSelect("i", div),
| |
− | strongs : q.domSelect("strong", div),
| |
− | ems : q.domSelect("em", div)
| |
− | }
| |
− |
| |
− | // keine potentiellen Daten gefunden? -> abbrechen!
| |
− | if (daten.bolds.length < 1
| |
− | && daten.italics.length < 1
| |
− | && daten.strongs.length < 1
| |
− | && daten.ems.length < 1
| |
− | ) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Daten sind also vorhanden? -> Auswerten
| |
− | q.each(daten, function (tagType) {
| |
− | q.each(tagType, function (d) {
| |
− | var test = d.innerHTML.replace(/<\/a>/i, "").replace(/]*>/i, ""); | |
− |
| |
− | if (test.match(/\(/)) {
| |
− | // Eingabefeld!
| |
− | test = q.domCreate({
| |
− | tagName : "span",
| |
− | className : quiz.loesungsClass + "_i",
| |
− | id : quiz.name + "_" + ids
| |
− | });
| |
− |
| |
− | test.innerHTML += d.innerHTML.replace(/^[^(]*(\(.*) *$/, "$1").replace(/ ?\(\)$/, "");
| |
− |
| |
− | test.insertBefore(q.domCreate({
| |
− | tagName : "input",
| |
− | type : "text",
| |
− | id : test.id + "i",
| |
− | onkeyup : function (e) { quiz.dragNDropAuswerten(); }
| |
− | }), test.firstChild);
| |
− |
| |
− | quiz.inputs.push({
| |
− | element : test,
| |
− | original : d,
| |
− | // Lösungsinhalt "säubern"
| |
− | loesung : d.innerHTML.replace(
| |
− | /[\t\r\n]/g, " "
| |
− | ).replace(
| |
− | /^([^(]+).*$/, "$1"
| |
− | ).replace(
| |
− | /( | )/, " "
| |
− | ).replace(
| |
− | / +/, " "
| |
− | ).quizTrim()
| |
− | });
| |
− |
| |
− | ids++; // verwendete ID eintragen, damit keine doppelten IDs entstehen
| |
− |
| |
− | } else {
| |
− | // Drag&Drop-Feld!
| |
− | if (d.innerHTML != "") {
| |
− | // Feld ist nicht leer
| |
− | test = q.domCreate({
| |
− | tagName : "span",
| |
− | className : q.feldClass
| |
− | });
| |
− |
| |
− | test.innerHTML = d.innerHTML.replace(/^ *([^ ](.*[^ ])?) *$/, "$1");
| |
− |
| |
− |
| |
− | /* Gibt es bereits Felder mit identischem Inhalt?
| |
− | Deren IDs müssen bis auf die Buchstaben am Ende übereinstimmen! */
| |
− | q.each(quiz.felder, function (f) {
| |
− | if (typeof(f.element) != "undefined"
| |
− | && f.element.innerHTML == test.innerHTML
| |
− | ) {
| |
− | // ID übernehmen!
| |
− | test.id = f.element.id;
| |
− | }
| |
− | });
| |
− |
| |
− | if (test.id == "") {
| |
− | test.id = quiz.name + "_" + ids + "a";
| |
− | ids++;
| |
− |
| |
− | } else {
| |
− | // übernommene ID eines bereits existierenden Feldes ändern
| |
− | test.id = test.id.substr(0, test.id.length - 1)
| |
− | + String.fromCharCode(test.id.charCodeAt(test.id.length - 1));
| |
− | }
| |
− |
| |
− | quiz.felder.push({
| |
− | element : test,
| |
− | original : d
| |
− | });
| |
− | }
| |
− | }
| |
− | });
| |
− | });
| |
− |
| |
− | // Keine brauchbare Daten? -> Verwerfen!
| |
− | i = 0;
| |
− | q.each(quiz.felder, function () {
| |
− | i++;
| |
− | });
| |
− |
| |
− | q.each(quiz.inputs, function () {
| |
− | i++;
| |
− | });
| |
− |
| |
− | if (i < 1) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Quiz in die Liste aufnehmen und initialisieren
| |
− | q.alleQuizze[quiz.name] = quiz;
| |
− | quiz.element.quiz = quiz;
| |
− | quiz.init();
| |
− |
| |
− | return true;
| |
− | },
| |
− |
| |
− |
| |
− | /* Diese Funktion erzeugt ein memo-quiz. Dazu braucht sie eine Tabelle innerhalb eines Elternelementes
| |
− | mit dem CSS-Klassen-Präfix "memo", z.B. "memo-quiz", wenn "-quiz" das Suffix der Quiz.triggerClass ist.
| |
− | In der Tabelle stehen die Set-Daten: Die Anzahl an Spalten steht für die Anzahl der Felder pro Set, die Anzahl
| |
− | der Zeilen ist die Anzahl der Sets. */
| |
− |
| |
− | memoQuiz : function (div) {
| |
− | var q = this,
| |
− | i, j, test, daten, tabelle;
| |
− |
| |
− | var quiz = {
| |
− | // Objekt-Gestalt eines memo-quizzes
| |
− | name : "Quiz-x", // Platzhalter - hier steht später etwas anderes.
| |
− | typ : "memo-quiz",
| |
− | inhaltsClass : "feld-inhalt", // CSS-Klasse für den Inhalt eines Feldes
| |
− | aktivClass : "aktiv", // CSS-Klasse für ein aktiviertes Feld
| |
− | fertigClass : "fertig", // CSS-Klasse für ein Feld, das aussortiert wurde
| |
− | element : div, // Referenz auf das DIV-Element, in welchem sich das Quiz befindet
| |
− | angeklickt : null, // Referenz auf das angeklickte Element innerhalb des DIVs
| |
− | felder : new Array(), // Hier stehen später Referenzen auf SPAN-Elemente.
| |
− | pool : q.domCreate({
| |
− | tagName : "p",
| |
− | className : q.poolClass
| |
− | }),
| |
− | setGroesse : 2, // Anzahl der zu einem Set gehörenden Felder
| |
− | versuche : 0, // Speichert die Anzahl Versuche, die für die Lösung gebraucht wurden.
| |
− | sprache : (div.lang && div.lang != "") ? div.lang : "de", // deutsche Meldungen als Voreinstellung
| |
− |
| |
− | // Funktion zum Aufdecken eines Feldes (kommt über Eventhandler onclick)
| |
− | aufdecken : function (e) {
| |
− | var t = this;
| |
− |
| |
− | e = e || window.event;
| |
− | t.angeklickt = e.target || e.srcElement; // W3C DOM <-> IE
| |
− |
| |
− | // Nur bei Klick auf ein Feld (oder eines seiner Nachfahren-Elemente) reagieren!
| |
− | test = t.angeklickt;
| |
− |
| |
− | while (!test.className
| |
− | || !test.className.match(new RegExp("(^|\\s)" + q.feldClass + "(\\s|$)"))
| |
− | ) {
| |
− | test = test.parentNode;
| |
− |
| |
− | if (test == document.body) {
| |
− | return false;
| |
− | }
| |
− | }
| |
− |
| |
− | q.aktivesQuiz = t;
| |
− | t.angeklickt = test; // das angeklickte Feld abspeichern
| |
− |
| |
− | // Feld wurde angeklickt -> aufdecken?
| |
− | test = q.domSelect("."+t.aktivClass, t.element);
| |
− |
| |
− | if (test.length >= t.setGroesse) {
| |
− | // Nein, denn es sind schon alle Felder für ein Set aufgedeckt!
| |
− | return false;
| |
− |
| |
− | } else {
| |
− | // Das aktuelle Set ist noch nicht vollständig aufgedeckt...
| |
− | if (!t.angeklickt.className.match(new RegExp(
| |
− | "(^|\\s)" + t.aktivClass + "(\\s|$)", ""
| |
− | ))) {
| |
− | // OK, Feld wurde noch nicht aufgedeckt. -> aufdecken
| |
− | t.angeklickt.className += " " + t.aktivClass;
| |
− |
| |
− | // eventuelle Markierungen aufheben (stört bei Bildern)
| |
− | try { window.getSelection().collapse(t.angeklickt, 0); }
| |
− | catch (e) { };
| |
− |
| |
− | try { document.selection.clear(); }
| |
− | catch (e) { };
| |
− |
| |
− | if (q.domSelect("."+t.aktivClass, t.element).length >= t.setGroesse) {
| |
− | // Alle Felder für ein Feld wurden aufgedeckt! -> auswerten
| |
− | window.setTimeout(function () { t.auswerten(); }, 1500);
| |
− | }
| |
− | }
| |
− | }
| |
− | },
| |
− |
| |
− | // Funktion zum Auswerten eines aufgedeckten Sets
| |
− | auswerten : function () {
| |
− | var t = this,
| |
− | i, ok, muster;
| |
− |
| |
− | // Anzahl Lösungsversuche um eins erhöhen
| |
− | t.versuche++;
| |
− |
| |
− | // aufgedeckte Felder ermitteln
| |
− | test = q.domSelect("."+t.aktivClass, t.element);
| |
− |
| |
− | // IDs der Felder vergleichen
| |
− | muster = new RegExp(test[0].id.replace(/^([^_]+_\d+).*$/, "$1"), ""); // ID des ersten Feldes ohne letzten Buchstaben
| |
− | ok = true; // Wir gehen von einer Übereinstimmung aus...
| |
− | q.each(test, function (i) {
| |
− | if (!i.id.match(muster)) {
| |
− | ok = false;
| |
− | }
| |
− | });
| |
− |
| |
− | // IDs haben übereingestimmt?
| |
− | muster = new RegExp(" ?" + t.aktivClass, "");
| |
− | q.each(test, function (i) {
| |
− | if (ok) {
| |
− | // Ja. -> aufgedekte Felder "entfernen"
| |
− | i.className = t.fertigClass;
| |
− | } else {
| |
− | // Nein! -> Felder wieder umdrehen!
| |
− | i.className = i.className.replace(muster, "");
| |
− | }
| |
− | });
| |
− |
| |
− | // Alle Felder abgeräumt?
| |
− | test = q.domSelect("."+Quiz.feldClass, this.element);
| |
− | if (test.length < 1) {
| |
− |
| |
− | // Gratulieren und nachfragen
| |
− | var nachfrage = q.meldungen[t.sprache]["lob" + (t.versuche > 2 ? 3 : t.versuche)]
| |
− | + " "
| |
− | + q.meldungen[t.sprache].alleGefunden
| |
− | + "\n"
| |
− | + q.meldungen[t.sprache]["ergebnis" + (t.versuche > 2 ? 3 : t.versuche)].replace(/%n/i, t.versuche)
| |
− | + "\n"
| |
− | + q.meldungen[t.sprache].erneut;
| |
− |
| |
− | if (confirm(
| |
− | q.meldungen[t.sprache]["lob" + (t.versuche > 2 ? 3 : t.versuche)]
| |
− | + " "
| |
− | + q.meldungen[t.sprache].alleGefunden
| |
− | + "\n"
| |
− | + q.meldungen[t.sprache][
| |
− | "ergebnis" + (t.versuche > 2 ? 3 : t.versuche)
| |
− | ].replace(/%n/i, t.versuche)
| |
− | + "\n"
| |
− | + q.meldungen[t.sprache].erneut
| |
− | )) {
| |
− | test = q.domSelect("."+Quiz.poolClass, this.element);
| |
− |
| |
− | if (test.length > 0)
| |
− | test[0].parentNode.removeChild(test[0]);
| |
− |
| |
− | t.init(); // Quiz erneut starten
| |
− |
| |
− | } else {
| |
− | t.element.onmousedown = null;
| |
− | t.element.onmousemove = null;
| |
− | t.element.onmouseup = null;
| |
− | t.solved = true;
| |
− | t.element.className += " "+q.fertigClass;
| |
− | }
| |
− | }
| |
− | },
| |
− |
| |
− | // Funktion zum Mischen und Austeilen der Wörter
| |
− | init : function () {
| |
− | var t = this,
| |
− | sets = new Array(),
| |
− | i, zufall;
| |
− |
| |
− | // Spracheinstellungen auf deutsch zurück korrigieren, falls entsprechende Sprachdaten fehlen
| |
− | if (!q.meldungen[t.sprache]) {
| |
− | t.sprache = "de";
| |
− | }
| |
− |
| |
− | /* Jeder Wert aus den Set-Daten wird zu einem SPAN-Element ("Feld") und erhält eine ID.
| |
− | Die ID eines solchen Feldes enthält den Namen des Quizes, die laufende Nummer des Sets, dem das Feld entstammt
| |
− | und einen "laufenden Buchstaben". Dadurch kann später die Zuordnung ausgewertet werden, da die ID bis auf den
| |
− | letzten Buchstaben übereinstimmen muss, wenn die Zuordnung stimmen soll. */
| |
− |
| |
− | t.element.appendChild(t.pool); // ins Dokument einfügen
| |
− |
| |
− | // Felder vermischt in den Pool schreiben
| |
− | t.felder.shuffle();
| |
− |
| |
− | q.each(t.felder, function (f) {
| |
− | t.pool.appendChild(f.cloneNode(true));
| |
− | });
| |
− |
| |
− | // Elternelement vorbereiten
| |
− | t.element.onclick = function (e) { t.aufdecken(e); }; // Eventhandler vergeben
| |
− | t.element.id = t.name; // ID vergeben
| |
− | t.versuche = 0; // Anzahl Versuche zurücksetzen
| |
− | }
| |
− | }
| |
− |
| |
− |
| |
− | // Laufende Nummer ermitteln -> Quiz-Name wird "quiz" + laufende Nummer
| |
− | i = 0;
| |
− | q.each(q.alleQuizze, function () {
| |
− | i++;
| |
− | });
| |
− | quiz.name = "quiz" + i;
| |
− |
| |
− | // Gibt es Quiz-Daten?
| |
− | tabelle = q.domSelect("table", div);
| |
− |
| |
− | if (tabelle.length < 1) {
| |
− | // Keine Tabelle für Quiz-Daten gefunden! -> abbrechen
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Daten sind also vorhanden? -> Auswerten
| |
− | test = q.domSelect("tr", tabelle[0]);
| |
− |
| |
− | // Tabellenzeilen nach Daten durchforsten
| |
− | for (i = 0; i < test.length; i++) {
| |
− | daten = q.domSelect("td", test[i]);
| |
− |
| |
− | if (daten.length > 1) {
| |
− | quiz.setGroesse = daten.length;
| |
− |
| |
− | for (j = 0; j < daten.length; j++) {
| |
− | // Feld abspeichern
| |
− | quiz.felder.push(q.domCreate({
| |
− | tagName : "span",
| |
− | className : q.feldClass,
| |
− | id : quiz.name + "_" + i + String.fromCharCode(j + 97)
| |
− | }));
| |
− |
| |
− | quiz.felder[quiz.felder.length -1].appendChild(q.domCreate({
| |
− | tagName : "span",
| |
− | className : quiz.inhaltsClass
| |
− | }));
| |
− |
| |
− | quiz.felder[quiz.felder.length -1].lastChild.innerHTML = daten[j].innerHTML;
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | // Keine brauchbare Daten? -> Verwerfen!
| |
− | i = 0;
| |
− | q.each(quiz.felder, function() {
| |
− | i++;
| |
− | });
| |
− |
| |
− | if (i < 1) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Quiz in die Liste aufnehmen und initialisieren
| |
− | q.alleQuizze[quiz.name] = quiz;
| |
− | tabelle[0].parentNode.removeChild(tabelle[0]);
| |
− | quiz.element.quiz = quiz;
| |
− | quiz.init();
| |
− |
| |
− | return true;
| |
− | },
| |
− |
| |
− |
| |
− | /* Diese Funktion erzeugt ein Multiple Choice - Quiz. Dazu braucht sie Textabsätze innerhalb eines Elternelementes
| |
− | mit dem CSS-Klassen-Präfix "multiplechoice", z.B. "multiplechoice-quiz", wenn "-quiz" das Suffix der Quiz.triggerClass ist.
| |
− | In den Textabsätzen stehen die jeweiligen Quiz-Fragen, die Antworten stehen am Ende der Absätze in runden Klammern. Falsche
| |
− | Antworten haben innerhalb der Klammer gleich als erstes Zeichen ein Ausrufezeichen, richtige Antworten nicht.
| |
− | Textabsätze ohne Klammernpaar am Ende werden nicht als Quiz-Fragen interpretiert. */
| |
− |
| |
− | multiplechoiceQuiz : function (div) {
| |
− | var q = this,
| |
− | fragen, i;
| |
− |
| |
− | var quiz = {
| |
− | // Objekt-Gestalt eines Multiple Choice - Quizzes
| |
− | name : "Quiz-x", // Platzhalter - hier steht später etwas anderes.
| |
− | typ : "Multiple Choice - Quiz",
| |
− | loesungsClass : "quiz-antworten", // CSS-Klasse für das Elternelement mit den Antworten
| |
− | element : div, // Referenz auf das DIV-Element, in welchem sich das Quiz befindet
| |
− | fragen : new Array(), // Hier stehen später die Fragen zusammen mit ihren Antworten
| |
− | sprache : (div.lang && div.lang != "") ? div.lang : "de", // deutsche Meldungen als Voreinstellung
| |
− |
| |
− | // Funktion zum Auswerten eines aufgedeckten Sets
| |
− | auswerten : function () {
| |
− | var t = this,
| |
− | anzahl, test, richtigkeit;
| |
− |
| |
− | // Antwort-Blöcke ermitteln
| |
− | richtigkeit = 0; // Anzahl der gezählten Treffer
| |
− | anzahl = 0; // Anzahl der möglichen richtigen Antworten
| |
− |
| |
− | q.each(q.domSelect("."+t.loesungsClass, t.element), function(a) {
| |
− | // Jeden Antwortblock einzeln durchgehen
| |
− | var ok = 0; // Anzahl Treffer abzüglich falscher Treffer
| |
− |
| |
− | q.each(q.domSelect("input", a), function(i) {
| |
− | // <li>-Element ermitteln, um es später einzufärben
| |
− | var li = i.parentNode;
| |
− |
| |
− | while (!li.tagName || !li.tagName.match(/^li$/i)) {
| |
− | li = li.parentNode;
| |
− | }
| |
− |
| |
− | // Checkbox unveränderlich machen
| |
− | i.disabled = "disabled";
| |
− |
| |
− | if (i.id.match(/_f$/)) {
| |
− | // Aha, eine Falschantwort...
| |
− | if (i.checked) {
| |
− | // ... wurde fälschlicherweise angewählt!
| |
− | li.className = "falsch";
| |
− | ok--;
| |
− | }
| |
− |
| |
− | } else {
| |
− | // Aha, eine richtige Antwort...
| |
− | li.className = "richtig";
| |
− | anzahl++; // Anzahl der möglichen richtigen Antworten erhöhen
| |
− |
| |
− | if (i.checked) {
| |
− | // ...wurde korrekt angewählt
| |
− | ok++;
| |
− | }
| |
− | }
| |
− | });
| |
− |
| |
− | // keine negative Wertung für eine Antwort
| |
− | ok = ok < 0 ? 0 : ok;
| |
− |
| |
− | richtigkeit += ok; // richtige Treffer merken
| |
− | });
| |
− |
| |
− | richtigkeit = (anzahl > 0) ?
| |
− | Math.floor(richtigkeit / anzahl * 1000) / 10 // auf eine Zehntelstelle genau
| |
− | : 0;
| |
− |
| |
− | // Auswertung ins Dokument schreiben
| |
− | t.element.appendChild(q.domCreate({
| |
− | tagName : "p",
| |
− | className : q.bewertungsClass,
| |
− | text : q.meldungen[t.sprache].ergebnisProzent.replace(/%n/i, richtigkeit)
| |
− | }));
| |
− |
| |
− | t.solved = true;
| |
− | t.element.className += " " + q.fertigClass;
| |
− |
| |
− | // Auswertungs-Button entfernen
| |
− | test = q.domSelect(".auswertungs-button", t.element);
| |
− |
| |
− | if (test.length > 0) {
| |
− | t.element.removeChild(test[0]);
| |
− | }
| |
− | },
| |
− |
| |
− | // Funktion zum Anzeigen der Fragen und der vermischten möglichen Antworten
| |
− | init : function () {
| |
− | var t = this,
| |
− | frage, antworten, i, j, html, ID;
| |
− |
| |
− | // Spracheinstellungen auf deutsch zurück korrigieren, falls entsprechende Sprachdaten fehlen
| |
− | if (!q.meldungen[t.sprache]) {
| |
− | t.sprache = "de";
| |
− | }
| |
− |
| |
− | /* Jede Antwort wird zu einem Listen-Element innerhalb einer geordneten Liste.
| |
− | Die Liste erhält die CSS-Klasse quiz.loesungsClass.
| |
− | Die Listenelemente erhalten eine ID, die sich nur am letzten Buchstaben unterscheidet.
| |
− | Die ID einer Falschantwort erhält zusätzlich ein "_f". */
| |
− |
| |
− | for (i = 0; i < t.fragen.length; i++) {
| |
− | // Frage in das Dokument schreiben
| |
− | frage = q.domCreate({
| |
− | tagName: "p"
| |
− | });
| |
− |
| |
− | frage.innerHTML = t.fragen[i].frage;
| |
− | t.element.insertBefore(frage, t.fragen[i].original);
| |
− |
| |
− | // Antworten zusammenstellen und vermischt ausgeben
| |
− | antworten = q.domCreate({
| |
− | tagName : "ol",
| |
− | className : t.loesungsClass
| |
− | });
| |
− |
| |
− | html = "";
| |
− | t.fragen[i].antworten.shuffle();
| |
− |
| |
− | for (j = 0; j < this.fragen[i].antworten.length; j++) {
| |
− | ID = this.name + "_" + i + String.fromCharCode(j + 97);
| |
− |
| |
− | if (this.fragen[i].antworten[j].match(/^\!/))
| |
− | ID += "_f"; // Falschantwort markieren
| |
− |
| |
− | html += '<li><input type="checkbox" id="' + ID + '">'
| |
− | + '<label for="' + ID + '"> '
| |
− | + t.fragen[i].antworten[j].replace(/^\!/, "")
| |
− | + "</label></li>";
| |
− | }
| |
− |
| |
− | antworten.innerHTML += html;
| |
− |
| |
− | t.element.insertBefore(frage, t.fragen[i].original);
| |
− | t.element.insertBefore(antworten, t.fragen[i].original);
| |
− | t.element.removeChild(t.fragen[i].original);
| |
− | }
| |
− |
| |
− | // Auswertungsbutton anzeigen
| |
− | t.element.appendChild(q.domCreate({
| |
− | tagName : "p",
| |
− | className : "auswertungs-button",
| |
− | text : q.meldungen[t.sprache].pruefen,
| |
− | onclick : function () { t.auswerten(); }
| |
− | }));
| |
− |
| |
− | // ID für das umgebende DIV-Element vergeben
| |
− | t.element.id = t.name;
| |
− | }
| |
− | }
| |
− |
| |
− |
| |
− | // Laufende Nummer ermitteln -> Quiz-Name wird "quiz" + laufende Nummer
| |
− | i = 0;
| |
− | q.each(q.alleQuizze, function() {
| |
− | i++;
| |
− | });
| |
− | quiz.name = "quiz" + i;
| |
− |
| |
− | // Gibt es Quiz-Daten?
| |
− | fragen = q.domSelect("p", div);
| |
− |
| |
− | if (fragen.length < 1) {
| |
− | // Keine Textabsätze für Quiz-Daten gefunden! -> abbrechen
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Daten sind also vorhanden? -> Auswerten
| |
− | q.each(fragen, function (f) {
| |
− | // Textabsatz durchforsten
| |
− | var test = f.innerHTML.replace(/[\t\r\n]/g, " "),
| |
− | daten = {
| |
− | frage : "",
| |
− | antworten : new Array(),
| |
− | original : null // Referenz auf den originalen Textabsatz, um ihn später zu entfernen
| |
− | };
| |
− |
| |
− | // Zeilenumbrüche und überflüssige Leerzeichen entfernen
| |
− | test = test.replace(/(<br>|<br\/>|<br \/>|&bnsp;| )*$/ig, "");
| |
− |
| |
− | while (test.match(/\)$/)) {
| |
− | daten.antworten.push(test.replace(/^.*\(([^\(\)]*)\)$/, "$1"));
| |
− |
| |
− | // extrahierte Antwort aus dem String entfernen
| |
− | test = test.replace(/^(.*)\([^\(\)]*\)$/, "$1");
| |
− | test = test.quizTrim();
| |
− | }
| |
− |
| |
− | // Passende Fragen im aktuellen Textabsatz gefunden?
| |
− | if (daten.antworten.length > 0) {
| |
− | // Ja! Frage mit dazu ...
| |
− | daten.frage = test;
| |
− | daten.original = f; // Referenz zum ursprünglichen Textabsatz
| |
− |
| |
− | // ... und Daten ins Quiz übertragen
| |
− | quiz.fragen.push(daten);
| |
− | }
| |
− | });
| |
− |
| |
− | // Keine brauchbare Daten? -> Verwerfen!
| |
− | i = 0;
| |
− | q.each(quiz.fragen, function() {
| |
− | i++;
| |
− | });
| |
− |
| |
− | if (i < 1) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Quiz in die Liste aufnehmen und initialisieren
| |
− | q.alleQuizze[quiz.name] = quiz;
| |
− | quiz.element.quiz = quiz;
| |
− | quiz.init();
| |
− |
| |
− | return true;
| |
− | },
| |
− |
| |
− |
| |
− | /* Diese Funktion erzeugt ein Schüttel-Quiz. Dazu braucht sie ein Elternelement mit dem
| |
− | CSS-Klassen-Präfix "schuettel", z.B. "schuettel-quiz", wenn "-quiz" das Suffix der Quiz.triggerClass ist.
| |
− | Die mit <strong>, <em>, <b> oder <i> ausgezeichneten Textstellen werden durch Drag&Drop-Felder ersetzt. Sollten
| |
− | Lösungshinweise in Klammern stehen, so werden die Textstellen durch Eingabefelder ersetzt. */
| |
− |
| |
− | schuettelQuiz : function (div) {
| |
− | var q = this,
| |
− | i, j, test, inhalt, daten;
| |
− |
| |
− | var quiz = {
| |
− | // Objekt-Gestalt eines Schüttel-Quizzes
| |
− | name : "Quiz-x", // Platzhalter - hier steht später etwas anderes.
| |
− | typ : "Schüttel-Quiz",
| |
− | loesungsClass : "luecke",
| |
− | element : div, // Referenz auf das DIV-Element, in welchem sich das Quiz befindet
| |
− | felder : new Array(), // Hier stehen später Referenzen auf die Text-Eingabefelder und ihre Lösungen
| |
− | auswertungsButton : null, // Hier steht später das HTML-Element des Auswertungs-Buttons.
| |
− | versuche : 0, // Speichert die Anzahl Versuche, die für die Lösung gebraucht wurden.
| |
− | sprache : (div.lang && div.lang != "") ? div.lang : "de", // deutsche Meldungen als Voreinstellung
| |
− |
| |
− | // Funktion zum Auswerten der Lösungen
| |
− | auswerten : function (klick) {
| |
− | var t = this,
| |
− | loesungen, ok;
| |
− |
| |
− | if (klick) {
| |
− | // Auswertungs-Button wurde geklickt! Auswerten!
| |
− | ok = true; // Mal davon ausgehen, dass alles richtig ist...
| |
− |
| |
− | // Anzahl Lösungsversuche um eins erhöhen
| |
− | t.versuche++;
| |
− |
| |
− | q.each(q.domSelect("."+t.loesungsClass, t.element), function(f) {
| |
− | var eingabe = q.domSelect("input", f),
| |
− | nummer;
| |
− |
| |
− | // bereits als richtig ausgewertete Felder enthalten kein Input-Element mehr!
| |
− | if (eingabe.length > 0) {
| |
− | nummer = eingabe[0].id.replace(/^.*_(\d+)$/, "$1");
| |
− |
| |
− | if (eingabe[0].value.toLowerCase() == t.felder[nummer].loesung.toLowerCase()) {
| |
− | // Eingabefeld wurde richtig ausgefüllt!
| |
− | f.innerHTML = t.felder[nummer].loesung;
| |
− |
| |
− | } else {
| |
− | // Eingabefeld wurde falsch ausgefüllt! -> leeren
| |
− | eingabe[0].value = "";
| |
− | ok = false;
| |
− | }
| |
− | }
| |
− | });
| |
− |
| |
− | if (ok) {
| |
− | // Quiz wurde korrekt gelöst! -> Erfolgsmeldung ausgeben
| |
− | t.element.appendChild(q.domCreate({
| |
− | tagName : "p",
| |
− | className : q.bewertungsClass,
| |
− | text : q.meldungen[t.sprache]["lob" + (t.versuche > 2 ? 3 : t.versuche)]
| |
− | + " "
| |
− | + q.meldungen[t.sprache][
| |
− | "ergebnis" + (t.versuche > 2 ? 3 : t.versuche)
| |
− | ].replace(/%n/i, t.versuche)
| |
− | }));
| |
− |
| |
− | t.solved = true;
| |
− | t.element.className += " " + q.fertigClass;
| |
− | }
| |
− | }
| |
− |
| |
− | // Auswertungsbutton entfernen, falls vorhanden
| |
− | if (t.auswertungsButton.parentNode) {
| |
− | t.auswertungsButton.parentNode.removeChild(t.auswertungsButton);
| |
− | }
| |
− |
| |
− | // Eingabefelder überprüfen
| |
− | loesungen = q.domSelect("input", t.element);
| |
− | ok = loesungen.length > 0; // Mal davon ausgehen, dass alle ausgefüllt sind... wenn es welche gibt!
| |
− |
| |
− | q.each(loesungen, function(l) {
| |
− | if (l.value == "") {
| |
− | ok = false; // Feld war leer!
| |
− | }
| |
− | });
| |
− |
| |
− | // Sind alle Eingabefelder ausgefüllt?
| |
− | if (ok) {
| |
− | // Ja. -> Button ins Dokument schreiben
| |
− | t.element.appendChild(t.auswertungsButton);
| |
− | }
| |
− | },
| |
− |
| |
− | // Funktion zum Umwandeln der Wörter zu Engabefeldern
| |
− | init : function () {
| |
− | var t = this,
| |
− | luecke;
| |
− |
| |
− | // Spracheinstellungen auf deutsch zurück korrigieren, falls entsprechende Sprachdaten fehlen
| |
− | if (!q.meldungen[t.sprache]) {
| |
− | t.sprache = "de";
| |
− | }
| |
− |
| |
− | /* Jeder markierte Textabschnitt (zum Markieren dienen die Elemente <i>, <b>, <em> und <strong>) wird durch ein
| |
− | SPAN-Element, in welchem sich ein Input-Element mit einer Lösucngsvorgabe in Klammern befindet, ersetzt.
| |
− | Es erhält die CSS_Klasse, die in quiz.loesungsClass definiert wurde.
| |
− |
| |
− | Beispiel: <p>Eine <i>Henne</i> legt ein.</p>
| |
− | wird zu
| |
− | <p>Eine <span class="luecke"><input id="......" /> (eeHnn)</span> legt ein Ei.</p>
| |
− |
| |
− | Die ID eines solchen Input-Elements korrespondiert mit der laufenden Nummer des Daten-Eintrages in
| |
− | "quiz.felder". */
| |
− |
| |
− | for (i = 0; i < t.felder.length; i++) {
| |
− | // Lücke mit Eingabe-Element vorbereiten
| |
− | luecke = q.domCreate({
| |
− | tagName : "span",
| |
− | className : t.loesungsClass,
| |
− | text : " ("
| |
− | + t.felder[i].loesung.toLowerCase().split("").shuffle().join("")
| |
− | + ")"
| |
− | });
| |
− |
| |
− | luecke.insertBefore(
| |
− | q.domCreate({
| |
− | tagName : "input",
| |
− | type : "text",
| |
− | name : t.name + "_" + i,
| |
− | id : t.name + "_" + i,
| |
− | onkeyup : function () { t.auswerten(); }
| |
− | }),
| |
− | luecke.firstChild
| |
− | );
| |
− |
| |
− | t.felder[i].element = luecke;
| |
− | }
| |
− |
| |
− | // Alle im Dokument markierten Wörter in Eingabefelder umwandeln
| |
− | q.each(t.felder, function (f) {
| |
− | f.original.parentNode.insertBefore(f.element, f.original);
| |
− | f.original.parentNode.removeChild(f.original);
| |
− | });
| |
− |
| |
− | // ID für das umgebende DIV-Element vergeben
| |
− | t.element.id = t.name;
| |
− |
| |
− | // Auswertungs-Button erzeugen
| |
− | t.auswertungsButton = q.domCreate({
| |
− | tagName : "p",
| |
− | className : "auswertungs-button",
| |
− | text : q.meldungen[t.sprache].pruefen,
| |
− | onclick : function () { t.auswerten(1); }
| |
− | });
| |
− | }
| |
− | };
| |
− |
| |
− | // Laufende Nummer ermitteln -> Quiz-Name wird "quiz" + laufende Nummer
| |
− | i = 0;
| |
− | q.each(q.alleQuizze, function () {
| |
− | i++;
| |
− | });
| |
− |
| |
− | quiz.name = "quiz" + i;
| |
− |
| |
− | // Gibt es Quiz-Daten?
| |
− | daten = {
| |
− | bolds : q.domSelect("b", div),
| |
− | italics : q.domSelect("i", div),
| |
− | strongs : q.domSelect("strong", div),
| |
− | ems : q.domSelect("em", div)
| |
− | }
| |
− |
| |
− | // keine potentiellen Daten gefunden? -> abbrechen!
| |
− | if (daten.bolds.length < 1
| |
− | && daten.italics.length < 1
| |
− | && daten.strongs.length < 1
| |
− | && daten.ems.length < 1
| |
− | ) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Daten sind also vorhanden? -> Auswerten
| |
− | q.each(daten, function (d) {
| |
− | q.each(d, function (f) {
| |
− | // Lösungsinhalt "säubern"
| |
− | quiz.felder.push({
| |
− | element : null,
| |
− | original : f,
| |
− | loesung : f.innerHTML.replace(
| |
− | /[\t\r\n]/g, " "
| |
− | ).replace(
| |
− | /^<\/?[^>]+>$/, ""
| |
− | ).replace(
| |
− | /(nbsp; | )/, " "
| |
− | ).replace(
| |
− | / +/, " "
| |
− | ).quizTrim()
| |
− | });
| |
− | });
| |
− | });
| |
− |
| |
− | // Brauchbare Daten?
| |
− | i = 0;
| |
− | q.each(quiz.felder, function () {
| |
− | i++;
| |
− | });
| |
− |
| |
− | if (i < 1) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Quiz in die Liste aufnehmen und initialisieren
| |
− | q.alleQuizze[quiz.name] = quiz;
| |
− | quiz.element.quiz = quiz;
| |
− | quiz.init();
| |
− |
| |
− | return true;
| |
− | },
| |
− |
| |
− |
| |
− | /* Diese Funktion erzeugt ein Kreuzwort-Quiz. Dazu braucht sie ein Elternelement mit dem
| |
− | CSS-Klassen-Präfix "kreuzwort", z.B. "kreuzwort-quiz", wenn "-quiz" das Suffix der Quiz.triggerClass ist.
| |
− | Die Daten für das Quiz müssen in einer zweispaltigen Tabelle stehen:
| |
− | 1. Zelle enthält das Lösungswort,
| |
− | 2. Zelle enthält eine Lösungshilfe
| |
− | */
| |
− |
| |
− | kreuzwortQuiz : function (div) {
| |
− | var q = this,
| |
− | i, tabelle;
| |
− |
| |
− | var quiz = {
| |
− | // Objekt-Gestalt eines Kreuzwort-Quizzes
| |
− | name : "Quiz-x", // Platzhalter - hier steht später etwas anderes.
| |
− | typ : "Kreuzwort-Quiz",
| |
− | loesungsClass : "feld",
| |
− | loesungsClass2 : "eingabe-feld",
| |
− | element : div, // Referenz auf das DIV-Element, in welchem sich das Quiz befindet
| |
− | eingabe : q.domCreate({ tagName : "div" }), // Eingabebereich
| |
− | tabelle : null, // Referenz auf das HTML-Element, in dem das Kreuzworträtsel angezeigt wird
| |
− | daten : new Array(), // Hier stehen später Objekte, die die Quiz-Daten enthalten.
| |
− | auswertungsButton : null, // Hier steht später das HTML-Element des Auswertungs-Buttons.
| |
− | versuche : 0, // Speichert die Anzahl Versuche, die für die Lösung gebraucht wurden.
| |
− | sprache : (div.lang && div.lang != "") ? div.lang : "de", // deutsche Meldungen als Voreinstellung
| |
− |
| |
− | // Funktion zum Auswerten der Lösungen
| |
− | auswerten : function (werte) {
| |
− | /* "werte" hat folgende Struktur: {
| |
− | wort: <String>,
| |
− | quizItem: {
| |
− | wort: <String>,
| |
− | x: <Number>,
| |
− | y: <Number>,
| |
− | hilfe: <String>,
| |
− | richtung: "waagrecht|senkrecht",
| |
− | name: <String>
| |
− | },
| |
− | form: <HTMLFormObject>
| |
− | } */
| |
− | var t = this,
| |
− | test = true,
| |
− | i, p, button, zelle, alleZellen, forms;
| |
− |
| |
− | if (werte.wort && werte.quizItem) {
| |
− | // Es wurde ein Button geklickt... Eintragen!
| |
− | p = {
| |
− | wort : werte.quizItem.wort,
| |
− | x : werte.quizItem.x,
| |
− | y : werte.quizItem.y,
| |
− | richtung : werte.quizItem.richtung
| |
− | };
| |
− |
| |
− | alleZellen = t.findeZellen(p);
| |
− |
| |
− | for (i = 0; i < alleZellen.length; i ++) {
| |
− | if (werte.wort.length > i) {
| |
− | // Buchstabe in die Zelle eintragen
| |
− | zelle = q.domSelect("."+t.loesungsClass2, alleZellen[i]); // span-Element für Buchstaben finden
| |
− |
| |
− | if (zelle.length > 0) {
| |
− | zelle[0].firstChild.nodeValue = werte.wort.substr(
| |
− | i, 1
| |
− | ).replace(
| |
− | / /, String.fromCharCode(160)
| |
− | );
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | // Eingabeformular(e) entfernen/aktualisieren
| |
− | werte.form.parentNode.removeChild(werte.form);
| |
− |
| |
− | forms = q.domSelect("form", t.eingabe);
| |
− | if (forms.length > 0) {
| |
− | // weitere Eingabe(n) möglich -> Formular(e) neu aufbauen
| |
− | p = new Array();
| |
− |
| |
− | q.each(forms, function (f) {
| |
− | p.push({
| |
− | wort : f.quizDaten.wort,
| |
− | x : f.quizDaten.x,
| |
− | y : f.quizDaten.y,
| |
− | hilfe : f.quizDaten.hilfe,
| |
− | richtung : f.quizDaten.richtung
| |
− | });
| |
− | });
| |
− |
| |
− | // Formulare neu erstellen lassen
| |
− | return t.eintragen(p);
| |
− |
| |
− | } else {
| |
− | // keine weiteren Eingaben mehr zu tätigen -> weg damit oder Auswertungsbutton anzeigen?
| |
− | q.each(q.domSelect("."+t.loesungsClass2, t.tabelle), function (a) {
| |
− | if (!a.lastChild.nodeValue
| |
− | || a.lastChild.nodeValue == ""
| |
− | || a.lastChild.nodeValue == String.fromCharCode(160)
| |
− | ) {
| |
− | test = false;
| |
− | }
| |
− | });
| |
− |
| |
− | if (test) {
| |
− | // Alles ausgefüllt! -> Auswertungs-Button anzeigen!
| |
− | q.each(q.domSelect("p", t.eingabe), function (a) {
| |
− | a.style.display = "none";
| |
− | });
| |
− |
| |
− | t.eingabe.insertBefore(t.auswertungsButton, t.eingabe.lastChild);
| |
− |
| |
− | } else {
| |
− | // weg damit!
| |
− | t.eingabe.style.display = "none";
| |
− | }
| |
− | }
| |
− |
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Auswertungsbutton geklickt?
| |
− | if (werte == "auswertungs-button") {
| |
− | // Auswerten!
| |
− | t.versuche++;
| |
− | test = true;
| |
− |
| |
− | q.each(q.domSelect("."+t.loesungsClass2, t.tabelle), function (a) {
| |
− | if (a.firstChild.nodeValue != a.parentNode.id.replace(
| |
− | /^.*(\w)$/, "$1"
| |
− | ).replace(
| |
− | /_/g, " "
| |
− | )) {
| |
− | // Falsche Eingabe! -> Löschen
| |
− | a.firstChild.nodeValue = String.fromCharCode(160);
| |
− | test = false;
| |
− | }
| |
− | });
| |
− |
| |
− | if (test) {
| |
− | // Alles richtig!
| |
− | t.eingabe.parentNode.insertBefore(
| |
− | q.domCreate({
| |
− | tagName : "p",
| |
− | className : q.bewertungsClass,
| |
− | text: q.meldungen[t.sprache]["lob" + (t.versuche > 2 ? 3 : t.versuche)]
| |
− | + " "
| |
− | + q.meldungen[t.sprache][
| |
− | "ergebnis" + (t.versuche > 2 ? 3 : t.versuche)
| |
− | ].replace(/%n/i, t.versuche)
| |
− | }),
| |
− | t.eingabe
| |
− | );
| |
− |
| |
− | // Auswertungs-Button und alle Eventhandler entfernen
| |
− | t.eingabe.parentNode.removeChild(t.eingabe);
| |
− | t.element.onmousedown = null;
| |
− | t.element.onmouseup = null;
| |
− | t.solved = true;
| |
− | t.element.className += " " + q.fertigClass;
| |
− |
| |
− | } else {
| |
− | // zurück zum Ausfüllen
| |
− | q.each(q.domSelect("p", t.eingabe), function (a) {
| |
− | a.style.display = "";
| |
− | });
| |
− |
| |
− | t.eingabe.style.display = "none";
| |
− | }
| |
− | }
| |
− |
| |
− | return false;
| |
− | },
| |
− |
| |
− | // Funktion zum Eintragen von Kreuzwort-Wörtern
| |
− | eintragen : function (werte) {
| |
− | /* "werte" hat folgende Struktur: Array[
| |
− | {
| |
− | wort: <String>,
| |
− | x: <Number>,
| |
− | y: <Number>,
| |
− | hilfe: <String>,
| |
− | richtung: "waagrecht|senkrecht"
| |
− | } // eventuell ein weiteres Objekt:
| |
− | ,{
| |
− | wort: <String>,
| |
− | x: <Number>,
| |
− | y: <Number>,
| |
− | hilfe: <String>,
| |
− | richtung: "waagrecht|senkrecht"
| |
− | }
| |
− | ] */
| |
− | var t = this,
| |
− | i, p, w, test, text, eingabefeld, zellen;
| |
− |
| |
− | // Auswertungsbutton entfernen falls vorhanden
| |
− | if (t.auswertungsButton.parentNode == t.eingabe) {
| |
− | t.eingabe.removeChild(t.auswertungsButton);
| |
− | }
| |
− |
| |
− | while (q.domSelect("form", t.eingabe).length > 0) {
| |
− | t.eingabe.removeChild(q.domSelect("form", t.eingabe)[0]);
| |
− | }
| |
− |
| |
− | // Formular erstellen - für jeden Suchbegriff eines
| |
− | q.each(werte, function (wert) {
| |
− | wert.name = t.name;
| |
− |
| |
− | eingabefeld = q.domCreate({
| |
− | tagName : "form",
| |
− | quizDaten : wert,
| |
− | onsubmit : function () {
| |
− | var werte = {
| |
− | wort : "",
| |
− | quizItem : this.quizDaten,
| |
− | form: this
| |
− | };
| |
− |
| |
− | q.each(
| |
− | q.domSelect("span", q.domSelect(".eingabezeile", this)[0]),
| |
− | function (s) {
| |
− | werte.wort += s.innerHTML.replace(/ /g, " ").quizTrim();
| |
− | }
| |
− | );
| |
− |
| |
− | return t.auswerten(werte);
| |
− | }
| |
− | });
| |
− | t.eingabe.appendChild(eingabefeld);
| |
− |
| |
− | // Textabsatz mit Lösungshinweis erstellen
| |
− | p = q.domCreate({
| |
− | tagName: "p",
| |
− | // die eigentliche Lösungshilfe
| |
− | text : wert.hilfe.replace(/^\d+ */, "")
| |
− | });
| |
− |
| |
− | // Die Richtung (mehrsprachig!) in einem extra <span>-Element
| |
− | p.insertBefore(
| |
− | q.domCreate({
| |
− | tagName : "span",
| |
− | className : "richtung",
| |
− | text: q.meldungen[t.sprache][wert.richtung] + ":"
| |
− | }),
| |
− | p.firstChild
| |
− | );
| |
− |
| |
− | // Nummer auch in einem extra <span>-Element
| |
− | p.insertBefore(
| |
− | q.domCreate({
| |
− | tagName : "span",
| |
− | className : "nummer",
| |
− | text: wert.hilfe.replace(/^(\d+).*$/, "$1")
| |
− | }),
| |
− | p.firstChild
| |
− | );
| |
− |
| |
− | eingabefeld.appendChild(p);
| |
− |
| |
− | // korrespondierende Zellen ermitteln, um bereits Eingetragenes mit anzubieten
| |
− | zellen = t.findeZellen({
| |
− | wort : wert.wort,
| |
− | x : wert.x,
| |
− | y : wert.y,
| |
− | richtung : wert.richtung
| |
− | });
| |
− |
| |
− | // Textabsatz als Eingabezeile erstellen, in welchem die Eingaben in <span>-Elementen stehen
| |
− | p = q.domCreate({
| |
− | tagName : "p",
| |
− | className : "eingabezeile"
| |
− | });
| |
− | eingabefeld.appendChild(p);
| |
− |
| |
− | // <span>-Elemente erstellen
| |
− | for (w = 0; w < wert.wort.length; w++) {
| |
− | // bereits vorhandenen Zelleninhalt vorbereiten
| |
− | test = zellen[w].innerHTML.replace(
| |
− | // HTML-Tags entfernen
| |
− | /<\/?[^>]+>/g, ""
| |
− | ).replace(
| |
− | // Leerzeichen
| |
− | / /g, " "
| |
− | ).replace(
| |
− | // nur letztes Zeichen nehmen (es könnte ja auch eine Eingabeziffer darin stehen)
| |
− | /.*(.)$/, "$1"
| |
− | ).quizTrim();
| |
− |
| |
− | // Zelleninhalt voreintragen
| |
− | p.appendChild(q.domCreate({
| |
− | tagName : "span",
| |
− | text : (test.length > 0 ? test : String.fromCharCode(160)),
| |
− | // dem versteckten Textinput den Focus geben
| |
− | onmouseup : function () {
| |
− | q.each(q.domSelect("span", this.parentNode), function (s) {
| |
− | s.className = "";
| |
− | });
| |
− |
| |
− | this.className = "aktiv";
| |
− | q.domSelect(".texteingabefeld", this.parentNode)[0].focus();
| |
− | }
| |
− | }));
| |
− | }
| |
− |
| |
− | // Submit-Button braucht keinen Eventhandler, da das Formular onsubmit geprüft wird.
| |
− | p.appendChild(q.domCreate({
| |
− | tagName : "input",
| |
− | type : "submit",
| |
− | value : q.meldungen[t.sprache].eintragen
| |
− | }));
| |
− |
| |
− | // Das versteckte Textinputfeld, das nach jedem Tastendruck ausgelesen wird.
| |
− | p.appendChild(q.domCreate({
| |
− | tagName : "input",
| |
− | type : "text",
| |
− | className : "texteingabefeld",
| |
− | // Eventhandler für jeden Tastenanschlag
| |
− | onkeyup : function (e) {
| |
− | return t.tasteAuswerten({
| |
− | obj: this,
| |
− | e: e
| |
− | });
| |
− | },
| |
− | // Eventhandler für das Verlieren des Focus
| |
− | onblur : function () {
| |
− | q.each(q.domSelect("span", this.parentNode), function(s) {
| |
− | s.className = "";
| |
− | });
| |
− | }
| |
− | }));
| |
− |
| |
− | // Erstes Eingabefeld aktiv setzen und den Fokus auf das versteckte Eingabefeld legen:
| |
− | window.setTimeout(function () {
| |
− | t.eingabefeldAktivieren({
| |
− | eingabezeile: q.domSelect(".eingabezeile", t.eingabe)[0],
| |
− | feldnummer: 0, // null für erstes Feld
| |
− | });
| |
− | }, 300);
| |
− | });
| |
− |
| |
− | t.eingabe.style.display = "block";
| |
− |
| |
− | return false;
| |
− | },
| |
− |
| |
− | // Eingabefeld aktivieren
| |
− | eingabefeldAktivieren : function (werte) {
| |
− | /* "werte " hat folgende Struktur: {
| |
− | eingabezeile: <HTMLParagraphElement>,
| |
− | feldnummer: <Number> (Wert beginnend bei 0!)
| |
− | } */
| |
− | var spans = q.domSelect("span", werte.eingabezeile);
| |
− |
| |
− | q.each(spans, function (s) {
| |
− | s.className = "";
| |
− | });
| |
− |
| |
− | if (werte.feldnummer < spans.length) {
| |
− | spans[werte.feldnummer].className = "aktiv";
| |
− | }
| |
− |
| |
− | q.domSelect(".texteingabefeld", werte.eingabezeile)[0].focus();
| |
− | },
| |
− |
| |
− | tasteAuswerten : function (werte) {
| |
− | // "werte" hat folgende Struktur; { obj: <input>-Element, e: event}
| |
− | var t = this,
| |
− | spans = q.domSelect("span", werte.obj.parentNode),
| |
− | gefunden = false,
| |
− | i, j, z;
| |
− |
| |
− | werte.e = werte.e || window.event;
| |
− |
| |
− | // aktuelles aktives Eingabefeld ermitteln
| |
− | for (i = 0; i < spans.length; i++) {
| |
− | if (spans[i].className == "aktiv") {
| |
− | gefunden = i;
| |
− | }
| |
− | }
| |
− |
| |
− |
| |
− | switch (werte.e.keyCode) {
| |
− | case 35: // End (Ende)
| |
− | // letztes Feld!
| |
− | t.eingabefeldAktivieren({
| |
− | eingabezeile: werte.obj.parentNode,
| |
− | feldnummer: spans.length -1
| |
− | });
| |
− | break;
| |
− | case 36: // Home (Pos1)
| |
− | // erstes Feld!
| |
− | t.eingabefeldAktivieren({
| |
− | eingabezeile: werte.obj.parentNode,
| |
− | feldnummer: 0
| |
− | });
| |
− | break;
| |
− | case 37: // Cursor left
| |
− | case 8: // Backspace
| |
− | // ein Feld zurück!
| |
− | if (gefunden !== false) {
| |
− | gefunden = gefunden > 0 ? gefunden -1 : 0;
| |
− |
| |
− | } else {
| |
− | // letztes Feld anwählen, da gerade keines aktiv war
| |
− | gefunden = spans.length -1;
| |
− | /* eventuell eingegebene Zeichen im <input>-Element entfernen,
| |
− | da diese sonst jetzt automatisch eingetragen werden! */
| |
− | werte.obj.value = "";
| |
− | }
| |
− |
| |
− | // bei Backspace Feld leeren!
| |
− | if (werte.e.keyCode == 8) {
| |
− | spans[gefunden].innerHTML = String.fromCharCode(160);
| |
− | }
| |
− |
| |
− | t.eingabefeldAktivieren({
| |
− | eingabezeile: werte.obj.parentNode,
| |
− | feldnummer: gefunden
| |
− | });
| |
− | break;
| |
− | case 39: // Cursor right
| |
− | // ein Feld vor!
| |
− | if (gefunden !== false) {
| |
− | gefunden = gefunden < spans.length -2 ? gefunden +1 : spans.length -1;
| |
− |
| |
− | t.eingabefeldAktivieren({
| |
− | eingabezeile: werte.obj.parentNode,
| |
− | feldnummer: gefunden
| |
− | });
| |
− | }
| |
− | break;
| |
− | }
| |
− |
| |
− | if (werte.obj.value.length > 0) {
| |
− | z = q.wandleZeichen(werte.obj.value.substr(0, 1));
| |
− | // bisherige Eingaben wieder löschen, da immer nur erster Buchstabe genommen wird
| |
− | werte.obj.value = "";
| |
− |
| |
− | if (z.length > 0) {
| |
− | j = false;
| |
− | for (i = 0; i < spans.length; i++) {
| |
− | if (spans[i].className && spans[i].className == "aktiv") {
| |
− | j = i;
| |
− | }
| |
− | }
| |
− |
| |
− | // eventuell sollen mehrere Zeichen eingetragen werden (z.B. bei Ligaturen oder Umlauten)
| |
− | for (i = 0; i < z.length; i++) {
| |
− | if (spans[j + i]) {
| |
− | spans[j + i].innerHTML = z.substr(i, 1);
| |
− | }
| |
− | }
| |
− |
| |
− | t.eingabefeldAktivieren({
| |
− | eingabezeile : spans[0].parentNode,
| |
− | feldnummer : j + i
| |
− | });
| |
− | }
| |
− | }
| |
− | },
| |
− |
| |
− | /* Funktion zum Ermitteln aller HTML-Elemente (td), in die ein Lösungswort
| |
− | geschrieben werden muss */
| |
− | findeZellen : function (werte) {
| |
− | /* "werte" hat folgende Struktur: {
| |
− | wort: <String>,
| |
− | x: <Number>,
| |
− | y: <Number>,
| |
− | richtung: "waagrecht|senkrecht"
| |
− | } */
| |
− | var t = this,
| |
− | zellen = new Array(),
| |
− | zelle, x, y, i;
| |
− |
| |
− | for (i = 0; i < werte.wort.length; i++) {
| |
− | zelle = werte.richtung == "waagrecht" ?
| |
− | q.domSelect("tr", t.tabelle)[werte.y] :
| |
− | q.domSelect("tr", t.tabelle)[werte.y + i];
| |
− |
| |
− | if (zelle) {
| |
− | zelle = werte.richtung == "waagrecht" ?
| |
− | q.domSelect("td", zelle)[werte.x + i] :
| |
− | q.domSelect("td", zelle)[werte.x];
| |
− | }
| |
− |
| |
− | if (zelle) {
| |
− | zellen.push(zelle);
| |
− | }
| |
− | }
| |
− |
| |
− | return zellen;
| |
− | },
| |
− |
| |
− | // Funktion zum Errichten der Tabelle des Kreuzwort-Quiz und zum Einrichten der Eventhandler
| |
− | init : function () {
| |
− | var t = this,
| |
− | kreuzwortGitter, tr, td, a, x, y;
| |
− |
| |
− | // Spracheinstellungen auf deutsch zurück korrigieren, falls entsprechende Sprachdaten fehlen
| |
− | if (!q.meldungen[t.sprache]) {
| |
− | t.sprache = "de";
| |
− | }
| |
− |
| |
− | /* Wörtergitter erzeugen, sodass nach Möglichkeit keine alleinstehenden Wörter
| |
− | im Gitter enthalten sind */
| |
− | kreuzwortGitter = q.erstelleWoerterGitter(
| |
− | t.daten,
| |
− | true, // true für "alle verbunden"
| |
− | false // false für "keine diagonalen Wörter"
| |
− | );
| |
− |
| |
− | // Daten und Gitter abspeichern
| |
− | t.daten = kreuzwortGitter.woerter;
| |
− | t.grid = kreuzwortGitter.gitter;
| |
− |
| |
− | // Tabelle befüllen
| |
− | for (y = 0; y < t.grid.length; y++) {
| |
− | tr = t.tabelle.insertRow(
| |
− | t.tabelle.rows.length <= 0 ? 0 : t.tabelle.rows.length
| |
− | );
| |
− |
| |
− | for (x = 0; x < this.grid[0].length; x++) {
| |
− | td = q.domCreate({
| |
− | tagName : "td",
| |
− | id : t.name + "_" + x + "_" + y
| |
− | });
| |
− |
| |
− | if (t.grid[y][x]) {
| |
− | td.id += "_" + t.grid[y][x];
| |
− | td.className = t.loesungsClass;
| |
− | }
| |
− |
| |
− | // Zelleninhalt
| |
− | if (t.grid[y][x]) {
| |
− | td.appendChild(q.domCreate({
| |
− | tagName : "span",
| |
− | className : t.loesungsClass2,
| |
− | text : String.fromCharCode(160)
| |
− | }));
| |
− |
| |
− | } else {
| |
− | td.innerHTML = String.fromCharCode(160);
| |
− | }
| |
− |
| |
− | // Zelle in Zeile einhängen
| |
− | tr.appendChild(td);
| |
− | }
| |
− | }
| |
− |
| |
− | // Einfügemarken und Eventhandler einrichten
| |
− | a = 1;
| |
− | q.each(t.daten, function (d) {
| |
− | var nummer = a, // Nummer der aktuellen Einfügemarke merken
| |
− | marke;
| |
− |
| |
− | x = d.x;
| |
− | y = d.y;
| |
− |
| |
− | if (td = t.tabelle.rows[y] && t.tabelle.rows[y].cells[x]) {
| |
− | // bereits eine Einfügemarke vorhanden?
| |
− | td.style.cursor = "pointer";
| |
− |
| |
− | if (!td.nummer) {
| |
− | // Nein! -> Einfügemarke erstellen
| |
− | marke = q.domCreate({
| |
− | tagName : "span",
| |
− | className : "einfuegemarke",
| |
− | text : nummer
| |
− | });
| |
− |
| |
− | td.insertBefore(marke, td.firstChild);
| |
− | td.nummer = nummer;
| |
− | a++; // Ziffer der Einfügemarke erhöhen
| |
− |
| |
− | } else {
| |
− | // Nummer der vorhandenen Einfügemarke merken
| |
− | nummer = td.nummer;
| |
− | }
| |
− |
| |
− | // Lösungshilfe mit Nummer der Einfügemarke versehen
| |
− | d.hilfe = nummer + " " + d.hilfe;
| |
− |
| |
− | // Eventhandler einrichten / erweitern
| |
− | td.daten = td.daten || new Array();
| |
− | td.daten.push(d); // auszuwertende Daten für Eingabedialog hinzufügen
| |
− |
| |
− | if (typeof(td.onclick) != "function") {
| |
− | td.onclick = function () {
| |
− | t.eintragen(this.daten);
| |
− | };
| |
− | }
| |
− | }
| |
− | });
| |
− |
| |
− | // Eingabebereich erstellen
| |
− | t.eingabe.className = "eingabe " + q.draggableClass;
| |
− |
| |
− | // Header des Eingabebereichs
| |
− | t.eingabe.appendChild(q.domCreate({
| |
− | tagName : "div",
| |
− | className : "eingabe-header"
| |
− | }));
| |
− |
| |
− | // "schließen"-Schaltfläche
| |
− | t.eingabe.lastChild.appendChild(q.domCreate({
| |
− | tagName : "span",
| |
− | className : "schliessen-button",
| |
− | onclick : function () {
| |
− | this.parentNode.parentNode.style.display = "";
| |
− | }
| |
− | }));
| |
− |
| |
− | t.eingabe.lastChild.lastChild.style.cursor = "pointer";
| |
− |
| |
− | // Textabsatz für einen Eingabehinweis erstellen, der ein verdecktes <span>-Element enthält
| |
− | t.eingabe.appendChild(q.domCreate({
| |
− | tagName : "p",
| |
− | className : "eingabehinweis",
| |
− | // Anzeigen des verdeckten <span>-Elementes bei Hover (für IE notwendig)
| |
− | onmouseover : function () {
| |
− | this.childNodes[0].style.display = "block";
| |
− | },
| |
− | // Verbergen des verdeckten <span>-Elementes beim Verlassen
| |
− | onmouseout : function () {
| |
− | this.childNodes[0].style.display = "";
| |
− | }
| |
− | }));
| |
− |
| |
− | // Eingabehinweis
| |
− | t.eingabe.lastChild.appendChild(q.domCreate({
| |
− | tagName : "span",
| |
− | text : q.meldungen[t.sprache].eingabehinweis
| |
− | }));
| |
− |
| |
− | t.tabelle.parentNode.insertBefore(t.eingabe, t.tabelle.nextSibling);
| |
− |
| |
− | // Eingabefeld durch Eventhandler für bewegliche Felder zu einem Fensterimitat machen
| |
− | t.element.onmousedown = q.startDrag;
| |
− | t.element.onmouseup = q.stopDrag;
| |
− |
| |
− | // Auswertungsbutton erstellen
| |
− | t.auswertungsButton = q.domCreate({
| |
− | tagName : "p",
| |
− | className : "auswertungs-button",
| |
− | text : q.meldungen[t.sprache].pruefen,
| |
− | onclick : function () { t.auswerten("auswertungs-button"); }
| |
− | });
| |
− |
| |
− | // ID für das umgebende DIV-Element vergeben
| |
− | t.element.id = t.name;
| |
− |
| |
− | // Für die Druckausgabe eine Liste der Lösungshilfen ausgeben
| |
− | t.element.appendChild(q.domCreate({
| |
− | tagName : "div",
| |
− | className : "uebersicht"
| |
− | }));
| |
− |
| |
− | // Listen ausgeben
| |
− | q.each(["senkrecht", "waagrecht"], function (r) {
| |
− | // Liste erzeugen
| |
− | var dl = q.domCreate({ tagName : "dl" });
| |
− |
| |
− | dl.appendChild(q.domCreate({
| |
− | tagName : "dt",
| |
− | text : q.meldungen[t.sprache][r]
| |
− | }));
| |
− |
| |
− | // passende Lösungshilfen ausfiltern
| |
− | q.each(t.daten, function (d) {
| |
− | if (d.richtung == r) {
| |
− | dl.appendChild(q.domCreate({
| |
− | tagName : "dd",
| |
− | text : d.hilfe.replace(/^\d+(.*)/, "$1")
| |
− | }));
| |
− |
| |
− | dl.lastChild.appendChild(q.domCreate({
| |
− | tagName : "span",
| |
− | text : d.hilfe.replace(/^(\d+).*/, "$1")
| |
− | }));
| |
− | }
| |
− | });
| |
− |
| |
− | t.element.lastChild.appendChild(dl);
| |
− | });
| |
− | }
| |
− | };
| |
− |
| |
− | // Laufende Nummer ermitteln -> Quiz-Name wird "quiz" + laufende Nummer
| |
− | i = 0;
| |
− | q.each(q.alleQuizze, function () {
| |
− | i++;
| |
− | });
| |
− | quiz.name = "quiz" + i;
| |
− |
| |
− | // Gibt es Quiz-Daten?
| |
− | tabelle = q.domSelect("table", div);
| |
− |
| |
− | if (tabelle.length < 1) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Daten sind also vorhanden? -> Tabellenzeilen nach Daten durchforsten
| |
− | q.each(tabelle[0].rows, function (tr) {
| |
− | var gefunden = new Array();
| |
− |
| |
− | if (tr.cells.length > 1) {
| |
− | // "Müll" entfernen
| |
− | gefunden[0] = tr.cells[0].innerHTML.replace(
| |
− | /<\/?[^>]+>/g, ""
| |
− | ).replace(
| |
− | /&/g, "&"
| |
− | ).replace(
| |
− | / /g, " "
| |
− | ).replace(/ /g, "_");
| |
− |
| |
− | gefunden[1] = tr.cells[1].innerHTML.replace(
| |
− | /<\/?[^>]+>/g, ""
| |
− | ).replace(
| |
− | /&/g, "&"
| |
− | ).replace(/ /g, " ");
| |
− |
| |
− | // Lösungswort in reine Großbuchstaben umwandeln
| |
− | gefunden[0] = q.wandleZeichen(gefunden[0]).toUpperCase();
| |
− |
| |
− | if (gefunden[0] != "" && gefunden[1] != "") {
| |
− | quiz.daten.push({
| |
− | wort : gefunden[0].quizTrim(),
| |
− | x : -1,
| |
− | y : -1,
| |
− | hilfe : gefunden[1].quizTrim()
| |
− | });
| |
− | }
| |
− | }
| |
− | });
| |
− |
| |
− | // Keine brauchbare Daten? -> Verwerfen!
| |
− | if (quiz.daten.length < 1) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // originale Tabelle durch leere Tabelle ersetzen
| |
− | quiz.tabelle = document.createElement("table");
| |
− | quiz.tabelle.className = "gitter";
| |
− | tabelle[0].parentNode.insertBefore(quiz.tabelle, tabelle[0].nextSibling);
| |
− | tabelle[0].parentNode.removeChild(tabelle[0]);
| |
− |
| |
− | // Quiz in die Liste aufnehmen und initialisieren
| |
− | q.alleQuizze[quiz.name] = quiz;
| |
− | quiz.element.quiz = quiz;
| |
− | quiz.init();
| |
− |
| |
− | return true;
| |
− | },
| |
− |
| |
− | erstelleWoerterGitter : function (woerter, alleVerbunden, diagonaleWoerter, keineFreienZwischenRaeume) {
| |
− | /* übergebene Parameter
| |
− | @woerter:
| |
− | Ein Array mit Wort-Objekten. Ein Wort-Objekt hat mindestens diese Struktur:
| |
− | wort = {
| |
− | wort : (String),
| |
− | hilfe : (String), // nur bei Aufruf aus dem Kreuzworträtsel-Quiz heraus
| |
− | wortOriginal : (String) // nur bei Aufruf aus dem Suchsel-Quiz heraus
| |
− | }
| |
− | Nach dieser Funktion kann ein Wort-Objekt dann auch so aussehen
| |
− | wort = {
| |
− | wort : (String),
| |
− | x : (Integer),
| |
− | y : (Integer),
| |
− | richtung : (String), "waagrecht|senkrecht"
| |
− | hilfe : (String), // nur bei Aufruf aus dem Kreuzworträtsel-Quiz heraus
| |
− | wortOriginal : (String) // nur bei Aufruf aus dem Suchsel-Quiz heraus
| |
− | }
| |
− | @alleVerbunden (true|false):
| |
− | Wenn true, werden bis zu 10 Versuche unternommen, ein Gitter zu erstellen,
| |
− | bei dem alle Begriffe miteinander verbunden sind.
| |
− | @diagonaleWoerter (true|false):
| |
− | Wenn true, werden Wörter auch diagonal eingepasst. Dabei ist die
| |
− | Leserichtung immer von links nach rechts, egal ob das Wort von links
| |
− | oben nach rechts unten, oder von links unten nach rechts oben verläuft.
| |
− | */
| |
− | var q = this;
| |
− | var fertige = new Array(); // Array mit fertigen Gittern
| |
− | var makel = 1, maxVersuche = alleVerbunden ? 10 : 1;
| |
− | var richtungen = diagonaleWoerter ?
| |
− | ["waagrecht", "senkrecht", "diagonal-loru", "diagonal-luro"]
| |
− | :
| |
− | ["waagrecht", "senkrecht"];
| |
− | var grid, abgelegte, erfolglose, test, zufall, i, wort, a,
| |
− | eingepasst, x, y, nummer, p, button, input, buchstaben, b, d, moeglicheRichtungen, r;
| |
− |
| |
− | // Gitter erzeugen, falls das nicht ohne Makel gelingt, bis zu 10x
| |
− | while (makel > 0 && fertige.length < maxVersuche) {
| |
− | makel = 0; // zuerst davon ausgehen, dass ein perfektes Gitter entstehen wird
| |
− | abgelegte = new Array(); // es wurde noch nichts abgelegt
| |
− | erfolglose = new Array(); // es gibt noch keine erfolglos eingepassten Wörter
| |
− |
| |
− | // Grid aufbauen
| |
− | test = 0;
| |
− | q.each(woerter, function (w) {
| |
− | test += w.wort.length; // Anzahl Buchstaben insgesamt
| |
− | });
| |
− |
| |
− | grid = new Array(test);
| |
− | for (i = 0; i < test; i++) {
| |
− | grid[i] = new Array(test);
| |
− | }
| |
− |
| |
− | // Wörter in zufälliger Reihenfolge ins Gitter einpassen - wenn es gelingt
| |
− | while (abgelegte.length < woerter.length) {
| |
− |
| |
− | test = true; // neue Zufallszahl erzwingen
| |
− | while (test) {
| |
− | zufall = Math.floor(Math.random() * woerter.length);
| |
− | test = false; // annehmen, dass die Zufallszahl noch nicht benutzt wurde
| |
− |
| |
− | // Wort bereits abgelegt?
| |
− | q.each(abgelegte, function (a) {
| |
− | if (a.wort == woerter[zufall].wort) {
| |
− | test = true;
| |
− | }
| |
− | });
| |
− |
| |
− | if (erfolglose.length > 0) {
| |
− | // bereits erfolglos probierte Wörter ausschließen
| |
− | q.each(erfolglose, function (e) {
| |
− | if (woerter[zufall] == e) {
| |
− | test = true;
| |
− | }
| |
− | });
| |
− | }
| |
− | }
| |
− |
| |
− | // Jetzt haben wir ein Wort zum Einpassen in das Gitter
| |
− | wort = woerter[zufall];
| |
− | wort.x = -1;
| |
− | wort.y = -1;
| |
− |
| |
− | // geeignete Stelle finden, um es einzupassen
| |
− | if (abgelegte.length > 0) {
| |
− |
| |
− | // weiteres Wort einfügen -> bereits eingesetzte Wörter der Reihe nach durchgehen
| |
− | for (a = 0; a < abgelegte.length; a++) {
| |
− |
| |
− | // schon eine passende Stelle zum Einpassen ermittelt?
| |
− | if (wort.x >= 0 && wort.y >= 0)
| |
− | break; // Ja! -> abbrechen!
| |
− |
| |
− | // zufälligen Buchstaben des Wortes nehmen und nach Übereinstimmungen mit eingepasstem Wort suchen
| |
− | buchstaben = new Array(); // benutzte Buchstaben leeren
| |
− | for (b = 0; b < wort.wort.length; b++) {
| |
− |
| |
− | // schon eine passende Stelle zum Einpassen ermittelt?
| |
− | if (wort.x >= 0 && wort.y >= 0)
| |
− | break; // Ja! -> abbrechen!
| |
− |
| |
− | test = true; // neue Zufallszahl erzwingen
| |
− | while (test) {
| |
− | zufall = Math.floor(Math.random() * wort.wort.length);
| |
− | test = buchstaben[zufall];
| |
− | }
| |
− |
| |
− | buchstaben[zufall] = true; // Buchstaben als benutzt markieren
| |
− |
| |
− | // Buchstabe in beiden Wörtern vorhanden?
| |
− | if (abgelegte[a].wort.indexOf(wort.wort.substr(zufall, 1)) >= 0) {
| |
− |
| |
− | // Ja! -> jeden Buchstaben des bereits eingepassten Wortes durchgehen
| |
− | for (eingepasst = 0; eingepasst < abgelegte[a].wort.length; eingepasst++) {
| |
− |
| |
− | // Wort bereits erfolgreich eingepasst?
| |
− | if (wort.x >= 0 && wort.y >= 0)
| |
− | break; // Ja! -> abbrechen
| |
− |
| |
− | if (abgelegte[a].wort.substr(eingepasst, 1) == wort.wort.substr(zufall, 1)) {
| |
− | // übereinstimmender Buchstabe ermittelt! -> Wort testweise ins Gitter einpassen
| |
− | test = true; // davon ausgehen, dass das Wort passt...
| |
− |
| |
− | // Position des Buchstabens im Gitter ermitteln
| |
− | if (abgelegte[a].richtung == "waagrecht") {
| |
− | x = abgelegte[a].x + eingepasst;
| |
− | y = abgelegte[a].y;
| |
− | }
| |
− | if (abgelegte[a].richtung == "senkrecht") {
| |
− | x = abgelegte[a].x;
| |
− | y = abgelegte[a].y + eingepasst;
| |
− | }
| |
− | if (abgelegte[a].richtung == "diagonal-loru") {
| |
− | x = abgelegte[a].x + eingepasst;
| |
− | y = abgelegte[a].y + eingepasst;
| |
− | }
| |
− | if (abgelegte[a].richtung == "diagonal-luro") {
| |
− | x = abgelegte[a].x + eingepasst;
| |
− | y = abgelegte[a].y - eingepasst;
| |
− | }
| |
− |
| |
− | // mögliche Richtungen für neu einzupassendes Wort ermitteln
| |
− | moeglicheRichtungen = [];
| |
− | for (i = 0; i < richtungen.length; i++) {
| |
− | if (richtungen[i] != abgelegte[a].richtung) {
| |
− | moeglicheRichtungen.push(richtungen[i]);
| |
− | }
| |
− | }
| |
− | moeglicheRichtungen.shuffle();
| |
− |
| |
− | while (moeglicheRichtungen.length) {
| |
− | // Richtung des einzupassenden Wortes festlegen
| |
− | wort.richtung = moeglicheRichtungen.pop();
| |
− |
| |
− | // im Gitter die Startposition des einzupassenden Wortes ermitteln
| |
− | if (wort.richtung == "senkrecht") {
| |
− | y = y - zufall; // "zufall" ist der Abstand des entsprechenden Buchstabens zum Wortbeginn
| |
− | }
| |
− | if (wort.richtung == "waagrecht") {
| |
− | x = x - zufall;
| |
− | }
| |
− | if (wort.richtung == "diagonal-loru") {
| |
− | x = x - zufall;
| |
− | y = y - zufall;
| |
− | }
| |
− | if (wort.richtung == "diagonal-luro") {
| |
− | x = x - zufall;
| |
− | y = y + zufall;
| |
− | }
| |
− |
| |
− | // zu belegende Felder im Gitter prüfen
| |
− | for (i = 0; i < wort.wort.length; i++) {
| |
− |
| |
− | if (wort.richtung == "waagrecht") {
| |
− | if (grid[y][x + i] && grid[y][x + i] != wort.wort.substr(i, 1)) {
| |
− | test = false;
| |
− | }
| |
− |
| |
− | // nebenan frei? (Kosmetik)
| |
− | if (!keineFreienZwischenRaeume) {
| |
− | /* alle bereits abgelegten Wörter daraufhin prüfen, ob sie im
| |
− | Bereich des Wortes parallel in einer Nachbarzeile verlaufen */
| |
− | q.each(abgelegte, function (a) {
| |
− | if (a.richtung == "waagrecht"
| |
− | && (a.y + 1 == y
| |
− | || a.y -1 == y)
| |
− | ) {
| |
− | if (// Nachbarwort länger?
| |
− | (a.x <= x &&
| |
− | a.wort.x + a.wort.length >= x + wort.wort.length)
| |
− | ||
| |
− | // Nachbarwort überlappt Anfang
| |
− | (a.x <= x
| |
− | && a.x + a.wort.length >= x)
| |
− | ||
| |
− | // Nachbarwort beginnt mitten im Wort
| |
− | (a.x > x
| |
− | && a.x <= x + wort.wort.length)
| |
− | ) {
| |
− | test = false; // ja -> verwerfen
| |
− | }
| |
− | }
| |
− | // beginnt ein senkrechtes Wort direkt unterhalb?
| |
− | if (a.richtung == "senkrecht" && a.y - 1 == y) {
| |
− | if (a.x >= x && a.x <= x + wort.wort.length) {
| |
− | test = false; // ja -> verwerfen
| |
− | }
| |
− | }
| |
− | });
| |
− | }
| |
− | }
| |
− | if (wort.richtung == "senkrecht") {
| |
− | if (grid[y + i][x] && grid[y + i][x] != wort.wort.substr(i, 1)) {
| |
− | test = false;
| |
− | }
| |
− |
| |
− | // nebenan frei? (Kosmetik)
| |
− | if (!keineFreienZwischenRaeume) {
| |
− | /* alle bereits abgelegten Wörter daraufhin prüfen, ob sie im
| |
− | Bereich des Wortes parallel in einer Nachbarspalte verlaufen */
| |
− | q.each(abgelegte, function (a) {
| |
− | if (a.richtung == "senkrecht"
| |
− | && (a.x == x + 1
| |
− | || a.x == x - 1)
| |
− | ) {
| |
− | if (// Nachbarwort länger?
| |
− | (a.y <= y &&
| |
− | a.wort.y + a.wort.length >= y + wort.wort.length)
| |
− | ||
| |
− | // Nachbarwort überlappt Anfang
| |
− | (a.y <= y
| |
− | && a.y + a.wort.length >= y)
| |
− | ||
| |
− | // Nachbarwort beginnt mitten im Wort
| |
− | (a.y > y
| |
− | && a.y <= y + wort.wort.length)
| |
− | ) {
| |
− | test = false; // leider nein
| |
− | }
| |
− | }
| |
− | // verläuft ein waagrechtes Wort direkt nebenan?
| |
− | if (a.richtung == "waagrecht" &&
| |
− | (a.x == x + 1 || a.x == x - wort.wort.length - 1)
| |
− | ) {
| |
− | if (a.y >= y && a.y <= y + wort.wort.length) {
| |
− | test = false; // ja -> verwerfen
| |
− | }
| |
− | }
| |
− | });
| |
− | }
| |
− | }
| |
− | if (wort.richtung == "diagonal-loru") {
| |
− | if (grid[y + i][x + i] && grid[y + i][x + i] != wort.wort.substr(i, 1)) {
| |
− | test = false;
| |
− | }
| |
− | }
| |
− | if (wort.richtung == "diagonal-luro") {
| |
− | if (grid[y - i][x + i] && grid[y - i][x + i] != wort.wort.substr(i, 1)) {
| |
− | test = false;
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | // Ist vor und nach dem Wort noch Platz? (Kosmetik)
| |
− | if (wort.richtung == "waagrecht") {
| |
− | if (grid[y][x - 1] || grid[y][x + wort.wort.length])
| |
− | test = false;
| |
− | }
| |
− | if (wort.richtung == "senkrecht") {
| |
− | if (grid[y - 1][x] || grid[y + wort.wort.length][x])
| |
− | test = false;
| |
− | }
| |
− | if (wort.richtung == "diagonal-loru") {
| |
− | if (grid[y - 1][x - 1] || grid[y + wort.wort.length][x + wort.wort.length])
| |
− | test = false;
| |
− | }
| |
− | if (wort.richtung == "diagonal-luro") {
| |
− | if (grid[y + 1][x - 1] || grid[y - wort.wort.length][x + wort.wort.length])
| |
− | test = false;
| |
− | }
| |
− |
| |
− | if (test) {
| |
− | // hat gepasst! -> Wort übernehmen lassen!
| |
− | wort.x = x;
| |
− | wort.y = y;
| |
− | erfolglose = new Array(); // erfolglos eingepasste Wörter wieder versuchen
| |
− | break; // weitere Tests abbrechen
| |
− | }
| |
− | }
| |
− |
| |
− | if (test)
| |
− | break; // weitere Tests abbrechen
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | if (wort.x < 0 && wort.y < 0) {
| |
− | // hat nicht gepasst! -> merken
| |
− | erfolglose.push(wort);
| |
− |
| |
− | if (erfolglose.length == (woerter.length - abgelegte.length)) {
| |
− | // anscheinend gibt es für die restlichen Wörter überhaupt keine geeignete Stelle... -> ein freies Plätzchen für aktuelles Wort finden! -> oben (0), links(1), unten(2) oder rechts(3)
| |
− | makel ++;
| |
− |
| |
− | zufall = Math.floor(Math.random() * 4);
| |
− |
| |
− | if (zufall & 1 == 1) {
| |
− | // links / rechts
| |
− | y = Math.floor(grid.length / 2) - Math.floor(wort.wort.length / 2);
| |
− | x = (zufall & 2) == 2 ? 0 : grid[0].length; // Wert muss unter- bzw. überboten werden, daher ist er zu klein/groß
| |
− |
| |
− | } else {
| |
− | // oben / unten
| |
− | x = Math.floor(grid[0].length / 2);
| |
− | y = (zufall & 2) == 2 ? 0 : grid.length;
| |
− | }
| |
− |
| |
− | wort.richtung = (zufall & 1) == 0 ? "waagrecht" : "senkrecht";
| |
− |
| |
− | // Koordinaten der abgelegten Wörter durchgehen, um freie Stelle zu ermitteln
| |
− | q.each(abgelegte, function (a) {
| |
− | if ((zufall & 1) == 1) {
| |
− | // links / rechts einschränken
| |
− | if ((zufall & 2) == 0 && a.x < x)
| |
− | x = a.x;
| |
− |
| |
− | if ((zufall & 2) == 2) {
| |
− | test = a.x;
| |
− | if (a.richtung == "waagrecht")
| |
− | test += a.wort.length;
| |
− |
| |
− | if (test > x)
| |
− | x = test;
| |
− | }
| |
− |
| |
− | } else {
| |
− | // oben / unten einschränken
| |
− | if ((zufall & 2) == 0 && a.y < y)
| |
− | y = a.y;
| |
− |
| |
− | if ((zufall & 2) == 2) {
| |
− | test = a.y;
| |
− | if (a.richtung == "senkrecht")
| |
− | test += a.wort.length;
| |
− |
| |
− | if (test > y)
| |
− | y = test;
| |
− | }
| |
− | }
| |
− | });
| |
− |
| |
− | // geeignete Position zum Einpassen gefunden!
| |
− | wort.x = (zufall & 2) == 0 ? x - 2 : x + 2;
| |
− | wort.y = (zufall & 2) == 0 ? y - 2 : y + 2;
| |
− |
| |
− | erfolglose = [];
| |
− | }
| |
− | }
| |
− |
| |
− | } else {
| |
− | // es ist das erste Wort -> direkt (senkrecht) einpassen
| |
− | wort.x = Math.floor(grid[0].length / 2);
| |
− | wort.y = Math.floor(grid.length / 2) - Math.floor(wort.wort.length / 2);
| |
− | wort.richtung = "senkrecht";
| |
− | }
| |
− |
| |
− | // abspeichern wenn Wort erfolgreich eingepasst werden konnte
| |
− | if (wort && wort.x >= 0 && wort.y >= 0) {
| |
− | abgelegte.push(wort);
| |
− |
| |
− | // Buchstaben in das Gitter eintragen
| |
− | for (i = 0; i < wort.wort.length; i++) {
| |
− | if (wort.richtung == "waagrecht") {
| |
− | grid[wort.y][wort.x + i] = wort.wort.substr(i, 1);
| |
− | }
| |
− | if (wort.richtung == "senkrecht") {
| |
− | grid[wort.y + i][wort.x] = wort.wort.substr(i, 1);
| |
− | }
| |
− | if (wort.richtung == "diagonal-loru") {
| |
− | grid[wort.y + i][wort.x + i] = wort.wort.substr(i, 1);
| |
− | }
| |
− | if (wort.richtung == "diagonal-luro") {
| |
− | grid[wort.y - i][wort.x + i] = wort.wort.substr(i, 1);
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | // fertig erstelltes und bestücktes Gitter abspeichern
| |
− | fertige.push({
| |
− | gitter : grid,
| |
− | daten : abgelegte,
| |
− | makel : makel
| |
− | });
| |
− | }
| |
− |
| |
− | // eventuell wurden nun mehrere Gitter erstellt
| |
− | if (makel > 0) {
| |
− |
| |
− | // anscheinend wurde kein perfektes Gitter erstellt -> das beste aus den maximal zehn erstellten aussuchen
| |
− | test = false;
| |
− | q.each(fertige, function (f) {
| |
− | if (!test || f.makel < test.makel)
| |
− | test = f;
| |
− | });
| |
− |
| |
− | // bester Versuch wurde ermittelt -> nehmen
| |
− | grid = test.gitter;
| |
− | abgelegte = test.daten;
| |
− |
| |
− | }
| |
− |
| |
− | // ausgewähltes Gitter beschneiden
| |
− | a = {
| |
− | x : {
| |
− | min : grid[0].length,
| |
− | max : 0
| |
− | },
| |
− |
| |
− | y : {
| |
− | min : grid.length,
| |
− | max : 0
| |
− | }
| |
− | };
| |
− |
| |
− | for (y = 0; y < grid.length; y++) {
| |
− | for (x = 0; x < grid[0].length; x++) {
| |
− | // Zelle befüllt? -> Koordinaten benutzen!
| |
− | if (grid[y][x]) {
| |
− |
| |
− | // min-Werte bei Bedarf verkleinern!
| |
− | a.x.min = (a.x.min > x) ? x : a.x.min;
| |
− | a.y.min = (a.y.min > y) ? y : a.y.min;
| |
− |
| |
− | // max-Werte bei Bedarf erhöhen
| |
− | a.x.max = (a.x.max < x) ? x : a.x.max;
| |
− | a.y.max = (a.y.max < y) ? y : a.y.max;
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | // min/max-Maße ermittelt -> Gitterinhalt in beschnittenes Gitter übertragen
| |
− | test = new Array(a.y.max - a.y.min + 1);
| |
− |
| |
− | for (y = 0; y < (a.y.max - a.y.min + 1); y++) { // zeilenweise
| |
− | test[y] = new Array(a.x.max - a.x.min + 1);
| |
− | for (x = 0; x < (a.x.max - a.x.min + 1); x++) { // spaltenweise
| |
− | if (grid[y + a.y.min][x + a.x.min])
| |
− | test[y][x] = grid[y + a.y.min][x + a.x.min]; // Inhalt übertragen
| |
− | }
| |
− | }
| |
− |
| |
− | grid = test; // altes Gitter durch neues ersetzen
| |
− |
| |
− | // eingetragene Koordinaten der Wörter korrigieren
| |
− | for (i = 0; i < abgelegte.length; i++) {
| |
− | abgelegte[i].x = abgelegte[i].x - a.x.min;
| |
− | abgelegte[i].y = abgelegte[i].y - a.y.min;
| |
− | }
| |
− |
| |
− | return { gitter : grid, woerter : abgelegte };
| |
− | },
| |
− |
| |
− |
| |
− | /* Diese Funktion erzeugt ein Suchsel-Quiz. Dazu braucht sie ein Elternelement mit dem
| |
− | CSS-Klassen-Präfix "suchsel", z.B. "suchsel-quiz", wenn "-quiz" das Suffix der Quiz.triggerClass ist.
| |
− | Die Daten für das Quiz müssen in einer einspaltigen Tabelle stehen.
| |
− | */
| |
− |
| |
− | suchselQuiz : function (div) {
| |
− | var q = this,
| |
− | i, tabelle;
| |
− |
| |
− | var quiz = {
| |
− | // Objekt-Gestalt eines Suchsel-Quizzes
| |
− | name : "Quiz-x", // Platzhalter - hier steht später etwas anderes.
| |
− | typ : "Suchsel-Quiz",
| |
− | element : div, // Referenz auf das DIV-Element, in welchem sich das Quiz befindet
| |
− | tabelle : null, // Referenz auf das HTML-Element, in dem das Suchsel angezeigt wird
| |
− | daten : new Array(), // Hier stehen später Objekte, die die Quiz-Daten enthalten.
| |
− | versuche : 0, // Speichert die Anzahl Versuche, die für die Lösung gebraucht wurden.
| |
− | sprache : (div.lang && div.lang != "") ? div.lang : "de", // deutsche Meldungen als Voreinstellung
| |
− | loesungsliste : null, // Referenz auf ein <ol>-Objekt, in dem bereits gefundene Wörter angezeigt werden
| |
− | markierungStart : null, // Referenz auf das erste markierte <td>-Element
| |
− | markierungEnde : null, // Referenz auf das letzte markierte <td>-Element
| |
− |
| |
− | // Funktion zum Auswerten der Lösungen
| |
− | auswerten : function () {
| |
− | var t = this,
| |
− | el = q.domSelect(".markiert", t.tabelle),
| |
− | betroffene = [],
| |
− | felder = [];
| |
− |
| |
− | if (el.length > 1) {
| |
− | t.versuche++;
| |
− |
| |
− | // Koordinaten der markierten Felder ermitteln
| |
− | q.each(el, function (f) {
| |
− | felder.push({
| |
− | buchstabe : f.innerHTML,
| |
− | x : f.id.replace(/^quiz\d+_(\d+)_.*/i, "$1"),
| |
− | y : f.id.replace(/.*_(\d+)$/i, "$1")
| |
− | });
| |
− | });
| |
− |
| |
− | // Jedes Lösungswort prüfen, ob sein Anfangsbuchstabe markiert wurde
| |
− | q.each(t.daten, function (d) {
| |
− | q.each(felder, function (f) {
| |
− | if (d.x == f.x && d.y == f.y) {
| |
− | // Lösungswort merken
| |
− | betroffene.push(d);
| |
− | }
| |
− | });
| |
− | });
| |
− |
| |
− | // Jedes betroffene Lösungswort prüfen, ob es vollständig markiert wurde
| |
− | q.each(betroffene, function (b) {
| |
− | var erfolg;
| |
− |
| |
− | // stimmt die Anzahl markierter Felder exakt?
| |
− | if (b.wort.length == felder.length) {
| |
− | // prüfen, ob alle markierten Felder auch die richtigen Felder sind
| |
− | erfolg = b; // mal davon ausgehen, dass alles passt
| |
− |
| |
− | q.each(felder, function (f) {
| |
− | if (b.richtung == "senkrecht") {
| |
− | // x-Werte immer identisch!
| |
− | if (f.x != b.x || f.y < b.y
| |
− | || f.y > b.y + b.wort.length -1
| |
− | ) {
| |
− | erfolg = false;
| |
− | }
| |
− | }
| |
− |
| |
− | if (b.richtung == "waagrecht") {
| |
− | // y-Werte immer identisch
| |
− | if (f.y != b.y || f.x < b.x
| |
− | || f.x > b.x + b.wort.length -1
| |
− | ) {
| |
− | erfolg = false;
| |
− | }
| |
− | }
| |
− |
| |
− | if (b.richtung == "diagonal-loru") {
| |
− | if (f.x - f.y != b.x - b.y
| |
− | || f.x < b.x
| |
− | || f.x > b.x + b.wort.length -1
| |
− | || f.y < b.y
| |
− | || f.y > b.y + b.wort.length -1
| |
− | ) {
| |
− | erfolg = false;
| |
− | }
| |
− | }
| |
− |
| |
− | if (b.richtung == "diagonal-luro") {
| |
− | if (Math.abs(f.x) + Math.abs(f.y) != b.x + b.y
| |
− | || f.x < b.x
| |
− | || f.x > b.x + b.wort.length -1
| |
− | || f.y > b.y
| |
− | || f.y < b.y - b.wort.length -1
| |
− | ) {
| |
− | erfolg = false;
| |
− | }
| |
− | }
| |
− | });
| |
− |
| |
− | if (erfolg) {
| |
− | // "erfolg" enthält das Datenobjekt der Lösung
| |
− | q.each(el, function(f) {
| |
− | // Markierungen dauerhaft machen
| |
− | f.className = f.className.replace(/ markiert/, "") + " aufgedeckt";
| |
− | });
| |
− |
| |
− | // Fund in die Liste eintragen
| |
− | erfolg.eingetragen = false;
| |
− | el = q.domSelect("li", t.loesungsliste);
| |
− |
| |
− | q.each(el, function (li) {
| |
− | // Wort bereits gefunden worden?
| |
− | if (li.innerHTML == erfolg.wortOriginal) {
| |
− | erfolg.eingetragen = true;
| |
− | }
| |
− |
| |
− | if (!erfolg.eingetragen &&
| |
− | (!li.className || li.className != "ausgefuellt")
| |
− | ) {
| |
− | li.innerHTML = erfolg.wortOriginal;
| |
− | li.className = "ausgefuellt";
| |
− |
| |
− | erfolg.eingetragen = true;
| |
− |
| |
− | if (q.domSelect(
| |
− | ".ausgefuellt", t.loesungsliste
| |
− | ).length == el.length
| |
− | ) {
| |
− | // letztes Wort wurde gefunden!
| |
− | t.beenden();
| |
− | }
| |
− | }
| |
− | });
| |
− | }
| |
− | }
| |
− | });
| |
− | }
| |
− |
| |
− | return false;
| |
− | },
| |
− |
| |
− | // entferne alle Markierungen
| |
− | alleMarkierungenEntfernen : function (mitHover) {
| |
− | var t = this;
| |
− |
| |
− | q.each(q.domSelect(".markiert", t.tabelle), function (f) {
| |
− | f.className = f.className.replace(/(^| )markiert/, "");
| |
− | });
| |
− |
| |
− | if (mitHover) {
| |
− | q.each(q.domSelect(".hover", t.tabelle), function (f) {
| |
− | f.className = f.className.replace(/(^| )hover/, "");
| |
− | });
| |
− | }
| |
− | },
| |
− |
| |
− | // Felder markieren, die die gegenwärtige Auswahl darstellen
| |
− | auswahlMarkieren : function () {
| |
− | var t = this,
| |
− | richtung = "",
| |
− | el, ende, start, steigung, x, y;
| |
− |
| |
− | /* In welche Richtung geht die Markierung denn?
| |
− | -> Zeilenweise die Tabelle durchlaufen,
| |
− | um X- und Y-Koordinaten der Markierungsenden zu ermitteln */
| |
− | for (y = 0; y < t.tabelle.rows.length; y++) {
| |
− | for (x = 0; x < t.tabelle.rows[y].cells.length; x++) {
| |
− | if (t.tabelle.rows[y].cells[x] == t.markierungStart) {
| |
− | start = { x : x, y : y };
| |
− | }
| |
− |
| |
− | if (t.tabelle.rows[y].cells[x] == t.markierungEnde) {
| |
− | ende = { x : x, y : y };
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | // Fehler passiert? -> beenden
| |
− | if (!start || !ende) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Steigung bestimmen, in der die Markierung erfolgen soll
| |
− | if ((ende.y - start.y) === 0) {
| |
− | // Division by Zero!
| |
− | steigung = 2; // hier genügt ein Wert > 1.5
| |
− | } else {
| |
− | // Quotient ist "legal"
| |
− | steigung = (ende.x - start.x) / (ende.y - start.y);
| |
− | }
| |
− |
| |
− | // Richtung aus der Steigung und der Koordinaten bestimmen
| |
− | if (Math.abs(steigung) >= 0.5 && Math.abs(steigung) <= 1.5) {
| |
− | // diagonal
| |
− | richtung = steigung > 0 ? "nw-so" : "no-sw";
| |
− | } else {
| |
− | // waagrecht/senkrecht
| |
− | richtung = Math.abs(steigung) > 1 ? "w-o" : "n-s";
| |
− | }
| |
− |
| |
− | // alle zu markierenden Felder ermitteln und markieren
| |
− | x = start.x;
| |
− | y = start.y;
| |
− | el = t.tabelle.rows[y].cells[x];
| |
− |
| |
− | while (el) {
| |
− | el.className = el.className.replace(/(^| )markiert/, "") + " markiert";
| |
− | // "richtung" enthält nun einen String (n-s|w-o|nw-so|no-sw)
| |
− | switch (richtung) {
| |
− | case "n-s":
| |
− | // nur y-Wert weiterzählen
| |
− | if (start.y > ende.y && y > ende.y) {
| |
− | y--;
| |
− | }
| |
− |
| |
− | if (start.y < ende.y && y < ende.y) {
| |
− | y++;
| |
− | }
| |
− | break;
| |
− |
| |
− | case "w-o":
| |
− | // nur x-Wert weiterzählen
| |
− | if (start.x > ende.x && x > ende.x) {
| |
− | x--;
| |
− | }
| |
− |
| |
− | if (start.x < ende.x && x < ende.x) {
| |
− | x++;
| |
− | }
| |
− | break;
| |
− |
| |
− | case "nw-so":
| |
− | if (start.x > ende.x && x > ende.x
| |
− | &&
| |
− | start.y > ende.y && y > ende.y
| |
− | ) {
| |
− | x--;
| |
− | y--;
| |
− | }
| |
− |
| |
− | if (start.x < ende.x && x < ende.x
| |
− | &&
| |
− | start.y < ende.y && y < ende.y
| |
− | ) {
| |
− | x++;
| |
− | y++;
| |
− | }
| |
− | break;
| |
− |
| |
− | case "no-sw":
| |
− | if (start.x > ende.x && x > ende.x
| |
− | &&
| |
− | start.y < ende.y && y < ende.y
| |
− | ) {
| |
− | x--;
| |
− | y++;
| |
− | }
| |
− |
| |
− | if (start.x < ende.x && x < ende.x
| |
− | &&
| |
− | start.y > ende.y && y > ende.y
| |
− | ) {
| |
− | x++;
| |
− | y--;
| |
− | }
| |
− | break;
| |
− | }
| |
− |
| |
− | // aufhören, wenn kein neues Feld zu markieren ist
| |
− | el = (el != t.tabelle.rows[y].cells[x]) ?
| |
− | t.tabelle.rows[y].cells[x] : false;
| |
− | }
| |
− | },
| |
− |
| |
− | // Quiz wurde erfolgreich gelöst -> Meldung ausgeben
| |
− | beenden : function () {
| |
− | var t = this;
| |
− |
| |
− | t.element.appendChild(q.domCreate({
| |
− | tagName : "p",
| |
− | className : q.bewertungsClass,
| |
− | text : q.meldungen[t.sprache]["lob" + (t.versuche > 2 ? 3 : t.versuche)]
| |
− | + " "
| |
− | + q.meldungen[t.sprache][
| |
− | "ergebnis" + (t.versuche > 2 ? 3 : t.versuche)
| |
− | ].replace(/%n/i, t.versuche)
| |
− | }));
| |
− |
| |
− | // Auswertungs-Button und alle Eventhandler entfernen
| |
− | t.tabelle.onmousedown = null;
| |
− | t.tabelle.onmousemove = null;
| |
− | t.tabelle.onmouseover = null;
| |
− | t.tabelle.onmouseup = null;
| |
− | t.solved = true;
| |
− | t.element.className += " "+q.fertigClass;
| |
− | },
| |
− |
| |
− | // Funktion zum Errichten der Tabelle des Suchsel-Quiz und zum Einrichten der Eventhandler
| |
− | init : function () {
| |
− | var t = this,
| |
− | kreuzwortGitter, platzhalter, tr, x, y;
| |
− |
| |
− | // Spracheinstellungen auf deutsch zurück korrigieren, falls entsprechende Sprachdaten fehlen
| |
− | if (!q.meldungen[t.sprache]) {
| |
− | t.sprache = "de";
| |
− | }
| |
− |
| |
− | // Gitter erzeugen
| |
− | kreuzwortGitter = q.erstelleWoerterGitter(
| |
− | t.daten,
| |
− | true, // true für "alle Wörter verbunden"
| |
− | true // true für "diagonale Wörter möglich"
| |
− | );
| |
− |
| |
− | // Daten und Gitter abspeichern
| |
− | t.daten = kreuzwortGitter.woerter;
| |
− | t.grid = kreuzwortGitter.gitter;
| |
− |
| |
− | // Lösungsliste befüllen
| |
− | platzhalter = 0;
| |
− | q.each(t.daten, function (d) {
| |
− | if (platzhalter < d.wortOriginal.length) {
| |
− | platzhalter = d.wortOriginal.length;
| |
− | }
| |
− | });
| |
− |
| |
− | platzhalter = new Array(platzhalter +3).join("_");
| |
− |
| |
− | q.each(t.daten, function (d) {
| |
− | t.loesungsliste.appendChild(q.domCreate({
| |
− | tagName : "li",
| |
− | text : platzhalter
| |
− | }));
| |
− | });
| |
− |
| |
− | // Tabelle befüllen
| |
− | for (y = 0; y < t.grid.length; y++) {
| |
− | tr = t.tabelle.insertRow(
| |
− | t.tabelle.rows.length <= 0 ? 0 : t.tabelle.rows.length
| |
− | );
| |
− |
| |
− | for (x = 0; x < t.grid[0].length; x++) {
| |
− | // Zelleninhalt vorbereiten
| |
− | tr.appendChild(q.domCreate({
| |
− | tagName : "td",
| |
− | id : t.name + "_" + x + "_" + y,
| |
− | text : t.grid[y][x] ?
| |
− | t.grid[y][x] : String.fromCharCode(
| |
− | 65 + Math.floor(Math.random() * 26)
| |
− | ).toUpperCase()
| |
− | }));
| |
− | }
| |
− | }
| |
− |
| |
− | // ID für das umgebende DIV-Element vergeben
| |
− | t.element.id = t.name;
| |
− |
| |
− | // Markierungsmechanismus einrichten
| |
− | t.tabelle.onmousedown = function (e) {
| |
− | var el = q.eventElement(e);
| |
− |
| |
− | if (el.tagName && el.tagName.match(/^td$/i)) {
| |
− | el.className = el.className.replace(/(^| )hover/, "") + " markiert";
| |
− |
| |
− | // Beginn der Markierung merken
| |
− | t.markierungStart = el;
| |
− |
| |
− | // Markiermodus einschalten
| |
− | t.markiermodus = true;
| |
− |
| |
− | // Markierungseffekt im IE unterbinden
| |
− | q.antiMarkierungsModusFuerIE(true);
| |
− |
| |
− | // Markierungseffekt in W3C-konformen Browsern unterbinden
| |
− | if (window.getSelection) {
| |
− | window.getSelection().removeAllRanges();
| |
− | }
| |
− | }
| |
− | e.preventDefault();
| |
− | return true;
| |
− | };
| |
− | t.tabelle.addEventListener("touchstart",t.tabelle.onmousedown);
| |
− | t.tabelle.onmouseover = function (e) {
| |
− | var el = q.eventElement(e);
| |
− |
| |
− |
| |
− | if (el.tagName && el.tagName.match(/^td$/i) && t.markiermodus) {
| |
− | t.markierungEnde = el;
| |
− | // bestehende Markierungen entfernen
| |
− | t.alleMarkierungenEntfernen();
| |
− |
| |
− | // neue Markierungen setzen
| |
− | t.auswahlMarkieren();
| |
− | }
| |
− | e.preventDefault();
| |
− |
| |
− | return true;
| |
− | };
| |
− |
| |
− | t.tabelle.onmousemove = function (e) {
| |
− | var el = q.eventElement(e);
| |
− |
| |
− | if (!t.markiermodus) {
| |
− | t.alleMarkierungenEntfernen(true); // mit Hover
| |
− |
| |
− | // setze hover-Markierung für aktuelles Element
| |
− | if (el.tagName && el.tagName.match(/^td$/i)) {
| |
− | el.className += " hover";
| |
− | }
| |
− |
| |
− | } else {
| |
− | // Markierungseffekt in W3C-konformen Browsern unterbinden
| |
− | if (window.getSelection) {
| |
− | window.getSelection().removeAllRanges();
| |
− | }
| |
− | }
| |
− |
| |
− | return true;
| |
− | };
| |
− | t.tabelle.addEventListener("touchmove",t.tabelle.onmouseover);
| |
− | t.tabelle.addEventListener("touchmove",t.tabelle.onmousemove);
| |
− |
| |
− | t.element.onmouseup = function (e) {
| |
− | // markierte Felder auswerten
| |
− | t.auswerten();
| |
− |
| |
− | // alle Markierungen entfernen
| |
− | t.alleMarkierungenEntfernen();
| |
− |
| |
− | // Beende Markiermodus
| |
− | t.markiermodus = false;
| |
− |
| |
− | // Markierungseffekt im IE wieder erlauben
| |
− | q.antiMarkierungsModusFuerIE();
| |
− |
| |
− | return true;
| |
− | };
| |
− | t.element.addEventListener("touchend",t.element.onmouseup);
| |
− | t.element.addEventListener("touchcancel",t.element.onmouseup);
| |
− |
| |
− | t.tabelle.onmouseout = function (e) {
| |
− | if (!t.markiermodus) {
| |
− | // entferne alle Markierungen (samt hover)
| |
− | t.alleMarkierungenEntfernen(true);
| |
− | }
| |
− | };
| |
− | }
| |
− | };
| |
− |
| |
− | // Laufende Nummer ermitteln -> Quiz-Name wird "quiz" + laufende Nummer
| |
− | i = 0;
| |
− | q.each(q.alleQuizze, function() {
| |
− | i++;
| |
− | });
| |
− | quiz.name = "quiz" + i;
| |
− |
| |
− | // Gibt es Quiz-Daten?
| |
− | tabelle = q.domSelect("table", div);
| |
− |
| |
− | if (tabelle.length < 1) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Daten sind also vorhanden? -> Auswerten
| |
− | q.each(tabelle[0].rows, function (tr) {
| |
− | var gefunden;
| |
− |
| |
− | if (tr.cells.length > 0) {
| |
− | // "Müll" entfernen
| |
− | gefunden = tr.cells[0].innerHTML.replace(
| |
− | /<\/?[^>]+>/g, ""
| |
− | ).replace(
| |
− | /&/g, "&"
| |
− | ).replace(
| |
− | / /g, " "
| |
− | ).replace(
| |
− | / /g, "_"
| |
− | ).quizTrim();
| |
− |
| |
− | if (gefunden != "") {
| |
− | quiz.daten.push({
| |
− | // Lösungswort in reine Großbuchstaben umwandeln
| |
− | wort : q.wandleZeichen(gefunden).toUpperCase(),
| |
− | wortOriginal : gefunden,
| |
− | x : -1,
| |
− | y : -1
| |
− | });
| |
− | }
| |
− | }
| |
− | });
| |
− |
| |
− | // Keine brauchbare Daten? -> Verwerfen!
| |
− | if (quiz.daten.length < 1) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // originale Tabelle durch leere Tabelle ersetzen
| |
− | quiz.tabelle = q.domCreate({
| |
− | tagName : "table",
| |
− | className : "gitter"
| |
− | });
| |
− | tabelle[0].parentNode.insertBefore(quiz.tabelle, tabelle[0].nextSibling);
| |
− | tabelle[0].parentNode.removeChild(tabelle[0]);
| |
− |
| |
− | // Liste mit gefundenen Lösungen erstellen
| |
− | quiz.loesungsliste = q.domCreate({
| |
− | tagName : "ol",
| |
− | className : "liste"
| |
− | });
| |
− | div.appendChild(quiz.loesungsliste);
| |
− |
| |
− | // Quiz in die Liste aufnehmen und initialisieren
| |
− | q.alleQuizze[quiz.name] = quiz;
| |
− | quiz.element.quiz = quiz;
| |
− | quiz.init();
| |
− |
| |
− | return true;
| |
− | },
| |
− |
| |
− |
| |
− | /* Diese Funktion erzeugt ein Quiz, das man auch als Hangman-Quiz kennt. Es müssen die Buchstaben
| |
− | eines Wortes geraten werden, um zu einer Lösung zu geraten. Zu viele Fehlversuche führen zum Verlieren
| |
− | des Spiels. */
| |
− |
| |
− | buchstabenratenQuiz : function (div) {
| |
− | var q = this,
| |
− | i, tabelle, test, daten, gefunden;
| |
− |
| |
− | var quiz = {
| |
− | // Objekt-Gestalt eines Suchsel-Quizzes
| |
− | name : "Quiz-x", // Platzhalter - hier steht später etwas anderes.
| |
− | typ : "Buchstabenraten-Quiz",
| |
− | element : div, // Referenz auf das DIV-Element, in welchem sich das Quiz befindet
| |
− | feld : null, // Referenz auf das HTML-Element, in dem das eigentliche Spiel angezeigt wird
| |
− | daten : new Array(), // Hier stehen später Objekte, die die Quiz-Daten enthalten.
| |
− | versuche : 0, // Speichert die Anzahl Versuche, die für die Lösung gebraucht wurden.
| |
− | sprache : (div.lang && div.lang != "") ? div.lang : "de", // deutsche Meldungen als Voreinstellung
| |
− | erkannteWoerter : new Array(), // speichert die bereits erratenen Wörter
| |
− | gestartet : false, // Steuert, ob Tastatureingaben überhaupt ausgewertet werden
| |
− | bilder : new Array(
| |
− | /* Hier stehen die Bilddateien für die verschiedenen Stadien der Grafik, die das drohende
| |
− | Spielende darstellt. Dabei gilt die erste Grafik als Spielende und die letzte Grafik als Spielstart. */
| |
− | "blume00.gif",
| |
− | "blume01.gif",
| |
− | "blume02.gif",
| |
− | "blume03.gif",
| |
− | "blume04.gif",
| |
− | "blume05.gif",
| |
− | "blume06.gif",
| |
− | "blume07.gif",
| |
− | "blume08.gif",
| |
− | "blume09.gif",
| |
− | "blume10.gif"
| |
− | ),
| |
− |
| |
− | // Funktion zum Auswerten der Lösungen
| |
− | auswerten : function (keyCode) {
| |
− | var t = this,
| |
− | c = q.wandleZeichen(String.fromCharCode(keyCode)),
| |
− | schonGeraten, treffer, ul, li;
| |
− |
| |
− | if (c) {
| |
− | ul = q.domSelect(".geratene-buchstaben ul", t.element)[0]; // Element muss vorhanden sein
| |
− |
| |
− | // testen, ob dieser Buchstabe bereits geraten worden war
| |
− | q.each(ul.childNodes, function (li) {
| |
− | if (li.firstChild.data == c) {
| |
− | schonGeraten = true;
| |
− | }
| |
− | });
| |
− | if(schonGeraten)
| |
− | return;
| |
− | // noch nicht geraten worden? -> auf Treffer testen
| |
− | if (!schonGeraten) {
| |
− | li = q.domCreate({
| |
− | tagName : "li",
| |
− | text : c
| |
− | });
| |
− |
| |
− | ul.appendChild(li);
| |
− |
| |
− | // Ist der Buchstabe im Lösungswort enthalten?
| |
− | ul = q.domSelect(".ratewort ", t.element)[0]; // Element ist garantiert vorhanden
| |
− |
| |
− | q.each(ul.childNodes, function (l) {
| |
− | if (l.buchstabe == c) {
| |
− | treffer = true;
| |
− | l.className = "erraten";
| |
− | l.firstChild.data = l.buchstabe;
| |
− | li.className = "treffer";
| |
− | }
| |
− | });
| |
− | }
| |
− |
| |
− | // Ergebnis?
| |
− | if (!treffer) {
| |
− | t.versuche++;
| |
− |
| |
− | // Statusbild aktualisieren
| |
− | q.domSelect(".statusbild img", t.feld)[0].src = q.baseURL
| |
− | + "/images/"
| |
− | + t.bilder[t.bilder.length - 1 - t.versuche];
| |
− |
| |
− | // Spiel zu Ende?
| |
− | if (t.versuche == t.bilder.length - 1) {
| |
− | t.beenden();
| |
− | }
| |
− |
| |
− | } else {
| |
− | // Wort komplett erkannt?
| |
− | q.each(ul.childNodes, function (li) {
| |
− | // ul ist #ratewort! Prüfen ob alle Felder einen Buchstaben enthalten
| |
− | if (li.firstChild.data == String.fromCharCode(160)) {
| |
− | treffer = false; // nicht alle Buchstaben sind schon erkannt
| |
− | }
| |
− | })
| |
− |
| |
− | if (treffer) {
| |
− | // nächstes Wort erraten lassen
| |
− | t.erkannteWoerter.push(t.daten[t.erkannteWoerter.length]);
| |
− |
| |
− | if (t.versuche > 0) {
| |
− | t.versuche--;
| |
− | }
| |
− |
| |
− | window.setTimeout(
| |
− | function () {
| |
− | t.wortAbfragen();
| |
− | },
| |
− | 2000
| |
− | );
| |
− | }
| |
− | }
| |
− | }
| |
− | },
| |
− |
| |
− | // Funktion zum starten des Quiz-Vorgangs
| |
− | wortAbfragen : function () {
| |
− | var t = this,
| |
− | platzhalter, i;
| |
− |
| |
− | // "Spielfeld" aufbauen
| |
− | while (t.feld.firstChild) {
| |
− | t.feld.removeChild(t.feld.firstChild);
| |
− | }
| |
− |
| |
− | var input = document.createElement("input");
| |
− | t.feld.appendChild(input);
| |
− | input.style.width=0;
| |
− | input.style.height=0;
| |
− | input.style.opacity=0;
| |
− | input.focus();
| |
− | t.feld.addEventListener("click",function(){input.focus()});
| |
− | input.addEventListener("keyup",function(e){
| |
− | if (q.aktivesQuiz === t && !t.solved && t.gestartet) {
| |
− | var str=this.value;
| |
− | t.auswerten(str.charCodeAt(str.length - 1));
| |
− | this.value="";
| |
− | }
| |
− | });
| |
− |
| |
− | if (t.erkannteWoerter.length < t.daten.length) {
| |
− | // Statusbild einfügen
| |
− | t.feld.appendChild(q.domCreate({
| |
− | tagName : "p",
| |
− | className : "statusbild"
| |
− | }));
| |
− |
| |
− | t.feld.lastChild.appendChild(q.domCreate({
| |
− | tagName : "img",
| |
− | src : q.baseURL + "images/" + t.bilder[t.bilder.length - 1 - t.versuche]
| |
− | }));
| |
− |
| |
− | // Eingabehinweis
| |
− | t.feld.appendChild(q.domCreate({
| |
− | tagName : "p",
| |
− | className : "eingabehinweis",
| |
− | // Anzeigen des verdeckten <span>-Elementes bei Hover (für IE notwendig)
| |
− | onmouseover : function () {
| |
− | this.childNodes[0].style.display = "block";
| |
− | },
| |
− | // Verbergen des verdeckten <span>-Elementes beim Verlassen
| |
− | onmouseout : function () {
| |
− | this.childNodes[0].style.display = "";
| |
− | }
| |
− | }));
| |
− |
| |
− | t.feld.lastChild.appendChild(q.domCreate({
| |
− | tagName : "span",
| |
− | text : q.meldungen[t.sprache].eingabehinweis_buchstabenraten
| |
− | }));
| |
− |
| |
− | // Leerfelder für das zu erratende Wort aufbauen
| |
− | t.feld.appendChild(q.domCreate({
| |
− | tagName : "ul",
| |
− | className : "ratewort",
| |
− | wort : t.daten[t.erkannteWoerter.length].wort
| |
− | }));
| |
− |
| |
− | q.each(t.daten[t.erkannteWoerter.length].wort.split(""), function (c) {
| |
− | t.feld.lastChild.appendChild(q.domCreate({
| |
− | tagName : "li",
| |
− | text: String.fromCharCode(160),
| |
− | buchstabe : q.wandleZeichen(c)
| |
− | }));
| |
− | });
| |
− | }
| |
− |
| |
− | // Liste bereits gefundener Wörter erstellen
| |
− | platzhalter = 0;
| |
− | q.each(t.daten, function (d) {
| |
− | if (platzhalter < d.wort.length) {
| |
− | platzhalter = d.wort.length;
| |
− | }
| |
− | });
| |
− |
| |
− | platzhalter = new Array(platzhalter +3).join("_");
| |
− |
| |
− | t.feld.appendChild(q.domCreate({
| |
− | tagName : "div",
| |
− | className : "erkannte-woerter"
| |
− | }));
| |
− |
| |
− | t.feld.lastChild.appendChild(q.domCreate({
| |
− | tagName : "p",
| |
− | text: q.meldungen[t.sprache].erkannteWoerter
| |
− | }));
| |
− |
| |
− | t.feld.lastChild.appendChild(q.domCreate({
| |
− | tagName : "ol"
| |
− | }));
| |
− |
| |
− | for (i = 0; i < t.daten.length; i++) {
| |
− | t.feld.lastChild.lastChild.appendChild(q.domCreate({
| |
− | tagName : "li",
| |
− | className : t.erkannteWoerter[i] ? "erkannt" : "",
| |
− | text : t.erkannteWoerter[i] ?
| |
− | t.erkannteWoerter[i].wortOriginal : platzhalter
| |
− | }));
| |
− | }
| |
− |
| |
− | if (t.erkannteWoerter.length < t.daten.length) {
| |
− | // Liste bereits geratener Buchstaben erstellen
| |
− | t.feld.appendChild(q.domCreate({
| |
− | tagName : "div",
| |
− | className : "geratene-buchstaben"
| |
− | }));
| |
− |
| |
− | t.feld.lastChild.appendChild(q.domCreate({
| |
− | tagName : "p",
| |
− | text: q.meldungen[t.sprache].gerateneBuchstaben
| |
− | }));
| |
− |
| |
− | t.feld.lastChild.appendChild(q.domCreate({
| |
− | tagName : "ul"
| |
− | }));
| |
− |
| |
− | // Tastatureingabe einschalten
| |
− | t.gestartet = true;
| |
− |
| |
− | } else {
| |
− | // Quiz schon zu ende gespielt?
| |
− | t.beenden();
| |
− | }
| |
− | },
| |
− |
| |
− | // Meldung zu Spielende ausgeben + Neustart-Button
| |
− | beenden : function () {
| |
− | var t = this;
| |
− |
| |
− | // erneutes Spiel anbieten
| |
− | t.feld.appendChild(t.startLink);
| |
− | t.startLink.firstChild.data = q.meldungen[t.sprache].erneut;
| |
− |
| |
− | t.solved = true;
| |
− | t.element.className += " "+q.fertigClass;
| |
− | },
| |
− |
| |
− | // Quiz initialisieren
| |
− | init : function () {
| |
− | var t = this;
| |
− |
| |
− | // ID für das umgebende DIV-Element vergeben
| |
− | t.element.id = t.name;
| |
− |
| |
− | // Start-Link erzeugen
| |
− | t.startLink = q.domCreate({
| |
− | tagName : "p",
| |
− | className : "start-link",
| |
− | text : q.meldungen[t.sprache].quizStarten,
| |
− | onclick : function () {
| |
− | t.solved = false;
| |
− | t.element.className = t.element.className.replace(
| |
− | new RegExp(" ?" + q.fertigClass), ""
| |
− | );
| |
− | t.daten.shuffle();
| |
− | t.versuche = 0;
| |
− | t.erkannteWoerter = new Array();
| |
− | t.wortAbfragen();
| |
− | }
| |
− | });
| |
− |
| |
− | t.feld.appendChild(t.startLink);
| |
− |
| |
− |
| |
− | }
| |
− | };
| |
− |
| |
− | // Laufende Nummer ermitteln -> Quiz-Name wird "quiz" + laufende Nummer
| |
− | i = 0;
| |
− | q.each(q.alleQuizze, function () {
| |
− | i++;
| |
− | });
| |
− | quiz.name = "quiz" + i;
| |
− |
| |
− | // Gibt es Quiz-Daten?
| |
− | tabelle = q.domSelect("table", div);
| |
− |
| |
− | if (tabelle.length < 1) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Daten sind also vorhanden? -> Auswerten
| |
− | q.each(tabelle[0].rows, function (tr) {
| |
− | var gefunden;
| |
− |
| |
− | if (tr.cells.length > 0) {
| |
− | // "Müll" entfernen
| |
− | gefunden = tr.cells[0].innerHTML.replace(
| |
− | /<\/?[^>]+>/g, ""
| |
− | ).replace(
| |
− | /&/g, "&"
| |
− | ).replace(
| |
− | / /g, " "
| |
− | ).replace(
| |
− | / /g, "_"
| |
− | ).quizTrim();
| |
− |
| |
− | if (gefunden != "") {
| |
− | quiz.daten.push({
| |
− | // Lösungswort in reine Großbuchstaben umwandeln
| |
− | wort : q.wandleZeichen(gefunden).toUpperCase(),
| |
− | wortOriginal : gefunden,
| |
− | x : -1,
| |
− | y : -1
| |
− | });
| |
− | }
| |
− | }
| |
− | });
| |
− |
| |
− | // Keine brauchbare Daten? -> Verwerfen!
| |
− | if (quiz.daten.length < 1) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // originale Tabelle entfernen
| |
− | tabelle[0].parentNode.removeChild(tabelle[0]);
| |
− |
| |
− | // "Spielfeld" erstellen und ins Dokument schreiben
| |
− | quiz.feld = q.domCreate({ tagName : "div" });
| |
− | quiz.element.appendChild(quiz.feld);
| |
− |
| |
− | // Quiz in die Liste aufnehmen und initialisieren
| |
− | q.alleQuizze[quiz.name] = quiz;
| |
− | quiz.element.quiz = quiz;
| |
− | quiz.init();
| |
− |
| |
− | return true;
| |
− | },
| |
− |
| |
− |
| |
− | /*
| |
− | ==================
| |
− | weitere Funktionen
| |
− | ==================
| |
− | */
| |
− | // Zeichen in eintragbare Buchstaben umwandeln: "s" ist ein String
| |
− | wandleZeichen : function (s) {
| |
− | var q = this,
| |
− | r = "",
| |
− | z, i, j;
| |
− |
| |
− | for (i = 0; i < s.length; i++) {
| |
− | if (s[i] == String.fromCharCode(160) || s[i] == String.fromCharCode(32)) {
| |
− | r += String.fromCharCode(160);
| |
− |
| |
− | } else {
| |
− | for (z in q.codeTabelle) {
| |
− | if (z.match(/^[A-Z][A-Z]?$/)) {
| |
− | for (j = 0; j < q.codeTabelle[z].length; j++) {
| |
− | if (s.substr(i, 1) == q.codeTabelle[z][j]) {
| |
− | r += z;
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | return r;
| |
− | },
| |
− |
| |
− | initQuizze : function () {
| |
− | var q = this;
| |
− |
| |
− | // deutsche Sprachausgabe als Default
| |
− | if (!q.meldungen) {
| |
− | q.meldungen = {};
| |
− | }
| |
− |
| |
− | if (!q.meldungen.de) {
| |
− | // Voreinstellungen für Mehrsprachigkeit
| |
− | q.meldungen.de = {
| |
− | pruefen : 'prüfen!',
| |
− | lob1 : 'Ausgezeichnet!',
| |
− | lob2 : 'Gut gemacht!',
| |
− | lob3 : 'Das war nicht schlecht!',
| |
− | ergebnis1 : 'Die Aufgabe wurde gleich beim ersten Versuch erfolgreich gelöst!',
| |
− | ergebnis2 : 'Die Aufgabe wurde nach nur zwei Versuchen erfolgreich gelöst!',
| |
− | ergebnis3 : 'Die Aufgabe wurde nach %n Versuchen erfolgreich gelöst!',
| |
− | alleGefunden : 'Alle Sets gefunden!', // memo-quiz - Es können auch Triplets, Quartette und mehr gefunden werden müssen
| |
− | erneut : 'Wie wär\'s mit einer neuen Runde?',
| |
− | ergebnisProzent : 'Die Antworten sind zu %n% richtig.', // Multiple-Choice-Quiz
| |
− | senkrecht : 'Senkrecht', // Kreuzworträtsel
| |
− | waagrecht : 'Waagrecht',
| |
− | eingabehinweis : 'Klicken Sie auf ein gr\u00fcnes Feld, um einen Buchstaben einzugeben!',
| |
− | eingabehinweis_buchstabenraten : 'Benutzen Sie die Tastatur zur Eingabe! Eventuell m\u00fcssen Sie erst in das Quiz klicken, um es zu aktivieren.'
| |
− | };
| |
− | }
| |
− |
| |
− | // prüfen, ob Code-Tabelle für UTF-8-Normalisierung und Mehrsprachenunterstützung geladen wurden
| |
− | if (!q.codeTabelle || !q.meldungen.en || !q.domSelect) {
| |
− | window.setTimeout(q.initQuizze, 100);
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Initialisierung der Quizze
| |
− | var quizBereiche = new Array(),
| |
− | muster = new RegExp(q.triggerClass),
| |
− | i, j, a, gefunden, typ, ok, css;
| |
− |
| |
− | // Alle DIVs daraufhin überprüfen, ob sie eine CSS-Klasse haben, die auf ein Quiz schließen lässt
| |
− | q.each(q.domSelect("div"), function (d) {
| |
− | if (d.className && d.className.match(muster)) {
| |
− | quizBereiche.push(d);
| |
− | }
| |
− | });
| |
− |
| |
− | // Alle Quiz-Bereiche gefunden -> Initialisieren
| |
− | if (quizBereiche.length > 0) {
| |
− | q.each(quizBereiche, function (d) {
| |
− | var typ = d.className.replace(/([^ ,]+)-quiz/, "$1"),
| |
− | gefunden, ok; // Initialisierung ok?
| |
− |
| |
− | if (typeof(q[typ + "Quiz"]) == "function") {
| |
− | ok = q[typ + "Quiz"](d); // entsprechende Quiz-Funktion zum Erstellen aufrufen
| |
− | }
| |
− |
| |
− | // Initialisierung OK? -> Warnungen entfernen
| |
− | if (ok) {
| |
− | q.each(q.domSelect(".js-hinweis", d), function (j) {
| |
− | j.parentNode.removeChild(j);
| |
− | });
| |
− | }
| |
− | });
| |
− | }
| |
− |
| |
− | // Wenn mindestens ein Quiz initialisiert wurde, dann Seite "bestücken".
| |
− | if (q.alleQuizze.quiz0) {
| |
− | // CSS für Quizbereiche einbinden
| |
− | q.domSelect("head")[0].appendChild(
| |
− | q.domCreate({
| |
− | tagName : "link",
| |
− | rel : "stylesheet",
| |
− | type : "text/css",
| |
− | media : "screen, projection",
| |
− | href : q.baseURL + "css/quiz.css"
| |
− | })
| |
− | );
| |
− |
| |
− | // Print-CSS für Quizbereiche einbinden
| |
− | q.domSelect("head")[0].appendChild(
| |
− | q.domCreate({
| |
− | tagName : "link",
| |
− | rel : "stylesheet",
| |
− | type : "text/css",
| |
− | media : "print",
| |
− | href : q.baseURL + "css/quiz-print.css"
| |
− | })
| |
− | );
| |
− |
| |
− |
| |
− | // Links innerhalb eines Quizzes solange deaktivieren, bis es gelöst ist:
| |
− | q.each(q.alleQuizze, function (a) {
| |
− | if (a.felder) {
| |
− | q.each(a.felder, function (f) {
| |
− | gefunden = [];
| |
− |
| |
− | if (f.getElementsByTagName) {
| |
− | gefunden = f.getElementsByTagName("a");
| |
− | }
| |
− |
| |
− | if (f.element && f.element.getElementsByTagName) {
| |
− | gefunden = f.element.getElementsByTagName("a");
| |
− | }
| |
− |
| |
− | q.each(gefunden, function (g) {
| |
− | g.quiz = a;
| |
− | g.oldOnClick = g.onclick;
| |
− | g.onclick = q.linkOnClick; // neue onclick-Funktion, die Klicks blocken kann
| |
− | });
| |
− | });
| |
− | }
| |
− |
| |
− | // onclick-EventHandler für jedes <div> eines Quizzes setzen
| |
− | if (typeof a.element.onclick == "function") {
| |
− | a.element.oldOnClick = a.element.onclick;
| |
− | }
| |
− |
| |
− | a.element.onclick = function (e) {
| |
− | q.aktivesQuiz = this.quiz;
| |
− | if (typeof this.oldOnClick == "function") {
| |
− | this.oldOnClick(e);
| |
− | }
| |
− | return true;
| |
− | };
| |
− | });
| |
− | }
| |
− | },
| |
− |
| |
− | // neue onclick-Funktion für Links
| |
− | linkOnClick : function (e) {
| |
− | if (this.quiz.typ == "Multiple Choice - Quiz"
| |
− | || this.quiz.typ == "Buchstabenraten-Quiz"
| |
− | || this.quiz.solved
| |
− | ) {
| |
− | if (typeof this.oldOnClick == "function") {
| |
− | this.oldOnClick(e);
| |
− | }
| |
− |
| |
− | return true;
| |
− | }
| |
− |
| |
− | return false;
| |
− | },
| |
− |
| |
− | /* Funktionen für Drag&Drop-Mechanismus */
| |
− | eventElement : function (e) {
| |
− | // ermittle aktuelles Element unter dem Mauszeiger
| |
− | e = e || window.event;
| |
− | if (e.touches) {
| |
− | var changedTouch = e.touches[0];
| |
− | return document.elementFromPoint(changedTouch.clientX, changedTouch.clientY);
| |
− | }
| |
− | return e.target || e.srcElement; // W3C DOM <-> IE
| |
− | },
| |
− |
| |
− | auswahl : function (element, ziel) {
| |
− | if (!Quiz.baseURL)
| |
− | Quiz.init();
| |
− |
| |
− | if (ziel) {
| |
− | // Drag&Drop hat stattgefunden!
| |
− | Quiz.aktivesQuiz.dragNDropAuswerten(element, ziel);
| |
− | }
| |
− |
| |
− | // User-Eingabe war "nur ein Klick"...
| |
− | return false;
| |
− | },
| |
− |
| |
− | startDrag : function (e) {
| |
− | var q = Quiz,
| |
− | muster = new RegExp("(^|\\s)" + q.draggableClass + "(\\s|$)"),
| |
− | test;
| |
− | q.dragElm = q.eventElement(e);
| |
− |
| |
− | test = q.dragElm;
| |
− |
| |
− | /* Nur bei Klick auf ein entsprechend ausgezeichnetes Element
| |
− | (oder eines seiner Nachfahren-Elemente) Drag&Drop-Verhalten zeigen! */
| |
− | while (test != document.body
| |
− | && (!test.className
| |
− | || !test.className.match(muster)
| |
− | )) {
| |
− | test = test.parentNode;
| |
− | }
| |
− |
| |
− | if (test != document.body && test.className.match(muster)) {
| |
− | q.dragElm = test;
| |
− | q.dragMode = true;
| |
− |
| |
− | q.dragElm.className = q.dragElm.className.replace(
| |
− | new RegExp(q.draggedClass, "g"),
| |
− | ""
| |
− | ).trim();
| |
− |
| |
− | q.dragElm.className += " " + q.draggedClass;
| |
− |
| |
− | e.preventDefault();
| |
− |
| |
− | // aktives Quiz eintragen
| |
− | q.aktivesQuiz = q.alleQuizze[q.dragElm.id.replace(/_.+/, "")];
| |
− | }
| |
− |
| |
− | return !q.dragMode;
| |
− | },
| |
− | touchStart : function (e) {
| |
− | var left = e.touches[0].clientX;
| |
− | var top = e.touches[0].clientY;
| |
− | Quiz.lastCoords.left = left;
| |
− | Quiz.lastCoords.top = top;
| |
− | },
| |
− | whileMove : function (e) {
| |
− | var q = Quiz;
| |
− | var left = e.clientX;
| |
− | var top = e.clientY;
| |
− |
| |
− | if(e.touches) {
| |
− | left = e.touches[0].clientX;
| |
− | top = e.touches[0].clientY;
| |
− | }
| |
− |
| |
− | dx = q.lastCoords.left - left;
| |
− | dy = q.lastCoords.top - top;
| |
− |
| |
− | // Mauskoordinaten speichern
| |
− | q.lastCoords.left = left;
| |
− | q.lastCoords.top = top;
| |
− |
| |
− | // falls gerade kein Element gezogen wird, hier beenden
| |
− | if (!q.dragElm || !q.dragMode) {
| |
− | return true;
| |
− | }
| |
− |
| |
− | // zu ziehendes Element bewegen
| |
− | q.dragElm.style.visibility='';
| |
− | q.dragElm.style.position='relative';
| |
− |
| |
− | q.dragged = true;
| |
− |
| |
− | e.preventDefault();
| |
− |
| |
− | // Abstand zu den letzten Mauskoordinaten berechnen
| |
− | var lastLeft=0;
| |
− | var lastTop=0;
| |
− |
| |
− | if(q.dragElm.style.left) {
| |
− | lastLeft = parseFloat(q.dragElm.style.left);
| |
− | lastTop = parseFloat(q.dragElm.style.top);
| |
− | }
| |
− | q.dragElm.style.left = lastLeft - dx + "px";
| |
− | q.dragElm.style.top = lastTop - dy + "px";
| |
− |
| |
− | q.highlightTarget();
| |
− | return true;
| |
− | },
| |
− | highlightTarget : function () {
| |
− | var q = Quiz;
| |
− | var rectDrag=q.dragElm.getBoundingClientRect();
| |
− | var elements=q.aktivesQuiz.element.getElementsByClassName(q.aktivesQuiz.loesungsClass);
| |
− | q.highlightElm=null;
| |
− | q.each(elements,function(element){
| |
− | var rect=element.getBoundingClientRect();
| |
− | element.className = element.className.replace(q.highlightClass,"").trim();
| |
− | if(rect.top<q.lastCoords.top &&
| |
− | rect.left<q.lastCoords.left &&
| |
− | rect.bottom>q.lastCoords.top &&
| |
− | rect.right>q.lastCoords.left){
| |
− | element.className += " "+q.highlightClass;
| |
− | q.highlightElm=element;
| |
− | }
| |
− |
| |
− | });
| |
− |
| |
− | },
| |
− |
| |
− | stopDrag : function (e) {
| |
− | var q = Quiz,
| |
− | returnVal;
| |
− |
| |
− | if (!q.dragElm || !q.dragElm.className) {
| |
− | return false;
| |
− | }
| |
− |
| |
− | // Anti-Markier-Effekt in IE beenden
| |
− | q.antiMarkierungsModusFuerIE();
| |
− |
| |
− | if (q.dragged) {
| |
− | // eventuelle aktive Eingabefelder deaktivieren - aber nur wenn Drag&Drop stattgefunden hat!
| |
− | q.each(q.domSelect("input"), function (i) {
| |
− | try { i.blur(); }
| |
− | catch (e) { }
| |
− |
| |
− | try { i.onblur(); }
| |
− | catch (e) { }
| |
− | });
| |
− | }
| |
− |
| |
− | // bewegtes Element wieder eingliedern
| |
− | q.dragElm.className = q.dragElm.className.replace(
| |
− | new RegExp(q.draggedClass, "g"),
| |
− | ""
| |
− | ).trim();
| |
− |
| |
− | // Sichtbarkeit wurde nur verändert, wenn das Element wirklich gezogen wurde...
| |
− | if (q.dragged) {
| |
− | q.dragElm.style.visibility = q.dragElmOldVisibility;
| |
− | q.dragElmOldVisibility = "";
| |
− | }
| |
− |
| |
− | // Position (nur!) bei Feldern wieder zurückstellen
| |
− | if (q.dragElm.className.match(new RegExp("(^|\\s)" + q.feldClass + "(\\s|$)"))
| |
− | && q.dragged
| |
− | ) {
| |
− | q.dragElm.style.top = "";
| |
− | q.dragElm.style.left = "";
| |
− | }
| |
− |
| |
− | // Rückgabewert bereitstellen
| |
− | returnVal = q.dragged ?
| |
− | // für Drag&Drop
| |
− | q.auswahl(q.dragElm, q.highlightElm) :
| |
− | // für einen simplen Klick (zweiter Parameter false!)
| |
− | q.auswahl(q.dragElm, false);
| |
− |
| |
− | // Variablen wieder löschen
| |
− | q.dragElm = null;
| |
− | q.dragged = false;
| |
− | q.dragMode = false;
| |
− |
| |
− | // gehighlightetes Element wieder abstellen
| |
− | if (q.highlightElm) {
| |
− | q.highlightElm.className = q.highlightElm.className.replace(
| |
− | new RegExp(" ?" + q.highlightClass), ""
| |
− | );
| |
− | q.highlightElm = null;
| |
− | }
| |
− |
| |
− | return returnVal;
| |
− | },
| |
− |
| |
− | einBlender : function (e) {
| |
− | var q = Quiz;
| |
− |
| |
− | if (q.dragElm) {
| |
− | q.dragElm.style.visibility = q.dragElmOldVisibility;
| |
− | }
| |
− |
| |
− | return true;
| |
− | },
| |
− |
| |
− | antiMarkierungsModusFuerIE : function (schalter) {
| |
− | var q = this;
| |
− |
| |
− | if (schalter) {
| |
− | // Anti-Markierungs-Effekt für IE einschalten
| |
− | q.oldDocOnSelectStart = document.onselectstart;
| |
− | q.oldDocOnDragStart = document.ondragstart;
| |
− | document.onselectstart = function () { return false;};
| |
− | document.ondragstart = function () { return false;};
| |
− |
| |
− | } else {
| |
− | // Anti-Markier-Effekt für IE beenden
| |
− | if (q.oldDocOnSelectStart
| |
− | || typeof(document.onselectstart) == "function"
| |
− | ) {
| |
− | document.onselectstart = q.oldDocOnSelectStart;
| |
− | }
| |
− |
| |
− | if (q.oldDocOnDragStart
| |
− | || typeof(document.ondragstart) == "function"
| |
− | ) {
| |
− | document.ondragstart = q.oldDocOnDragStart;
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | };
| |
− |
| |
− | /*!
| |
− | * Sizzle CSS Selector Engine
| |
− | * Copyright 2011, The Dojo Foundation
| |
− | * Released under the MIT, BSD, and GPL Licenses.
| |
− | * More information: http://sizzlejs.com/
| |
− | */
| |
− | (function(){
| |
− |
| |
− | var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
| |
− | expando = "sizcache" + (Math.random() + '').replace('.', ''),
| |
− | done = 0,
| |
− | toString = Object.prototype.toString,
| |
− | hasDuplicate = false,
| |
− | baseHasDuplicate = true,
| |
− | rBackslash = /\\/g,
| |
− | rReturn = /\r\n/g,
| |
− | rNonWord = /\W/;
| |
− |
| |
− | // Here we check if the JavaScript engine is using some sort of
| |
− | // optimization where it does not always call our comparision
| |
− | // function. If that is the case, discard the hasDuplicate value.
| |
− | // Thus far that includes Google Chrome.
| |
− | [0, 0].sort(function() {
| |
− | baseHasDuplicate = false;
| |
− | return 0;
| |
− | });
| |
− |
| |
− | var Sizzle = function( selector, context, results, seed ) {
| |
− | results = results || [];
| |
− | context = context || document;
| |
− |
| |
− | var origContext = context;
| |
− |
| |
− | if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
| |
− | return [];
| |
− | }
| |
− |
| |
− | if ( !selector || typeof selector !== "string" ) {
| |
− | return results;
| |
− | }
| |
− |
| |
− | var m, set, checkSet, extra, ret, cur, pop, i,
| |
− | prune = true,
| |
− | contextXML = Sizzle.isXML( context ),
| |
− | parts = [],
| |
− | soFar = selector;
| |
− |
| |
− | // Reset the position of the chunker regexp (start from head)
| |
− | do {
| |
− | chunker.exec( "" );
| |
− | m = chunker.exec( soFar );
| |
− |
| |
− | if ( m ) {
| |
− | soFar = m[3];
| |
− |
| |
− | parts.push( m[1] );
| |
− |
| |
− | if ( m[2] ) {
| |
− | extra = m[3];
| |
− | break;
| |
− | }
| |
− | }
| |
− | } while ( m );
| |
− |
| |
− | if ( parts.length > 1 && origPOS.exec( selector ) ) {
| |
− |
| |
− | if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
| |
− | set = posProcess( parts[0] + parts[1], context, seed );
| |
− |
| |
− | } else {
| |
− | set = Expr.relative[ parts[0] ] ?
| |
− | [ context ] :
| |
− | Sizzle( parts.shift(), context );
| |
− |
| |
− | while ( parts.length ) {
| |
− | selector = parts.shift();
| |
− |
| |
− | if ( Expr.relative[ selector ] ) {
| |
− | selector += parts.shift();
| |
− | }
| |
− |
| |
− | set = posProcess( selector, set, seed );
| |
− | }
| |
− | }
| |
− |
| |
− | } else {
| |
− | // Take a shortcut and set the context if the root selector is an ID
| |
− | // (but not if it'll be faster if the inner selector is an ID)
| |
− | if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
| |
− | Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
| |
− |
| |
− | ret = Sizzle.find( parts.shift(), context, contextXML );
| |
− | context = ret.expr ?
| |
− | Sizzle.filter( ret.expr, ret.set )[0] :
| |
− | ret.set[0];
| |
− | }
| |
− |
| |
− | if ( context ) {
| |
− | ret = seed ?
| |
− | { expr: parts.pop(), set: makeArray(seed) } :
| |
− | Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
| |
− |
| |
− | set = ret.expr ?
| |
− | Sizzle.filter( ret.expr, ret.set ) :
| |
− | ret.set;
| |
− |
| |
− | if ( parts.length > 0 ) {
| |
− | checkSet = makeArray( set );
| |
− |
| |
− | } else {
| |
− | prune = false;
| |
− | }
| |
− |
| |
− | while ( parts.length ) {
| |
− | cur = parts.pop();
| |
− | pop = cur;
| |
− |
| |
− | if ( !Expr.relative[ cur ] ) {
| |
− | cur = "";
| |
− | } else {
| |
− | pop = parts.pop();
| |
− | }
| |
− |
| |
− | if ( pop == null ) {
| |
− | pop = context;
| |
− | }
| |
− |
| |
− | Expr.relative[ cur ]( checkSet, pop, contextXML );
| |
− | }
| |
− |
| |
− | } else {
| |
− | checkSet = parts = [];
| |
− | }
| |
− | }
| |
− |
| |
− | if ( !checkSet ) {
| |
− | checkSet = set;
| |
− | }
| |
− |
| |
− | if ( !checkSet ) {
| |
− | Sizzle.error( cur || selector );
| |
− | }
| |
− |
| |
− | if ( toString.call(checkSet) === "[object Array]" ) {
| |
− | if ( !prune ) {
| |
− | results.push.apply( results, checkSet );
| |
− |
| |
− | } else if ( context && context.nodeType === 1 ) {
| |
− | for ( i = 0; checkSet[i] != null; i++ ) {
| |
− | if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
| |
− | results.push( set[i] );
| |
− | }
| |
− | }
| |
− |
| |
− | } else {
| |
− | for ( i = 0; checkSet[i] != null; i++ ) {
| |
− | if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
| |
− | results.push( set[i] );
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | } else {
| |
− | makeArray( checkSet, results );
| |
− | }
| |
− |
| |
− | if ( extra ) {
| |
− | Sizzle( extra, origContext, results, seed );
| |
− | Sizzle.uniqueSort( results );
| |
− | }
| |
− |
| |
− | return results;
| |
− | };
| |
− |
| |
− | Sizzle.uniqueSort = function( results ) {
| |
− | if ( sortOrder ) {
| |
− | hasDuplicate = baseHasDuplicate;
| |
− | results.sort( sortOrder );
| |
− |
| |
− | if ( hasDuplicate ) {
| |
− | for ( var i = 1; i < results.length; i++ ) {
| |
− | if ( results[i] === results[ i - 1 ] ) {
| |
− | results.splice( i--, 1 );
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | return results;
| |
− | };
| |
− |
| |
− | Sizzle.matches = function( expr, set ) {
| |
− | return Sizzle( expr, null, null, set );
| |
− | };
| |
− |
| |
− | Sizzle.matchesSelector = function( node, expr ) {
| |
− | return Sizzle( expr, null, null, [node] ).length > 0;
| |
− | };
| |
− |
| |
− | Sizzle.find = function( expr, context, isXML ) {
| |
− | var set, i, len, match, type, left;
| |
− |
| |
− | if ( !expr ) {
| |
− | return [];
| |
− | }
| |
− |
| |
− | for ( i = 0, len = Expr.order.length; i < len; i++ ) {
| |
− | type = Expr.order[i];
| |
− |
| |
− | if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
| |
− | left = match[1];
| |
− | match.splice( 1, 1 );
| |
− |
| |
− | if ( left.substr( left.length - 1 ) !== "\\" ) {
| |
− | match[1] = (match[1] || "").replace( rBackslash, "" );
| |
− | set = Expr.find[ type ]( match, context, isXML );
| |
− |
| |
− | if ( set != null ) {
| |
− | expr = expr.replace( Expr.match[ type ], "" );
| |
− | break;
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | if ( !set ) {
| |
− | set = typeof context.getElementsByTagName !== "undefined" ?
| |
− | context.getElementsByTagName( "*" ) :
| |
− | [];
| |
− | }
| |
− |
| |
− | return { set: set, expr: expr };
| |
− | };
| |
− |
| |
− | Sizzle.filter = function( expr, set, inplace, not ) {
| |
− | var match, anyFound,
| |
− | type, found, item, filter, left,
| |
− | i, pass,
| |
− | old = expr,
| |
− | result = [],
| |
− | curLoop = set,
| |
− | isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
| |
− |
| |
− | while ( expr && set.length ) {
| |
− | for ( type in Expr.filter ) {
| |
− | if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
| |
− | filter = Expr.filter[ type ];
| |
− | left = match[1];
| |
− |
| |
− | anyFound = false;
| |
− |
| |
− | match.splice(1,1);
| |
− |
| |
− | if ( left.substr( left.length - 1 ) === "\\" ) {
| |
− | continue;
| |
− | }
| |
− |
| |
− | if ( curLoop === result ) {
| |
− | result = [];
| |
− | }
| |
− |
| |
− | if ( Expr.preFilter[ type ] ) {
| |
− | match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
| |
− |
| |
− | if ( !match ) {
| |
− | anyFound = found = true;
| |
− |
| |
− | } else if ( match === true ) {
| |
− | continue;
| |
− | }
| |
− | }
| |
− |
| |
− | if ( match ) {
| |
− | for ( i = 0; (item = curLoop[i]) != null; i++ ) {
| |
− | if ( item ) {
| |
− | found = filter( item, match, i, curLoop );
| |
− | pass = not ^ found;
| |
− |
| |
− | if ( inplace && found != null ) {
| |
− | if ( pass ) {
| |
− | anyFound = true;
| |
− |
| |
− | } else {
| |
− | curLoop[i] = false;
| |
− | }
| |
− |
| |
− | } else if ( pass ) {
| |
− | result.push( item );
| |
− | anyFound = true;
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | if ( found !== undefined ) {
| |
− | if ( !inplace ) {
| |
− | curLoop = result;
| |
− | }
| |
− |
| |
− | expr = expr.replace( Expr.match[ type ], "" );
| |
− |
| |
− | if ( !anyFound ) {
| |
− | return [];
| |
− | }
| |
− |
| |
− | break;
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | // Improper expression
| |
− | if ( expr === old ) {
| |
− | if ( anyFound == null ) {
| |
− | Sizzle.error( expr );
| |
− |
| |
− | } else {
| |
− | break;
| |
− | }
| |
− | }
| |
− |
| |
− | old = expr;
| |
− | }
| |
− |
| |
− | return curLoop;
| |
− | };
| |
− |
| |
− | Sizzle.error = function( msg ) {
| |
− | throw new Error( "Syntax error, unrecognized expression: " + msg );
| |
− | };
| |
− |
| |
− | /**
| |
− | * Utility function for retreiving the text value of an array of DOM nodes
| |
− | * @param {Array|Element} elem
| |
− | */
| |
− | var getText = Sizzle.getText = function( elem ) {
| |
− | var i, node,
| |
− | nodeType = elem.nodeType,
| |
− | ret = "";
| |
− |
| |
− | if ( nodeType ) {
| |
− | if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
| |
− | // Use textContent || innerText for elements
| |
− | if ( typeof elem.textContent === 'string' ) {
| |
− | return elem.textContent;
| |
− | } else if ( typeof elem.innerText === 'string' ) {
| |
− | // Replace IE's carriage returns
| |
− | return elem.innerText.replace( rReturn, '' );
| |
− | } else {
| |
− | // Traverse it's children
| |
− | for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
| |
− | ret += getText( elem );
| |
− | }
| |
− | }
| |
− | } else if ( nodeType === 3 || nodeType === 4 ) {
| |
− | return elem.nodeValue;
| |
− | }
| |
− | } else {
| |
− |
| |
− | // If no nodeType, this is expected to be an array
| |
− | for ( i = 0; (node = elem[i]); i++ ) {
| |
− | // Do not traverse comment nodes
| |
− | if ( node.nodeType !== 8 ) {
| |
− | ret += getText( node );
| |
− | }
| |
− | }
| |
− | }
| |
− | return ret;
| |
− | };
| |
− |
| |
− | var Expr = Sizzle.selectors = {
| |
− | order: [ "ID", "NAME", "TAG" ],
| |
− |
| |
− | match: {
| |
− | ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
| |
− | CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
| |
− | NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
| |
− | ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
| |
− | TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
| |
− | CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
| |
− | POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
| |
− | PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
| |
− | },
| |
− |
| |
− | leftMatch: {},
| |
− |
| |
− | attrMap: {
| |
− | "class": "className",
| |
− | "for": "htmlFor"
| |
− | },
| |
− |
| |
− | attrHandle: {
| |
− | href: function( elem ) {
| |
− | return elem.getAttribute( "href" );
| |
− | },
| |
− | type: function( elem ) {
| |
− | return elem.getAttribute( "type" );
| |
− | }
| |
− | },
| |
− |
| |
− | relative: {
| |
− | "+": function(checkSet, part){
| |
− | var isPartStr = typeof part === "string",
| |
− | isTag = isPartStr && !rNonWord.test( part ),
| |
− | isPartStrNotTag = isPartStr && !isTag;
| |
− |
| |
− | if ( isTag ) {
| |
− | part = part.toLowerCase();
| |
− | }
| |
− |
| |
− | for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
| |
− | if ( (elem = checkSet[i]) ) {
| |
− | while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
| |
− |
| |
− | checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
| |
− | elem || false :
| |
− | elem === part;
| |
− | }
| |
− | }
| |
− |
| |
− | if ( isPartStrNotTag ) {
| |
− | Sizzle.filter( part, checkSet, true );
| |
− | }
| |
− | },
| |
− |
| |
− | ">": function( checkSet, part ) {
| |
− | var elem,
| |
− | isPartStr = typeof part === "string",
| |
− | i = 0,
| |
− | l = checkSet.length;
| |
− |
| |
− | if ( isPartStr && !rNonWord.test( part ) ) {
| |
− | part = part.toLowerCase();
| |
− |
| |
− | for ( ; i < l; i++ ) {
| |
− | elem = checkSet[i];
| |
− |
| |
− | if ( elem ) {
| |
− | var parent = elem.parentNode;
| |
− | checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
| |
− | }
| |
− | }
| |
− |
| |
− | } else {
| |
− | for ( ; i < l; i++ ) {
| |
− | elem = checkSet[i];
| |
− |
| |
− | if ( elem ) {
| |
− | checkSet[i] = isPartStr ?
| |
− | elem.parentNode :
| |
− | elem.parentNode === part;
| |
− | }
| |
− | }
| |
− |
| |
− | if ( isPartStr ) {
| |
− | Sizzle.filter( part, checkSet, true );
| |
− | }
| |
− | }
| |
− | },
| |
− |
| |
− | "": function(checkSet, part, isXML){
| |
− | var nodeCheck,
| |
− | doneName = done++,
| |
− | checkFn = dirCheck;
| |
− |
| |
− | if ( typeof part === "string" && !rNonWord.test( part ) ) {
| |
− | part = part.toLowerCase();
| |
− | nodeCheck = part;
| |
− | checkFn = dirNodeCheck;
| |
− | }
| |
− |
| |
− | checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
| |
− | },
| |
− |
| |
− | "~": function( checkSet, part, isXML ) {
| |
− | var nodeCheck,
| |
− | doneName = done++,
| |
− | checkFn = dirCheck;
| |
− |
| |
− | if ( typeof part === "string" && !rNonWord.test( part ) ) {
| |
− | part = part.toLowerCase();
| |
− | nodeCheck = part;
| |
− | checkFn = dirNodeCheck;
| |
− | }
| |
− |
| |
− | checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
| |
− | }
| |
− | },
| |
− |
| |
− | find: {
| |
− | ID: function( match, context, isXML ) {
| |
− | if ( typeof context.getElementById !== "undefined" && !isXML ) {
| |
− | var m = context.getElementById(match[1]);
| |
− | // Check parentNode to catch when Blackberry 4.6 returns
| |
− | // nodes that are no longer in the document #6963
| |
− | return m && m.parentNode ? [m] : [];
| |
− | }
| |
− | },
| |
− |
| |
− | NAME: function( match, context ) {
| |
− | if ( typeof context.getElementsByName !== "undefined" ) {
| |
− | var ret = [],
| |
− | results = context.getElementsByName( match[1] );
| |
− |
| |
− | for ( var i = 0, l = results.length; i < l; i++ ) {
| |
− | if ( results[i].getAttribute("name") === match[1] ) {
| |
− | ret.push( results[i] );
| |
− | }
| |
− | }
| |
− |
| |
− | return ret.length === 0 ? null : ret;
| |
− | }
| |
− | },
| |
− |
| |
− | TAG: function( match, context ) {
| |
− | if ( typeof context.getElementsByTagName !== "undefined" ) {
| |
− | return context.getElementsByTagName( match[1] );
| |
− | }
| |
− | }
| |
− | },
| |
− | preFilter: {
| |
− | CLASS: function( match, curLoop, inplace, result, not, isXML ) {
| |
− | match = " " + match[1].replace( rBackslash, "" ) + " ";
| |
− |
| |
− | if ( isXML ) {
| |
− | return match;
| |
− | }
| |
− |
| |
− | for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
| |
− | if ( elem ) {
| |
− | if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
| |
− | if ( !inplace ) {
| |
− | result.push( elem );
| |
− | }
| |
− |
| |
− | } else if ( inplace ) {
| |
− | curLoop[i] = false;
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | return false;
| |
− | },
| |
− |
| |
− | ID: function( match ) {
| |
− | return match[1].replace( rBackslash, "" );
| |
− | },
| |
− |
| |
− | TAG: function( match, curLoop ) {
| |
− | return match[1].replace( rBackslash, "" ).toLowerCase();
| |
− | },
| |
− |
| |
− | CHILD: function( match ) {
| |
− | if ( match[1] === "nth" ) {
| |
− | if ( !match[2] ) {
| |
− | Sizzle.error( match[0] );
| |
− | }
| |
− |
| |
− | match[2] = match[2].replace(/^\+|\s*/g, '');
| |
− |
| |
− | // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
| |
− | var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
| |
− | match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
| |
− | !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
| |
− |
| |
− | // calculate the numbers (first)n+(last) including if they are negative
| |
− | match[2] = (test[1] + (test[2] || 1)) - 0;
| |
− | match[3] = test[3] - 0;
| |
− | }
| |
− | else if ( match[2] ) {
| |
− | Sizzle.error( match[0] );
| |
− | }
| |
− |
| |
− | // TODO: Move to normal caching system
| |
− | match[0] = done++;
| |
− |
| |
− | return match;
| |
− | },
| |
− |
| |
− | ATTR: function( match, curLoop, inplace, result, not, isXML ) {
| |
− | var name = match[1] = match[1].replace( rBackslash, "" );
| |
− |
| |
− | if ( !isXML && Expr.attrMap[name] ) {
| |
− | match[1] = Expr.attrMap[name];
| |
− | }
| |
− |
| |
− | // Handle if an un-quoted value was used
| |
− | match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
| |
− |
| |
− | if ( match[2] === "~=" ) {
| |
− | match[4] = " " + match[4] + " ";
| |
− | }
| |
− |
| |
− | return match;
| |
− | },
| |
− |
| |
− | PSEUDO: function( match, curLoop, inplace, result, not ) {
| |
− | if ( match[1] === "not" ) {
| |
− | // If we're dealing with a complex expression, or a simple one
| |
− | if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
| |
− | match[3] = Sizzle(match[3], null, null, curLoop);
| |
− |
| |
− | } else {
| |
− | var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
| |
− |
| |
− | if ( !inplace ) {
| |
− | result.push.apply( result, ret );
| |
− | }
| |
− |
| |
− | return false;
| |
− | }
| |
− |
| |
− | } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
| |
− | return true;
| |
− | }
| |
− |
| |
− | return match;
| |
− | },
| |
− |
| |
− | POS: function( match ) {
| |
− | match.unshift( true );
| |
− |
| |
− | return match;
| |
− | }
| |
− | },
| |
− |
| |
− | filters: {
| |
− | enabled: function( elem ) {
| |
− | return elem.disabled === false && elem.type !== "hidden";
| |
− | },
| |
− |
| |
− | disabled: function( elem ) {
| |
− | return elem.disabled === true;
| |
− | },
| |
− |
| |
− | checked: function( elem ) {
| |
− | return elem.checked === true;
| |
− | },
| |
− |
| |
− | selected: function( elem ) {
| |
− | // Accessing this property makes selected-by-default
| |
− | // options in Safari work properly
| |
− | if ( elem.parentNode ) {
| |
− | elem.parentNode.selectedIndex;
| |
− | }
| |
− |
| |
− | return elem.selected === true;
| |
− | },
| |
− |
| |
− | parent: function( elem ) {
| |
− | return !!elem.firstChild;
| |
− | },
| |
− |
| |
− | empty: function( elem ) {
| |
− | return !elem.firstChild;
| |
− | },
| |
− |
| |
− | has: function( elem, i, match ) {
| |
− | return !!Sizzle( match[3], elem ).length;
| |
− | },
| |
− |
| |
− | header: function( elem ) {
| |
− | return (/h\d/i).test( elem.nodeName );
| |
− | },
| |
− |
| |
− | text: function( elem ) {
| |
− | var attr = elem.getAttribute( "type" ), type = elem.type;
| |
− | // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
| |
− | // use getAttribute instead to test this case
| |
− | return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
| |
− | },
| |
− |
| |
− | radio: function( elem ) {
| |
− | return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
| |
− | },
| |
− |
| |
− | checkbox: function( elem ) {
| |
− | return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
| |
− | },
| |
− |
| |
− | file: function( elem ) {
| |
− | return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
| |
− | },
| |
− |
| |
− | password: function( elem ) {
| |
− | return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
| |
− | },
| |
− |
| |
− | submit: function( elem ) {
| |
− | var name = elem.nodeName.toLowerCase();
| |
− | return (name === "input" || name === "button") && "submit" === elem.type;
| |
− | },
| |
− |
| |
− | image: function( elem ) {
| |
− | return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
| |
− | },
| |
− |
| |
− | reset: function( elem ) {
| |
− | var name = elem.nodeName.toLowerCase();
| |
− | return (name === "input" || name === "button") && "reset" === elem.type;
| |
− | },
| |
− |
| |
− | button: function( elem ) {
| |
− | var name = elem.nodeName.toLowerCase();
| |
− | return name === "input" && "button" === elem.type || name === "button";
| |
− | },
| |
− |
| |
− | input: function( elem ) {
| |
− | return (/input|select|textarea|button/i).test( elem.nodeName );
| |
− | },
| |
− |
| |
− | focus: function( elem ) {
| |
− | return elem === elem.ownerDocument.activeElement;
| |
− | }
| |
− | },
| |
− | setFilters: {
| |
− | first: function( elem, i ) {
| |
− | return i === 0;
| |
− | },
| |
− |
| |
− | last: function( elem, i, match, array ) {
| |
− | return i === array.length - 1;
| |
− | },
| |
− |
| |
− | even: function( elem, i ) {
| |
− | return i % 2 === 0;
| |
− | },
| |
− |
| |
− | odd: function( elem, i ) {
| |
− | return i % 2 === 1;
| |
− | },
| |
− |
| |
− | lt: function( elem, i, match ) {
| |
− | return i < match[3] - 0;
| |
− | },
| |
− |
| |
− | gt: function( elem, i, match ) {
| |
− | return i > match[3] - 0;
| |
− | },
| |
− |
| |
− | nth: function( elem, i, match ) {
| |
− | return match[3] - 0 === i;
| |
− | },
| |
− |
| |
− | eq: function( elem, i, match ) {
| |
− | return match[3] - 0 === i;
| |
− | }
| |
− | },
| |
− | filter: {
| |
− | PSEUDO: function( elem, match, i, array ) {
| |
− | var name = match[1],
| |
− | filter = Expr.filters[ name ];
| |
− |
| |
− | if ( filter ) {
| |
− | return filter( elem, i, match, array );
| |
− |
| |
− | } else if ( name === "contains" ) {
| |
− | return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
| |
− |
| |
− | } else if ( name === "not" ) {
| |
− | var not = match[3];
| |
− |
| |
− | for ( var j = 0, l = not.length; j < l; j++ ) {
| |
− | if ( not[j] === elem ) {
| |
− | return false;
| |
− | }
| |
− | }
| |
− |
| |
− | return true;
| |
− |
| |
− | } else {
| |
− | Sizzle.error( name );
| |
− | }
| |
− | },
| |
− |
| |
− | CHILD: function( elem, match ) {
| |
− | var first, last,
| |
− | doneName, parent, cache,
| |
− | count, diff,
| |
− | type = match[1],
| |
− | node = elem;
| |
− |
| |
− | switch ( type ) {
| |
− | case "only":
| |
− | case "first":
| |
− | while ( (node = node.previousSibling) ) {
| |
− | if ( node.nodeType === 1 ) {
| |
− | return false;
| |
− | }
| |
− | }
| |
− |
| |
− | if ( type === "first" ) {
| |
− | return true;
| |
− | }
| |
− |
| |
− | node = elem;
| |
− |
| |
− | /* falls through */
| |
− | case "last":
| |
− | while ( (node = node.nextSibling) ) {
| |
− | if ( node.nodeType === 1 ) {
| |
− | return false;
| |
− | }
| |
− | }
| |
− |
| |
− | return true;
| |
− |
| |
− | case "nth":
| |
− | first = match[2];
| |
− | last = match[3];
| |
− |
| |
− | if ( first === 1 && last === 0 ) {
| |
− | return true;
| |
− | }
| |
− |
| |
− | doneName = match[0];
| |
− | parent = elem.parentNode;
| |
− |
| |
− | if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
| |
− | count = 0;
| |
− |
| |
− | for ( node = parent.firstChild; node; node = node.nextSibling ) {
| |
− | if ( node.nodeType === 1 ) {
| |
− | node.nodeIndex = ++count;
| |
− | }
| |
− | }
| |
− |
| |
− | parent[ expando ] = doneName;
| |
− | }
| |
− |
| |
− | diff = elem.nodeIndex - last;
| |
− |
| |
− | if ( first === 0 ) {
| |
− | return diff === 0;
| |
− |
| |
− | } else {
| |
− | return ( diff % first === 0 && diff / first >= 0 );
| |
− | }
| |
− | }
| |
− | },
| |
− |
| |
− | ID: function( elem, match ) {
| |
− | return elem.nodeType === 1 && elem.getAttribute("id") === match;
| |
− | },
| |
− |
| |
− | TAG: function( elem, match ) {
| |
− | return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
| |
− | },
| |
− |
| |
− | CLASS: function( elem, match ) {
| |
− | return (" " + (elem.className || elem.getAttribute("class")) + " ")
| |
− | .indexOf( match ) > -1;
| |
− | },
| |
− |
| |
− | ATTR: function( elem, match ) {
| |
− | var name = match[1],
| |
− | result = Sizzle.attr ?
| |
− | Sizzle.attr( elem, name ) :
| |
− | Expr.attrHandle[ name ] ?
| |
− | Expr.attrHandle[ name ]( elem ) :
| |
− | elem[ name ] != null ?
| |
− | elem[ name ] :
| |
− | elem.getAttribute( name ),
| |
− | value = result + "",
| |
− | type = match[2],
| |
− | check = match[4];
| |
− |
| |
− | return result == null ?
| |
− | type === "!=" :
| |
− | !type && Sizzle.attr ?
| |
− | result != null :
| |
− | type === "=" ?
| |
− | value === check :
| |
− | type === "*=" ?
| |
− | value.indexOf(check) >= 0 :
| |
− | type === "~=" ?
| |
− | (" " + value + " ").indexOf(check) >= 0 :
| |
− | !check ?
| |
− | value && result !== false :
| |
− | type === "!=" ?
| |
− | value !== check :
| |
− | type === "^=" ?
| |
− | value.indexOf(check) === 0 :
| |
− | type === "$=" ?
| |
− | value.substr(value.length - check.length) === check :
| |
− | type === "|=" ?
| |
− | value === check || value.substr(0, check.length + 1) === check + "-" :
| |
− | false;
| |
− | },
| |
− |
| |
− | POS: function( elem, match, i, array ) {
| |
− | var name = match[2],
| |
− | filter = Expr.setFilters[ name ];
| |
− |
| |
− | if ( filter ) {
| |
− | return filter( elem, i, match, array );
| |
− | }
| |
− | }
| |
− | }
| |
− | };
| |
− |
| |
− | var origPOS = Expr.match.POS,
| |
− | fescape = function(all, num){
| |
− | return "\\" + (num - 0 + 1);
| |
− | };
| |
− |
| |
− | for ( var type in Expr.match ) {
| |
− | Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
| |
− | Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
| |
− | }
| |
− | // Expose origPOS
| |
− | // "global" as in regardless of relation to brackets/parens
| |
− | Expr.match.globalPOS = origPOS;
| |
− |
| |
− | var makeArray = function( array, results ) {
| |
− | array = Array.prototype.slice.call( array, 0 );
| |
− |
| |
− | if ( results ) {
| |
− | results.push.apply( results, array );
| |
− | return results;
| |
− | }
| |
− |
| |
− | return array;
| |
− | };
| |
− |
| |
− | // Perform a simple check to determine if the browser is capable of
| |
− | // converting a NodeList to an array using builtin methods.
| |
− | // Also verifies that the returned array holds DOM nodes
| |
− | // (which is not the case in the Blackberry browser)
| |
− | try {
| |
− | Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
| |
− |
| |
− | // Provide a fallback method if it does not work
| |
− | } catch( e ) {
| |
− | makeArray = function( array, results ) {
| |
− | var i = 0,
| |
− | ret = results || [];
| |
− |
| |
− | if ( toString.call(array) === "[object Array]" ) {
| |
− | Array.prototype.push.apply( ret, array );
| |
− |
| |
− | } else {
| |
− | if ( typeof array.length === "number" ) {
| |
− | for ( var l = array.length; i < l; i++ ) {
| |
− | ret.push( array[i] );
| |
− | }
| |
− |
| |
− | } else {
| |
− | for ( ; array[i]; i++ ) {
| |
− | ret.push( array[i] );
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | return ret;
| |
− | };
| |
− | }
| |
− |
| |
− | var sortOrder, siblingCheck;
| |
− |
| |
− | if ( document.documentElement.compareDocumentPosition ) {
| |
− | sortOrder = function( a, b ) {
| |
− | if ( a === b ) {
| |
− | hasDuplicate = true;
| |
− | return 0;
| |
− | }
| |
− |
| |
− | if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
| |
− | return a.compareDocumentPosition ? -1 : 1;
| |
− | }
| |
− |
| |
− | return a.compareDocumentPosition(b) & 4 ? -1 : 1;
| |
− | };
| |
− |
| |
− | } else {
| |
− | sortOrder = function( a, b ) {
| |
− | // The nodes are identical, we can exit early
| |
− | if ( a === b ) {
| |
− | hasDuplicate = true;
| |
− | return 0;
| |
− |
| |
− | // Fallback to using sourceIndex (in IE) if it's available on both nodes
| |
− | } else if ( a.sourceIndex && b.sourceIndex ) {
| |
− | return a.sourceIndex - b.sourceIndex;
| |
− | }
| |
− |
| |
− | var al, bl,
| |
− | ap = [],
| |
− | bp = [],
| |
− | aup = a.parentNode,
| |
− | bup = b.parentNode,
| |
− | cur = aup;
| |
− |
| |
− | // If the nodes are siblings (or identical) we can do a quick check
| |
− | if ( aup === bup ) {
| |
− | return siblingCheck( a, b );
| |
− |
| |
− | // If no parents were found then the nodes are disconnected
| |
− | } else if ( !aup ) {
| |
− | return -1;
| |
− |
| |
− | } else if ( !bup ) {
| |
− | return 1;
| |
− | }
| |
− |
| |
− | // Otherwise they're somewhere else in the tree so we need
| |
− | // to build up a full list of the parentNodes for comparison
| |
− | while ( cur ) {
| |
− | ap.unshift( cur );
| |
− | cur = cur.parentNode;
| |
− | }
| |
− |
| |
− | cur = bup;
| |
− |
| |
− | while ( cur ) {
| |
− | bp.unshift( cur );
| |
− | cur = cur.parentNode;
| |
− | }
| |
− |
| |
− | al = ap.length;
| |
− | bl = bp.length;
| |
− |
| |
− | // Start walking down the tree looking for a discrepancy
| |
− | for ( var i = 0; i < al && i < bl; i++ ) {
| |
− | if ( ap[i] !== bp[i] ) {
| |
− | return siblingCheck( ap[i], bp[i] );
| |
− | }
| |
− | }
| |
− |
| |
− | // We ended someplace up the tree so do a sibling check
| |
− | return i === al ?
| |
− | siblingCheck( a, bp[i], -1 ) :
| |
− | siblingCheck( ap[i], b, 1 );
| |
− | };
| |
− |
| |
− | siblingCheck = function( a, b, ret ) {
| |
− | if ( a === b ) {
| |
− | return ret;
| |
− | }
| |
− |
| |
− | var cur = a.nextSibling;
| |
− |
| |
− | while ( cur ) {
| |
− | if ( cur === b ) {
| |
− | return -1;
| |
− | }
| |
− |
| |
− | cur = cur.nextSibling;
| |
− | }
| |
− |
| |
− | return 1;
| |
− | };
| |
− | }
| |
− |
| |
− | // Check to see if the browser returns elements by name when
| |
− | // querying by getElementById (and provide a workaround)
| |
− | (function(){
| |
− | // We're going to inject a fake input element with a specified name
| |
− | var form = document.createElement("div"),
| |
− | id = "script" + (new Date()).getTime(),
| |
− | root = document.documentElement;
| |
− |
| |
− | | |
− |
| |
− | // Inject it into the root element, check its status, and remove it quickly
| |
− | root.insertBefore( form, root.firstChild );
| |
− |
| |
− | // The workaround has to do additional checks after a getElementById
| |
− | // Which slows things down for other browsers (hence the branching)
| |
− | if ( document.getElementById( id ) ) {
| |
− | Expr.find.ID = function( match, context, isXML ) {
| |
− | if ( typeof context.getElementById !== "undefined" && !isXML ) {
| |
− | var m = context.getElementById(match[1]);
| |
− |
| |
− | return m ?
| |
− | m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
| |
− | [m] :
| |
− | undefined :
| |
− | [];
| |
− | }
| |
− | };
| |
− |
| |
− | Expr.filter.ID = function( elem, match ) {
| |
− | var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
| |
− |
| |
− | return elem.nodeType === 1 && node && node.nodeValue === match;
| |
− | };
| |
− | }
| |
− |
| |
− | root.removeChild( form );
| |
− |
| |
− | // release memory in IE
| |
− | root = form = null;
| |
− | })();
| |
− |
| |
− | (function(){
| |
− | // Check to see if the browser returns only elements
| |
− | // when doing getElementsByTagName("*")
| |
− |
| |
− | // Create a fake element
| |
− | var div = document.createElement("div");
| |
− | div.appendChild( document.createComment("") );
| |
− |
| |
− | // Make sure no comments are found
| |
− | if ( div.getElementsByTagName("*").length > 0 ) {
| |
− | Expr.find.TAG = function( match, context ) {
| |
− | var results = context.getElementsByTagName( match[1] );
| |
− |
| |
− | // Filter out possible comments
| |
− | if ( match[1] === "*" ) {
| |
− | var tmp = [];
| |
− |
| |
− | for ( var i = 0; results[i]; i++ ) {
| |
− | if ( results[i].nodeType === 1 ) {
| |
− | tmp.push( results[i] );
| |
− | }
| |
− | }
| |
− |
| |
− | results = tmp;
| |
− | }
| |
− |
| |
− | return results;
| |
− | };
| |
− | }
| |
− |
| |
− | // Check to see if an attribute returns normalized href attributes
| |
− | | |
− |
| |
− | if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
| |
− | div.firstChild.getAttribute("href") !== "#" ) {
| |
− |
| |
− | Expr.attrHandle.href = function( elem ) {
| |
− | return elem.getAttribute( "href", 2 );
| |
− | };
| |
− | }
| |
− |
| |
− | // release memory in IE
| |
− | div = null;
| |
− | })();
| |
− |
| |
− | if ( document.querySelectorAll ) {
| |
− | (function(){
| |
− | var oldSizzle = Sizzle,
| |
− | div = document.createElement("div"),
| |
− | id = "__sizzle__";
| |
− |
| |
− | div.innerHTML = "<p class='TEST'></p>";
| |
− |
| |
− | // Safari can't handle uppercase or unicode characters when
| |
− | // in quirks mode.
| |
− | if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
| |
− | return;
| |
− | }
| |
− |
| |
− | Sizzle = function( query, context, extra, seed ) {
| |
− | context = context || document;
| |
− |
| |
− | // Only use querySelectorAll on non-XML documents
| |
− | // (ID selectors don't work in non-HTML documents)
| |
− | if ( !seed && !Sizzle.isXML(context) ) {
| |
− | // See if we find a selector to speed up
| |
− | var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
| |
− |
| |
− | if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
| |
− | // Speed-up: Sizzle("TAG")
| |
− | if ( match[1] ) {
| |
− | return makeArray( context.getElementsByTagName( query ), extra );
| |
− |
| |
− | // Speed-up: Sizzle(".CLASS")
| |
− | } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
| |
− | return makeArray( context.getElementsByClassName( match[2] ), extra );
| |
− | }
| |
− | }
| |
− |
| |
− | if ( context.nodeType === 9 ) {
| |
− | // Speed-up: Sizzle("body")
| |
− | // The body element only exists once, optimize finding it
| |
− | if ( query === "body" && context.body ) {
| |
− | return makeArray( [ context.body ], extra );
| |
− |
| |
− | // Speed-up: Sizzle("#ID")
| |
− | } else if ( match && match[3] ) {
| |
− | var elem = context.getElementById( match[3] );
| |
− |
| |
− | // Check parentNode to catch when Blackberry 4.6 returns
| |
− | // nodes that are no longer in the document #6963
| |
− | if ( elem && elem.parentNode ) {
| |
− | // Handle the case where IE and Opera return items
| |
− | // by name instead of ID
| |
− | if ( elem.id === match[3] ) {
| |
− | return makeArray( [ elem ], extra );
| |
− | }
| |
− |
| |
− | } else {
| |
− | return makeArray( [], extra );
| |
− | }
| |
− | }
| |
− |
| |
− | try {
| |
− | return makeArray( context.querySelectorAll(query), extra );
| |
− | } catch(qsaError) {}
| |
− |
| |
− | // qSA works strangely on Element-rooted queries
| |
− | // We can work around this by specifying an extra ID on the root
| |
− | // and working up from there (Thanks to Andrew Dupont for the technique)
| |
− | // IE 8 doesn't work on object elements
| |
− | } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
| |
− | var oldContext = context,
| |
− | old = context.getAttribute( "id" ),
| |
− | nid = old || id,
| |
− | hasParent = context.parentNode,
| |
− | relativeHierarchySelector = /^\s*[+~]/.test( query );
| |
− |
| |
− | if ( !old ) {
| |
− | context.setAttribute( "id", nid );
| |
− | } else {
| |
− | nid = nid.replace( /'/g, "\\$&" );
| |
− | }
| |
− | if ( relativeHierarchySelector && hasParent ) {
| |
− | context = context.parentNode;
| |
− | }
| |
− |
| |
− | try {
| |
− | if ( !relativeHierarchySelector || hasParent ) {
| |
− | return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
| |
− | }
| |
− |
| |
− | } catch(pseudoError) {
| |
− | } finally {
| |
− | if ( !old ) {
| |
− | oldContext.removeAttribute( "id" );
| |
− | }
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | return oldSizzle(query, context, extra, seed);
| |
− | };
| |
− |
| |
− | for ( var prop in oldSizzle ) {
| |
− | Sizzle[ prop ] = oldSizzle[ prop ];
| |
− | }
| |
− |
| |
− | // release memory in IE
| |
− | div = null;
| |
− | })();
| |
− | }
| |
− |
| |
− | (function(){
| |
− | var html = document.documentElement,
| |
− | matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
| |
− |
| |
− | if ( matches ) {
| |
− | // Check to see if it's possible to do matchesSelector
| |
− | // on a disconnected node (IE 9 fails this)
| |
− | var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
| |
− | pseudoWorks = false;
| |
− |
| |
− | try {
| |
− | // This should fail with an exception
| |
− | // Gecko does not error, returns false instead
| |
− | matches.call( document.documentElement, "[test!='']:sizzle" );
| |
− |
| |
− | } catch( pseudoError ) {
| |
− | pseudoWorks = true;
| |
− | }
| |
− |
| |
− | Sizzle.matchesSelector = function( node, expr ) {
| |
− | // Make sure that attribute selectors are quoted
| |
− | expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
| |
− |
| |
− | if ( !Sizzle.isXML( node ) ) {
| |
− | try {
| |
− | if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
| |
− | var ret = matches.call( node, expr );
| |
− |
| |
− | // IE 9's matchesSelector returns false on disconnected nodes
| |
− | if ( ret || !disconnectedMatch ||
| |
− | // As well, disconnected nodes are said to be in a document
| |
− | // fragment in IE 9, so check for that
| |
− | node.document && node.document.nodeType !== 11 ) {
| |
− | return ret;
| |
− | }
| |
− | }
| |
− | } catch(e) {}
| |
− | }
| |
− |
| |
− | return Sizzle(expr, null, null, [node]).length > 0;
| |
− | };
| |
− | }
| |
− | })();
| |
− |
| |
− | (function(){
| |
− | var div = document.createElement("div");
| |
− |
| |
− | div.innerHTML = "<div class='test e'></div><div class='test'></div>";
| |
− |
| |
− | // Opera can't find a second classname (in 9.6)
| |
− | // Also, make sure that getElementsByClassName actually exists
| |
− | if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
| |
− | return;
| |
− | }
| |
− |
| |
− | // Safari caches class attributes, doesn't catch changes (in 3.2)
| |
− | div.lastChild.className = "e";
| |
− |
| |
− | if ( div.getElementsByClassName("e").length === 1 ) {
| |
− | return;
| |
− | }
| |
− |
| |
− | Expr.order.splice(1, 0, "CLASS");
| |
− | Expr.find.CLASS = function( match, context, isXML ) {
| |
− | if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
| |
− | return context.getElementsByClassName(match[1]);
| |
− | }
| |
− | };
| |
− |
| |
− | // release memory in IE
| |
− | div = null;
| |
− | })();
| |
− |
| |
− | function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
| |
− | for ( var i = 0, l = checkSet.length; i < l; i++ ) {
| |
− | var elem = checkSet[i];
| |
− |
| |
− | if ( elem ) {
| |
− | var match = false;
| |
− |
| |
− | elem = elem[dir];
| |
− |
| |
− | while ( elem ) {
| |
− | if ( elem[ expando ] === doneName ) {
| |
− | match = checkSet[elem.sizset];
| |
− | break;
| |
− | }
| |
− |
| |
− | if ( elem.nodeType === 1 && !isXML ){
| |
− | elem[ expando ] = doneName;
| |
− | elem.sizset = i;
| |
− | }
| |
− |
| |
− | if ( elem.nodeName.toLowerCase() === cur ) {
| |
− | match = elem;
| |
− | break;
| |
− | }
| |
− |
| |
− | elem = elem[dir];
| |
− | }
| |
− |
| |
− | checkSet[i] = match;
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
| |
− | for ( var i = 0, l = checkSet.length; i < l; i++ ) {
| |
− | var elem = checkSet[i];
| |
− |
| |
− | if ( elem ) {
| |
− | var match = false;
| |
− |
| |
− | elem = elem[dir];
| |
− |
| |
− | while ( elem ) {
| |
− | if ( elem[ expando ] === doneName ) {
| |
− | match = checkSet[elem.sizset];
| |
− | break;
| |
− | }
| |
− |
| |
− | if ( elem.nodeType === 1 ) {
| |
− | if ( !isXML ) {
| |
− | elem[ expando ] = doneName;
| |
− | elem.sizset = i;
| |
− | }
| |
− |
| |
− | if ( typeof cur !== "string" ) {
| |
− | if ( elem === cur ) {
| |
− | match = true;
| |
− | break;
| |
− | }
| |
− |
| |
− | } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
| |
− | match = elem;
| |
− | break;
| |
− | }
| |
− | }
| |
− |
| |
− | elem = elem[dir];
| |
− | }
| |
− |
| |
− | checkSet[i] = match;
| |
− | }
| |
− | }
| |
− | }
| |
− |
| |
− | if ( document.documentElement.contains ) {
| |
− | Sizzle.contains = function( a, b ) {
| |
− | return a !== b && (a.contains ? a.contains(b) : true);
| |
− | };
| |
− |
| |
− | } else if ( document.documentElement.compareDocumentPosition ) {
| |
− | Sizzle.contains = function( a, b ) {
| |
− | return !!(a.compareDocumentPosition(b) & 16);
| |
− | };
| |
− |
| |
− | } else {
| |
− | Sizzle.contains = function() {
| |
− | return false;
| |
− | };
| |
− | }
| |
− |
| |
− | Sizzle.isXML = function( elem ) {
| |
− | // documentElement is verified for cases where it doesn't yet exist
| |
− | // (such as loading iframes in IE - #4833)
| |
− | var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
| |
− |
| |
− | return documentElement ? documentElement.nodeName !== "HTML" : false;
| |
− | };
| |
− |
| |
− | var posProcess = function( selector, context, seed ) {
| |
− | var match,
| |
− | tmpSet = [],
| |
− | later = "",
| |
− | root = context.nodeType ? [context] : context;
| |
− |
| |
− | // Position selectors must be done after the filter
| |
− | // And so must :not(positional) so we move all PSEUDOs to the end
| |
− | while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
| |
− | later += match[0];
| |
− | selector = selector.replace( Expr.match.PSEUDO, "" );
| |
− | }
| |
− |
| |
− | selector = Expr.relative[selector] ? selector + "*" : selector;
| |
− |
| |
− | for ( var i = 0, l = root.length; i < l; i++ ) {
| |
− | Sizzle( selector, root[i], tmpSet, seed );
| |
− | }
| |
− |
| |
− | return Sizzle.filter( later, tmpSet );
| |
− | };
| |
− |
| |
− | // EXPOSE
| |
− | if (!window.Quiz)
| |
− | window.Quiz = new Object();
| |
− |
| |
− | window.Quiz.domSelect = Sizzle;
| |
− |
| |
− | })();
| |
− |
| |
− | // initialisieren
| |
− | Quiz.init();
| |