2012-09-30 21:15:55 +02:00
|
|
|
//= require jquery
|
|
|
|
//= require jquery-ui
|
|
|
|
//= require jquery_ujs
|
2013-06-17 16:05:23 +02:00
|
|
|
//= require select2
|
2012-10-06 17:14:57 +02:00
|
|
|
//= require twitter/bootstrap
|
2012-09-30 21:15:55 +02:00
|
|
|
//= require jquery.tokeninput
|
2013-07-07 01:47:22 +02:00
|
|
|
//= require bootstrap-datepicker/core
|
|
|
|
//= require bootstrap-datepicker/locales/bootstrap-datepicker.de
|
|
|
|
//= require bootstrap-datepicker/locales/bootstrap-datepicker.nl
|
2012-09-30 21:15:55 +02:00
|
|
|
//= require jquery.observe_field
|
|
|
|
//= require rails.validations
|
|
|
|
//= require_self
|
|
|
|
//= require ordering
|
|
|
|
|
2013-06-13 11:59:05 +02:00
|
|
|
// allow touch devices to work on click events
|
|
|
|
// http://stackoverflow.com/a/16221066
|
|
|
|
$.fn.extend({ _on: (function(){ return $.fn.on; })() });
|
|
|
|
$.fn.extend({
|
|
|
|
on: (function(){
|
|
|
|
var isTouchSupported = 'ontouchstart' in window || window.DocumentTouch && document instanceof DocumentTouch;
|
|
|
|
return function( types, selector, data, fn, one ) {
|
|
|
|
if (typeof types == 'string' && isTouchSupported && !(types.match(/touch/gi))) types = types.replace(/click/gi, 'touchstart');
|
2013-06-20 01:20:13 +02:00
|
|
|
return this._on( types, selector, data, fn, one );
|
2013-06-13 11:59:05 +02:00
|
|
|
};
|
|
|
|
}()),
|
|
|
|
});
|
|
|
|
|
2013-06-13 23:33:24 +02:00
|
|
|
// function for sorting DOM elements
|
|
|
|
$.fn.sorter = (function(){
|
|
|
|
// Thanks to James Padolsey and Avi Deitcher
|
|
|
|
// http://james.padolsey.com/javascript/sorting-elements-with-jquery/#comment-29400
|
|
|
|
var sort = [].sort;
|
|
|
|
|
|
|
|
return function(comparator, getSortable) {
|
|
|
|
getSortable = getSortable || function(){return this;};
|
|
|
|
|
|
|
|
var sorted = sort.call(this, comparator); // sort all elements in memory
|
|
|
|
var prevElmt = null;
|
|
|
|
for(i=sorted.length-1; i>=0; --i) { // loop starting from last
|
|
|
|
var criterionElmt = sorted[i];
|
|
|
|
var curElmt = ( 'function' === typeof getSortable ) ? ( getSortable.call(criterionElmt) ) : ( criterionElmt );
|
|
|
|
var parent = curElmt.parentNode;
|
|
|
|
if (!prevElmt) {
|
|
|
|
parent.appendChild(curElmt); // place last element to the end
|
|
|
|
} else {
|
|
|
|
parent.insertBefore(curElmt, prevElmt); // move each element before the previous one
|
|
|
|
}
|
|
|
|
prevElmt = curElmt;
|
|
|
|
}
|
|
|
|
return sorted;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
})();
|
|
|
|
|
2011-05-15 22:06:54 +02:00
|
|
|
// Load following statements, when DOM is ready
|
|
|
|
$(function() {
|
2011-05-19 19:49:37 +02:00
|
|
|
|
|
|
|
// Show/Hide a specific DOM element
|
2012-07-27 18:03:46 +02:00
|
|
|
$('a[data-toggle-this]').live('click', function() {
|
2011-05-19 19:49:37 +02:00
|
|
|
$($(this).data('toggle-this')).toggle();
|
2011-05-15 22:06:54 +02:00
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
2011-05-27 14:09:01 +02:00
|
|
|
// Remove this item from DOM
|
2012-07-27 18:03:46 +02:00
|
|
|
$('a[data-remove-this]').live('click', function() {
|
2011-05-27 14:09:01 +02:00
|
|
|
$($(this).data('remove-this')).remove();
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
2011-05-19 19:49:37 +02:00
|
|
|
// Check/Uncheck a single checkbox
|
|
|
|
$('[data-check-this]').live('click', function() {
|
|
|
|
var checkbox = $($(this).data('check-this'));
|
|
|
|
checkbox.attr('checked', !checkbox.is(':checked'));
|
|
|
|
highlightRow(checkbox);
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
2011-06-10 13:53:51 +02:00
|
|
|
// Check/Uncheck all checkboxes for a specific form
|
2011-05-19 19:49:37 +02:00
|
|
|
$('input[data-check-all]').live('click', function() {
|
2013-06-06 17:06:05 +02:00
|
|
|
var status = $(this).is(':checked');
|
|
|
|
var context = $(this).data('check-all');
|
|
|
|
var elms = $('input[type="checkbox"]', context);
|
|
|
|
for(i=elms.length-1; i>=0; --i) { // performance can be an issue here, so use native loop
|
|
|
|
var elm = elms[i];
|
|
|
|
elm.checked = status;
|
|
|
|
highlightRow($(elm));
|
|
|
|
}
|
2011-05-19 19:49:37 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
// Submit form when changing a select menu.
|
|
|
|
$('form[data-submit-onchange] select').live('change', function() {
|
|
|
|
var confirmMessage = $(this).children(':selected').data('confirm');
|
2012-10-28 18:03:50 +01:00
|
|
|
if (confirmMessage) {
|
|
|
|
if (confirm(confirmMessage)) {
|
|
|
|
$(this).parents('form').submit();
|
|
|
|
}
|
2011-05-19 19:49:37 +02:00
|
|
|
} else {
|
|
|
|
$(this).parents('form').submit();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
// Submit form when changing text of an input field
|
|
|
|
// Use jquery observe_field plugin
|
|
|
|
$('form[data-submit-onchange] input[type=text]').each(function() {
|
|
|
|
$(this).observe_field(1, function() {
|
|
|
|
$(this).parents('form').submit();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// Submit form when clicking on checkbox
|
|
|
|
$('form[data-submit-onchange] input[type=checkbox]:not(input[data-ignore-onchange])').click(function() {
|
|
|
|
$(this).parents('form').submit();
|
|
|
|
});
|
|
|
|
|
|
|
|
$('[data-redirect-to]').bind('change', function() {
|
|
|
|
var newLocation = $(this).children(':selected').val();
|
|
|
|
if (newLocation != "") {
|
|
|
|
document.location.href = newLocation;
|
|
|
|
}
|
|
|
|
});
|
2011-06-10 11:43:56 +02:00
|
|
|
|
|
|
|
// Remote paginations
|
|
|
|
$('div.pagination[data-remote] a').live('click', function() {
|
|
|
|
$.getScript($(this).attr('href'));
|
|
|
|
return false;
|
|
|
|
});
|
2011-06-20 00:48:05 +02:00
|
|
|
|
|
|
|
// Show and hide loader on ajax callbacks
|
|
|
|
$('*[data-remote]').bind('ajax:beforeSend', function() {
|
|
|
|
$('#loader').show();
|
|
|
|
});
|
|
|
|
|
|
|
|
$('*[data-remote]').bind('ajax:complete', function() {
|
|
|
|
$('#loader').hide();
|
|
|
|
});
|
|
|
|
|
|
|
|
// Disable submit button on ajax forms
|
|
|
|
$('form[data-remote]').bind('ajax:beforeSend', function() {
|
|
|
|
$(this).children('input[type="submit"]').attr('disabled', 'disabled');
|
|
|
|
});
|
2012-10-08 21:52:03 +02:00
|
|
|
|
|
|
|
// Use bootstrap datepicker for dateinput
|
2013-07-07 01:47:22 +02:00
|
|
|
$('.datepicker').datepicker({format: 'yyyy-mm-dd', language: I18n.locale});
|
2013-06-13 23:33:24 +02:00
|
|
|
|
|
|
|
// Init table sorting
|
2013-06-17 15:43:42 +02:00
|
|
|
var myBars = $('.sorter-bar');
|
2013-06-13 23:33:24 +02:00
|
|
|
myBars.html('<button type="button" class="sorter-button btn btn-mini"><i class="icon-chevron-up"></i></button><button type="button" class="sorter-button btn btn-mini"><i class="icon-chevron-down"></i></button>');
|
2013-06-17 15:43:42 +02:00
|
|
|
$('button:nth-child(1)', myBars).click(function(e) {sortTable(e, false);});
|
|
|
|
$('button:nth-child(2)', myBars).click(function(e) {sortTable(e, true);});
|
|
|
|
// A title attribute ('sort ascending order') would be nice here.
|
|
|
|
// However, for a tiny detail like that it is not worth to translate everything:
|
|
|
|
// http://foodsoft.51229.x6.nabble.com/How-to-I18n-content-which-is-dynamically-loaded-via-javascript-assets-td75.html#a76
|
|
|
|
|
|
|
|
// Sort tables with a default sort
|
|
|
|
$('.sorter-bar.default-sort-asc button:nth-child(1)').trigger('click');
|
|
|
|
$('.sorter-bar.default-sort-desc button:nth-child(2)').trigger('click');
|
2011-05-19 19:49:37 +02:00
|
|
|
});
|
2011-05-15 22:06:54 +02:00
|
|
|
|
2013-06-13 23:33:24 +02:00
|
|
|
// compare two elements interpreted as text
|
|
|
|
function compareText(a, b) {
|
|
|
|
return $.trim(a.textContent).toLowerCase() < $.trim(b.textContent).toLowerCase() ? -1 : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// wrapper for $.fn.sorter (see above) for sorting tables
|
|
|
|
function sortTable(e, inverted) {
|
|
|
|
var sign = ( inverted ) ? ( -1 ) : ( 1 );
|
|
|
|
|
|
|
|
var myBar = $(e.currentTarget).closest('.sorter-bar'); // bar containing the clicked up/down arrow
|
|
|
|
var sortCriterion = myBar.data('sortCriterion'); // class name of (usually td) elements which define the order
|
|
|
|
var compareFunction = myBar.data('compareFunction'); // function to compare two element contents for ordering
|
|
|
|
var sortElement = myBar.data('sortElement'); // name of function which returns the movable element (default: 'thisParent')
|
|
|
|
var myTable = myBar.closest('table'); // table to sort
|
|
|
|
|
|
|
|
sortElement = ( 'undefined' === typeof sortElement ) ? ( function() {return this.parentNode;} ) : ( window[sortElement] ); // is this dirty?
|
|
|
|
|
|
|
|
$('.' + sortCriterion, myTable).sorter(
|
|
|
|
function(a, b) {
|
|
|
|
return sign*window[compareFunction](a, b); // again dirty?
|
|
|
|
},
|
|
|
|
sortElement
|
|
|
|
);
|
|
|
|
|
|
|
|
$('.sorter-button', myTable).removeClass('btn-primary active');
|
|
|
|
$(e.currentTarget).addClass('btn-primary active');
|
|
|
|
}
|
|
|
|
|
2013-06-17 15:43:42 +02:00
|
|
|
// retrigger last sort function for elements in a context (e.g. after DOM update)
|
|
|
|
function updateSort(context) {
|
|
|
|
$('.sorter-bar button.active.btn-primary', context).trigger('click');
|
2013-06-13 23:33:24 +02:00
|
|
|
}
|
2009-01-06 11:49:19 +01:00
|
|
|
|
|
|
|
// gives the row an yellow background
|
2013-06-06 17:09:22 +02:00
|
|
|
function highlightRow(checkbox) {
|
2013-06-13 23:33:24 +02:00
|
|
|
var row = checkbox.closest('tr');
|
|
|
|
if (checkbox.is(':checked')) {
|
|
|
|
row.addClass('selected');
|
|
|
|
} else {
|
|
|
|
row.removeClass('selected');
|
|
|
|
}
|
2009-01-06 11:49:19 +01:00
|
|
|
}
|
2009-02-09 20:12:56 +01:00
|
|
|
|
|
|
|
// Use with auto_complete to set a unique id,
|
|
|
|
// e.g. when the user selects a (may not unique) name
|
|
|
|
// There must be a hidden field with the id 'hidden_field'
|
|
|
|
function setHiddenId(text, li) {
|
|
|
|
$('hidden_id').value = li.id;
|
2013-06-13 23:33:24 +02:00
|
|
|
}
|