diff --git a/cdn/js/bootstrap-fileupload.js b/cdn/js/bootstrap-fileupload.js
new file mode 100755
index 0000000..e205f31
--- /dev/null
+++ b/cdn/js/bootstrap-fileupload.js
@@ -0,0 +1,125 @@
+/* ===========================================================
+ * bootstrap-fileupload.js j1a
+ * http://jasny.github.com/bootstrap/javascript.html#fileupload
+ * ===========================================================
+ * Copyright 2012 Jasny BV, Netherlands.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+!function ($) {
+
+ "use strict"; // jshint ;_
+
+ /* INPUTMASK PUBLIC CLASS DEFINITION
+ * ================================= */
+
+ var Fileupload = function (element, options) {
+ this.$element = $(element)
+ this.type = this.$element.data('uploadtype') || (this.$element.find('.thumbnail').length > 0 ? "image" : "file")
+
+ this.$input = this.$element.find(':file')
+ if (this.$input.length === 0) return
+
+ this.name = this.$input.attr('name') || options.name
+
+ this.$hidden = this.$element.find(':hidden[name="'+this.name+'"]')
+ if (this.$hidden.length === 0) {
+ this.$hidden = $('')
+ this.$element.prepend(this.$hidden)
+ }
+
+ this.$preview = this.$element.find('.fileupload-preview')
+ var height = this.$preview.css('height')
+ if (this.$preview.css('display') != 'inline' && height != '0px' && height != 'none') this.$preview.css('line-height', height)
+
+ this.$remove = this.$element.find('[data-dismiss="fileupload"]')
+
+ this.listen()
+ }
+
+ Fileupload.prototype = {
+
+ listen: function() {
+ this.$input.on('change.fileupload', $.proxy(this.change, this))
+ if (this.$remove) this.$remove.on('click.fileupload', $.proxy(this.clear, this))
+ },
+
+ change: function(e, invoked) {
+ var file = e.target.files !== undefined ? e.target.files[0] : { name: e.target.value.replace(/^.+\\/, '') }
+ if (!file || invoked === 'clear') return
+
+ this.$hidden.attr('name', '')
+ this.$input.attr('name', this.name)
+
+ if (this.type === "image" && this.$preview.length > 0 && (typeof file.type !== "undefined" ? file.type.match('image.*') : file.name.match('\\.(gif|png|jpe?g)$')) && typeof FileReader !== "undefined") {
+ var reader = new FileReader()
+ var preview = this.$preview
+ var element = this.$element
+
+ reader.onload = function(e) {
+ preview.html('')
+ element.addClass('fileupload-exists').removeClass('fileupload-new')
+ }
+
+ reader.readAsDataURL(file)
+ } else {
+ this.$preview.text(file.name)
+ this.$element.addClass('fileupload-exists').removeClass('fileupload-new')
+ }
+ },
+
+ clear: function(e) {
+ this.$hidden.val('')
+ this.$hidden.attr('name', this.name)
+ this.$input.attr('name', '')
+
+ this.$preview.html('')
+ this.$element.addClass('fileupload-new').removeClass('fileupload-exists')
+
+ this.$input.trigger('change', [ 'clear' ])
+
+ e.preventDefault()
+ return false
+ }
+ }
+
+
+ /* INPUTMASK PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.fileupload = function (options) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('fileupload')
+ if (!data) $this.data('fileupload', (data = new Fileupload(this, options)))
+ })
+ }
+
+ $.fn.fileupload.Constructor = Fileupload
+
+
+ /* INPUTMASK DATA-API
+ * ================== */
+
+ $(function () {
+ $('body').on('click.fileupload.data-api', '[data-provides="fileupload"]', function (e) {
+ var $this = $(this)
+ if ($this.data('fileupload')) return
+ $this.fileupload($this.data())
+
+ if ($(e.target).data('dismiss') == 'fileupload') $(e.target).trigger('click.fileupload')
+ })
+ })
+
+}(window.jQuery)
diff --git a/cdn/js/bootstrap-inputmask.js b/cdn/js/bootstrap-inputmask.js
new file mode 100755
index 0000000..f741408
--- /dev/null
+++ b/cdn/js/bootstrap-inputmask.js
@@ -0,0 +1,361 @@
+/* ===========================================================
+ * bootstrap-inputmask.js j1
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
+ * Based on Masked Input plugin by Josh Bush (digitalbush.com)
+ * ===========================================================
+ * Copyright 2012 Jasny BV, Netherlands.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+ var isIphone = (window.orientation !== undefined),
+ isAndroid = navigator.userAgent.toLowerCase().indexOf("android") > -1
+
+ $.mask = {
+ //Predefined character definitions
+ definitions: {
+ '9': "[0-9]",
+ 'a': "[A-Za-z]",
+ '?': "[A-Za-z0-9]",
+ '*': "."
+ },
+ dataName:"rawMaskFn"
+ }
+
+
+ /* INPUTMASK PUBLIC CLASS DEFINITION
+ * ================================= */
+
+ var Inputmask = function (element, options) {
+ if (isAndroid) return // No support because caret positioning doesn't work on Android
+
+ this.$element = $(element)
+ this.mask = options.mask
+ this.options = $.extend({}, $.fn.inputmask.defaults, options)
+
+ this.init()
+ this.listen()
+
+ this.checkVal() //Perform initial check for existing values
+ }
+
+ Inputmask.prototype = {
+
+ init: function() {
+ var defs = $.mask.definitions
+ var len = this.mask.length
+
+ this.tests = []
+ this.partialPosition = this.mask.length
+ this.firstNonMaskPos = null
+
+ $.each(this.mask.split(""), $.proxy(function(i, c) {
+ if (c == '?') {
+ len--
+ this.partialPosition = i
+ } else if (defs[c]) {
+ this.tests.push(new RegExp(defs[c]))
+ if(this.firstNonMaskPos === null)
+ this.firstNonMaskPos = this.tests.length - 1
+ } else {
+ this.tests.push(null)
+ }
+ }, this))
+
+ this.buffer = $.map(this.mask.split(""), $.proxy(function(c, i) {
+ if (c != '?') return defs[c] ? this.options.placeholder : c
+ }, this))
+
+ this.focusText = this.$element.val()
+
+ this.$element.data($.mask.dataName, $.proxy(function() {
+ return $.map(this.buffer, function(c, i) {
+ return this.tests[i] && c != this.options.placeholder ? c : null
+ }).join('')
+ }, this))
+ },
+
+ listen: function() {
+ if (this.$element.attr("readonly")) return
+
+ var pasteEventName = ($.browser.msie ? 'paste' : 'input') + ".mask"
+
+ this.$element
+ .on("unmask", $.proxy(this.unmask, this))
+
+ .on("focus.mask", $.proxy(this.focusEvent, this))
+ .on("blur.mask", $.proxy(this.blurEvent, this))
+
+ .on("keydown.mask", $.proxy(this.keydownEvent, this))
+ .on("keypress.mask", $.proxy(this.keypressEvent, this))
+
+ .on(pasteEventName, $.proxy(this.pasteEvent, this))
+ },
+
+ //Helper Function for Caret positioning
+ caret: function(begin, end) {
+ if (this.$element.length === 0) return
+ if (typeof begin == 'number') {
+ end = (typeof end == 'number') ? end : begin
+ return this.$element.each(function() {
+ if (this.setSelectionRange) {
+ this.setSelectionRange(begin, end)
+ } else if (this.createTextRange) {
+ var range = this.createTextRange()
+ range.collapse(true)
+ range.moveEnd('character', end)
+ range.moveStart('character', begin)
+ range.select()
+ }
+ })
+ } else {
+ if (this.$element[0].setSelectionRange) {
+ begin = this.$element[0].selectionStart
+ end = this.$element[0].selectionEnd
+ } else if (document.selection && document.selection.createRange) {
+ var range = document.selection.createRange()
+ begin = 0 - range.duplicate().moveStart('character', -100000)
+ end = begin + range.text.length
+ }
+ return {
+ begin: begin,
+ end: end
+ }
+ }
+ },
+
+ seekNext: function(pos) {
+ var len = this.mask.length
+ while (++pos <= len && !this.tests[pos]);
+
+ return pos
+ },
+
+ seekPrev: function(pos) {
+ while (--pos >= 0 && !this.tests[pos]);
+
+ return pos
+ },
+
+ shiftL: function(begin,end) {
+ var len = this.mask.length
+
+ if(begin<0) return
+
+ for (var i = begin,j = this.seekNext(end); i < len; i++) {
+ if (this.tests[i]) {
+ if (j < len && this.tests[i].test(this.buffer[j])) {
+ this.buffer[i] = this.buffer[j]
+ this.buffer[j] = this.options.placeholder
+ } else
+ break
+ j = this.seekNext(j)
+ }
+ }
+ this.writeBuffer()
+ this.caret(Math.max(this.firstNonMaskPos, begin))
+ },
+
+ shiftR: function(pos) {
+ var len = this.mask.length
+
+ for (var i = pos, c = this.options.placeholder; i < len; i++) {
+ if (this.tests[i]) {
+ var j = this.seekNext(i)
+ var t = this.buffer[i]
+ this.buffer[i] = c
+ if (j < len && this.tests[j].test(t))
+ c = t
+ else
+ break
+ }
+ }
+ },
+
+ unmask: function() {
+ this.$element
+ .unbind(".mask")
+ .removeData("inputmask")
+ },
+
+ focusEvent: function() {
+ this.focusText = this.$element.val()
+ var len = this.mask.length
+ var pos = this.checkVal()
+ this.writeBuffer()
+
+ var that = this
+ var moveCaret = function() {
+ if (pos == len)
+ that.caret(0, pos)
+ else
+ that.caret(pos)
+ }
+
+ if ($.browser.msie)
+ moveCaret()
+ else
+ setTimeout(moveCaret, 0)
+ },
+
+ blurEvent: function() {
+ this.checkVal()
+ if (this.$element.val() != this.focusText)
+ this.$element.trigger('change')
+ },
+
+ keydownEvent: function(e) {
+ var k=e.which
+
+ //backspace, delete, and escape get special treatment
+ if (k == 8 || k == 46 || (isIphone && k == 127)) {
+ var pos = this.caret(),
+ begin = pos.begin,
+ end = pos.end
+
+ if (end-begin === 0) {
+ begin = k!=46 ? this.seekPrev(begin) : (end=this.seekNext(begin-1))
+ end = k==46 ? this.seekNext(end) : end
+ }
+ this.clearBuffer(begin, end)
+ this.shiftL(begin,end-1)
+
+ return false
+ } else if (k == 27) {//escape
+ this.$element.val(this.focusText)
+ this.caret(0, this.checkVal())
+ return false
+ }
+ },
+
+ keypressEvent: function(e) {
+ var len = this.mask.length
+
+ var k = e.which,
+ pos = this.caret()
+
+ if (e.ctrlKey || e.altKey || e.metaKey || k<32) {//Ignore
+ return true
+ } else if (k) {
+ if (pos.end - pos.begin !== 0) {
+ this.clearBuffer(pos.begin, pos.end)
+ this.shiftL(pos.begin, pos.end-1)
+ }
+
+ var p = this.seekNext(pos.begin - 1)
+ if (p < len) {
+ var c = String.fromCharCode(k)
+ if (this.tests[p].test(c)) {
+ this.shiftR(p)
+ this.buffer[p] = c
+ this.writeBuffer()
+ var next = this.seekNext(p)
+ this.caret(next)
+ }
+ }
+ return false
+ }
+ },
+
+ pasteEvent: function() {
+ var that = this
+
+ setTimeout(function() {
+ that.caret(that.checkVal(true))
+ }, 0)
+ },
+
+ clearBuffer: function(start, end) {
+ var len = this.mask.length
+
+ for (var i = start; i < end && i < len; i++) {
+ if (this.tests[i])
+ this.buffer[i] = this.options.placeholder
+ }
+ },
+
+ writeBuffer: function() {
+ return this.$element.val(this.buffer.join('')).val()
+ },
+
+ checkVal: function(allow) {
+ var len = this.mask.length
+ //try to place characters where they belong
+ var test = this.$element.val()
+ var lastMatch = -1
+
+ for (var i = 0, pos = 0; i < len; i++) {
+ if (this.tests[i]) {
+ this.buffer[i] = this.options.placeholder
+ while (pos++ < test.length) {
+ var c = test.charAt(pos - 1)
+ if (this.tests[i].test(c)) {
+ this.buffer[i] = c
+ lastMatch = i
+ break
+ }
+ }
+ if (pos > test.length)
+ break
+ } else if (this.buffer[i] == test.charAt(pos) && i != this.partialPosition) {
+ pos++
+ lastMatch = i
+ }
+ }
+ if (!allow && lastMatch + 1 < this.partialPosition) {
+ this.$element.val("")
+ this.clearBuffer(0, len)
+ } else if (allow || lastMatch + 1 >= this.partialPosition) {
+ this.writeBuffer()
+ if (!allow) this.$element.val(this.$element.val().substring(0, lastMatch + 1))
+ }
+ return (this.partialPosition ? i : this.firstNonMaskPos)
+ }
+ }
+
+
+ /* INPUTMASK PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.inputmask = function (options) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('inputmask')
+ if (!data) $this.data('inputmask', (data = new Inputmask(this, options)))
+ })
+ }
+
+ $.fn.inputmask.defaults = {
+ placeholder: "_"
+ }
+
+ $.fn.inputmask.Constructor = Inputmask
+
+
+ /* INPUTMASK DATA-API
+ * ================== */
+
+ $(function () {
+ $('body').on('focus.inputmask.data-api', '[data-mask]', function (e) {
+ var $this = $(this)
+ if ($this.data('inputmask')) return
+ e.preventDefault()
+ $this.inputmask($this.data())
+ })
+ })
+
+}(window.jQuery)
\ No newline at end of file
diff --git a/cdn/js/bootstrap-rowlink.js b/cdn/js/bootstrap-rowlink.js
new file mode 100755
index 0000000..7c8259f
--- /dev/null
+++ b/cdn/js/bootstrap-rowlink.js
@@ -0,0 +1,71 @@
+/* ============================================================
+ * bootstrap-rowlink.js j1
+ * http://jasny.github.com/bootstrap/javascript.html#rowlink
+ * ============================================================
+ * Copyright 2012 Jasny BV, Netherlands.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+ var Rowlink = function (element, options) {
+ options = $.extend({}, $.fn.rowlink.defaults, options)
+ var tr = element.nodeName == 'tr' ? $(element) : $(element).find('tr:has(td)')
+
+ tr.each(function() {
+ var link = $(this).find(options.target).first()
+ if (!link.length) return
+
+ var href = link.attr('href')
+
+ $(this).find('td').not('.nolink').click(function() {
+ window.location = href;
+ })
+
+ $(this).addClass('rowlink')
+ link.replaceWith(link.html())
+ })
+ }
+
+
+ /* ROWLINK PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.rowlink = function (options) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('rowlink')
+ if (!data) $this.data('rowlink', (data = new Rowlink(this, options)))
+ })
+ }
+
+ $.fn.rowlink.defaults = {
+ target: "a"
+ }
+
+ $.fn.rowlink.Constructor = Rowlink
+
+
+ /* ROWLINK DATA-API
+ * ================== */
+
+ $(function () {
+ $('[data-provides="rowlink"]').each(function () {
+ $(this).rowlink($(this).data())
+ })
+ })
+
+}(window.jQuery)
diff --git a/cdn/js/jasny-bootstrap.js b/cdn/js/jasny-bootstrap.js
new file mode 100755
index 0000000..a54e621
--- /dev/null
+++ b/cdn/js/jasny-bootstrap.js
@@ -0,0 +1,557 @@
+/* ===========================================================
+ * bootstrap-inputmask.js j1
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
+ * Based on Masked Input plugin by Josh Bush (digitalbush.com)
+ * ===========================================================
+ * Copyright 2012 Jasny BV, Netherlands.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+ var isIphone = (window.orientation !== undefined),
+ isAndroid = navigator.userAgent.toLowerCase().indexOf("android") > -1
+
+ $.mask = {
+ //Predefined character definitions
+ definitions: {
+ '9': "[0-9]",
+ 'a': "[A-Za-z]",
+ '?': "[A-Za-z0-9]",
+ '*': "."
+ },
+ dataName:"rawMaskFn"
+ }
+
+
+ /* INPUTMASK PUBLIC CLASS DEFINITION
+ * ================================= */
+
+ var Inputmask = function (element, options) {
+ if (isAndroid) return // No support because caret positioning doesn't work on Android
+
+ this.$element = $(element)
+ this.mask = options.mask
+ this.options = $.extend({}, $.fn.inputmask.defaults, options)
+
+ this.init()
+ this.listen()
+
+ this.checkVal() //Perform initial check for existing values
+ }
+
+ Inputmask.prototype = {
+
+ init: function() {
+ var defs = $.mask.definitions
+ var len = this.mask.length
+
+ this.tests = []
+ this.partialPosition = this.mask.length
+ this.firstNonMaskPos = null
+
+ $.each(this.mask.split(""), $.proxy(function(i, c) {
+ if (c == '?') {
+ len--
+ this.partialPosition = i
+ } else if (defs[c]) {
+ this.tests.push(new RegExp(defs[c]))
+ if(this.firstNonMaskPos === null)
+ this.firstNonMaskPos = this.tests.length - 1
+ } else {
+ this.tests.push(null)
+ }
+ }, this))
+
+ this.buffer = $.map(this.mask.split(""), $.proxy(function(c, i) {
+ if (c != '?') return defs[c] ? this.options.placeholder : c
+ }, this))
+
+ this.focusText = this.$element.val()
+
+ this.$element.data($.mask.dataName, $.proxy(function() {
+ return $.map(this.buffer, function(c, i) {
+ return this.tests[i] && c != this.options.placeholder ? c : null
+ }).join('')
+ }, this))
+ },
+
+ listen: function() {
+ if (this.$element.attr("readonly")) return
+
+ var pasteEventName = ($.browser.msie ? 'paste' : 'input') + ".mask"
+
+ this.$element
+ .on("unmask", $.proxy(this.unmask, this))
+
+ .on("focus.mask", $.proxy(this.focusEvent, this))
+ .on("blur.mask", $.proxy(this.blurEvent, this))
+
+ .on("keydown.mask", $.proxy(this.keydownEvent, this))
+ .on("keypress.mask", $.proxy(this.keypressEvent, this))
+
+ .on(pasteEventName, $.proxy(this.pasteEvent, this))
+ },
+
+ //Helper Function for Caret positioning
+ caret: function(begin, end) {
+ if (this.$element.length === 0) return
+ if (typeof begin == 'number') {
+ end = (typeof end == 'number') ? end : begin
+ return this.$element.each(function() {
+ if (this.setSelectionRange) {
+ this.setSelectionRange(begin, end)
+ } else if (this.createTextRange) {
+ var range = this.createTextRange()
+ range.collapse(true)
+ range.moveEnd('character', end)
+ range.moveStart('character', begin)
+ range.select()
+ }
+ })
+ } else {
+ if (this.$element[0].setSelectionRange) {
+ begin = this.$element[0].selectionStart
+ end = this.$element[0].selectionEnd
+ } else if (document.selection && document.selection.createRange) {
+ var range = document.selection.createRange()
+ begin = 0 - range.duplicate().moveStart('character', -100000)
+ end = begin + range.text.length
+ }
+ return {
+ begin: begin,
+ end: end
+ }
+ }
+ },
+
+ seekNext: function(pos) {
+ var len = this.mask.length
+ while (++pos <= len && !this.tests[pos]);
+
+ return pos
+ },
+
+ seekPrev: function(pos) {
+ while (--pos >= 0 && !this.tests[pos]);
+
+ return pos
+ },
+
+ shiftL: function(begin,end) {
+ var len = this.mask.length
+
+ if(begin<0) return
+
+ for (var i = begin,j = this.seekNext(end); i < len; i++) {
+ if (this.tests[i]) {
+ if (j < len && this.tests[i].test(this.buffer[j])) {
+ this.buffer[i] = this.buffer[j]
+ this.buffer[j] = this.options.placeholder
+ } else
+ break
+ j = this.seekNext(j)
+ }
+ }
+ this.writeBuffer()
+ this.caret(Math.max(this.firstNonMaskPos, begin))
+ },
+
+ shiftR: function(pos) {
+ var len = this.mask.length
+
+ for (var i = pos, c = this.options.placeholder; i < len; i++) {
+ if (this.tests[i]) {
+ var j = this.seekNext(i)
+ var t = this.buffer[i]
+ this.buffer[i] = c
+ if (j < len && this.tests[j].test(t))
+ c = t
+ else
+ break
+ }
+ }
+ },
+
+ unmask: function() {
+ this.$element
+ .unbind(".mask")
+ .removeData("inputmask")
+ },
+
+ focusEvent: function() {
+ this.focusText = this.$element.val()
+ var len = this.mask.length
+ var pos = this.checkVal()
+ this.writeBuffer()
+
+ var that = this
+ var moveCaret = function() {
+ if (pos == len)
+ that.caret(0, pos)
+ else
+ that.caret(pos)
+ }
+
+ if ($.browser.msie)
+ moveCaret()
+ else
+ setTimeout(moveCaret, 0)
+ },
+
+ blurEvent: function() {
+ this.checkVal()
+ if (this.$element.val() != this.focusText)
+ this.$element.trigger('change')
+ },
+
+ keydownEvent: function(e) {
+ var k=e.which
+
+ //backspace, delete, and escape get special treatment
+ if (k == 8 || k == 46 || (isIphone && k == 127)) {
+ var pos = this.caret(),
+ begin = pos.begin,
+ end = pos.end
+
+ if (end-begin === 0) {
+ begin = k!=46 ? this.seekPrev(begin) : (end=this.seekNext(begin-1))
+ end = k==46 ? this.seekNext(end) : end
+ }
+ this.clearBuffer(begin, end)
+ this.shiftL(begin,end-1)
+
+ return false
+ } else if (k == 27) {//escape
+ this.$element.val(this.focusText)
+ this.caret(0, this.checkVal())
+ return false
+ }
+ },
+
+ keypressEvent: function(e) {
+ var len = this.mask.length
+
+ var k = e.which,
+ pos = this.caret()
+
+ if (e.ctrlKey || e.altKey || e.metaKey || k<32) {//Ignore
+ return true
+ } else if (k) {
+ if (pos.end - pos.begin !== 0) {
+ this.clearBuffer(pos.begin, pos.end)
+ this.shiftL(pos.begin, pos.end-1)
+ }
+
+ var p = this.seekNext(pos.begin - 1)
+ if (p < len) {
+ var c = String.fromCharCode(k)
+ if (this.tests[p].test(c)) {
+ this.shiftR(p)
+ this.buffer[p] = c
+ this.writeBuffer()
+ var next = this.seekNext(p)
+ this.caret(next)
+ }
+ }
+ return false
+ }
+ },
+
+ pasteEvent: function() {
+ var that = this
+
+ setTimeout(function() {
+ that.caret(that.checkVal(true))
+ }, 0)
+ },
+
+ clearBuffer: function(start, end) {
+ var len = this.mask.length
+
+ for (var i = start; i < end && i < len; i++) {
+ if (this.tests[i])
+ this.buffer[i] = this.options.placeholder
+ }
+ },
+
+ writeBuffer: function() {
+ return this.$element.val(this.buffer.join('')).val()
+ },
+
+ checkVal: function(allow) {
+ var len = this.mask.length
+ //try to place characters where they belong
+ var test = this.$element.val()
+ var lastMatch = -1
+
+ for (var i = 0, pos = 0; i < len; i++) {
+ if (this.tests[i]) {
+ this.buffer[i] = this.options.placeholder
+ while (pos++ < test.length) {
+ var c = test.charAt(pos - 1)
+ if (this.tests[i].test(c)) {
+ this.buffer[i] = c
+ lastMatch = i
+ break
+ }
+ }
+ if (pos > test.length)
+ break
+ } else if (this.buffer[i] == test.charAt(pos) && i != this.partialPosition) {
+ pos++
+ lastMatch = i
+ }
+ }
+ if (!allow && lastMatch + 1 < this.partialPosition) {
+ this.$element.val("")
+ this.clearBuffer(0, len)
+ } else if (allow || lastMatch + 1 >= this.partialPosition) {
+ this.writeBuffer()
+ if (!allow) this.$element.val(this.$element.val().substring(0, lastMatch + 1))
+ }
+ return (this.partialPosition ? i : this.firstNonMaskPos)
+ }
+ }
+
+
+ /* INPUTMASK PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.inputmask = function (options) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('inputmask')
+ if (!data) $this.data('inputmask', (data = new Inputmask(this, options)))
+ })
+ }
+
+ $.fn.inputmask.defaults = {
+ placeholder: "_"
+ }
+
+ $.fn.inputmask.Constructor = Inputmask
+
+
+ /* INPUTMASK DATA-API
+ * ================== */
+
+ $(function () {
+ $('body').on('focus.inputmask.data-api', '[data-mask]', function (e) {
+ var $this = $(this)
+ if ($this.data('inputmask')) return
+ e.preventDefault()
+ $this.inputmask($this.data())
+ })
+ })
+
+}(window.jQuery)/* ============================================================
+ * bootstrap-rowlink.js j1
+ * http://jasny.github.com/bootstrap/javascript.html#rowlink
+ * ============================================================
+ * Copyright 2012 Jasny BV, Netherlands.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+ var Rowlink = function (element, options) {
+ options = $.extend({}, $.fn.rowlink.defaults, options)
+ var tr = element.nodeName == 'tr' ? $(element) : $(element).find('tr:has(td)')
+
+ tr.each(function() {
+ var link = $(this).find(options.target).first()
+ if (!link.length) return
+
+ var href = link.attr('href')
+
+ $(this).find('td').not('.nolink').click(function() {
+ window.location = href;
+ })
+
+ $(this).addClass('rowlink')
+ link.replaceWith(link.html())
+ })
+ }
+
+
+ /* ROWLINK PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.rowlink = function (options) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('rowlink')
+ if (!data) $this.data('rowlink', (data = new Rowlink(this, options)))
+ })
+ }
+
+ $.fn.rowlink.defaults = {
+ target: "a"
+ }
+
+ $.fn.rowlink.Constructor = Rowlink
+
+
+ /* ROWLINK DATA-API
+ * ================== */
+
+ $(function () {
+ $('[data-provides="rowlink"]').each(function () {
+ $(this).rowlink($(this).data())
+ })
+ })
+
+}(window.jQuery)
+/* ===========================================================
+ * bootstrap-fileupload.js j1a
+ * http://jasny.github.com/bootstrap/javascript.html#fileupload
+ * ===========================================================
+ * Copyright 2012 Jasny BV, Netherlands.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+!function ($) {
+
+ "use strict"; // jshint ;_
+
+ /* INPUTMASK PUBLIC CLASS DEFINITION
+ * ================================= */
+
+ var Fileupload = function (element, options) {
+ this.$element = $(element)
+ this.type = this.$element.data('uploadtype') || (this.$element.find('.thumbnail').length > 0 ? "image" : "file")
+
+ this.$input = this.$element.find(':file')
+ if (this.$input.length === 0) return
+
+ this.name = this.$input.attr('name') || options.name
+
+ this.$hidden = this.$element.find(':hidden[name="'+this.name+'"]')
+ if (this.$hidden.length === 0) {
+ this.$hidden = $('')
+ this.$element.prepend(this.$hidden)
+ }
+
+ this.$preview = this.$element.find('.fileupload-preview')
+ var height = this.$preview.css('height')
+ if (this.$preview.css('display') != 'inline' && height != '0px' && height != 'none') this.$preview.css('line-height', height)
+
+ this.$remove = this.$element.find('[data-dismiss="fileupload"]')
+
+ this.listen()
+ }
+
+ Fileupload.prototype = {
+
+ listen: function() {
+ this.$input.on('change.fileupload', $.proxy(this.change, this))
+ if (this.$remove) this.$remove.on('click.fileupload', $.proxy(this.clear, this))
+ },
+
+ change: function(e, invoked) {
+ var file = e.target.files !== undefined ? e.target.files[0] : { name: e.target.value.replace(/^.+\\/, '') }
+ if (!file || invoked === 'clear') return
+
+ this.$hidden.val('')
+ this.$hidden.attr('name', '')
+ this.$input.attr('name', this.name)
+
+ if (this.type === "image" && this.$preview.length > 0 && (typeof file.type !== "undefined" ? file.type.match('image.*') : file.name.match('\\.(gif|png|jpe?g)$')) && typeof FileReader !== "undefined") {
+ var reader = new FileReader()
+ var preview = this.$preview
+ var element = this.$element
+
+ reader.onload = function(e) {
+ preview.html('
')
+ element.addClass('fileupload-exists').removeClass('fileupload-new')
+ }
+
+ reader.readAsDataURL(file)
+ } else {
+ this.$preview.text(file.name)
+ this.$element.addClass('fileupload-exists').removeClass('fileupload-new')
+ }
+ },
+
+ clear: function(e) {
+ this.$hidden.val('')
+ this.$hidden.attr('name', this.name)
+ this.$input.attr('name', '')
+
+ this.$preview.html('')
+ this.$element.addClass('fileupload-new').removeClass('fileupload-exists')
+
+ this.$input.trigger('change', [ 'clear' ])
+
+ e.preventDefault()
+ return false
+ }
+ }
+
+
+ /* INPUTMASK PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.fileupload = function (options) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('fileupload')
+ if (!data) $this.data('fileupload', (data = new Fileupload(this, options)))
+ })
+ }
+
+ $.fn.fileupload.Constructor = Fileupload
+
+
+ /* INPUTMASK DATA-API
+ * ================== */
+
+ $(function () {
+ $('body').on('click.fileupload.data-api', '[data-provides="fileupload"]', function (e) {
+ var $this = $(this)
+ if ($this.data('fileupload')) return
+ $this.fileupload($this.data())
+
+ if ($(e.target).data('dismiss') == 'fileupload') $(e.target).trigger('click.fileupload')
+ })
+ })
+
+}(window.jQuery)
diff --git a/cdn/js/jasny-bootstrap.min.js b/cdn/js/jasny-bootstrap.min.js
index 1dc034f..d5d873e 100755
--- a/cdn/js/jasny-bootstrap.min.js
+++ b/cdn/js/jasny-bootstrap.min.js
@@ -1 +1,6 @@
-!function(a){"use strict";var b=function(b,c){this.$element=a(b);this.options=a.extend({},a.fn.timepicker.defaults,c,this.$element.data());this.minuteStep=this.options.minuteStep||this.minuteStep;this.secondStep=this.options.secondStep||this.secondStep;this.showMeridian=this.options.showMeridian||this.showMeridian;this.showSeconds=this.options.showSeconds||this.showSeconds;this.showInputs=this.options.showInputs||this.showInputs;this.disableFocus=this.options.disableFocus||this.disableFocus;this.template=this.options.template||this.template;this.modalBackdrop=this.options.modalBackdrop||this.modalBackdrop;this.defaultTime=this.options.defaultTime||this.defaultTime;this.open=false;this.init()};b.prototype={constructor:b,init:function(){if(this.$element.parent().hasClass("input-append")){this.$element.parent(".input-append").find(".add-on").on("click",a.proxy(this.showWidget,this));this.$element.on({focus:a.proxy(this.highlightUnit,this),click:a.proxy(this.highlightUnit,this),keypress:a.proxy(this.elementKeypress,this),blur:a.proxy(this.blurElement,this)})}else{if(this.template){this.$element.on({focus:a.proxy(this.showWidget,this),click:a.proxy(this.showWidget,this),blur:a.proxy(this.blurElement,this)})}else{this.$element.on({focus:a.proxy(this.highlightUnit,this),click:a.proxy(this.highlightUnit,this),keypress:a.proxy(this.elementKeypress,this),blur:a.proxy(this.blurElement,this)})}}this.$widget=a(this.getTemplate()).appendTo("body");this.$widget.on("click",a.proxy(this.widgetClick,this));if(this.showInputs){this.$widget.find("input").on({click:function(){this.select()},keypress:a.proxy(this.widgetKeypress,this),change:a.proxy(this.updateFromWidgetInputs,this)})}this.setDefaultTime(this.defaultTime)},showWidget:function(b){b.stopPropagation();b.preventDefault();if(this.open){return}this.$element.trigger("show");if(this.disableFocus){this.$element.blur()}var c=a.extend({},this.$element.offset(),{height:this.$element[0].offsetHeight});this.updateFromElementVal();a("html").trigger("click.timepicker.data-api").one("click.timepicker.data-api",a.proxy(this.hideWidget,this));if(this.template==="modal"){this.$widget.modal("show").on("hidden",a.proxy(this.hideWidget,this))}else{this.$widget.css({top:c.top+c.height,left:c.left});if(!this.open){this.$widget.addClass("open")}}this.open=true;this.$element.trigger("shown")},hideWidget:function(){this.$element.trigger("hide");if(this.template==="modal"){this.$widget.modal("hide")}else{this.$widget.removeClass("open")}this.open=false;this.$element.trigger("hidden")},widgetClick:function(b){b.stopPropagation();b.preventDefault();var c=a(b.target).closest("a").data("action");if(c){this[c]();this.update()}},widgetKeypress:function(b){var c=a(b.target).closest("input").attr("name");switch(b.keyCode){case 9:if(this.showMeridian){if(c=="meridian"){this.hideWidget()}}else{if(this.showSeconds){if(c=="second"){this.hideWidget()}}else{if(c=="minute"){this.hideWidget()}}}break;case 27:this.hideWidget();break;case 38:switch(c){case"hour":this.incrementHour();break;case"minute":this.incrementMinute();break;case"second":this.incrementSecond();break;case"meridian":this.toggleMeridian();break}this.update();break;case 40:switch(c){case"hour":this.decrementHour();break;case"minute":this.decrementMinute();break;case"second":this.decrementSecond();break;case"meridian":this.toggleMeridian();break}this.update();break}},elementKeypress:function(a){var b=this.$element.get(0);switch(a.keyCode){case 0:break;case 9:this.updateFromElementVal();if(this.showMeridian){if(this.highlightedUnit!="meridian"){a.preventDefault();this.highlightNextUnit()}}else{if(this.showSeconds){if(this.highlightedUnit!="second"){a.preventDefault();this.highlightNextUnit()}}else{if(this.highlightedUnit!="minute"){a.preventDefault();this.highlightNextUnit()}}}break;case 27:this.updateFromElementVal();break;case 37:this.updateFromElementVal();this.highlightPrevUnit();break;case 38:switch(this.highlightedUnit){case"hour":this.incrementHour();break;case"minute":this.incrementMinute();break;case"second":this.incrementSecond();break;case"meridian":this.toggleMeridian();break}this.updateElement();break;case 39:this.updateFromElementVal();this.highlightNextUnit();break;case 40:switch(this.highlightedUnit){case"hour":this.decrementHour();break;case"minute":this.decrementMinute();break;case"second":this.decrementSecond();break;case"meridian":this.toggleMeridian();break}this.updateElement();break}if(a.keyCode!==0&&a.keyCode!==8&&a.keyCode!==9&&a.keyCode!==46){a.preventDefault()}},setValues:function(a){if(this.showMeridian){var b=a.split(" ");var c=b[0].split(":");this.meridian=b[1]}else{var c=a.split(":")}this.hour=parseInt(c[0],10);this.minute=parseInt(c[1],10);this.second=parseInt(c[2],10);if(isNaN(this.hour)){this.hour=1}if(isNaN(this.minute)){this.minute=0}if(this.showMeridian){if(this.hour>12){this.hour=12}else if(this.hour<1){this.hour=1}if(this.meridian=="am"||this.meridian=="a"){this.meridian="AM"}else if(this.meridian=="pm"||this.meridian=="p"){this.meridian="PM"}if(this.meridian!="AM"&&this.meridian!="PM"){this.meridian="AM"}}if(this.minute<0){this.minute=0}else if(this.minute>60){this.minute=60}if(this.showSeconds){if(isNaN(this.second)){this.second=0}else if(this.second<0){this.second=0}else if(this.second>60){this.second=60}}this.updateElement();this.updateWidget()},setMeridian:function(a){if(a=="a"||a=="am"||a=="AM"){this.meridian="AM"}else if(a=="p"||a=="pm"||a=="PM"){this.meridian="PM"}else{this.updateWidget()}this.updateElement()},setDefaultTime:function(a){if(a){if(a==="current"){var b=new Date;var c=b.getHours();var d=Math.floor(b.getMinutes()/this.minuteStep)*this.minuteStep;var e=Math.floor(b.getSeconds()/this.secondStep)*this.secondStep;var f="AM";if(this.showMeridian){if(c===0){c=12}else if(c>=12){if(c>12){c=c-12}f="PM"}else{f="AM"}}this.hour=c;this.minute=d;this.second=e;this.meridian=f}else if(a==="value"){this.setValues(this.$element.val())}else{this.setValues(a)}this.update()}else{this.hour=0;this.minute=0;this.second=0}},formatTime:function(a,b,c,d){a=a<10?"0"+a:a;b=b<10?"0"+b:b;c=c<10?"0"+c:c;return a+":"+b+(this.showSeconds?":"+c:"")+(this.showMeridian?" "+d:"")},getTime:function(){return this.formatTime(this.hour,this.minute,this.second,this.meridian)},setTime:function(a){this.setValues(a);this.update()},update:function(){this.updateElement();this.updateWidget()},blurElement:function(){this.highlightedUnit=undefined;this.updateFromElementVal()},updateElement:function(){var a=this.getTime();this.$element.val(a).change();switch(this.highlightedUnit){case"hour":this.highlightHour();break;case"minute":this.highlightMinute();break;case"second":this.highlightSecond();break;case"meridian":this.highlightMeridian();break}},updateWidget:function(){if(this.showInputs){this.$widget.find("input.bootstrap-timepicker-hour").val(this.hour<10?"0"+this.hour:this.hour);this.$widget.find("input.bootstrap-timepicker-minute").val(this.minute<10?"0"+this.minute:this.minute);if(this.showSeconds){this.$widget.find("input.bootstrap-timepicker-second").val(this.second<10?"0"+this.second:this.second)}if(this.showMeridian){this.$widget.find("input.bootstrap-timepicker-meridian").val(this.meridian)}}else{this.$widget.find("span.bootstrap-timepicker-hour").text(this.hour);this.$widget.find("span.bootstrap-timepicker-minute").text(this.minute<10?"0"+this.minute:this.minute);if(this.showSeconds){this.$widget.find("span.bootstrap-timepicker-second").text(this.second<10?"0"+this.second:this.second)}if(this.showMeridian){this.$widget.find("span.bootstrap-timepicker-meridian").text(this.meridian)}}},updateFromElementVal:function(a){var b=this.$element.val();if(b){this.setValues(b);this.updateWidget()}},updateFromWidgetInputs:function(){var b=a("input.bootstrap-timepicker-hour").val()+":"+a("input.bootstrap-timepicker-minute").val()+(this.showSeconds?":"+a("input.bootstrap-timepicker-second").val():"")+(this.showMeridian?" "+a("input.bootstrap-timepicker-meridian").val():"");this.setValues(b)},getCursorPosition:function(){var a=this.$element.get(0);if("selectionStart"in a){return a.selectionStart}else if(document.selection){a.focus();var b=document.selection.createRange();var c=document.selection.createRange().text.length;b.moveStart("character",-a.value.length);return b.text.length-c}},highlightUnit:function(){var a=this.$element.get(0);this.position=this.getCursorPosition();if(this.position>=0&&this.position<=2){this.highlightHour()}else if(this.position>=3&&this.position<=5){this.highlightMinute()}else if(this.position>=6&&this.position<=8){if(this.showSeconds){this.highlightSecond()}else{this.highlightMeridian()}}else if(this.position>=9&&this.position<=11){this.highlightMeridian()}},highlightNextUnit:function(){switch(this.highlightedUnit){case"hour":this.highlightMinute();break;case"minute":if(this.showSeconds){this.highlightSecond()}else{this.highlightMeridian()}break;case"second":this.highlightMeridian();break;case"meridian":this.highlightHour();break}},highlightPrevUnit:function(){switch(this.highlightedUnit){case"hour":this.highlightMeridian();break;case"minute":this.highlightHour();break;case"second":this.highlightMinute();break;case"meridian":if(this.showSeconds){this.highlightSecond()}else{this.highlightMinute()}break}},highlightHour:function(){this.highlightedUnit="hour";this.$element.get(0).setSelectionRange(0,2)},highlightMinute:function(){this.highlightedUnit="minute";this.$element.get(0).setSelectionRange(3,5)},highlightSecond:function(){this.highlightedUnit="second";this.$element.get(0).setSelectionRange(6,8)},highlightMeridian:function(){this.highlightedUnit="meridian";if(this.showSeconds){this.$element.get(0).setSelectionRange(9,11)}else{this.$element.get(0).setSelectionRange(6,8)}},incrementHour:function(){if(this.showMeridian){if(this.hour===11){this.toggleMeridian()}else if(this.hour===12){return this.hour=1}}if(this.hour===23){return this.hour=0}this.hour=this.hour+1},decrementHour:function(){if(this.showMeridian){if(this.hour===1){return this.hour=12}else if(this.hour===12){this.toggleMeridian()}}if(this.hour===0){return this.hour=23}this.hour=this.hour-1},incrementMinute:function(){var a=this.minute+this.minuteStep-this.minute%this.minuteStep;if(a>59){this.incrementHour();this.minute=a-60}else{this.minute=a}},decrementMinute:function(){var a=this.minute-this.minuteStep;if(a<0){this.decrementHour();this.minute=a+60}else{this.minute=a}},incrementSecond:function(){var a=this.second+this.secondStep-this.second%this.secondStep;if(a>59){this.incrementMinute();this.second=a-60}else{this.second=a}},decrementSecond:function(){var a=this.second-this.secondStep;if(a<0){this.decrementMinute();this.second=a+60}else{this.second=a}},toggleMeridian:function(){this.meridian=this.meridian==="AM"?"PM":"AM";this.update()},getTemplate:function(){if(this.options.templates[this.options.template]){return this.options.templates[this.options.template]}if(this.showInputs){var a='';var b='';var c='';var d=''}else{var a='';var b='';var c='';var d=''}var e='