// This is a manifest file that'll be compiled into including all the files listed below. // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically // be included in the compiled file accessible from http://example.com/assets/application.js // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // the compiled file. // //= require jquery //= require jquery_ujs //= require twitter/bootstrap //= require select2 //= require has_accounts_engine/accounting //= require has_accounts_engine/accounting-jquery //= require has_accounts_engine/bootstrap.datepicker //= require_tree . // Application specific behaviour function addAlternateTableBehaviour() { $("table.list tr:odd").addClass("odd"); } // Dirty Form function makeEditForm(form) { var buttons = form.find("fieldset.buttons"); buttons.animate({opacity: 1}, 1000); } function addDirtyForm() { $(".form-view form").dirty_form() .dirty(function(event, data){ makeEditForm($(this)); }) $(".form-view").focusin(function() {makeEditForm($(this))}); } function addNestedFormBehaviour() { $('body').on('click', '.delete-nested-form-item', function(event) { var item = $(this).parents('.nested-form-item'); // Hide item item.hide(); // Mark as ready to delete item.find("input[name$='[_destroy]']").val("1"); item.addClass('delete'); // Drop input fields to prevent browser validation problems item.find(":input").not("[name$='[_destroy]'], [name$='[id]']").remove(); // TODO: should be callbacks updatePositions($(this).parents('.nested-form-container')); updateLineItems(); // Don't follow link event.preventDefault(); }); } // Currency helpers function currencyRound(value) { if (isNaN(value)) { return 0.0; }; rounded = Math.round(value * 20) / 20; return rounded.toFixed(2); } // Line Item calculation function updateLineItemPrice(lineItem) { var list = lineItem.parent(); var reference_code = lineItem.find(":input[name$='[reference_code]']").val(); var quantity = lineItem.find(":input[name$='[quantity]']").val(); if (quantity == '%' || quantity == 'saldo_of') { var included_items; if (reference_code == '') { included_items = lineItem.prevAll('.line_item'); } else { // Should match using ~= but acts_as_taggable_adds_colons between tags included_items = list.find(":input[name$='[code]'][value='" + reference_code + "']").parents('.line_item, .saldo_line_item'); if (included_items.length == 0) { // Should match using ~= but acts_as_taggable_adds_colons between tags included_items = list.find(":input[name$='[include_in_saldo_list]'][value*='" + reference_code + "']").parents('.line_item, .saldo_line_item'); } } var price_input = lineItem.find(":input[name$='[price]']"); price_input.val(calculateTotalAmount(included_items)); } } function updateAllLineItemPrices() { $('.line_item, .saldo_line_item').each(function() { updateLineItemPrice($(this)); }); } function calculateLineItemTotalAmount(lineItem) { var times_input = lineItem.find(":input[name$='[times]']"); var times = accounting.parse(times_input.val()); if (isNaN(times)) { times = 1; }; var quantity_input = lineItem.find(":input[name$='[quantity]']"); var price_input = lineItem.find(":input[name$='[price]']"); var price = accounting.parse(price_input.val()); // For 'saldo_of' items, we don't take accounts into account if (quantity_input.val() == "saldo_of") { return currencyRound(price); }; var direct_account_id = $('#line_items').data('direct-account-id'); var direct_account_factor = $('#line_items').data('direct-account-factor'); var factor = 0; if (lineItem.find(":input[name$='[credit_account_id]']").val() == direct_account_id) { factor = 1; }; if (lineItem.find(":input[name$='[debit_account_id]']").val() == direct_account_id) { factor = -1; }; if (quantity_input.val() == '%') { times = times / 100; }; return currencyRound(times * price * factor * direct_account_factor); } function updateLineItemTotalAmount(lineItem) { var total_amount_input = lineItem.find(".total_amount"); var total_amount = accounting.formatNumber(calculateLineItemTotalAmount(lineItem)); // Update Element total_amount_input.text(total_amount); } function calculateTotalAmount(lineItems) { var total_amount = 0; $(lineItems).each(function() { total_amount += accounting.parse($(this).find(".total_amount").text()); }); return currencyRound(total_amount); } function updateLineItems() { if ($('#line_items').length > 0) { $('.line_item, .saldo_line_item').each(function() { updateLineItemPrice($(this)); updateLineItemTotalAmount($(this)); }); }; } // Recalculate after every key stroke function handleLineItemChange(event) { // If character is if(event.keyCode == 13) { // ...trigger form action $(event.currentTarget).submit(); } else if(event.keyCode == 32) { // ...trigger form action $(event.currentTarget).submit(); } else { updateLineItems(); } } function addCalculateTotalAmountBehaviour() { $("#line_items").find(":input[name$='[times]'], :input[name$='[quantity]'], :input[name$='[price]'], input[name$='[reference_code]']").on('keyup', handleLineItemChange); $("#line_items").bind("sortstop", handleLineItemChange); } // Sorting function updatePositions(collection) { var items = collection.find('.nested-form-item').not('.delete'); items.each(function(index, element) { $(this).find("input[id$='_position']").val(index + 1) }); } function initAccounting() { // accounting.js // Settings object that controls default parameters for library methods: accounting.settings = { currency: { symbol : "", // default currency symbol is '$' format: "%v", // controls output: %s = symbol, %v = value/number (can be object: see below) decimal : ".", // decimal point separator thousand: "'", // thousands separator precision : 2 // decimal places }, number: { precision : 2, // default precision on numbers is 0 thousand: "'", decimal : "." } } } // Initialize behaviours function initializeBehaviours() { // Init settings initAccounting(); // from cyt.js addComboboxBehaviour(); addAutofocusBehaviour(); addDatePickerBehaviour(); addLinkifyContainersBehaviour(); addIconTooltipBehaviour(); addModalBehaviour(); // application addAlternateTableBehaviour(); addNestedFormBehaviour(); addCalculateTotalAmountBehaviour(); updateLineItems(); // twitter bootstrap $(function () { $(".alert").alert(); $("*[rel=popover]").popover({ offset: 10 }); $('.small-tooltip').tooltip({ placement: 'right' }); }) // select2 $('.select2').select2({ allowClear: true }); $('.select2-tags').each(function(index, element) { var tags = $(element).data('tags') || ''; $(element).select2({ tags: tags, tokenSeparators: [","] }) }) } // Loads functions after DOM is ready $(document).ready(initializeBehaviours);