theodi/open-data-certificate

View on GitHub
app/assets/javascripts/application.js

Summary

Maintainability
B
4 hrs
Test Coverage
//= require jquery
//= require jquery_ujs
//= require twitter/bootstrap
//= require twitter/bootstrap/rails/confirm

//= require hogan
//= require jquery.textchange.min
//= require modernizr.custom.76670
//= require placeholder
//= require polyfill
//= require typeahead
//= require url

//= require admin
//= require surveyor_all
//= require tracking

/* global $, alert, Hogan */

// whether or not the homepage map should be loaded
window.enableMap = document.querySelectorAll && Modernizr.svg;

$(document).ready(function($){
  //////
  // Rails support
  //

  'use strict';

  // Display when an remote form failed
  $(document).on('ajax:error', 'form[data-remote-error-message]', function(){
    var message = $(this).data('remote-error-message'),
        $target = $('.form-errors', this);

    if($target.size()){
      // create a div to show the message in
      $('<div>', {'class':'alert alert-box alert-alert'})
        .append($('<h3>',{text:message}))
        .appendTo($target);
    } else {
      alert(message);
    }

  }).on('ajax:beforeSend.rails', 'form[data-remote-error-message]', function(){
    $('.form-errors', this).empty();
  });

  // Event to close menus when clicking away off them
  var openMenu = false;
  $(document).on('click', function() {
    if (openMenu) {
      openMenu.removeClass('active');
      openMenu.data('target').removeClass('active');
      openMenu = false;
    }
  });

  // Bind related elements for each toggle button
  $('[data-dropdown=toggle]').each(function() {
    var self = $(this);
    self.data('target', $(self.data('target')));
    self.data('parent', $(self.data('parent')));

    // Event to prevent menus being closed when clicked on them
    self.data('target').click(function(e) { e.stopPropagation(); });
  });

  // Trigger dropdown buttons
  $(document).on('click', '[data-dropdown=toggle]', function() {
    var self = $(this);
    var active = !self.data('target').hasClass('active');

    self.data('parent').find('[data-dropdown=toggle]').each(function() {
      var self = $(this);
      self.removeClass('active');
      self.data('target').removeClass('active');
    });

    self.toggleClass('active', active);
    self.data('target').toggleClass('active', active);
    openMenu = active && self;

    return false;
  });

  // Toggles content based on a button
  $('[data-content=toggle]').each(function() {
    var self = $(this);
    self.data('target', self.find(self.data('target')));
    self.data('button', self.find(self.data('button')));

    self.data('button').click(function() {
      self.data('target').animate({opacity: 'toggle'}, 250);
    });
  });

  $('[data-content=highlight]').click(function() {
    this.select();
  });

  // display confirmation of clicking certain buttons
  $(document).on('click', '[data-btn-confirmable]', function(){
    var $this = $(this),
        message = $this.data('btn-confirmable');

    if(message) $this.is('input') ? $this.val(message) : $this.text(message);

    $this.addClass('btn-confirmed disabled');

  });


  //////
  // Questionnaire

  // a map from reference_id to the relevant fieldset (DOM, not $wrapped)
  var reference_id_els = {};
  var $surveyElements = $('[data-reference-identifier]');
  $surveyElements.each(function(){
    reference_id_els[$(this).data('reference-identifier')] = this;
  });

  // The fieldset surrounding an input is the base of a question being 'active', it will
  // - have an 'active' class added
  // - emit 'odc.focus' & 'odc.blur' events (?)
  $surveyElements.on('mouseenter', function(){
    $(this).addClass('active').data('mouseover', true).trigger('_focus');
  }).on('mouseleave', function(){;
    $(this).removeClass('active').data('mouseover', false).trigger('_blur');
  });

  // trigger the highlighting of fieldsets
  $('#surveyor')
    .on('focus', 'fieldset', function(){
      $(this).addClass('active').trigger('_focus');
    })
    .on('blur', 'fieldset', function(){
      if (!$(this).data('mouseover')) {
        $(this).removeClass('active').trigger('_blur');
      }
    });

  // binding the text of this to the value of a
  // particular input, keyed by data-reference-identifier
  // (this is for the the title to show the questionnaire title)
  $('[data-bind-to-input]').each(function(){
    var $bound = $(this),
        original = $bound.text(),
        el = reference_id_els[$bound.data('bind-to-input')];

    $(el).find('input').on('keyup', function(){
      $bound.text($(this).val() || original);
    });
  });


  // elements that have to be shown along with the fieldsets
  $('[data-meta-for]').each(function() {
    var ref_id = $(this).data('meta-for'),
        $el = $(reference_id_els[ref_id]),
        $row = $(this).closest('.question-row'),
        metas = $el.data('metas') || [];

    metas.push(this);
    $el.data('metas', metas);

    if ($el.hasClass('input')) {
      $row.data('input-metas', $row.data('input-metas') || []);
      $row.data('input-metas').push(this);
    }
  });

  var $currentRow = $();

  // Moves highlighting to a row on hover and tab, removes focus from the previous row
  $surveyElements.filter('.question-row').on('_focus', function() {
    if ($currentRow[0] != $(this).closest('.question-row')[0]) {

      $($currentRow.data('metas')).hide();
      $($currentRow.data('input-metas')).hide();

      $currentRow = $(this).closest('.question-row');
    }

    $($(this).data('metas')).show();
    $($currentRow.data('metas')).show();

  });

  // Shows the appropriate information for a radio button or checkbox
  $surveyElements.filter('.input').on('_focus', function() {
    $($currentRow.data('input-metas')).hide();
    $($(this).data('metas')).show();
  });

  // Removes highlighting and information on mouseleave
  $surveyElements.filter('fieldset').on('mouseleave', function(){
    $($currentRow.data('metas')).hide();
    $($currentRow.data('input-metas')).hide();

    $currentRow = $();
  });

  // deal with accordion section changes
  $('.survey-section .collapse').on('show', function(e){
    if (e.target == this) {
      $(this).prev().removeClass('inactive');
    }
  }).on('hidden', function(e){
    if (e.target == this) {
      $(this).prev().addClass('inactive');
    }
  });

  $('.affixed').each(function(){
    var $this = $(this),
        h = $this.height();

    // lock the height and affix the child node
    $this.height(h).children().affix({ offset: $this.position() });

    $('#status_panel').affix({offset:$this.position(), top:10});

  });

  // Old IE only supports :hover on anchors
  $('#status_panel').hover(function(){
    $(this).addClass('hover');
  }, function(){
    $(this).removeClass('hover');
  });

  $('#status_panel').click(function(){
    $(this).toggleClass('stick');
  });

  // Start with status panel in sticky mode, then hide after 10 seconds
  $('#status_panel').toggleClass('stick');
  setTimeout(function() {
    $('#status_panel').removeClass('stick');
  },5000);

  $('.survey-intro .submit').click(function() {
    var button = $(this);
    $(this).addClass('disabled');
    $(this).removeClass('error');
    $(this).popover('show');

    var form = $(this.form);
    var formUrl = new Url(form.attr('action'));
    formUrl.path = formUrl.path + ".json";

    $.ajax({
      type: 'PUT',
      cache: false,
      url: formUrl.toString(),
      data: form.serialize(),
      success: function(data) {
        window.location.replace(data.survey_path)
      },
      error: function(xhr) {
        button.removeClass('disabled')
        button.addClass('error')
        var popover = button.data('popover')
        if (xhr.status == 404) {
          popover.options.content = button.data('content')
          $("#start_url_explanation").attr('style', 'display: block')
        } else {
          popover.options.content = button.data('error')
        }
        popover.show()
        setTimeout(function(){ popover.hide() }, 3000);
      },
      timeout: 120000
    })
    return false;
  });

  // scroll to question / repeated section
  var $question = $(document.location.hash);
  if ($question.length !== 0) {
    // open up survey section
    $question
      .parents('.survey-section')
      .find('ul')
      .on('shown', function () {
        // scroll to the question (taking into account header)
        $('body').scrollTop($question.offset().top - 130);
      })
      .collapse('show');
  }

  // Open sections that contain incomplete mandatory questions
  if ($('#surveyor').hasClass('highlight-mandatory')) {
    $('.survey-section:has(.mandatory.no-response:not(.q_hidden))')
      .find('ul')
      .collapse('show');
  }


  // Questionnaire status panel
  $('#status_panel').on('update', function(){
    var panel = this;

    // progress url set as data attribute
    var url = $(this).data('progress-url');

    $(panel).addClass('loading');

    $.getJSON(url)
    .then(function(data){
      $(panel).removeClass('loading');

      var show_bar = data.attained == 'none'

      var levels = ['basic', 'pilot', 'standard', 'exemplar'];
      $.each(levels, function(idx, level) {
          var bar = $('#bar-' + level);
          if (show_bar) {
            bar.width(data[level] + '%');
            bar.parent('.progress').show();
            show_bar = false;
          } else {
            bar.parent('.progress').hide();
            show_bar = data.attained == level;
          }
      });

      $('#panel_handle')
        // removed any 'attained-' classes
        .toggleClass(function(i, name){return name.indexOf('attained-') === -1})
        .addClass('attained-' + data.attained);
    });
  });


  // when surveyor has displayed/hidden elements
  $(document).on('surveyor-update', function(){
    $('#status_panel').trigger('update');
  });

  // also on load
  $('#status_panel').trigger('update');


  // Placeholders for <= IE9 - https://github.com/mathiasbynens/jquery-placeholder

  // If the browser supports HTML5 placeholder, it won't do anything

  $('input, textarea').placeholder();


  // ## dashboard

  // initialise some of the popover
  $('.popdown').popover({
    placement:'bottom',
    trigger:'hover'
  });


  // search typeahead
  $('.typeahead-search').typeahead([{
      name:'datasets',
      header: '<h3>Datasets</h3>',
      template: '<p class="attained attained-{{attained_index}}">{{value}}</p>',
      engine: Hogan,
      remote: {
        url:'/datasets/typeahead?mode=dataset&q=%QUERY'
      }
    },
    {
      name:'publisher',
      header: '<h3>Publisher</h3>',
      remote: {
        url:'/datasets/typeahead?mode=publisher&q=%QUERY'
      }
    },
    {
      name:'jurisdiction',
      header: '<h3>Jurisdiction</h3>',
      remote: {
        url:'/datasets/typeahead?mode=country&q=%QUERY'
      }
    }
  ])
  .on('typeahead:selected typeahead:autocompleted', function(e, datum){
    if(datum.path){ document.location = datum.path; }
  });

  // toggle advanced search
  $('form .advanced-search button[name=advanced-search]').on('click', function(e) {
    $(this).siblings('.options').toggleClass('hidden');
    $(this).blur();
  });

  // Stop the jump to the top of the page when the delete dialog is confirmed.
  // placeholder till bluerail/twitter-bootstrap-rails-confirm#9 gets published
  $(document).on('click', "#confirmation_dialog [href='#']", function(e){
    e.preventDefault();
  })

  .on('click', '.dataset .show-more, .dataset .hide-more', function(){
    $(this).parents('.dataset').toggleClass('expanded', $(this).hasClass('show-more'));
  })

  .on('click', '.join-discussion a', function(e){
    e.preventDefault();
    var top = $('.juvia-add-comment-form').prev().offset().top;
    $('body').animate({scrollTop:top})
  });

  var certificateBody = $('.certificate-data, #surveyor');

  certificateBody.click(function() {
    certificateBody.find('.odc-popover').popover('hide');
  });

  certificateBody.find('.odc-popover').each(function() {
    var self = $(this);
    self.popover({
      trigger: 'manual',
      html: true,
      content: function() {
        // pull out the content from the child element (hidden with css)
        $(this).data('visible', true);
        return $('.odc-popover-content', this).html();
      },
      template: '<div class="popover popover-light"><div class="arrow"></div>'+
                '<h3 class="popover-title"></h3><div class="popover-content"></div></div>'
    });
  });

  certificateBody.on('click', '.odc-popover', function() {
    certificateBody.find('.odc-popover').not(this).popover('hide');
    $(this).popover('toggle');
    return false;
  });

  certificateBody
    .on('mouseover', '.answer', function(){$(this).toggleClass('odc-popover-active', true)})
    .on('mouseout',  '.answer', function(){$(this).toggleClass('odc-popover-active', false)});

  // Replace select boxes visually
  $('#surveyor select').each(function() {
    var self = $(this);

    var selectBox = $('<div class="select-box">');
    self.wrap($('<div class="select-wrapper">')).before(selectBox);
    selectBox.text(self.find(':selected').text());

    self.change(function(e) {
        selectBox.text(self.find(':selected').text());
    });
  });

  $('.claim .approval [data-type=json]').on('ajax:success', function(evt, data, status, xhr) {
    var buttons = $(this).parents('.approval').find('input[type=submit]');
    var button = $(this).find('input[type=submit]');
    var label = button.data('disabled-text');
    window.setTimeout(function() {
        button.val(data.message);
        buttons.prop('disabled', true);
    }, 0);
  });

  Tracking.init();
});