openModal: function()

in kitsune/sumo/static/sumo/js/markup.js [726:1010]


  openModal: function(e) {
    var me = this,
      $editor = $(me.textarea).closest('.editor'),
    // TODO: look at using a js template solution (jquery-tmpl?)
      $html = $(
          '<section class="marky">' +
          '<div class="search simple-search-form">' +
          '<input type="text" name="q" id="filter-responses-field" placeholder="' +
          gettext('Search for common responses') + '" class="searchbox"/>' +
          '</div></div>' +
          '<div class="area">' +
          '<div id="responses-area">' +
          '<h2 class="heading-label">' + gettext('Categories') + '</h2>' +
          '<ul class="category-list">' +
          '<li class="status-indicator busy">' + gettext('Loading...') + '</li>' +
          '</ul></div>' +
          '<div id="response-list-area">' +
          '<h2 class="heading-label">' + gettext('Responses') + '</h2>' +
          '<h4 class="nocat-label">' + gettext('Please select a category from the previous column or start a search.') + '</h4>' +
          '<p class="response-list"/>' +
          '</div>' +
          '<div id="response-content-area">' +
          '<h2 class="heading-label preview-label">' + gettext('Response editor') + '</h2>' +
          '<div class="sumo-button-wrap">' +
          '<button class="toggle-view sumo-button">' + gettext('Switch to preview mode') + '</button>' +
          '</div>' +
          '<div class="field has-md-textarea response-preview is-condensed">' +
          '<textarea id="response-content">' +
          '</textarea></div>' +
          '<p class="response-preview-rendered"></p>' +
          '</div>' +
          '</div>' +
          '</div>' +
          '<div class="placeholder" /><div class="submit sumo-button-wrap" id="response-submit-area">' +
          '<button id="insert-response" class="sumo-button primary-button">' + gettext('Insert Response') + '</button>' +
          '<a href="#cancel" class="sumo-button secondary-button kbox-cancel">' + gettext('Cancel') + '</a>' +
          '</div>' +
          '</section>'
      ),
      selectedText = me.getSelectedText(),
      kbox;

    var cannedResponsesUrl = '/kb/common-forum-responses';
    var previewUrl = 'answer-preview-async';

    function updatePreview() {
      var response = $('#response-content').val();
      var token = $('[name=csrfmiddlewaretoken]').attr('value');

      toggleThrobber(true);

      $.ajax({
        type: 'POST',
        url: previewUrl,
        data: {
          content: response,
          csrfmiddlewaretoken: token
        },
        dataType: 'html',
        success: function(html) {
          var $container = $('.response-preview-rendered');
          var $response_preview = $(html).find('.main-content');
          $container.html($response_preview);
        },
        complete: function() {
          toggleThrobber(false);
        }
      });
    }

    function getContent(articleUrl) {
      // If the article doesn't exist, it has /new in its URL
      // Don't query nonexisting articles
      if (!articleUrl || articleUrl.indexOf('/new') !== -1) {
        return;
      }

      toggleThrobber(true);

      $.ajax({
        url: articleUrl + '/edit',
        dataType: 'html',
        success: function(data, status) {
          var article_src = $('#id_content', data).val();
          var $textbox = $('#response-content');
          $textbox.val(article_src);
          $textbox.data('slug', articleUrl);
          updatePreview();
        },
        complete: function() {
          toggleThrobber(false);
        }
      });
    }

    function toggleThrobber(busy) {
      var $label = $('.preview-label');
      if (busy) {
        $label.addClass('busy');
      } else {
        $label.removeClass('busy');
      }
    }

    function isAllowedToUseResponse(response_target) {
      if (response_target.indexOf('#') === -1) {
        // No permission markers: Everyone's allowed
        return true;
      }

      var articleUrl = response_target.split('#')[0];
      var permBits = response_target.split('#')[1];
      response_target = articleUrl;

      for (var i = 0; i < permBits.length; i++) {
        var bit = permBits[i];
        if (me.permissionBits.indexOf(bit) !== -1) {
          return true;
        }
      }
      return false;
    }

    function insertResponse() {
      var sourceContent = $('#response-content').val();
      var slug = $('#response-content').data('slug');
      var $responseTextbox = $('#id_content');
      var targetContent = $responseTextbox.val();

      trackEvent('common_forum_response_insert', {slug});

      $responseTextbox.val(targetContent + sourceContent);
    }

    function searchResponses(term) {
      term = term.toLowerCase().trim();
      var $searchHeading = $html.find('#response-list-area .heading-label');
      var $noCategorySelected = $html.find('.nocat-label');
      var $responseLists = $html.find('.response-list ul');
      var $responses = $html.find('.response');
      var $responseListArea = $html.find('#response-list-area');
      var $responsesArea = $html.find('#responses-area');

      if (term === '') {
        $searchHeading.text(gettext('Responses'));
        $responseListArea.removeClass('filtered');
        $responsesArea.removeClass('filtered');
        $noCategorySelected.show();
        $responses.show();
        $responseLists.hide();
        return;
      }

      $responseListArea.addClass('filtered');
      $responsesArea.addClass('filtered');
      $searchHeading.text(gettext('Matching responses'));
      $noCategorySelected.hide();
      $responseLists.show();

      $responses.each(function() {
        var text = $(this).text().toLowerCase();
        if (text.indexOf(term) === -1) {
          $(this).hide();
        } else {
          $(this).show();
        }
      });
    }

    function loadCannedResponses() {
      var siteLanguage = window.location.pathname.split('/')[1];
      var targetUrl = '/' + siteLanguage + cannedResponsesUrl;

      $.ajax({
        url: targetUrl,
        type: 'GET',
        dataType: 'html',
        success: function(html) {
          var $categoryList = $('.category-list'),
            $responsesList = $('.response-list'),
            $categories = $(html).find('[id^=w_]');

          $categoryList.empty();
          $responsesList.empty();

          $categories.each(function() {
            var label = $(this).text(),
              $headingItem = $(document.createElement('li')),
              $responses = $(document.createElement('ul')).addClass('sidebar-nav').hide(),
              $catResponses = $(this).nextUntil('[id^=w_]').find('a'),
              $noCatLabel = $html.find('.nocat-label'),
              $otherResponses,
              $otherHeadings;

            $catResponses.each(function() {
              var $response = $(document.createElement('li')).addClass('response').text($(this).text());
              var response_target = $(this).attr('href');
              var canUseResponse = isAllowedToUseResponse(response_target);
              response_target = response_target.split('#')[0];

              if (canUseResponse) {
                $response.on("click", function() {
                  $('.response-list li').not($(this)).removeClass('selected');
                  $(this).addClass('selected');
                  getContent(response_target);
                });

                $responses.append($response);
              }
            });

            $headingItem.addClass('response-heading').text(label)
              .on('click', function() {
                $noCatLabel.hide();
                $otherResponses = $responsesList.find('ul').not($responses);
                $otherResponses.hide();

                $otherHeadings = $categoryList.find('.response-heading').not($headingItem);
                $otherHeadings.removeClass('selected');

                $(this).addClass('selected');
                $responses.show();
              });

            $categoryList.append($headingItem);
            $responsesList.append($responses);
          });
        },
        error: function() {
          var statusIndicator = $('.status-indicator');
          statusIndicator.removeClass('busy');
          statusIndicator.text(gettext('There was an error checking for canned responses.'));
        }
      });

      // return true so that the kbox actually opens:
      return true;
    }

    kbox = new KBox($html, {
      title: this.name,
      destroy: true,
      modal: true,
      id: 'media-modal',
      container: $('body'),
      position: 'none',
      preOpen: loadCannedResponses
    });

    kbox.open();

    $html.find('#insert-response').on("click", function() {
      insertResponse();
      kbox.close();
    });

    $html.find('#filter-responses-field').on('keyup', function() {
      var term = $(this).val();
      searchResponses(term);
    });

    var $previewLabel = $html.find('.preview-label');
    var $contentArea = $html.find('.response-preview');
    var $renderedPreview = $html.find('.response-preview-rendered');

    $html.find('.toggle-view').on("click", function() {
      if ($contentArea.is(':visible')) {
        updatePreview();
        $previewLabel.text(gettext('Response preview'));
        $(this).text(gettext('Switch to edit mode'));

        $contentArea.hide();
        $renderedPreview.show();
      } else {
        $previewLabel.text(gettext('Response editor'));
        $(this).text(gettext('Switch to preview mode'));

        $contentArea.show();
        $renderedPreview.hide();
      }
    });

    e.preventDefault();
    return false;
  },