<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require bootstrap.min
// require turbolinks
//= require lodash.min
//= require_tree .

(function(){
  'use strict';
  window.onload = function() {
    var BigEarth = {
      init: function(){
        $('.btc, .usd').click(function(evt){
          if($(evt.currentTarget).hasClass('btc')) {
            $('.btc').addClass('hide')
            $('.usd').removeClass('hide')
          } else if($(evt.currentTarget).hasClass('usd')) {
            $('.usd').addClass('hide')
            $('.btc').removeClass('hide')
          }
        });
      }
    };

    var BookmarkBtn = {
      init: function(){
        var bookmarks = JSON.parse(localStorage.getItem('bookmarks'));
        var bookmark = _.find(bookmarks, function(bookmark) {
          return bookmark.path === window.location.pathname;
        });

        if(bookmark) {
          $('.bookmark').text('Bookmarked').attr('href', '/apps/bookmarks');
        }

        $('.bookmark').click(function(evt) {
          if($(evt.currentTarget).text() != 'Bookmarked') {
            BookmarkBtn.set_bookmark(evt);
            evt.preventDefault();
          }
        });

        $('.clear_all_bookmarks').click(function(evt) {
          BookmarkBtn.clear_all_bookmarks();
          evt.preventDefault();
        });
      },
      set_bookmark: function(evt) {
        var bookmarks = localStorage.getItem('bookmarks');
        if(bookmarks === null) {
          bookmarks = [];
        } else {
          bookmarks = JSON.parse(bookmarks);
        }
        var bookmark = _.find(bookmarks, function(bookmark) {
          return bookmark.path === window.location.pathname;
        });
        if(_.isUndefined(bookmark)) {
          bookmarks.push({
            path: window.location.pathname,
            created_at: Date.now(),
            id: $(evt.currentTarget).data('page_id'),
            bookmark_type: $(evt.currentTarget).data('bookmark_type')
          });
          $('.bookmark').text('Bookmarked').attr('href', '/apps/bookmarks');
        }
        localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
      },
      clear_all_bookmarks: function(){
        localStorage.removeItem('bookmarks');
        $('#block_bookmarks ul, #transaction_bookmarks ul, #address_bookmarks ul').hide()
        $('#block_bookmarks li, #transaction_bookmarks li, #address_bookmarks li').remove()
        $('#block_bookmarks p, #transaction_bookmarks p, #address_bookmarks p').show()
        Bookmarks.hide_sum();
      }
    };
    var Bookmarks = {
      init: function() {
        var bookmarks = JSON.parse(localStorage.getItem('bookmarks'));
        var block_bookmarks = _.filter(bookmarks, function(bookmark) {
          return bookmark.bookmark_type === 'block';
        });
        var transaction_bookmarks = _.filter(bookmarks, function(bookmark) {
          return bookmark.bookmark_type === 'transaction';
        });
        var address_bookmarks = _.filter(bookmarks, function(bookmark) {
          return bookmark.bookmark_type === 'address';
        });

        if(!_.isEmpty(block_bookmarks)) {
          this.build_bookmarks(block_bookmarks);
        }

        if(!_.isEmpty(transaction_bookmarks)) {
          this.build_bookmarks(transaction_bookmarks);
        }

        if(!_.isEmpty(address_bookmarks)) {
          this.build_bookmarks(address_bookmarks);
        }
        $('.delete_bookmark').click(function(evt) {
          Bookmarks.delete_bookmark(evt);
        });
      },
      build_bookmarks: function(bookmarks) {
        if(!_.isEmpty(bookmarks)) {
          $('#' + bookmarks[0].bookmark_type + '_bookmarks p').hide()
          $('#' + bookmarks[0].bookmark_type + '_bookmarks ul').removeClass('hide');
          _.each(bookmarks, function(bookmark, index) {
            $('#' + bookmark.bookmark_type + '_bookmarks ul').append($('
' + _.truncate(bookmark.id, {length: 45}) + 'Delete
'))
            if(bookmark.bookmark_type === 'address') {
              var $sum_footer = $('#sum_btc').closest('.panel-footer');
              if($sum_footer.is(':hidden')) {
                $sum_footer.removeClass('hide');
              }
              Bookmarks.fetch_address(bookmark.id);
            }
          });
        }
      },
      delete_bookmark: function(evt){
        var bkmks = JSON.parse(localStorage.getItem('bookmarks'));
        var balance = $($($(evt.currentTarget)[0]).find('span')[0]).data('balance');
        var address = $($($(evt.currentTarget)[0]).find('span')[0]).data('id');
        var new_bkmks = _.reject(bkmks, function(bk) {
          return bk.path == $(evt.currentTarget).parents('.list-group-item').find('.bookmark_path').attr('href');
        });
        var parent_ul = $(evt.currentTarget).closest('.list-group');
        $(evt.currentTarget).parents('.list-group-item').remove();
        if(!$(parent_ul).children('li').length) {
          $(parent_ul).closest('.panel-body').find('ul').hide().end().find('p').show();
        }

        if(!_.isUndefined(balance)) {
          Bookmarks.calculate_address_total({
            balance: balance,
            address: address
          }, 'subtract');
        }
        localStorage.setItem('bookmarks', JSON.stringify(new_bkmks));
        evt.preventDefault();

      },
      fetch_address: function(address){
        $.getJSON('/addresses/' + address + '.json', function(data) {
          Bookmarks.calculate_address_total(data.data, 'add');
        });
      },
      calculate_address_total: function(data, operation_type) {
        var new_balance = parseFloat(data.balance);
        $($('[data-id="' + data.address + '"]')[0]).attr('data-balance', new_balance.toFixed(8));
        var $sum = $('#sum_btc'),
            $sum_usd = $('#sum_usd'),
            $sum_footer = $sum.closest('.panel-footer'),
            $sum_li = $sum.closest('.panel').find('.panel-body li');
        var existing_total = parseFloat($sum.text());
        var new_total;
        if(operation_type === 'add') {
          new_total = existing_total + new_balance;
        } else if (operation_type === 'subtract') {
          new_total = existing_total - new_balance;
        }
        var usd_exchange_rate = $('body').data('value');
        var new_usd = _.round(new_total * usd_exchange_rate, 2);
        $sum.text(new_total.toFixed(8) + ' BTC').attr('title', '$' + new_usd.toLocaleString());
        $sum_usd.text('$' + new_usd.toLocaleString()).attr('title', new_total + ' BTC');
        $($sum.closest('.pull-right')[0]).attr('title', new_total.toLocaleString());
        if(!$sum_li.length && $sum_footer.is(':visible')) {
          Bookmarks.hide_sum();
        }
      },
      hide_sum: function($sum) {
          $('#address_bookmarks .panel-footer').hide();
      }
    };
    var Utility = {
      number_with_commas: function(x) {
        return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
      }
    };
    BigEarth.init();
    BookmarkBtn.init();
    if($('#block_bookmarks').length) {
      Bookmarks.init();
    }
  };
}());
<commit_msg>Formatting balances.<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require bootstrap.min
// require turbolinks
//= require lodash.min
//= require_tree .

(function(){
  'use strict';
  window.onload = function() {
    var BigEarth = {
      init: function(){
        $('.btc, .usd').click(function(evt){
          if($(evt.currentTarget).hasClass('btc')) {
            $('.btc').addClass('hide')
            $('.usd').removeClass('hide')
          } else if($(evt.currentTarget).hasClass('usd')) {
            $('.usd').addClass('hide')
            $('.btc').removeClass('hide')
          }
        });
      }
    };

    var BookmarkBtn = {
      init: function(){
        var bookmarks = JSON.parse(localStorage.getItem('bookmarks'));
        var bookmark = _.find(bookmarks, function(bookmark) {
          return bookmark.path === window.location.pathname;
        });

        if(bookmark) {
          $('.bookmark').text('Bookmarked').attr('href', '/apps/bookmarks');
        }

        $('.bookmark').click(function(evt) {
          if($(evt.currentTarget).text() != 'Bookmarked') {
            BookmarkBtn.set_bookmark(evt);
            evt.preventDefault();
          }
        });

        $('.clear_all_bookmarks').click(function(evt) {
          BookmarkBtn.clear_all_bookmarks();
          evt.preventDefault();
        });
      },
      set_bookmark: function(evt) {
        var bookmarks = localStorage.getItem('bookmarks');
        if(bookmarks === null) {
          bookmarks = [];
        } else {
          bookmarks = JSON.parse(bookmarks);
        }
        var bookmark = _.find(bookmarks, function(bookmark) {
          return bookmark.path === window.location.pathname;
        });
        if(_.isUndefined(bookmark)) {
          bookmarks.push({
            path: window.location.pathname,
            created_at: Date.now(),
            id: $(evt.currentTarget).data('page_id'),
            bookmark_type: $(evt.currentTarget).data('bookmark_type')
          });
          $('.bookmark').text('Bookmarked').attr('href', '/apps/bookmarks');
        }
        localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
      },
      clear_all_bookmarks: function(){
        localStorage.removeItem('bookmarks');
        $('#block_bookmarks ul, #transaction_bookmarks ul, #address_bookmarks ul').hide()
        $('#block_bookmarks li, #transaction_bookmarks li, #address_bookmarks li').remove()
        $('#block_bookmarks p, #transaction_bookmarks p, #address_bookmarks p').show()
        Bookmarks.hide_sum();
      }
    };
    var Bookmarks = {
      init: function() {
        var bookmarks = JSON.parse(localStorage.getItem('bookmarks'));
        var block_bookmarks = _.filter(bookmarks, function(bookmark) {
          return bookmark.bookmark_type === 'block';
        });
        var transaction_bookmarks = _.filter(bookmarks, function(bookmark) {
          return bookmark.bookmark_type === 'transaction';
        });
        var address_bookmarks = _.filter(bookmarks, function(bookmark) {
          return bookmark.bookmark_type === 'address';
        });

        if(!_.isEmpty(block_bookmarks)) {
          this.build_bookmarks(block_bookmarks);
        }

        if(!_.isEmpty(transaction_bookmarks)) {
          this.build_bookmarks(transaction_bookmarks);
        }

        if(!_.isEmpty(address_bookmarks)) {
          this.build_bookmarks(address_bookmarks);
        }
        $('.delete_bookmark').click(function(evt) {
          Bookmarks.delete_bookmark(evt);
        });
      },
      build_bookmarks: function(bookmarks) {
        if(!_.isEmpty(bookmarks)) {
          $('#' + bookmarks[0].bookmark_type + '_bookmarks p').hide()
          $('#' + bookmarks[0].bookmark_type + '_bookmarks ul').removeClass('hide');
          _.each(bookmarks, function(bookmark, index) {
            $('#' + bookmark.bookmark_type + '_bookmarks ul').append($('
' +
            '' + _.truncate(bookmark.id, {length: 45}) + '' +
            'balance' +
            '' +
              'Delete' +
            '
'))
            if(bookmark.bookmark_type === 'address') {
              var $sum_footer = $('#sum_btc').closest('.panel-footer');
              if($sum_footer.is(':hidden')) {
                $sum_footer.removeClass('hide');
              }
              Bookmarks.fetch_address(bookmark.id);
            }
          });
        }
      },
      delete_bookmark: function(evt){
        var bkmks = JSON.parse(localStorage.getItem('bookmarks'));
        var balance = $($($(evt.currentTarget)[0]).find('span')[0]).data('balance');
        var address = $($($(evt.currentTarget)[0]).find('span')[0]).data('id');
        var new_bkmks = _.reject(bkmks, function(bk) {
          return bk.path == $(evt.currentTarget).parents('.list-group-item').find('.bookmark_path').attr('href');
        });
        var parent_ul = $(evt.currentTarget).closest('.list-group');
        $(evt.currentTarget).parents('.list-group-item').remove();
        if(!$(parent_ul).children('li').length) {
          $(parent_ul).closest('.panel-body').find('ul').hide().end().find('p').show();
        }

        if(!_.isUndefined(balance)) {
          Bookmarks.calculate_address_total({
            balance: balance,
            address: address
          }, 'subtract');
        }
        // localStorage.setItem('bookmarks', JSON.stringify(new_bkmks));
        evt.preventDefault();

      },
      fetch_address: function(address){
        $.getJSON('/addresses/' + address + '.json', function(data) {
          Bookmarks.calculate_address_total(data.data, 'add');
        });
      },
      calculate_address_total: function(data, operation_type) {
        var new_balance = parseFloat(data.balance);
        $($('[data-id="' + data.address + '"]')[0]).attr('data-balance', new_balance.toFixed(8));
        var $sum = $('#sum_btc'),
            $sum_usd = $('#sum_usd'),
            $sum_footer = $sum.closest('.panel-footer'),
            $sum_li = $sum.closest('.panel').find('.panel-body li');
        var existing_total = parseFloat(_.trimEnd($sum.text(), ' BTC'));
        var new_total;
        if(operation_type === 'add') {
          new_total = existing_total + new_balance;
        } else if (operation_type === 'subtract') {
          new_total = existing_total - new_balance;
        }
        var usd_exchange_rate = $('body').data('value');
        var new_usd = _.round(new_total * usd_exchange_rate, 2);
        var split_btc = new_total.toFixed(8).toString().split('.');
        split_btc[0] = Utility.number_with_commas(split_btc[0]);
        var formatted_btc = split_btc.join('.');
        $sum.text(formatted_btc + ' BTC').attr('title', '$' + new_usd.toLocaleString());
        $sum_usd.text('$' + new_usd.toLocaleString()).attr('title', formatted_btc + ' BTC');
        $($sum.closest('.pull-right')[0]).attr('title', new_total.toLocaleString());
        if(!$sum_li.length && $sum_footer.is(':visible')) {
          Bookmarks.hide_sum();
        }
      },
      hide_sum: function($sum) {
          $('#address_bookmarks .panel-footer').hide();
      }
    };
    var Utility = {
      number_with_commas: function(x) {
        return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
      }
    };
    BigEarth.init();
    BookmarkBtn.init();
    if($('#block_bookmarks').length) {
      Bookmarks.init();
    }
  };
}());
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//

//= require jquery
//= require foundation
//= require jquery_ujs
//= require underscore
//= require backbone
//= require lessonoverflow
//= require_tree ../templates
//= require_tree ./models
//= require_tree ./collections
//= require_tree ./views
//= require_tree ./routers
//= require_tree .
<commit_msg>reorders js<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//

//= require jquery
//= require jquery_ujs
//= require foundation
//= require underscore
//= require backbone
//= require lessonoverflow
//= require_tree ../templates
//= require_tree ./models
//= require_tree ./collections
//= require_tree ./views
//= require_tree ./routers
//= require_tree .
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require jquery-fileupload/basicplus
//= require underscore
//= require bootstrap
//= require ckeditor-jquery
//= require ckeditor/plugins/sharedspace/sharedspace
//= require scrollToFixed
//= require chosen-jquery
//= require jquery.dotdotdot
//= require jquery.timeago
//= require ./polyfills
//= require react
//= require react-chosen
//= require spin
//= require namespace
//= require handlebars
//= require ember
//= require ember-data
//= require_self
//= require e_tahi
//= require_tree .

(function(context) {
  var development = true;

  context.ETahi = Ember.Application.create({
    rootElement: '#ember-app',

    // Ember
    LOG_STACKTRACE_ON_DEPRECATION  : development,
    LOG_BINDINGS                   : development,
    LOG_TRANSITIONS                : development,
    LOG_TRANSITIONS_INTERNAL       : false,
    LOG_VIEW_LOOKUPS               : false,
    LOG_ACTIVE_GENERATION          : false,
    // Tahi
    LOG_RSVP_ERRORS                : development,
    LOG_VIEW_RENDERING_PERFORMANCE : development
  });

  ETahi.ApplicationAdapter = DS.ActiveModelAdapter.extend({
    ajaxError: function(jqXHR) {
      var error = this._super(jqXHR);
      if (jqXHR && jqXHR.status === 401) {
        window.location.href = 'http://' + window.location.host
      }
      return error;
    }
  });
})(window);
<commit_msg>Redirect to /users/sign_in on ajax 401<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require jquery-fileupload/basicplus
//= require underscore
//= require bootstrap
//= require ckeditor-jquery
//= require ckeditor/plugins/sharedspace/sharedspace
//= require scrollToFixed
//= require chosen-jquery
//= require jquery.dotdotdot
//= require jquery.timeago
//= require ./polyfills
//= require react
//= require react-chosen
//= require spin
//= require namespace
//= require handlebars
//= require ember
//= require ember-data
//= require_self
//= require e_tahi
//= require_tree .

(function(context) {
  var development = true;

  context.ETahi = Ember.Application.create({
    rootElement: '#ember-app',

    // Ember
    LOG_STACKTRACE_ON_DEPRECATION  : development,
    LOG_BINDINGS                   : development,
    LOG_TRANSITIONS                : development,
    LOG_TRANSITIONS_INTERNAL       : false,
    LOG_VIEW_LOOKUPS               : false,
    LOG_ACTIVE_GENERATION          : false,
    // Tahi
    LOG_RSVP_ERRORS                : development,
    LOG_VIEW_RENDERING_PERFORMANCE : development
  });

  ETahi.ApplicationAdapter = DS.ActiveModelAdapter.extend({
    ajaxError: function(jqXHR) {
      var error = this._super(jqXHR);
      if (jqXHR && jqXHR.status === 401) {
        window.location.href = '/users/sign_in'
      }
      return error;
    }
  });

  $(document).ajaxError(function(event, jqXHR, ajaxSettings, thrownError) {
    if (jqXHR.status === 401) {
      document.location.href = '/users/sign_in';
    }
  });
})(window);
<|endoftext|>


<commit_before>//= require jquery2
//= require jquery_ujs
//= require jquery.ui.datepicker
//= require chosen-jquery
//= require leaflet
//= require forms

/* Dynamically filter the forms that are shown for the actors and actions pages
 */
var filterForms = function() {
  var forms = document.querySelectorAll('#form-actor, #form-action');
  var level = document.querySelector('#actor_type, #act_type, #actor_micro_type');

  /* If the page doesn't have the necessary filter, we exit the function */
  if(!level) { return; }

  /* When level has a new value, we update the list of visible forms */
  level.addEventListener('change', function(e) {
    var value = e.currentTarget.value.toLowerCase();
    value = value.replace('actor', '').replace('act', '');

    /* We first add the _hidden class to all the elements */
    for(var i = 0, j = forms.length; i < j; i++) {
      forms[i].classList.add('_hidden');
    }

    if(value.length > 0) {
      /* Then the forms which are targeted by the filter loose it */
      var filteredForms = [].filter.call(forms, function(form) {
        return form.classList.contains(value);
      });

      for(var i = 0, j = filteredForms.length; i < j; i++) {
        filteredForms[i].classList.remove('_hidden');
      }
    }
  });
};

var showDatepicker = function() {
  var dateFields = document.querySelectorAll('.js-datepicker');
  var minDate, startDate;
  for(var i = 0, j = dateFields.length; i < j; i++) {
    minDate = new Date(dateFields[i].getAttribute('data-min-date').split('-'));
    maxDate = new Date(dateFields[i].getAttribute('data-max-date').split('-'));
    if(dateFields[i].value.length > 0) {
      /* We remove the time from the value */
      dateFields[i].value = dateFields[i].value.split(' ')[0];
    }
    $(dateFields[i]).datepicker({
      minDate: minDate,
      maxDate: maxDate,
      dateFormat: 'yy-mm-dd',
      yearRange: dateFields[i].getAttribute('data-min-date').split('-')[0] + ':' +
        dateFields[i].getAttribute('data-max-date').split('-')[0],
      changeMonth: true,
      changeYear: true
    });
  }
};

var showMultiselect = function() {
  var multiselects = $('.js-mselect');

  for(var i = 0; i < multiselects.length; i++) {
    multiselects[i].classList.add('chosen');
    multiselects[i].classList.add('chosen-select');
  }

  multiselects.chosen();
};

/* Display a mini map into the container and return it */
var createPreviewMap = function(container) {
  /* We show the map */
  var layer = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
    attribution: '© OpenStreetMap contributors, © CartoDB'
  });

  var southWest = L.latLng(-85, -720.0),
      northEast = L.latLng(85, 720.0),
      bounds = L.latLngBounds(southWest, northEast);

  var map = L.map(container, {
    center: [16.77, -23.70],
    zoom: 1,
    minZoom: 1,
    maxBounds: bounds
  });

  map.addLayer(layer);
  return map;
};

/* Add a marker to a map at the given coordinates and return it */
var dropMarkerOn = function(map, lat, lng) {
  var marker = L.marker(L.latLng(lat, lng));
  marker.addTo(map);
  return marker;
};

/* Remove a given marker from the map passed as argument */
var removeMarkerFrom = function(map, marker) {
  map.removeLayer(marker);
};

/* Return the address associated to coordinates with the Nominatim service. It
 * uses the promise architecture to execute code when the information is
 * available. */
var retrieveAddressFrom = function(lat, lng) {
  var deferred = $.Deferred();

  var ajax = $.ajax({
    url: 'http://nominatim.openstreetmap.org/reverse',
    data: {
      format: 'json',
      lat: lat,
      lon: lng
    }
  });

  ajax.done(function(data) {
    var res = data.address || {};
    res.lat = lat;
    res.lng = lng;
    deferred.resolve(res);
  }).fail(function() {
      console.warn('Unable to retrieve the address from the Nominatim service');
    });

  return deferred.promise();
};

/* Initialize a mini map into the container and connects the inputs to the map
 * so when the user clicks on it, the fields are autocompleted and when the
 * fields are modified, the map displays a marker */
var initPreviewMap = function(container) {
  var map = createPreviewMap(container.querySelector('.map-preview'));

  /* Cache for the form fields related to a location */
  var latField     = container.querySelector('.localization_lat');
  var lngField     = container.querySelector('.localization_long');
  var cityField    = container.querySelector('.localization_city');
  var countryField = container.querySelector('.localization_country');
  var zipcodeField = container.querySelector('.localization_zip_code');

  /* Method to fill the inputs with the address contained in the param */
  var autocompleteInputs = function(address, options) {
    /* If true, force means that all the inputs should have their value updated,
     * otherwise just the ones that are blank */
    var force = options && options.force;

    latField.value     = force || latField.value.length === 0 ?
      address.lat : latField.value;
    lngField.value     = force || lngField.value.length === 0 ?
      address.lng : lngField.value;
    cityField.value    = force || cityField.value.length === 0 ?
      address.city || address.town || address.village || '' : cityField.value;
    zipcodeField.value = force || zipcodeField.value.length === 0 ?
      address.postcode || '' : zipcodeField.value;

    if(address.country_code) {
      countryField.options[countryField.selectedIndex].selected = false;
      countryField.querySelector('option[value="' +
        address.country_code.toUpperCase() + '"]').selected = true;
    }
  };

  /* If the form already stores coordinates, we add the marker on the map */
  var marker; /* The current marker on the map */
  if(latField.value.length > 0 && lngField.value.length > 0) {
    marker = dropMarkerOn(map, latField.value, lngField.value);
  }

  /* We watch the inputs changes and map clicks only if the user is able to
   * modify the form (ie if it's not disabled) */
  if(!container.classList.contains('disabled')) {

    /* When the user click on the map, we display a marker and updates the inputs
     * accordingly */
    map.on('click', function(e) {
      var lat = e.latlng.lat,
          lng = e.latlng.lng;
      if(marker) { removeMarkerFrom(map, marker); }
      marker = dropMarkerOn(map, lat, lng);
      retrieveAddressFrom(lat, lng).done(function(address) {
        autocompleteInputs(address, { force: true });
      });
    });

    /* When the user fills the inputs, we try to autocomplete the others */
    var inputsListener = function() {
      if(latField.value.length === 0 || lngField.value.length === 0) {
        return;
      }
      retrieveAddressFrom(latField.value,
        lngField.value).done(autocompleteInputs);
      /* We add a marker to the location */
      if(marker) { removeMarkerFrom(map, marker); }
      marker = dropMarkerOn(map, latField.value, lngField.value);
    };
    $(latField).on('change', inputsListener);
    $(lngField).on('change', inputsListener);
  }
};

/* Polyfill for Element.matches
 * Source: https://developer.mozilla.org/en/docs/Web/API/Element/matches */
var matches = function(elm, selector) {
    var matches = (elm.document || elm.ownerDocument).querySelectorAll(selector),
        i = matches.length;
    while (--i >= 0 && matches.item(i) !== elm) ;
    return i > -1;
};

/* Return the closest parent to an element that matches the selector */
var getClosestParent = function(element, selector) {
  var res = null;
  var currentElement = element;
  while(currentElement !== document) {
    currentElement = currentElement.parentNode;
    if(currentElement.matches && currentElement.matches(selector) ||
      !currentElement.matches && matches(currentElement, selector)) {
      res = currentElement;
      break;
    }
  }
  return res;
};

function onReady() {
  filterForms();
  showMultiselect();
  showDatepicker();
  /* Initialize the mini maps attached to the location forms */
  var previewMaps = document.querySelectorAll('.map-preview');
  var form;
  for(var i = 0, j = previewMaps.length; i < j; i++) {
    form = getClosestParent(previewMaps[i], '.form-inputs');
    if(form) {
      initPreviewMap(getClosestParent(previewMaps[i], '.form-inputs'));
    }
  }
}

document.addEventListener('DOMContentLoaded', onReady);
<commit_msg>adds foundation javascript<commit_after>//= require jquery2
//= require jquery_ujs
//= require jquery.ui.datepicker
//= require chosen-jquery
//= require leaflet
//= require forms
//= require foundation

/* Dynamically filter the forms that are shown for the actors and actions pages
 */
var filterForms = function() {
  var forms = document.querySelectorAll('#form-actor, #form-action');
  var level = document.querySelector('#actor_type, #act_type, #actor_micro_type');

  /* If the page doesn't have the necessary filter, we exit the function */
  if(!level) { return; }

  /* When level has a new value, we update the list of visible forms */
  level.addEventListener('change', function(e) {
    var value = e.currentTarget.value.toLowerCase();
    value = value.replace('actor', '').replace('act', '');

    /* We first add the _hidden class to all the elements */
    for(var i = 0, j = forms.length; i < j; i++) {
      forms[i].classList.add('_hidden');
    }

    if(value.length > 0) {
      /* Then the forms which are targeted by the filter loose it */
      var filteredForms = [].filter.call(forms, function(form) {
        return form.classList.contains(value);
      });

      for(var i = 0, j = filteredForms.length; i < j; i++) {
        filteredForms[i].classList.remove('_hidden');
      }
    }
  });
};

var showDatepicker = function() {
  var dateFields = document.querySelectorAll('.js-datepicker');
  var minDate, startDate;
  for(var i = 0, j = dateFields.length; i < j; i++) {
    minDate = new Date(dateFields[i].getAttribute('data-min-date').split('-'));
    maxDate = new Date(dateFields[i].getAttribute('data-max-date').split('-'));
    if(dateFields[i].value.length > 0) {
      /* We remove the time from the value */
      dateFields[i].value = dateFields[i].value.split(' ')[0];
    }
    $(dateFields[i]).datepicker({
      minDate: minDate,
      maxDate: maxDate,
      dateFormat: 'yy-mm-dd',
      yearRange: dateFields[i].getAttribute('data-min-date').split('-')[0] + ':' +
        dateFields[i].getAttribute('data-max-date').split('-')[0],
      changeMonth: true,
      changeYear: true
    });
  }
};

var showMultiselect = function() {
  var multiselects = $('.js-mselect');

  for(var i = 0; i < multiselects.length; i++) {
    multiselects[i].classList.add('chosen');
    multiselects[i].classList.add('chosen-select');
  }

  multiselects.chosen();
};

/* Display a mini map into the container and return it */
var createPreviewMap = function(container) {
  /* We show the map */
  var layer = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
    attribution: '© OpenStreetMap contributors, © CartoDB'
  });

  var southWest = L.latLng(-85, -720.0),
      northEast = L.latLng(85, 720.0),
      bounds = L.latLngBounds(southWest, northEast);

  var map = L.map(container, {
    center: [16.77, -23.70],
    zoom: 1,
    minZoom: 1,
    maxBounds: bounds
  });

  map.addLayer(layer);
  return map;
};

/* Add a marker to a map at the given coordinates and return it */
var dropMarkerOn = function(map, lat, lng) {
  var marker = L.marker(L.latLng(lat, lng));
  marker.addTo(map);
  return marker;
};

/* Remove a given marker from the map passed as argument */
var removeMarkerFrom = function(map, marker) {
  map.removeLayer(marker);
};

/* Return the address associated to coordinates with the Nominatim service. It
 * uses the promise architecture to execute code when the information is
 * available. */
var retrieveAddressFrom = function(lat, lng) {
  var deferred = $.Deferred();

  var ajax = $.ajax({
    url: 'http://nominatim.openstreetmap.org/reverse',
    data: {
      format: 'json',
      lat: lat,
      lon: lng
    }
  });

  ajax.done(function(data) {
    var res = data.address || {};
    res.lat = lat;
    res.lng = lng;
    deferred.resolve(res);
  }).fail(function() {
      console.warn('Unable to retrieve the address from the Nominatim service');
    });

  return deferred.promise();
};

/* Initialize a mini map into the container and connects the inputs to the map
 * so when the user clicks on it, the fields are autocompleted and when the
 * fields are modified, the map displays a marker */
var initPreviewMap = function(container) {
  var map = createPreviewMap(container.querySelector('.map-preview'));

  /* Cache for the form fields related to a location */
  var latField     = container.querySelector('.localization_lat');
  var lngField     = container.querySelector('.localization_long');
  var cityField    = container.querySelector('.localization_city');
  var countryField = container.querySelector('.localization_country');
  var zipcodeField = container.querySelector('.localization_zip_code');

  /* Method to fill the inputs with the address contained in the param */
  var autocompleteInputs = function(address, options) {
    /* If true, force means that all the inputs should have their value updated,
     * otherwise just the ones that are blank */
    var force = options && options.force;

    latField.value     = force || latField.value.length === 0 ?
      address.lat : latField.value;
    lngField.value     = force || lngField.value.length === 0 ?
      address.lng : lngField.value;
    cityField.value    = force || cityField.value.length === 0 ?
      address.city || address.town || address.village || '' : cityField.value;
    zipcodeField.value = force || zipcodeField.value.length === 0 ?
      address.postcode || '' : zipcodeField.value;

    if(address.country_code) {
      countryField.options[countryField.selectedIndex].selected = false;
      countryField.querySelector('option[value="' +
        address.country_code.toUpperCase() + '"]').selected = true;
    }
  };

  /* If the form already stores coordinates, we add the marker on the map */
  var marker; /* The current marker on the map */
  if(latField.value.length > 0 && lngField.value.length > 0) {
    marker = dropMarkerOn(map, latField.value, lngField.value);
  }

  /* We watch the inputs changes and map clicks only if the user is able to
   * modify the form (ie if it's not disabled) */
  if(!container.classList.contains('disabled')) {

    /* When the user click on the map, we display a marker and updates the inputs
     * accordingly */
    map.on('click', function(e) {
      var lat = e.latlng.lat,
          lng = e.latlng.lng;
      if(marker) { removeMarkerFrom(map, marker); }
      marker = dropMarkerOn(map, lat, lng);
      retrieveAddressFrom(lat, lng).done(function(address) {
        autocompleteInputs(address, { force: true });
      });
    });

    /* When the user fills the inputs, we try to autocomplete the others */
    var inputsListener = function() {
      if(latField.value.length === 0 || lngField.value.length === 0) {
        return;
      }
      retrieveAddressFrom(latField.value,
        lngField.value).done(autocompleteInputs);
      /* We add a marker to the location */
      if(marker) { removeMarkerFrom(map, marker); }
      marker = dropMarkerOn(map, latField.value, lngField.value);
    };
    $(latField).on('change', inputsListener);
    $(lngField).on('change', inputsListener);
  }
};

/* Polyfill for Element.matches
 * Source: https://developer.mozilla.org/en/docs/Web/API/Element/matches */
var matches = function(elm, selector) {
    var matches = (elm.document || elm.ownerDocument).querySelectorAll(selector),
        i = matches.length;
    while (--i >= 0 && matches.item(i) !== elm) ;
    return i > -1;
};

/* Return the closest parent to an element that matches the selector */
var getClosestParent = function(element, selector) {
  var res = null;
  var currentElement = element;
  while(currentElement !== document) {
    currentElement = currentElement.parentNode;
    if(currentElement.matches && currentElement.matches(selector) ||
      !currentElement.matches && matches(currentElement, selector)) {
      res = currentElement;
      break;
    }
  }
  return res;
};

function onReady() {
  filterForms();
  showMultiselect();
  showDatepicker();
  /* Initialize the mini maps attached to the location forms */
  var previewMaps = document.querySelectorAll('.map-preview');
  var form;
  for(var i = 0, j = previewMaps.length; i < j; i++) {
    form = getClosestParent(previewMaps[i], '.form-inputs');
    if(form) {
      initPreviewMap(getClosestParent(previewMaps[i], '.form-inputs'));
    }
  }
}

$(document).foundation();
document.addEventListener('DOMContentLoaded', onReady);
<|endoftext|>


<commit_before>//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require jquery-ui/widgets/datepicker
//= require jquery-ui/i18n/datepicker-de
//= require jszip/dist/jszip
//= require pdfmake/build/pdfmake
//= require pdfmake/build/vfs_fonts
//= require datatables.net/js/jquery.dataTables.js
//= require datatables.net-bs4/js/dataTables.bootstrap4.js
//= require datatables.net-buttons/js/dataTables.buttons.js
//= require datatables.net-buttons-bs4/js/buttons.bootstrap4.js
//= require datatables.net-buttons/js/buttons.html5.js
//= require datatables.net-buttons/js/buttons.print.js
//= require datatables.net-buttons/js/buttons.colVis.js
//= require select2/dist/js/select2
//= require popper.js/dist/umd/popper
//= require bootstrap/dist/js/bootstrap
//= require adwhois
<commit_msg>use jquery3<commit_after>//= require jquery3
//= require rails-ujs
//= require turbolinks
//= require jquery-ui/widgets/datepicker
//= require jquery-ui/i18n/datepicker-de
//= require jszip/dist/jszip
//= require pdfmake/build/pdfmake
//= require pdfmake/build/vfs_fonts
//= require datatables.net/js/jquery.dataTables.js
//= require datatables.net-bs4/js/dataTables.bootstrap4.js
//= require datatables.net-buttons/js/dataTables.buttons.js
//= require datatables.net-buttons-bs4/js/buttons.bootstrap4.js
//= require datatables.net-buttons/js/buttons.html5.js
//= require datatables.net-buttons/js/buttons.print.js
//= require datatables.net-buttons/js/buttons.colVis.js
//= require select2/dist/js/select2
//= require popper.js/dist/umd/popper
//= require bootstrap/dist/js/bootstrap
//= require adwhois
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require handlebars
//= require ember
//= require ember-data
//= require local_storage_adapter
//= require_self
//= require kickstarter_rails4_ember_heroku

// for more details see: http://emberjs.com/guides/application/
KickstarterRails4EmberHeroku = Ember.Application.create();
KickstarterRails4EmberHeroku.ApplicationAdapter = DS.LSAdapter.extend({
  namespace: 'todos-emberjs'
});

//= require_tree .<commit_msg>Removed require tree . in application.js<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require handlebars
//= require ember
//= require ember-data
//= require local_storage_adapter
//= require_self
//= require kickstarter_rails4_ember_heroku

// for more details see: http://emberjs.com/guides/application/
KickstarterRails4EmberHeroku = Ember.Application.create();
KickstarterRails4EmberHeroku.ApplicationAdapter = DS.LSAdapter.extend({
  namespace: 'todos-emberjs'
});
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
// vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require rails-ujs
//= require turbolinks
//= require_tree .
<commit_msg>Application js file updated.<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
// vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require rails-ujs
//= require turbolinks
//= require_tree .
//= require jquery
//= require jquery_ujs
//= require materialize-sprockets
//= require materialize/extras/nouislider
<|endoftext|>


<commit_before>/*
 *= require jquery
 *= require rails
 *= require jquery-ui
 *= require bootstrap
 *= require bootstrap/sticky-popover
 *= require bootstrap/modal-form
 *= require bootstrap/modal-ajax
 *= require bootstrap/scrollspy
 *= require bootstrap/affix
 *= require wysihtml5_parser_rules/advanced
 *= require wysihtml5-0.3.0_rc2
 *= require bootstrap-wysihtml5-0.0.2
 *= require_self
 */

/* Unused?
jQuery(document).ready(function($) {
  $('.collapsible .head').click(function(e) {
      $(this).toggleClass('toggle');
      $(this).next().toggle();
      e.preventDefault();
  }).next().hide();
});*/

jQuery(document).ready(function($) {
  // TODO: Not AJAX friendly
  $('.bar[data-percentage]').each(function() {
    $(this).css({ width: $(this).data('percentage') + '%' })
  });
});

jQuery(document).ready(function($) {
  // Monitor Bootstrap Tooltips to remove the tooltip if the triggering element
  // becomes hidden or removed.
  //
  // * $currentTip needed because tooltips don't fire events until Bootstrap
  //   2.3.0 and $currentTarget.tooltip('hide') doesn't seem to work when it's
  //   not in the DOM
  // * $currentTarget.data('tooltip-monitor') is a flag to ensure only one
  //   monitor per element
  function monitorTooltip($currentTarget) {
    var monitorFn
      , monitorPeriod = 500
      , monitorTimeoutId = null
      , $currentTip
      , dataTooltip;

    if (!$currentTarget.data('tooltip-monitor')) {
      dataTooltip = $currentTarget.data('tooltip');
      $currentTip = dataTooltip && dataTooltip.$tip;

      monitorFn = function() {
        dataTooltip = dataTooltip || $currentTarget.data('tooltip');
        $currentTip = $currentTip || (dataTooltip && dataTooltip.$tip);

        if (!$currentTarget.is(':visible')) {
          $currentTip && $currentTip.remove();
          $currentTarget.data('tooltip-monitor', false);
        } else if ($currentTip && $currentTip.is(':visible')) {
          monitorTimeoutId = setTimeout(monitorFn, monitorPeriod);
        } else {
          $currentTarget.data('tooltip-monitor', false);
        }
      };

      monitorTimeoutId = setTimeout(monitorFn, monitorPeriod);
      $currentTarget.data('tooltip-monitor', true);
    }
  };

  $('body').on('shown', '.modal', function() {
    $('.tooltip').hide();;
  });

  // Listeners for initial tooltip mouseovers
  $('body').on('mouseover', '[data-toggle="tooltip"], [rel=tooltip]', function(e) {
    var $currentTarget = $(e.currentTarget);

    if (!$currentTarget.data('tooltip')) {
      $currentTarget
        .tooltip({ delay: 300 })
        .triggerHandler(e);
    }

    monitorTooltip($currentTarget);
  });
});

// Setup for Popovers
jQuery(document).ready(function($) {
  var defaults = {
    delay: { show: 300, hide: 150 },
    placement: 'left',
    content: function(trigger) {
      var $trigger = $(trigger);

      var $el = $(new Spinner().spin().el);
      $el.css({
        width: '100px',
        height: '100px',
        left: '50px',
        top: '50px',
        zIndex : calculate_spinner_z_index
       });
      return $el[0];
    }
  };

  // Listeners for initial mouseovers for stick-hover
  $('body').on('mouseover', 'a[data-popover-trigger="sticky-hover"]', function(e) {
    // If popover instance doesn't exist already, create it and
    // force the 'enter' event.
    if (!$(e.currentTarget).data('sticky_popover')) {
      $(e.currentTarget)
        .sticky_popover($.extend({}, defaults, {
          trigger: 'sticky-hover'
          , placement : function() {
            if(this.$element.closest(".widget-area:first-child").length)
              return "right";
            else
              return "left";
          }
        }))
        .triggerHandler(e);
    }
  });

  // Listeners for initial clicks for popovers
  $('body').on('click', 'a[data-popover-trigger="click"]', function(e) {
    e.preventDefault();
    if (!$(e.currentTarget).data('sticky_popover')) {
      $(e.currentTarget)
        .sticky_popover($.extend({}, defaults, { trigger: 'click' }))
        .triggerHandler(e);
    }
  });

  // Remove widgets
  $('body').on('click', '.widget .header .remove', function(e) {
    e.preventDefault();
    var $this = $(this),
        $widget = $this.closest(".widget");
    $widget.fadeOut();
  });

  // Contract/Expand widget
  $('body').on('click', '.widget .header .showhide, .widget .header .widget-showhide a', function(e) {

    if($(this).is(".widget-showhide"))
      e.preventDefault();

    showhide.call(this);
  });

  function showhide(command) {
    $(this).each(function() {
      var $this = $(this)
          , $content = $this.closest(".widget").find(".content")
          , $filter = $this.closest(".widget").find(".filter")
          , cmd = command;

      if(typeof cmd === "undefined" || cmd === "toggle") {
        cmd = $this.hasClass("active") ? "hide" : "show";
      }

      if(cmd === "hide") {
        $content.slideUp();
        $filter.slideUp();
        $this.removeClass("active");
      } else if(cmd === "show") {
        $content.slideDown();
        $filter.slideDown();
        $this.addClass("active");
      }
    });

  }

  $.fn.showhide = showhide;

  // Show/hide tree leaf content
  $('body').on('click', '.tree-structure .oneline, .tree-structure .description, .tree-structure .view-more', oneline);

  function oneline(command) {
    $(this).each(function() {
      var $this = $(this)
        , $leaf = $this.closest('[class*=span]').parent().children("[class*=span]:first")
        , $title = $leaf.find('.oneline')
        , $description = $leaf.find('.description')
        , $view = $leaf.closest('.row-fluid').find('.view-more')
        , cmd = command
        ;

      if ($description.length > 0) {
        if(typeof cmd !== "string") {
          cmd = $description.hasClass("in") ? "hide" : "view";
        }

        if(cmd === "view") {
          $description.addClass('in');
          $title.find('.description-inline').addClass('out');
          if ($title.is('.description-only')) {
            $title.addClass('out');
          }
          $view.text('hide');
        } else if(cmd === "hide") {
          $description.removeClass('in');
          $title.find('.description-inline').removeClass('out');
          if ($title.is('.description-only')) {
            $title.removeClass('out');
          }
          $view.text('view');
        }
      }
    });
  }

  $.fn.oneline = oneline;

  // Open quick find
  $('body').on('focus', '.quick-search-holder input', function() {
    var $this = $(this),
    $quickFind = $this.closest(".quick-search").find(".quick-search-results");
    $quickFind.fadeIn();

    if($(".quick-search-results").css("display") == "block"){
      $('.quick-search-holder').addClass('open');
    }

    $('.quick-search-results .remove').click(function() {
      $('.quick-search-holder').removeClass('open');
    });

  });

  // Remove quick find
  $('body').on('click', '.quick-search-results .remove', function(e) {
    e.preventDefault();
    var $this = $(this),
        $quickFind = $this.closest(".quick-search-results");
    $quickFind.fadeOut();
  });

  // Close other popovers when one is shown
  $('body').on('show.popover', function(e) {
    $('[data-sticky_popover]').each(function() {
      var popover = $(this).data('sticky_popover');
      popover && popover.hide();
    });
  });

  // Close all popovers on custom event
  $('body').on('kill-all-popovers', function(e) {
    // FIXME: This may be incompatible with bootstrap popover assumptions...
    // This is when the triggering element has been removed from the DOM
    // so we have to kill the popover elements themselves.
    $('.popover').remove();
  });
});

$(document).ajaxComplete(function(event, request){
  var flash = $.parseJSON(request.getResponseHeader('X-Flash-Messages'));
  if (!flash) return;
  $(['notice', 'error', 'warning']).each(function(i, prop) {
    $('.flash > .' + prop).html(flash[prop] || '');
  });
});

$(window).load(function(){

  // tree

  $('body').on('click', 'ul.tree .item-title', function(e) {
    var $this = $(this),
        $content = $this.closest('li').find('.item-content');

    if($this.hasClass("active")) {
      $content.slideUp('fast');
      $this.removeClass("active");
    } else {
      $content.slideDown('fast');
      $this.addClass("active");
    }

  });

  // tree-structure

  $('body').on('click', 'ul.tree-structure .item-main .grcobject, ul.tree-structure .item-main .openclose', function(e) {
    openclose.call(this);
    e.stopPropagation();
  });

  function openclose(command) {
    var $that = $(this)
    , use_slide = $that.length < 100

    $that.each(function(){
      var $this = $(this)
        , $main = $this.closest('.item-main')
        , $li = $main.closest('li')
        , $content = $li.children('.item-content')
        , $icon = $main.find('.openclose')
        , cmd = command;

      if(typeof cmd !== "string" || cmd === "toggle") {
        cmd = $icon.hasClass("active") ? "close" : "open";
      }

      if (cmd === "close") {

        use_slide ? $content.slideUp('fast') : $content.css("display", "none");
        $icon.removeClass('active');
      } else if(cmd === "open") {
        use_slide ? $content.slideDown('fast') : $content.css("display", "block");
        $icon.addClass('active');
      }
    });
  }

  $.fn.openclose = openclose;

  $('.widget-area').sortable({
    connectWith: '.widget-area'
    , placeholder: 'drop-placeholder'
    , handle : "header, .header"
    , items : ".widget"
  });

});

jQuery(document).ready(function($) {
  var containerSize = $('.container-fluid').width(),
      containerWide = 1200,
      containerNarrow = 960,
      containerDelta = $(window).width() - containerSize;

  $('.container-fluid').css('width', containerSize);

  $(window).on('resize', function(e) {
    var width = $(window).width();
    // Only auto-resize when in 100% mode
    if ($('body').find('.menu').find('.screen-size span').text().trim() == '100%') {
      $('.container-fluid').addClass('resizable').css('width', width - containerDelta);
      $(this).closest('.menu').find('.screen-size span').text('100%');
    }

    if(width < 720) {
      $(".quick-search-results").css("width", width);
    } else {
      $(".quick-search-results").css("width", "");
    }
  });

  $('body').on('click', '.full-view', function(e) {
    var width = $(window).width();
    e.preventDefault();
    $('.container-fluid').addClass('resizable').css('width', width - containerDelta);
    $(this).closest('.menu').find('.screen-size span').text('100%');
  });

  $('body').on('click', '.wide-view', function(e) {
    e.preventDefault();
    $('.container-fluid').addClass('resizable').css('width', containerWide);
    $(this).closest('.menu').find('.screen-size span').text('Wide');
  });

  $('body').on('click', '.narrow-view', function(e) {
    e.preventDefault();
    $('.container-fluid').addClass('resizable').css('width', containerNarrow);
    $(this).closest('.menu').find('.screen-size span').text('Narrow');
  });

  if ($('#welcome').length > 0) {
		$('#user_session_email').focus();
	}

});

jQuery(function($){
  $.fn.cms_wysihtml5 = function() {

    this.wysihtml5({
        link: true,
        image: false,
        html: true,
        'font-styles': false,
        parserRules: wysihtml5ParserRules })

    this.each(function() {
      var $that = $(this)
      , editor = $that.data("wysihtml5").editor;

      editor.on("change", function(data) {
        $that.html(this.getValue()).trigger("change");
      });
    })
  }
});
<commit_msg>Story 45571995: Added height resizing for all wysihtml5 edit boxes<commit_after>/*
 *= require jquery
 *= require rails
 *= require jquery-ui
 *= require bootstrap
 *= require bootstrap/sticky-popover
 *= require bootstrap/modal-form
 *= require bootstrap/modal-ajax
 *= require bootstrap/scrollspy
 *= require bootstrap/affix
 *= require wysihtml5_parser_rules/advanced
 *= require wysihtml5-0.3.0_rc2
 *= require bootstrap-wysihtml5-0.0.2
 *= require_self
 */

/* Unused?
jQuery(document).ready(function($) {
  $('.collapsible .head').click(function(e) {
      $(this).toggleClass('toggle');
      $(this).next().toggle();
      e.preventDefault();
  }).next().hide();
});*/

jQuery(document).ready(function($) {
  // TODO: Not AJAX friendly
  $('.bar[data-percentage]').each(function() {
    $(this).css({ width: $(this).data('percentage') + '%' })
  });
});

jQuery(document).ready(function($) {
  // Monitor Bootstrap Tooltips to remove the tooltip if the triggering element
  // becomes hidden or removed.
  //
  // * $currentTip needed because tooltips don't fire events until Bootstrap
  //   2.3.0 and $currentTarget.tooltip('hide') doesn't seem to work when it's
  //   not in the DOM
  // * $currentTarget.data('tooltip-monitor') is a flag to ensure only one
  //   monitor per element
  function monitorTooltip($currentTarget) {
    var monitorFn
      , monitorPeriod = 500
      , monitorTimeoutId = null
      , $currentTip
      , dataTooltip;

    if (!$currentTarget.data('tooltip-monitor')) {
      dataTooltip = $currentTarget.data('tooltip');
      $currentTip = dataTooltip && dataTooltip.$tip;

      monitorFn = function() {
        dataTooltip = dataTooltip || $currentTarget.data('tooltip');
        $currentTip = $currentTip || (dataTooltip && dataTooltip.$tip);

        if (!$currentTarget.is(':visible')) {
          $currentTip && $currentTip.remove();
          $currentTarget.data('tooltip-monitor', false);
        } else if ($currentTip && $currentTip.is(':visible')) {
          monitorTimeoutId = setTimeout(monitorFn, monitorPeriod);
        } else {
          $currentTarget.data('tooltip-monitor', false);
        }
      };

      monitorTimeoutId = setTimeout(monitorFn, monitorPeriod);
      $currentTarget.data('tooltip-monitor', true);
    }
  };

  $('body').on('shown', '.modal', function() {
    $('.tooltip').hide();;
  });

  // Listeners for initial tooltip mouseovers
  $('body').on('mouseover', '[data-toggle="tooltip"], [rel=tooltip]', function(e) {
    var $currentTarget = $(e.currentTarget);

    if (!$currentTarget.data('tooltip')) {
      $currentTarget
        .tooltip({ delay: 300 })
        .triggerHandler(e);
    }

    monitorTooltip($currentTarget);
  });
});

// Setup for Popovers
jQuery(document).ready(function($) {
  var defaults = {
    delay: { show: 300, hide: 150 },
    placement: 'left',
    content: function(trigger) {
      var $trigger = $(trigger);

      var $el = $(new Spinner().spin().el);
      $el.css({
        width: '100px',
        height: '100px',
        left: '50px',
        top: '50px',
        zIndex : calculate_spinner_z_index
       });
      return $el[0];
    }
  };

  // Listeners for initial mouseovers for stick-hover
  $('body').on('mouseover', 'a[data-popover-trigger="sticky-hover"]', function(e) {
    // If popover instance doesn't exist already, create it and
    // force the 'enter' event.
    if (!$(e.currentTarget).data('sticky_popover')) {
      $(e.currentTarget)
        .sticky_popover($.extend({}, defaults, {
          trigger: 'sticky-hover'
          , placement : function() {
            if(this.$element.closest(".widget-area:first-child").length)
              return "right";
            else
              return "left";
          }
        }))
        .triggerHandler(e);
    }
  });

  // Listeners for initial clicks for popovers
  $('body').on('click', 'a[data-popover-trigger="click"]', function(e) {
    e.preventDefault();
    if (!$(e.currentTarget).data('sticky_popover')) {
      $(e.currentTarget)
        .sticky_popover($.extend({}, defaults, { trigger: 'click' }))
        .triggerHandler(e);
    }
  });

  // Remove widgets
  $('body').on('click', '.widget .header .remove', function(e) {
    e.preventDefault();
    var $this = $(this),
        $widget = $this.closest(".widget");
    $widget.fadeOut();
  });

  // Contract/Expand widget
  $('body').on('click', '.widget .header .showhide, .widget .header .widget-showhide a', function(e) {

    if($(this).is(".widget-showhide"))
      e.preventDefault();

    showhide.call(this);
  });

  function showhide(command) {
    $(this).each(function() {
      var $this = $(this)
          , $content = $this.closest(".widget").find(".content")
          , $filter = $this.closest(".widget").find(".filter")
          , cmd = command;

      if(typeof cmd === "undefined" || cmd === "toggle") {
        cmd = $this.hasClass("active") ? "hide" : "show";
      }

      if(cmd === "hide") {
        $content.slideUp();
        $filter.slideUp();
        $this.removeClass("active");
      } else if(cmd === "show") {
        $content.slideDown();
        $filter.slideDown();
        $this.addClass("active");
      }
    });

  }

  $.fn.showhide = showhide;

  // Show/hide tree leaf content
  $('body').on('click', '.tree-structure .oneline, .tree-structure .description, .tree-structure .view-more', oneline);

  function oneline(command) {
    $(this).each(function() {
      var $this = $(this)
        , $leaf = $this.closest('[class*=span]').parent().children("[class*=span]:first")
        , $title = $leaf.find('.oneline')
        , $description = $leaf.find('.description')
        , $view = $leaf.closest('.row-fluid').find('.view-more')
        , cmd = command
        ;

      if ($description.length > 0) {
        if(typeof cmd !== "string") {
          cmd = $description.hasClass("in") ? "hide" : "view";
        }

        if(cmd === "view") {
          $description.addClass('in');
          $title.find('.description-inline').addClass('out');
          if ($title.is('.description-only')) {
            $title.addClass('out');
          }
          $view.text('hide');
        } else if(cmd === "hide") {
          $description.removeClass('in');
          $title.find('.description-inline').removeClass('out');
          if ($title.is('.description-only')) {
            $title.removeClass('out');
          }
          $view.text('view');
        }
      }
    });
  }

  $.fn.oneline = oneline;

  // Open quick find
  $('body').on('focus', '.quick-search-holder input', function() {
    var $this = $(this),
    $quickFind = $this.closest(".quick-search").find(".quick-search-results");
    $quickFind.fadeIn();

    if($(".quick-search-results").css("display") == "block"){
      $('.quick-search-holder').addClass('open');
    }

    $('.quick-search-results .remove').click(function() {
      $('.quick-search-holder').removeClass('open');
    });

  });

  // Remove quick find
  $('body').on('click', '.quick-search-results .remove', function(e) {
    e.preventDefault();
    var $this = $(this),
        $quickFind = $this.closest(".quick-search-results");
    $quickFind.fadeOut();
  });

  // Close other popovers when one is shown
  $('body').on('show.popover', function(e) {
    $('[data-sticky_popover]').each(function() {
      var popover = $(this).data('sticky_popover');
      popover && popover.hide();
    });
  });

  // Close all popovers on custom event
  $('body').on('kill-all-popovers', function(e) {
    // FIXME: This may be incompatible with bootstrap popover assumptions...
    // This is when the triggering element has been removed from the DOM
    // so we have to kill the popover elements themselves.
    $('.popover').remove();
  });
});

$(document).ajaxComplete(function(event, request){
  var flash = $.parseJSON(request.getResponseHeader('X-Flash-Messages'));
  if (!flash) return;
  $(['notice', 'error', 'warning']).each(function(i, prop) {
    $('.flash > .' + prop).html(flash[prop] || '');
  });
});

$(window).load(function(){

  // tree

  $('body').on('click', 'ul.tree .item-title', function(e) {
    var $this = $(this),
        $content = $this.closest('li').find('.item-content');

    if($this.hasClass("active")) {
      $content.slideUp('fast');
      $this.removeClass("active");
    } else {
      $content.slideDown('fast');
      $this.addClass("active");
    }

  });

  // tree-structure

  $('body').on('click', 'ul.tree-structure .item-main .grcobject, ul.tree-structure .item-main .openclose', function(e) {
    openclose.call(this);
    e.stopPropagation();
  });

  function openclose(command) {
    var $that = $(this)
    , use_slide = $that.length < 100

    $that.each(function(){
      var $this = $(this)
        , $main = $this.closest('.item-main')
        , $li = $main.closest('li')
        , $content = $li.children('.item-content')
        , $icon = $main.find('.openclose')
        , cmd = command;

      if(typeof cmd !== "string" || cmd === "toggle") {
        cmd = $icon.hasClass("active") ? "close" : "open";
      }

      if (cmd === "close") {

        use_slide ? $content.slideUp('fast') : $content.css("display", "none");
        $icon.removeClass('active');
      } else if(cmd === "open") {
        use_slide ? $content.slideDown('fast') : $content.css("display", "block");
        $icon.addClass('active');
      }
    });
  }

  $.fn.openclose = openclose;

  $('.widget-area').sortable({
    connectWith: '.widget-area'
    , placeholder: 'drop-placeholder'
    , handle : "header, .header"
    , items : ".widget"
  });

});

jQuery(document).ready(function($) {
  var containerSize = $('.container-fluid').width(),
      containerWide = 1200,
      containerNarrow = 960,
      containerDelta = $(window).width() - containerSize;

  $('.container-fluid').css('width', containerSize);

  $(window).on('resize', function(e) {
    var width = $(window).width();
    // Only auto-resize when in 100% mode
    if ($('body').find('.menu').find('.screen-size span').text().trim() == '100%') {
      $('.container-fluid').addClass('resizable').css('width', width - containerDelta);
      $(this).closest('.menu').find('.screen-size span').text('100%');
    }

    if(width < 720) {
      $(".quick-search-results").css("width", width);
    } else {
      $(".quick-search-results").css("width", "");
    }
  });

  $('body').on('click', '.full-view', function(e) {
    var width = $(window).width();
    e.preventDefault();
    $('.container-fluid').addClass('resizable').css('width', width - containerDelta);
    $(this).closest('.menu').find('.screen-size span').text('100%');
  });

  $('body').on('click', '.wide-view', function(e) {
    e.preventDefault();
    $('.container-fluid').addClass('resizable').css('width', containerWide);
    $(this).closest('.menu').find('.screen-size span').text('Wide');
  });

  $('body').on('click', '.narrow-view', function(e) {
    e.preventDefault();
    $('.container-fluid').addClass('resizable').css('width', containerNarrow);
    $(this).closest('.menu').find('.screen-size span').text('Narrow');
  });

  if ($('#welcome').length > 0) {
		$('#user_session_email').focus();
	}

});

jQuery(function($){
  $.fn.cms_wysihtml5 = function() {

    this.wysihtml5({
        link: true,
        image: false,
        html: true,
        'font-styles': false,
        parserRules: wysihtml5ParserRules })

    this.each(function() {
      var $that = $(this)
      , editor = $that.data("wysihtml5").editor;

      editor.on("change", function(data) {
        $that.html(this.getValue()).trigger("change");
      });

      $that.closest(".wysiwyg-area").resizable({
        handles : "s"
        , minHeight : 100
        , alsoResize : "#" + $that.uniqueId().attr("id") + ", #" + $that.closest(".wysiwyg-area").uniqueId().attr("id") + " iframe"
        , autoHide : false
      }).bind("resizestop", function(ev) {
        $that.css({"display" : "block", "height" : $that.height() + 20}); //10px offset between reported height and styled height.
        editor.composer.style();// re-copy new size of textarea to composer
        $that.css("display", "none");
      });
    })
  }
});
<|endoftext|>


<commit_before>/* global Fae, FCH, Cookies */

/**
 * Fae tables
 * @namespace tables
 * @memberof Fae
 */
Fae.tables = {

  /**
   * Base cookie string for sorting per site per page
   * @type {String}
   * @see {@link tables.defaultSortCookie}
   * @see {@link tables.columnSorting}
   * @see {@link tables.sortColumnsFromCookies}
   */
  sort_cookie_name: 'Fae_table_sort_preferences',

  ready: function() {
    // @depreciation - remove `|| FCH.exists('.main_table-sort_columns')` and only use FCH.exists('.js-sort-column') in v2.0
    if (FCH.exists('.js-sort-column') || FCH.exists('.main_table-sort_columns')) {
      this.dateColumnSorting();
      this.columnSorting();
      this.defaultSortCookie();
      this.sortColumnsFromCookies();
    }

    // @depreciation - remove || FCH.exists('.main_content-sortable-handle') and only use FCH.exists('.sortable-handle') in v2.0
    if (FCH.exists('.sortable-handle') || FCH.exists('.main_content-sortable-handle')) {
      this.rowSorting();
    }

    this.stickyTableHeader();

    if (FCH.exists('.collapsible')) {
      this.collapsibleTable();
    }

    // @depreciation - remove conditional wrapping and call endingSelectShim like `this.endingSelectShim()` in v2.0
    if (FCH.exists('form ' + Fae.content_selector)) {
      this.endingSelectShim(Fae.content_selector);
    }

    if (FCH.exists('.js-tooltip')) {
      this.tooltip();
    }
  },

  /**
   * Sort columns in tables if applicable
   */
  columnSorting: function() {
    var _this = this;
    var path = window.location.pathname;
    var cookie_value = Cookies.getJSON(_this.sort_cookie_name);

    // @depreciation - remove `, .main_table-sort_columns` and only use '.js-sort-column' in v2.0
    $('.js-sort-column, .main_table-sort_columns')
      .tablesorter()
      .on('sortEnd', function(e) {
        var $this = $(this);
        cookie_value = Cookies.getJSON(_this.sort_cookie_name);
        var idx = $this.index() - 1;

        // Create object if the index isn't available at this path
        if (!cookie_value[path].hasOwnProperty(idx)) {
          cookie_value[path][idx] = {};
        }

        // Insert the sort data at the index of the table in the array
        cookie_value[path][idx] = $this.data('tablesorter').sortList;

        // Save it to the cookie as a string
        Cookies.set(_this.sort_cookie_name, cookie_value);

        _this.replaceStickyTableHeader($this.siblings('.sticky-table-header'), $this);
      });
  },

  /**
   * Add smart sorting for dates
   * @has_test {features/date_sort_spec.rb}
   */
  dateColumnSorting: function() {
    $.tablesorter.addParser({
      id: 'mmddyy',
      is: function(s) {
        // testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
        return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{2})/).test((s || '').replace(/\s+/g, ' ').replace(/[\-.,]/g, '/'));
      },
      format: function(s, table, cell, cellIndex) {
        if (s) {
          var c = table.config,
            ci = c.$headers.filter('[data-column=' + cellIndex + ']:last'),
            format = ci.length && ci[0].dateFormat || $.tablesorter.getData( ci, $.tablesorter.getColumnData( table, c.headers, cellIndex ), 'dateFormat') || c.dateFormat;
          s = s.replace(/\s+/g, ' ').replace(/[\-.,]/g, '/'); // escaped - because JSHint in Firefox was showing it as an error
          if (format === 'mmddyy') {
            s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{2})/, '$3/$1/$2');
          }
        }
        return s ? $.tablesorter.formatFloat( (new Date(s).getTime() || s), table) : s;
      },
      type: 'numeric'
    });
  },

  /**
   * Ensure this page has a key in the table sort hash cookie
   */
  defaultSortCookie: function() {
    var path = window.location.pathname;
    var cookie_value = Cookies.getJSON(this.sort_cookie_name);

    // If cookie hasn't been created for this session
    if (!cookie_value || $.isEmptyObject(cookie_value)) {
      cookie_value = {};
    }

    // Create hash object for this path if it hasn't been done yet
    if (!cookie_value.hasOwnProperty(path)) {
      cookie_value[path] = {};
    }

    Cookies.set(this.sort_cookie_name, cookie_value);
  },

  /**
   * Sort column by stored cookie
   * @has_test {requests/fae_table_sort_spec.rb}
   */
  sortColumnsFromCookies: function() {
    var path = window.location.pathname;
    var cookie_value = Cookies.getJSON(this.sort_cookie_name);

    // Exit early if sort cookie is nothing or there's no cookie at the present path
    if (!cookie_value || $.isEmptyObject(cookie_value) || !cookie_value[path] || $.isEmptyObject(cookie_value[path])) {
      return;
    }

    // @depreciation - remove `, .main_table-sort_columns` and only use '.js-sort-column' in v2.0
    $('.js-sort-column, .main_table-sort_columns').each(function(idx) {
      // If this table exists in the cookie hash
      if (cookie_value[path].hasOwnProperty(idx)) {
        // Use array value within another array because of how tablesorter accepts this argument
        $(this).trigger('sorton', [ cookie_value[path][idx] ]);
      }
    });
  },

  /**
   * Make table rows draggable by user
   */
  rowSorting: function() {
    // @depreciation - remove sort_selector var in v2.0
    var sort_selector = FCH.exists('.sortable-handle') ? '.sortable-handle' : '.main_content-sortable-handle';

    // @depreciation - remove `, .main_content-sortable` and only use '.js-sort-row' in v2.0
    $('.js-sort-row, .main_content-sortable').sortable({
      items: 'tbody tr',
      opacity: 0.8,
      // @depreciation - replace sort_selector with '.sortable-handle' in v2.0
      handle: (sort_selector),

      //helper function to preserve the width of the table row
      helper: function(e, $tr) {
        var $originals = $tr.children();
        var $helper = $tr.clone();
        var $ths = $tr.closest('table').find('th');

        $helper.children().each(function(index) {
          // Set helper cell sizes to match the original sizes
          $(this).width($originals.eq(index).width());
          //set the THs width so they don't go collapsey
          $ths.eq(index).width($ths.eq(index).width());
        });

        return $helper;
      },

      // on stop, set the THs back to no inline width for repsonsivity
      stop: function(e, ui) {
        $(ui.item).closest('table').find('th').css('width', '');
      },

      update: function() {
        var $this = $(this);
        var serial = $this.sortable('serialize');
        var object = serial.substr(0, serial.indexOf('['));

        $.ajax({
          url: Fae.path+'/sort/'+object,
          type: 'post',
          data: serial,
          dataType: 'script',
          complete: function(request){
            // sort complete messaging can go here
          }
        });
      }
    });
  },

  /**
   * Enable collapsible tables by clicking the h3 preceding a table. Also enables open/close all
   */
  collapsibleTable: function() {
    var $collapsible = $('.collapsible');
    var $toggle = $('.collapsible-toggle');

    // If there's only one table, don't bother with collapsing everything
    // Also, remove the open/close all toggle and the table subheaders
    if ($collapsible.length === 1) {
      $collapsible.removeClass('collapsible');
      $collapsible.find('h3').remove();
      $toggle.remove();

      return;
    }

    $toggle.click(function() {
      var $this = $(this);

      if ($this.hasClass('close-all')) {
        $this.text('Open All');
        $collapsible.removeClass('active');

      } else {
        $this.text('Close All');
        $collapsible.addClass('active');

      }

      Fae.tables.sizeFixedHeader();

      $this.toggleClass('close-all');
    });

    $('.collapsible h3').click(function() {
      var $this = $(this);
      /** @type {Boolean} */
      var toggleHasCloseAll = $toggle.hasClass('close-all');

      $this.parent().toggleClass('active');

      // Change toggle messaging as appropriate
      // First check if there are open drawers
      if ($('.collapsible.active').length > 1) {

        // Change toggle text if it isn't already close all
        if(!toggleHasCloseAll) {
          $toggle.text('Close All');
          $toggle.addClass('close-all');
        }
      } else {

        // Change toggle text if it isn't already open all
        if(toggleHasCloseAll) {
          $toggle.text('Open All');
          $toggle.removeClass('close-all');
        }
      }

      Fae.tables.sizeFixedHeader();
    });
  },

  /**
   * Add extra space if the last item in a form is a select menu so the dropdown doesn't run off the screen or section
   * @param {String} selector - Last of type element to target
   * @deprecation remove selector arg and replace selector variable with '.content' in v2.0
   */
  endingSelectShim: function(selector) {
    $('form ' + selector + ':last-of-type').each(function() {
      var $last_item = $(this).find('.input:last-of-type');

      if( $last_item.hasClass('select') ) {
        $(this).addClass('-bottom-shim');
      }
    });
  },

  /**
   * Fix a table header to the top of the view on scroll
   */
  stickyTableHeader: function() {
    var _this = this;
    var $sticky_tables = $('.content table:not(.stuck-table)');

    // Add sticky psuedo tables after our main table to hold the fixed header
    $sticky_tables.each(function() {
      var $this = $(this);
      var $header = $this.find('thead').clone();

      var $fixed_header = $('<table />', {
        class: 'sticky-table-header stuck-table'
      });

      $fixed_header.append( $header );
      $this.after($fixed_header);

      if ($this.hasClass('tablesorter')) {
        _this.proxyStickyTableHeaderClicks($fixed_header, $this);
      }
    });

    /**
     * FCH callback for scroll - If the table header is in range, show it, otherwise hide it
     * @private
     */
    function stickyTableHeaderScroll() {
      var offset = FCH.$window.scrollTop();

      $('.sticky-table-header').each(function() {
        var $this = $(this);
        var top_offset = $this.data('table-top');
        var tableBottom = $this.data('table-bottom');

        if (offset >= top_offset && offset <= tableBottom) {
          $this.show();
        } else {
          $this.hide();
        }
      });
    }

    FCH.load.push( Fae.tables.sizeFixedHeader );
    FCH.resize.push( Fae.tables.sizeFixedHeader );
    FCH.scroll.push(stickyTableHeaderScroll);
  },

  /**
   * Proxy clicks from .sticky-table-header to underlying tablesorter instance
   */
  proxyStickyTableHeaderClicks: function($fixed_header, $sticky_table) {
    $fixed_header.on('click', 'th', function(e) {
      $sticky_table
        .find("th[data-column='" + $(e.currentTarget).data('column') + "']")
        .trigger('sort');
    });
  },

  /**
   *
   */
  replaceStickyTableHeader: function($fixed_header, $sticky_table) {
    // console.log('Replacing sticky header with table source', $fixed_header, $sticky_table);
    $fixed_header.find('thead').html($sticky_table.find('thead').html());
  },

  /**
   * Cache offset and height values to spare expensive calculations on scroll
   */
  sizeFixedHeader: function() {
    var $tables = $('.content table');
    // @depreciation - change value from ternary to $('.js-content-header').outerHeight() in v2.0
    var header_height = FCH.exists('.js-content-header') ? $('.js-content-header').outerHeight() : $('.main_content-header').outerHeight();
    if(FCH.large_down) {
      header_height = $('#js-main-header').outerHeight();
    }

    /**
     * Add offset and height values per each table
     * @private
     */
    function applyOffset() {
      var $this = $(this);

      // If this is a collapsible item and the table is hidden, forget it
      if($this.parent().hasClass('collapsible') && !$this.parent().hasClass('active')) {
        return;
      }

      // Content header is not present on mobile but the main header is stuck
      if (FCH.bp.large_down) {
        header_height = $('#js-main-header').outerHeight();
      }

      var top_offset = $this.offset().top - header_height;
      var thead_height = $this.find('thead').outerHeight();
      var bottom_offset = $this.height() + top_offset - thead_height;
      var $fixed_header = $this.next('.sticky-table-header');

      // For whatever reason IE9 does not pickup the .sticky plugin
      if(!FCH.exists('.js-will-be-sticky')) {
        top_offset += header_height;
        header_height = 0;
      }

      // Force offsets to be greater than the header_height
      top_offset = Math.max(header_height, top_offset);
      bottom_offset = Math.max(header_height, bottom_offset);

      $fixed_header.data({
        'table-top' : top_offset,
        'table-bottom' : bottom_offset
      });

      $fixed_header.css({
        width: $this.outerWidth(),
        height: thead_height,
        top: header_height
      });
    }

    $tables.each( applyOffset );

    Fae.navigation.lockFooter();
  },

  /**
   * Generate a tooltip for all .js-tooltip elements using their title attribute
   */
  tooltip: function() {
    // Generate tooltip
    $('.js-tooltip').each(function() {
      var $this = $(this);
      var $tooltip_element = $('<span />', {
        class: 'tooltip',
        text: $this.attr('title')
      });

      $this.addClass('tooltip-parent');

      $this.prepend( $tooltip_element );
    });
  }
};
<commit_msg>Refs #61163 - Comment cleanup<commit_after>/* global Fae, FCH, Cookies */

/**
 * Fae tables
 * @namespace tables
 * @memberof Fae
 */
Fae.tables = {

  /**
   * Base cookie string for sorting per site per page
   * @type {String}
   * @see {@link tables.defaultSortCookie}
   * @see {@link tables.columnSorting}
   * @see {@link tables.sortColumnsFromCookies}
   */
  sort_cookie_name: 'Fae_table_sort_preferences',

  ready: function() {
    // @depreciation - remove `|| FCH.exists('.main_table-sort_columns')` and only use FCH.exists('.js-sort-column') in v2.0
    if (FCH.exists('.js-sort-column') || FCH.exists('.main_table-sort_columns')) {
      this.dateColumnSorting();
      this.columnSorting();
      this.defaultSortCookie();
      this.sortColumnsFromCookies();
    }

    // @depreciation - remove || FCH.exists('.main_content-sortable-handle') and only use FCH.exists('.sortable-handle') in v2.0
    if (FCH.exists('.sortable-handle') || FCH.exists('.main_content-sortable-handle')) {
      this.rowSorting();
    }

    this.stickyTableHeader();

    if (FCH.exists('.collapsible')) {
      this.collapsibleTable();
    }

    // @depreciation - remove conditional wrapping and call endingSelectShim like `this.endingSelectShim()` in v2.0
    if (FCH.exists('form ' + Fae.content_selector)) {
      this.endingSelectShim(Fae.content_selector);
    }

    if (FCH.exists('.js-tooltip')) {
      this.tooltip();
    }
  },

  /**
   * Sort columns in tables if applicable
   */
  columnSorting: function() {
    var _this = this;
    var path = window.location.pathname;
    var cookie_value = Cookies.getJSON(_this.sort_cookie_name);

    // @depreciation - remove `, .main_table-sort_columns` and only use '.js-sort-column' in v2.0
    $('.js-sort-column, .main_table-sort_columns')
      .tablesorter()
      .on('sortEnd', function(e) {
        var $this = $(this);
        cookie_value = Cookies.getJSON(_this.sort_cookie_name);
        var idx = $this.index() - 1;

        // Create object if the index isn't available at this path
        if (!cookie_value[path].hasOwnProperty(idx)) {
          cookie_value[path][idx] = {};
        }

        // Insert the sort data at the index of the table in the array
        cookie_value[path][idx] = $this.data('tablesorter').sortList;

        // Save it to the cookie as a string
        Cookies.set(_this.sort_cookie_name, cookie_value);

        _this.replaceStickyTableHeader($this.siblings('.sticky-table-header'), $this);
      });
  },

  /**
   * Add smart sorting for dates
   * @has_test {features/date_sort_spec.rb}
   */
  dateColumnSorting: function() {
    $.tablesorter.addParser({
      id: 'mmddyy',
      is: function(s) {
        // testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
        return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{2})/).test((s || '').replace(/\s+/g, ' ').replace(/[\-.,]/g, '/'));
      },
      format: function(s, table, cell, cellIndex) {
        if (s) {
          var c = table.config,
            ci = c.$headers.filter('[data-column=' + cellIndex + ']:last'),
            format = ci.length && ci[0].dateFormat || $.tablesorter.getData( ci, $.tablesorter.getColumnData( table, c.headers, cellIndex ), 'dateFormat') || c.dateFormat;
          s = s.replace(/\s+/g, ' ').replace(/[\-.,]/g, '/'); // escaped - because JSHint in Firefox was showing it as an error
          if (format === 'mmddyy') {
            s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{2})/, '$3/$1/$2');
          }
        }
        return s ? $.tablesorter.formatFloat( (new Date(s).getTime() || s), table) : s;
      },
      type: 'numeric'
    });
  },

  /**
   * Ensure this page has a key in the table sort hash cookie
   */
  defaultSortCookie: function() {
    var path = window.location.pathname;
    var cookie_value = Cookies.getJSON(this.sort_cookie_name);

    // If cookie hasn't been created for this session
    if (!cookie_value || $.isEmptyObject(cookie_value)) {
      cookie_value = {};
    }

    // Create hash object for this path if it hasn't been done yet
    if (!cookie_value.hasOwnProperty(path)) {
      cookie_value[path] = {};
    }

    Cookies.set(this.sort_cookie_name, cookie_value);
  },

  /**
   * Sort column by stored cookie
   * @has_test {requests/fae_table_sort_spec.rb}
   */
  sortColumnsFromCookies: function() {
    var path = window.location.pathname;
    var cookie_value = Cookies.getJSON(this.sort_cookie_name);

    // Exit early if sort cookie is nothing or there's no cookie at the present path
    if (!cookie_value || $.isEmptyObject(cookie_value) || !cookie_value[path] || $.isEmptyObject(cookie_value[path])) {
      return;
    }

    // @depreciation - remove `, .main_table-sort_columns` and only use '.js-sort-column' in v2.0
    $('.js-sort-column, .main_table-sort_columns').each(function(idx) {
      // If this table exists in the cookie hash
      if (cookie_value[path].hasOwnProperty(idx)) {
        // Use array value within another array because of how tablesorter accepts this argument
        $(this).trigger('sorton', [ cookie_value[path][idx] ]);
      }
    });
  },

  /**
   * Make table rows draggable by user
   */
  rowSorting: function() {
    // @depreciation - remove sort_selector var in v2.0
    var sort_selector = FCH.exists('.sortable-handle') ? '.sortable-handle' : '.main_content-sortable-handle';

    // @depreciation - remove `, .main_content-sortable` and only use '.js-sort-row' in v2.0
    $('.js-sort-row, .main_content-sortable').sortable({
      items: 'tbody tr',
      opacity: 0.8,
      // @depreciation - replace sort_selector with '.sortable-handle' in v2.0
      handle: (sort_selector),

      //helper function to preserve the width of the table row
      helper: function(e, $tr) {
        var $originals = $tr.children();
        var $helper = $tr.clone();
        var $ths = $tr.closest('table').find('th');

        $helper.children().each(function(index) {
          // Set helper cell sizes to match the original sizes
          $(this).width($originals.eq(index).width());
          //set the THs width so they don't go collapsey
          $ths.eq(index).width($ths.eq(index).width());
        });

        return $helper;
      },

      // on stop, set the THs back to no inline width for repsonsivity
      stop: function(e, ui) {
        $(ui.item).closest('table').find('th').css('width', '');
      },

      update: function() {
        var $this = $(this);
        var serial = $this.sortable('serialize');
        var object = serial.substr(0, serial.indexOf('['));

        $.ajax({
          url: Fae.path+'/sort/'+object,
          type: 'post',
          data: serial,
          dataType: 'script',
          complete: function(request){
            // sort complete messaging can go here
          }
        });
      }
    });
  },

  /**
   * Enable collapsible tables by clicking the h3 preceding a table. Also enables open/close all
   */
  collapsibleTable: function() {
    var $collapsible = $('.collapsible');
    var $toggle = $('.collapsible-toggle');

    // If there's only one table, don't bother with collapsing everything
    // Also, remove the open/close all toggle and the table subheaders
    if ($collapsible.length === 1) {
      $collapsible.removeClass('collapsible');
      $collapsible.find('h3').remove();
      $toggle.remove();

      return;
    }

    $toggle.click(function() {
      var $this = $(this);

      if ($this.hasClass('close-all')) {
        $this.text('Open All');
        $collapsible.removeClass('active');

      } else {
        $this.text('Close All');
        $collapsible.addClass('active');

      }

      Fae.tables.sizeFixedHeader();

      $this.toggleClass('close-all');
    });

    $('.collapsible h3').click(function() {
      var $this = $(this);
      /** @type {Boolean} */
      var toggleHasCloseAll = $toggle.hasClass('close-all');

      $this.parent().toggleClass('active');

      // Change toggle messaging as appropriate
      // First check if there are open drawers
      if ($('.collapsible.active').length > 1) {

        // Change toggle text if it isn't already close all
        if(!toggleHasCloseAll) {
          $toggle.text('Close All');
          $toggle.addClass('close-all');
        }
      } else {

        // Change toggle text if it isn't already open all
        if(toggleHasCloseAll) {
          $toggle.text('Open All');
          $toggle.removeClass('close-all');
        }
      }

      Fae.tables.sizeFixedHeader();
    });
  },

  /**
   * Add extra space if the last item in a form is a select menu so the dropdown doesn't run off the screen or section
   * @param {String} selector - Last of type element to target
   * @deprecation remove selector arg and replace selector variable with '.content' in v2.0
   */
  endingSelectShim: function(selector) {
    $('form ' + selector + ':last-of-type').each(function() {
      var $last_item = $(this).find('.input:last-of-type');

      if( $last_item.hasClass('select') ) {
        $(this).addClass('-bottom-shim');
      }
    });
  },

  /**
   * Fix a table header to the top of the view on scroll
   */
  stickyTableHeader: function() {
    var _this = this;
    var $sticky_tables = $('.content table:not(.stuck-table)');

    // Add sticky psuedo tables after our main table to hold the fixed header
    $sticky_tables.each(function() {
      var $this = $(this);
      var $header = $this.find('thead').clone();

      var $fixed_header = $('<table />', {
        class: 'sticky-table-header stuck-table'
      });

      $fixed_header.append( $header );
      $this.after($fixed_header);

      if ($this.hasClass('tablesorter')) {
        _this.proxyStickyTableHeaderClicks($fixed_header, $this);
      }
    });

    /**
     * FCH callback for scroll - If the table header is in range, show it, otherwise hide it
     * @private
     */
    function stickyTableHeaderScroll() {
      var offset = FCH.$window.scrollTop();

      $('.sticky-table-header').each(function() {
        var $this = $(this);
        var top_offset = $this.data('table-top');
        var tableBottom = $this.data('table-bottom');

        if (offset >= top_offset && offset <= tableBottom) {
          $this.show();
        } else {
          $this.hide();
        }
      });
    }

    FCH.load.push( Fae.tables.sizeFixedHeader );
    FCH.resize.push( Fae.tables.sizeFixedHeader );
    FCH.scroll.push(stickyTableHeaderScroll);
  },

  /**
   * Proxy clicks from .sticky-table-header to underlying tablesorter instance
   */
  proxyStickyTableHeaderClicks: function($fixed_header, $sticky_table) {
    $fixed_header.on('click', 'th', function(e) {
      $sticky_table
        .find("th[data-column='" + $(e.currentTarget).data('column') + "']")
        .trigger('sort');
    });
  },

  /**
   *
   */
  replaceStickyTableHeader: function($fixed_header, $sticky_table) {
    $fixed_header.find('thead').html($sticky_table.find('thead').html());
  },

  /**
   * Cache offset and height values to spare expensive calculations on scroll
   */
  sizeFixedHeader: function() {
    var $tables = $('.content table');
    // @depreciation - change value from ternary to $('.js-content-header').outerHeight() in v2.0
    var header_height = FCH.exists('.js-content-header') ? $('.js-content-header').outerHeight() : $('.main_content-header').outerHeight();
    if(FCH.large_down) {
      header_height = $('#js-main-header').outerHeight();
    }

    /**
     * Add offset and height values per each table
     * @private
     */
    function applyOffset() {
      var $this = $(this);

      // If this is a collapsible item and the table is hidden, forget it
      if($this.parent().hasClass('collapsible') && !$this.parent().hasClass('active')) {
        return;
      }

      // Content header is not present on mobile but the main header is stuck
      if (FCH.bp.large_down) {
        header_height = $('#js-main-header').outerHeight();
      }

      var top_offset = $this.offset().top - header_height;
      var thead_height = $this.find('thead').outerHeight();
      var bottom_offset = $this.height() + top_offset - thead_height;
      var $fixed_header = $this.next('.sticky-table-header');

      // For whatever reason IE9 does not pickup the .sticky plugin
      if(!FCH.exists('.js-will-be-sticky')) {
        top_offset += header_height;
        header_height = 0;
      }

      // Force offsets to be greater than the header_height
      top_offset = Math.max(header_height, top_offset);
      bottom_offset = Math.max(header_height, bottom_offset);

      $fixed_header.data({
        'table-top' : top_offset,
        'table-bottom' : bottom_offset
      });

      $fixed_header.css({
        width: $this.outerWidth(),
        height: thead_height,
        top: header_height
      });
    }

    $tables.each( applyOffset );

    Fae.navigation.lockFooter();
  },

  /**
   * Generate a tooltip for all .js-tooltip elements using their title attribute
   */
  tooltip: function() {
    // Generate tooltip
    $('.js-tooltip').each(function() {
      var $this = $(this);
      var $tooltip_element = $('<span />', {
        class: 'tooltip',
        text: $this.attr('title')
      });

      $this.addClass('tooltip-parent');

      $this.prepend( $tooltip_element );
    });
  }
};
<|endoftext|>