diff --git a/Connections/database_functions.php b/Connections/database_functions.php index 9dbdd6e..204ce83 100644 --- a/Connections/database_functions.php +++ b/Connections/database_functions.php @@ -7,6 +7,12 @@ define("ACCOUNTING_GROUP", "Sales"); define("DEFAULT_TRANSACTION_TYPE", "Sale - Used Parts"); define("DEFAULT_SHOP_USER", "Volunteer"); +/* Change Fund - A specific amount of money for the purpose of making change. + The amount on hand should remain the same at all times; + therefore a change funds does not require replenishment. +*/ +define("CHANGE_FUND", 20); + // How many hours should the shop be open from the time a person logins? Hours display in pulldown in shop_log.php // No overtime for volunteers. :) // shop will be current shop for the 24hr day yyyy-mm-dd (currently no check for hrs, only date) diff --git a/css/transactions.css b/css/transactions.css index 180b5db..ab71579 100644 --- a/css/transactions.css +++ b/css/transactions.css @@ -21,4 +21,11 @@ form[name=FormEdit] select:focus { color: green; } +/* distinguish deposits */ +.deposit { + background-color: #FFDB58; +} +.deposit [type='checkbox'] { + display: none; +} diff --git a/include_header.html b/include_header.html index 63b3c1b..c270ff7 100644 --- a/include_header.html +++ b/include_header.html @@ -27,6 +27,7 @@ function resetTimer() + diff --git a/js/jquery.mask.js b/js/jquery.mask.js new file mode 100644 index 0000000..b591bc8 --- /dev/null +++ b/js/jquery.mask.js @@ -0,0 +1,479 @@ +/** + * jquery.mask.js + * @version: v1.11.2 + * @author: Igor Escobar + * + * Created by Igor Escobar on 2012-03-10. Please report any bug at http://blog.igorescobar.com + * + * Copyright (c) 2012 Igor Escobar http://blog.igorescobar.com + * + * The MIT License (http://www.opensource.org/licenses/mit-license.php) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +/*jshint laxbreak: true */ +/* global define */ + +// UMD (Universal Module Definition) patterns for JavaScript modules that work everywhere. +// https://github.com/umdjs/umd/blob/master/jqueryPlugin.js +(function (factory) { + if (typeof define === "function" && define.amd) { + // AMD. Register as an anonymous module. + define(["jquery"], factory); + } else { + // Browser globals + factory(window.jQuery || window.Zepto); + } +}(function ($) { + "use strict"; + var Mask = function (el, mask, options) { + el = $(el); + + var jMask = this, old_value = el.val(), regexMask; + + mask = typeof mask === "function" ? mask(el.val(), undefined, el, options) : mask; + + var p = { + invalid: [], + getCaret: function () { + try { + var sel, + pos = 0, + ctrl = el.get(0), + dSel = document.selection, + cSelStart = ctrl.selectionStart; + + // IE Support + if (dSel && navigator.appVersion.indexOf("MSIE 10") === -1) { + sel = dSel.createRange(); + sel.moveStart('character', el.is("input") ? -el.val().length : -el.text().length); + pos = sel.text.length; + } + // Firefox support + else if (cSelStart || cSelStart === '0') { + pos = cSelStart; + } + + return pos; + } catch (e) {} + }, + setCaret: function(pos) { + try { + if (el.is(":focus")) { + var range, ctrl = el.get(0); + + if (ctrl.setSelectionRange) { + ctrl.setSelectionRange(pos,pos); + } else if (ctrl.createTextRange) { + range = ctrl.createTextRange(); + range.collapse(true); + range.moveEnd('character', pos); + range.moveStart('character', pos); + range.select(); + } + } + } catch (e) {} + }, + events: function() { + el + .on('keyup.mask', p.behaviour) + .on("paste.mask drop.mask", function() { + setTimeout(function() { + el.keydown().keyup(); + }, 100); + }) + .on('change.mask', function(){ + el.data('changed', true); + }) + .on("blur.mask", function(){ + if (old_value !== el.val() && !el.data('changed')) { + el.trigger("change"); + } + el.data('changed', false); + }) + // it's very important that this callback remains in this position + // otherwhise old_value it's going to work buggy + .on('keydown.mask, blur.mask', function() { + old_value = el.val(); + }) + // select all text on focus + .on('focus.mask', function (e) { + if (options.selectOnFocus === true) { + $(e.target).select(); + } + }) + // clear the value if it not complete the mask + .on("focusout.mask", function() { + if (options.clearIfNotMatch && !regexMask.test(p.val())) { + p.val(''); + } + }); + }, + getRegexMask: function() { + var maskChunks = [], translation, pattern, optional, recursive, oRecursive, r; + + for (var i = 0; i < mask.length; i++) { + translation = jMask.translation[mask[i]]; + + if (translation) { + + pattern = translation.pattern.toString().replace(/.{1}$|^.{1}/g, ""); + optional = translation.optional; + recursive = translation.recursive; + + if (recursive) { + maskChunks.push(mask[i]); + oRecursive = {digit: mask[i], pattern: pattern}; + } else { + maskChunks.push(!optional && !recursive ? pattern : (pattern + "?")); + } + + } else { + maskChunks.push(mask[i].replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')); + } + } + + r = maskChunks.join(""); + + if (oRecursive) { + r = r.replace(new RegExp("(" + oRecursive.digit + "(.*" + oRecursive.digit + ")?)"), "($1)?") + .replace(new RegExp(oRecursive.digit, "g"), oRecursive.pattern); + } + + return new RegExp(r); + }, + destroyEvents: function() { + el.off(['keydown', 'keyup', 'paste', 'drop', 'blur', 'focusout', ''].join('.mask ')); + }, + val: function(v) { + var isInput = el.is('input'), + method = isInput ? 'val' : 'text', + r; + + if (arguments.length > 0) { + if (el[method]() !== v) { + el[method](v); + } + r = el; + } else { + r = el[method](); + } + + return r; + }, + getMCharsBeforeCount: function(index, onCleanVal) { + for (var count = 0, i = 0, maskL = mask.length; i < maskL && i < index; i++) { + if (!jMask.translation[mask.charAt(i)]) { + index = onCleanVal ? index + 1 : index; + count++; + } + } + return count; + }, + caretPos: function (originalCaretPos, oldLength, newLength, maskDif) { + var translation = jMask.translation[mask.charAt(Math.min(originalCaretPos - 1, mask.length - 1))]; + + return !translation ? p.caretPos(originalCaretPos + 1, oldLength, newLength, maskDif) + : Math.min(originalCaretPos + newLength - oldLength - maskDif, newLength); + }, + behaviour: function(e) { + e = e || window.event; + p.invalid = []; + var keyCode = e.keyCode || e.which; + if ($.inArray(keyCode, jMask.byPassKeys) === -1) { + + var caretPos = p.getCaret(), + currVal = p.val(), + currValL = currVal.length, + changeCaret = caretPos < currValL, + newVal = p.getMasked(), + newValL = newVal.length, + maskDif = p.getMCharsBeforeCount(newValL - 1) - p.getMCharsBeforeCount(currValL - 1); + + p.val(newVal); + + // change caret but avoid CTRL+A + if (changeCaret && !(keyCode === 65 && e.ctrlKey)) { + // Avoid adjusting caret on backspace or delete + if (!(keyCode === 8 || keyCode === 46)) { + caretPos = p.caretPos(caretPos, currValL, newValL, maskDif); + } + p.setCaret(caretPos); + } + + return p.callbacks(e); + } + }, + getMasked: function (skipMaskChars) { + var buf = [], + value = p.val(), + m = 0, maskLen = mask.length, + v = 0, valLen = value.length, + offset = 1, addMethod = "push", + resetPos = -1, + lastMaskChar, + check; + + if (options.reverse) { + addMethod = "unshift"; + offset = -1; + lastMaskChar = 0; + m = maskLen - 1; + v = valLen - 1; + check = function () { + return m > -1 && v > -1; + }; + } else { + lastMaskChar = maskLen - 1; + check = function () { + return m < maskLen && v < valLen; + }; + } + + while (check()) { + var maskDigit = mask.charAt(m), + valDigit = value.charAt(v), + translation = jMask.translation[maskDigit]; + + if (translation) { + if (valDigit.match(translation.pattern)) { + buf[addMethod](valDigit); + if (translation.recursive) { + if (resetPos === -1) { + resetPos = m; + } else if (m === lastMaskChar) { + m = resetPos - offset; + } + + if (lastMaskChar === resetPos) { + m -= offset; + } + } + m += offset; + } else if (translation.optional) { + m += offset; + v -= offset; + } else if (translation.fallback) { + buf[addMethod](translation.fallback); + m += offset; + v -= offset; + } else { + p.invalid.push({p: v, v: valDigit, e: translation.pattern}); + } + v += offset; + } else { + if (!skipMaskChars) { + buf[addMethod](maskDigit); + } + + if (valDigit === maskDigit) { + v += offset; + } + + m += offset; + } + } + + var lastMaskCharDigit = mask.charAt(lastMaskChar); + if (maskLen === valLen + 1 && !jMask.translation[lastMaskCharDigit]) { + buf.push(lastMaskCharDigit); + } + + return buf.join(""); + }, + callbacks: function (e) { + var val = p.val(), + changed = val !== old_value, + defaultArgs = [val, e, el, options], + callback = function(name, criteria, args) { + if (typeof options[name] === "function" && criteria) { + options[name].apply(this, args); + } + }; + + callback('onChange', changed === true, defaultArgs); + callback('onKeyPress', changed === true, defaultArgs); + callback('onComplete', val.length === mask.length, defaultArgs); + callback('onInvalid', p.invalid.length > 0, [val, e, el, p.invalid, options]); + } + }; + + + // public methods + jMask.mask = mask; + jMask.options = options; + jMask.remove = function() { + var caret = p.getCaret(); + p.destroyEvents(); + p.val(jMask.getCleanVal()); + p.setCaret(caret - p.getMCharsBeforeCount(caret)); + return el; + }; + + // get value without mask + jMask.getCleanVal = function() { + return p.getMasked(true); + }; + + jMask.init = function(only_mask) { + only_mask = only_mask || false; + options = options || {}; + + jMask.byPassKeys = $.jMaskGlobals.byPassKeys; + jMask.translation = $.jMaskGlobals.translation; + + jMask.translation = $.extend({}, jMask.translation, options.translation); + jMask = $.extend(true, {}, jMask, options); + + regexMask = p.getRegexMask(); + + if (only_mask === false) { + + if (options.placeholder) { + el.attr('placeholder' , options.placeholder); + } + + // autocomplete needs to be off. we can't intercept events + // the browser doesn't fire any kind of event when something is + // selected in a autocomplete list so we can't sanitize it. + el.attr('autocomplete', 'off'); + p.destroyEvents(); + p.events(); + + var caret = p.getCaret(); + p.val(p.getMasked()); + p.setCaret(caret + p.getMCharsBeforeCount(caret, true)); + + } else { + p.events(); + p.val(p.getMasked()); + } + }; + + jMask.init(!el.is("input")); + }; + + $.maskWatchers = {}; + var HTMLAttributes = function () { + var input = $(this), + options = {}, + prefix = "data-mask-", + mask = input.attr('data-mask'); + + if (input.attr(prefix + 'reverse')) { + options.reverse = true; + } + + if (input.attr(prefix + 'clearifnotmatch')) { + options.clearIfNotMatch = true; + } + + if (input.attr(prefix + 'selectonfocus') === 'true') { + options.selectOnFocus = true; + } + + if (notSameMaskObject(input, mask, options)) { + return input.data('mask', new Mask(this, mask, options)); + } + }, + notSameMaskObject = function(field, mask, options) { + options = options || {}; + var maskObject = $(field).data('mask'), + stringify = JSON.stringify, + value = $(field).val() || $(field).text(); + try { + if (typeof mask === "function") { + mask = mask(value); + } + return typeof maskObject !== "object" || stringify(maskObject.options) !== stringify(options) || maskObject.mask !== mask; + } catch (e) {} + }; + + + $.fn.mask = function(mask, options) { + options = options || {}; + var selector = this.selector, + globals = $.jMaskGlobals, + interval = $.jMaskGlobals.watchInterval, + maskFunction = function() { + if (notSameMaskObject(this, mask, options)) { + return $(this).data('mask', new Mask(this, mask, options)); + } + }; + + $(this).each(maskFunction); + + if (selector && selector !== "" && globals.watchInputs) { + clearInterval($.maskWatchers[selector]); + $.maskWatchers[selector] = setInterval(function(){ + $(document).find(selector).each(maskFunction); + }, interval); + } + return this; + }; + + $.fn.unmask = function() { + clearInterval($.maskWatchers[this.selector]); + delete $.maskWatchers[this.selector]; + return this.each(function() { + var dataMask = $(this).data('mask'); + if (dataMask) { + dataMask.remove().removeData('mask'); + } + }); + }; + + $.fn.cleanVal = function() { + return this.data('mask').getCleanVal(); + }; + + $.applyDataMask = function() { + $(document).find($.jMaskGlobals.maskElements).filter(globals.dataMaskAttr).each(HTMLAttributes); + } + + var globals = { + maskElements: 'input,td,span,div', + dataMaskAttr: '*[data-mask]', + dataMask: true, + watchInterval: 300, + watchInputs: true, + watchDataMask: false, + byPassKeys: [9, 16, 17, 18, 36, 37, 38, 39, 40, 91], + translation: { + '0': {pattern: /\d/}, + '9': {pattern: /\d/, optional: true}, + '#': {pattern: /\d/, recursive: true}, + 'A': {pattern: /[a-zA-Z0-9]/}, + 'S': {pattern: /[a-zA-Z]/} + } + }; + + $.jMaskGlobals = $.jMaskGlobals || {}; + globals = $.jMaskGlobals = $.extend(true, {}, globals, $.jMaskGlobals); + + // looking for inputs with data-mask attribute + if (globals.dataMask) { $.applyDataMask(); } + + setInterval(function(){ + if ($.jMaskGlobals.watchDataMask) { $.applyDataMask(); } + }, globals.watchInterval); +})); diff --git a/js/transaction.js b/js/transaction.js index 3b4b79e..df27c4c 100644 --- a/js/transaction.js +++ b/js/transaction.js @@ -17,7 +17,6 @@ $(function() { $.post("json/transaction.php",{ paid: 0, transaction_id: this.name } ); } }); - // editing a transaction if ( $("input[name='shop_id']").length ) { @@ -33,6 +32,9 @@ $(function() { $("input[name='payment_type']").attr("tabindex",8); $("select[name='sold_to']").attr("tabindex",9); $("select[name='sold_by']").attr("tabindex",10); + + // require that values be filled in a particular fashion + $("#date").mask("0000-00-00"); $transaction_id = $("input[name='transaction_id']").val(); @@ -47,6 +49,9 @@ $(function() { when a full date (yyyy-mm-dd) is entered. */ if ( $("#date_startstorage").length ) { + // require that values be filled in a particular fashion + $("#date_startstorage").mask("0000-00-00"); + var date_value = $("#date").val(); var date_test = /^\d{4}-((0\d)|(1[012]))-(([012]\d)|3[01])$/.test(date_value); diff --git a/transaction_log.php b/transaction_log.php index cd3d8d3..0b34afc 100644 --- a/transaction_log.php +++ b/transaction_log.php @@ -7,6 +7,7 @@ $page_individual_history_log = INDIVIDUAL_HISTORY_LOG; $storage_period = STORAGE_PERIOD; $default_transaction_type = DEFAULT_TRANSACTION_TYPE; $number_of_transactions = NUMBER_OF_TRANSACTIONS; +$change_fund = CHANGE_FUND; //transaction ID if($_GET['trans_id']>0){ @@ -405,7 +406,7 @@ if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "ChangeDate")) { } else { //This section executes if it is not the transaction_id selected NOT FOR EDIT ?>