crossword-8.x-1.x-dev/js/crossword.js

js/crossword.js
(function ($, Drupal, once, drupalSettings) {

  Drupal.behaviors.crossword = {
    attach: function (context, settings) {
      var selector = drupalSettings.crossword.selector;
      once('crossword-init', selector).forEach(function(crossword){
        var $crossword = $(crossword);
        var data = drupalSettings.crossword.data;
        // Handle persisting revealed status.
        data.revealed = Drupal.behaviors.crossword.isRevealed(data.id);
        if (data.revealed) {
          $crossword.addClass('crossword-revealed');
        }
        var answers = Drupal.behaviors.crossword.loadAnswers(data);
        var Crossword = new Drupal.Crossword.Crossword(data, answers);
        Crossword.$crossword = $crossword;
        Crossword.$activeCluesText = $('.active-clues-text', $crossword);
        $crossword.data("Crossword", Crossword);

        Drupal.behaviors.crossword.addCrosswordEventHandlers($crossword, data);
        Drupal.behaviors.crossword.connectClues($crossword, data);
        Drupal.behaviors.crossword.connectSquares($crossword, data);
        Drupal.behaviors.crossword.addInputHandlers($crossword, data);
        Drupal.behaviors.crossword.addKeydownHandlers($crossword, data);
        Drupal.behaviors.crossword.addClickHandlers($crossword, data);

        // Trick the display into updating now that everything is connected.
        Crossword.setActiveClue(Crossword.activeClue);

        // Handle checkboxes for settings.
        // Show-errors setting.
        if ($('#show-errors', $crossword).prop('checked')) {
          $crossword.addClass('show-errors');
        }
        once('crossword-show-errors-change', '#show-errors', crossword).forEach(function(element) {
          $(element).on('change', function () {
            $crossword.toggleClass('show-errors');
            localStorage.setItem('#show-errors', $(this).prop('checked'));
          });
        });
        // Show-references setting.
        if ($('#show-references', $crossword).prop('checked')) {
          $crossword.addClass('show-references');
        }
        once('crossword-show-references-change', '#show-references', crossword).forEach(function(element){
          $(element).on('change', function(){
            $crossword.toggleClass('show-references');
            localStorage.setItem('#show-references', $(this).prop('checked'));
          });
        });
        // Show-clue setting.
        if ($('#show-clues', $crossword).prop('checked') === false) {
          $crossword.addClass('hide-clues');
        }
        once('crossword-show-clues-change', '#show-clues', crossword).forEach(function(element){
          $(element).on('change', function(){
            $crossword.toggleClass('hide-clues');
            localStorage.setItem('#show-clues', $(this).prop('checked'));
          });
        });
        // Load settings from storage to override defaults.
        Drupal.behaviors.crossword.loadSettings($crossword)

        // Instructions button is an odd duck.
        once('crossword-button-instructions', '.button-instructions', crossword).forEach(function(element){
          $(element).click(function(e){
            e.preventDefault();
            $('.crossword-instructions-container', $crossword).toggleClass('active');
          });
        });
      });
    },
    loadSettings: function($crossword) {
      var settings = [
        '#show-errors',
        '#show-references',
        '#show-clues',
      ];
      settings.forEach(function(setting) {
        if (localStorage.getItem(setting) !== null) {
          if (String($(setting, $crossword).prop('checked')) !== localStorage.getItem(setting)) {
            $(setting, $crossword).trigger('click');
          }
        }
      });
    },
    loadAnswers: function (data) {
      var key = 'crossword:' + data.id;
      var storage;
      if (localStorage.getItem(key) !== null) {
        storage = JSON.parse(localStorage.getItem(key));
        if (storage['answers']) {
          return storage['answers'];
        }
      }
      // If we haven't returned, no answers are saved yet.
      var emptyAnswers = Drupal.behaviors.crossword.emptyAnswers(data);
      if (!storage) {
        storage = {};
      }
      storage['answers'] = emptyAnswers;
      localStorage.setItem(key, JSON.stringify(storage));
      return emptyAnswers;
    },
    saveAnswers: function (id, answers) {
      var key = 'crossword:' + id;
      var storage;
      if (localStorage.getItem(key) !== null) {
        storage = JSON.parse(localStorage.getItem(key));
      }
      if (!storage) {
        storage = {};
      }
      storage['answers'] = answers;
      localStorage.setItem(key, JSON.stringify(storage));
    },
    saveRevealed: function (id, revealed) {
      var key = 'crossword:' + id;
      var storage;
      if (localStorage.getItem(key) !== null) {
        storage = JSON.parse(localStorage.getItem(key));
      }
      if (!storage) {
        storage = {};
      }
      storage['revealed'] = revealed;
      localStorage.setItem(key, JSON.stringify(storage));
    },
    isRevealed: function (id) {
      var key = 'crossword:' + id;
      if (localStorage.getItem(key) !== null) {
        var storage = JSON.parse(localStorage.getItem(key));
        if (storage['revealed']) {
          return storage['revealed'];
        }
      }
      return false;
    },
    emptyAnswers: function (data) {
      var grid = data.puzzle.grid;
      var answers = [];
      for (var row_index = 0; row_index < grid.length; row_index++) {
        answers.push([]);
        for (var col_index = 0; col_index < grid[row_index].length; col_index++) {
          if (data.puzzle.grid[row_index][col_index].hint) {
            // A hint is always visible, even when loading the first time.
            answers[row_index].push(data.puzzle.grid[row_index][col_index].fill);
          }
          else {
            answers[row_index].push(null);
          }
        }
      }
      return answers;
    },
    connectSquares: function ($crossword, data) {
      $('.crossword-square', $crossword).each(function(){
        var row = Number($(this).data('row'));
        var col = Number($(this).data('col'));
        $(this).data("Square", $crossword.data("Crossword").grid[row][col]);
        $(this).data("Square").connect($(this));
      });
    },
    connectClues: function ($crossword, data) {
      $('.crossword-clue', $crossword).each(function(){
        if ($(this).data('clue-index-across') !== undefined) {
          var index = Number($(this).data('clue-index-across'));
          $(this).data("Clue", $crossword.data("Crossword").clues.across[index]);
        }
        else {
          var index = Number($(this).data('clue-index-down'));
          $(this).data("Clue", $crossword.data("Crossword").clues.down[index]);
        }
        $(this).data("Clue").connect($(this));
      });
    },
    addInputHandlers: function($crossword, data) {
      var Crossword = $crossword.data("Crossword");
      $('.crossword-square input', $crossword).on('input', function(e){
        if (e.target.value) {
          Crossword.setAnswer(e.target.value, Drupal.behaviors.crossword.rebusEntryActive(e.target.value)).focus();
          $(this).val("");
        }
      });
      // Make sure non-crossword inputs, like a searchbar, still work.
      $('input:not(".crossword-input")').on('focus', function() {
        Crossword.escape();
      });
    },
    addKeydownHandlers: function($crossword, data) {
      var Crossword = $crossword.data("Crossword");

      $(document).on("keydown", function(event) {
        if (Crossword.activeClue) {
          //for arrows, spacebar, escape, and tab
          switch(event.keyCode) {
            case 27:
              //escape
              // Opt out of key hijacking!
              event.preventDefault();
              Crossword.escape();
              Drupal.behaviors.crossword.turnOffRebus();
              break;
            case 38:
              //up
              event.preventDefault();
              Crossword.moveActiveSquare('up').focus();
              Drupal.behaviors.crossword.turnOffRebus();
              break;
            case 37:
              //left
              event.preventDefault();
              Drupal.behaviors.crossword.turnOffRebus();
              if (event.shiftKey) {
                Crossword.retreatToPreviousUnsolvedClue().focus();
              } else {
                Crossword.moveActiveSquare('left').focus();
              }
              break;
            case 39:
              //right
              event.preventDefault();
              Drupal.behaviors.crossword.turnOffRebus();
              if (event.shiftKey) {
                Crossword.advanceToNextUnsolvedClue().focus();
              } else {
                Crossword.moveActiveSquare('right').focus();
              }
              break;
            case 40:
              //down
              event.preventDefault();
              Crossword.moveActiveSquare('down').focus();
              Drupal.behaviors.crossword.turnOffRebus();
              break;
            case 32:
              //spacebar
              event.preventDefault();
              // Escape from rebus or toggle direction.
              if (Drupal.behaviors.crossword.rebusEntryActive("spacebar")) {
                Crossword.advanceActiveSquare().focus();
                Drupal.behaviors.crossword.turnOffRebus();
              } else {
                Crossword.changeDir().focus();
              }
              break;
            case 13:
              //return
              event.preventDefault();
              Drupal.behaviors.crossword.turnOffRebus();
              Crossword.advanceActiveSquare().focus();
              break;
            case 9:
              //tab
              event.preventDefault();
              Drupal.behaviors.crossword.turnOffRebus();
              if (event.shiftKey) {
                Crossword.retreatActiveClue().focus();
              } else {
                Crossword.advanceActiveClue().focus();
              }
              break;
            case 46:
            case 8:
              //backspace
              Crossword.setAnswer("", Drupal.behaviors.crossword.rebusEntryActive("backspace")).focus();
              break;
            case 82:
              // r + CTRL toggles rebus.
              if (event.ctrlKey) {
                event.preventDefault();
                Drupal.behaviors.crossword.toggleRebus();
              }
              break;
            case 67:
              // c + CTRL cheats.
              if (event.ctrlKey) {
                event.preventDefault();
                $('.button-cheat', $crossword).trigger('click');
                Drupal.behaviors.crossword.turnOffRebus();
                Crossword.focus();
              }
              break;
            case 73:
              // i + CTRL toggles instructions.
              if (event.ctrlKey) {
                event.preventDefault();
                $('.crossword-instructions-container', $crossword).toggleClass('active').focus();
              }
              break;
            case 69:
              // e + CTRL toggles errors.
              if (event.ctrlKey) {
                event.preventDefault();
                $('#show-errors', $crossword).trigger('click').
                Crossword.focus();
              }
              break;
            default:
              // In any other case add focus so letter can always be entered.
              // Helpful if user is clicking buttons and using keyboard.
              Crossword.focus();
              break;
          }
        }
      });
    },
    addClickHandlers: function ($crossword, data) {
      var Crossword = $crossword.data("Crossword");

      once('crossword-square-click', '.crossword-square').forEach(function(element){
        $(element).click(function(){
          if ($(this).data("Square") == Crossword.activeSquare && $(this).hasClass('focus')) {
            Crossword.changeDir();
          }
          else {
            Crossword.setActiveSquare($(this).data("Square"));
            Drupal.behaviors.crossword.turnOffRebus();
          }
          Crossword.focus();
        });
      });

      once('crossword-clue-click', '.crossword-clue').forEach(function(element){
        $(element).click(function(){
          Crossword.setActiveClue($(this).data("Clue")).focus();
          Drupal.behaviors.crossword.turnOffRebus();
        });
      });

      once('crossword-clue-change-click', '.crossword-clue-change').forEach(function(element){
        $(element).click(function(e){
          e.preventDefault();
          var dir = $(this).data('dir');
          var change = Number($(this).data('clue-change'));
          Crossword.changeActiveClue(dir, change);
          Drupal.behaviors.crossword.turnOffRebus();
        });
      });

      once('crossword-express-click', '.next-clue-express').forEach(function(element){
        $(element).click(function(e){
          e.preventDefault();
          Crossword.advanceToNextUnsolvedClue();
          Drupal.behaviors.crossword.turnOffRebus();
        });
      });

      once('crossword-express-click', '.prev-clue-express').forEach(function(element){
        $(element).click(function(e){
          e.preventDefault();
          Crossword.retreatToPreviousUnsolvedClue();
          Drupal.behaviors.crossword.turnOffRebus();
        });
      });

      once('crossword-dir-change-click', '.crossword-dir-change').forEach(function(element){
        $(element).click(function(e){
          e.preventDefault();
          var dir = $(this).data('dir');
          if (dir != Crossword.dir) {
            Crossword.changeDir();
          }
        });
      });

      once('crossword-cheat-click', '.button-cheat').forEach(function(element){
        $(element).click(function(e){
          e.preventDefault();
          if ($(this).data('confirm')) {
            var message = $(this).data('confirm');
            if (!confirm(message)) {
              return;
            }
          }
          Crossword.cheat();
          Drupal.behaviors.crossword.turnOffRebus();
        });
      });

      once('crossword-undo-click', '.button-undo').forEach(function(element){
        $(element).click(function(e){
          e.preventDefault();
          if ($(this).data('confirm')) {
            var message = $(this).data('confirm');
            if (!confirm(message)) {
              return;
            }
          }
          Crossword.undo().focus();
          Drupal.behaviors.crossword.turnOffRebus();
        });
      });

      once('crossword-redo-click', '.button-redo').forEach(function(element){
        $(element).click(function(e){
          e.preventDefault();
          if ($(this).data('confirm')) {
            var message = $(this).data('confirm');
            if (!confirm(message)) {
              return;
            }
          }
          Crossword.redo().focus();
          Drupal.behaviors.crossword.turnOffRebus();
        });
      });

      once('crossword-solution-click', '.button-solution').forEach(function(element){
        $(element).click(function(e){
          e.preventDefault();
          if ($(this).data('confirm')) {
            var message = $(this).data('confirm');
            if (!confirm(message)) {
              return;
            }
          }
          Crossword.reveal();
        });
      });

      once('crossword-clear-click', '.button-clear').forEach(function(element){
        $(element).click(function(e){
          e.preventDefault();
          if ($(this).data('confirm')) {
            var message = $(this).data('confirm');
            if (!confirm(message)) {
              return;
            }
          }
          Crossword.clear();
        });
      });

      // When activating rebus entry, re-focus onto crossword.
      once('crossword-rebus-click', '.rebus-entry').forEach(function(element){
        $(element).click(function(e){
          Crossword.focus();
        });
      });
    },
    addCrosswordEventHandlers: function ($crossword, data) {
      $('.crossword-clue, .crossword-square', $crossword)
        .on('crossword-active', function(){
          $(this).addClass('active');
        })
        .on('crossword-highlight', function(){
          $(this).addClass('highlight');
        })
        .on('crossword-reference', function(){
          $(this).addClass('reference');
        })
        .on('crossword-error', function(){
          $(this).addClass('error');
        })
        .on('crossword-ok', function(){
          $(this).removeClass('error');
        })
        .on('crossword-off', function(){
          $(this)
            .removeClass('active')
            .removeClass('highlight')
            .removeClass('reference')
            .removeClass('focus')
            .find('input').blur();
        })
        .on('crossword-cheat', function(){
          $(this).addClass('cheat');
        });

      $('.crossword-square', $crossword)
        .on('crossword-answer', function(e, answer){
          $(this).find('.square-fill').text(answer.toUpperCase());
          var Crossword = $crossword.data("Crossword");
          Drupal.behaviors.crossword.saveAnswers(Crossword.id, Crossword.getAnswers())
        })
        .on('crossword-rebus', function(){
          $(this).addClass('rebus');
        })
        .on('crossword-not-rebus', function(){
          $(this).removeClass('rebus');
        })
        .on('crossword-focus', function(){
          $(this).addClass('focus');
          $(this).find('input').focus();
        })
        .on('crossword-active', function(){
          // Manage aria-label.
          var Crossword = $crossword.data("Crossword");
          var dir = Crossword.dir;
          var Square = $(this).data("Square");
          if (Square && Square.isFirstLetter(dir)) {
            var Clue = Square[dir];
            var solvedString = Crossword.solved ? "The puzzle has been solved. Well done! " : "";
            var revealedString = Crossword.revealed ? "The puzzle has been revealed. " : "";
            var errorString = Crossword.showingErrors() && Clue.hasError() ? " Contains error." : "";
            $(this).find('input').attr("aria-label", solvedString + revealedString + Clue.getAriaClueText() + ". " + Clue.getAriaCurrentString() + errorString);
          }
          else {
            $(this).find('input').attr("aria-label","");
          }
        });

      $('.crossword-clue', $crossword)
        .on('crossword-clue-complete', function(){
          $(this).addClass('complete');
        })
        .on('crossword-clue-not-complete', function(){
          $(this).removeClass('complete');
        });

      $('.active-clues-text', $crossword)
        .on('crossword-active', function(e, Clue){
          // Try to copy clue html from dom.
          // If no $clue, build html ourselves.
          if (Clue['$clue']) {
            var $clue_copy = $('<div class="active ' + Clue.dir + '">' + Clue['$clue'].html() + '</div>');
            $clue_copy.data("real-clue", Clue['$clue']);
            $clue_copy.click(function(){
              $(this).data("real-clue").trigger("click");
            });
            $(this).html($clue_copy);
          }
          else {
            var $clue = $('<div class="active ' + Clue.dir + '"><span class="numeral">' + Clue.numeral + '</span><span class="text"></span></div>');
            $clue.find('.text').html(Clue.text);
            $(this).html($clue);
          }
          if (Clue.references) {
            for (var i = 0; i < Clue.references.length; i++) {
              if (Clue.references[i]['$clue']) {
                var $reference_copy = $('<div class="reference ' + Clue.references[i].dir + '">' + Clue.references[i]['$clue'].html() + '</div>');
                $reference_copy.data("real-clue", Clue.references[i]['$clue']);
                $reference_copy.click(function () {
                  $(this).data("real-clue").trigger("click");
                });
                $(this).append($reference_copy);
              }
              else {
                var $reference = $('<div class="reference ' + Clue.references[i].dir + '"><span class="numeral">' + Clue.references[i].numeral + '</span><span class="text"></span></div>');
                $reference.find('.text').html(Clue.references[i].text);
                $(this).append($reference);
              }
            }
          }
        })
        .on('crossword-off', function() {
          $(this).html(null);
        });

      $crossword
        .on('crossword-solved', function() {
          $(this).addClass('crossword-solved');
          console.log('The crossword puzzle has been solved.');
        })
        .on('crossword-revealed', function() {
          $(this).addClass('crossword-revealed');
          Drupal.behaviors.crossword.saveRevealed(data.id , 'revealed');
        })
        .on('crossword-clear', function() {
          $(this).removeClass('crossword-solved').removeClass('crossword-revealed');
          Drupal.behaviors.crossword.saveRevealed(data.id , '');
        });
    },
    rebusEntryActive: function(letter) {
      return $('.rebus-entry').prop('checked');
    },
    turnOffRebus: function() {
      $('.rebus-entry').prop('checked', false);
    },
    toggleRebus: function() {
      $('.rebus-entry').prop('checked', !$('.rebus-entry').prop('checked'));
    },
  }
})(jQuery, Drupal, once, drupalSettings);

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc