Browse Source

Changes on javascript behavior

ahwelp 2 năm trước cách đây
mục cha
commit
5320f602f8
2 tập tin đã thay đổi với 514 bổ sung468 xóa
  1. 120 0
      public/dist/libs.js
  2. 394 468
      public/dist/script.js

+ 120 - 0
public/dist/libs.js

@@ -0,0 +1,120 @@
+/*
+ * ============================== - Async Help
+ *                                  _    _      _
+ *     /\                          | |  | |    | |
+ *    /  \   ___ _   _ _ __   ___  | |__| | ___| |_ __
+ *   / /\ \ / __| | | | '_ \ / __| |  __  |/ _ \ | '_ \
+ *  / ____ \\__ \ |_| | | | | (__  | |  | |  __/ | |_) |
+ * /_/    \_\___/\__, |_| |_|\___| |_|  |_|\___|_| .__/
+ *                __/ |                          | |
+ *               |___/                           |_|
+ *
+*/
+
+function asyncRedirect(target, method) {
+    $('#progress').removeClass('hidden');
+    let request = fetch(target, {
+        method: method,
+        headers: {
+            'Content-Type': 'application/x-www-form-urlencoded',
+            'X-Requested-With': 'fetch'
+        }
+    }).then(function (response) {
+        return response.text();
+    }).then(function (data) {
+        $('body #content').html(data).trigger('reloaded');
+        history.replaceState({}, '', target);
+    }).catch(function (error) {
+
+    }).finally(function () {
+        $('#progress').addClass('hidden');
+    });
+}
+
+/*
+ * Fill a given element with content on a
+ * remote location
+ *
+ */
+function asyncFill(target, method, location, callback = function () { }, params = {}, payload = {}) {
+    fetch(target, {
+        method: method,
+        headers: {
+            'Content-Type': 'application/x-www-form-urlencoded',
+            'X-Requested-With': 'fetch'
+        }
+    }).then(function (response) {
+        return response.text();
+    }).then(function (data) {
+        $(location).html(data).trigger('filled');
+    }).catch(function (error) {
+    }).finally(function () {
+        callback(params);
+    });
+}
+
+/**
+ * Search any type of content on a remote location
+ *
+ **/
+async function asyncContent(target, method, type, callback = function () { }) {
+    return fetch(target, {
+        method: method,
+        headers: {
+            'Content-Type': 'application/x-www-form-urlencoded',
+            'X-Requested-With': 'fetch'
+        }
+    }).then(function (response) {
+        var content = "";
+
+        if (type == 'text') {
+            content = response.text();
+        } else {
+            content = response.json();
+        }
+
+        return {
+            "status": response.ok,
+            "content": content
+        };
+
+    }).then(function (data) {
+        callback(data.content);
+        return data;
+    }).finally(function (content) {
+
+    });
+
+}
+
+
+/*
+ * ============================== Modal
+ *   _  __           _       _
+ * |  \/  |         | |     | |
+ * | \  / | ___   __| | __ _| |
+ * | |\/| |/ _ \ / _` |/ _` | |
+ * | |  | | (_) | (_| | (_| | |
+ * |_|  |_|\___/ \__,_|\__,_|_|
+ *
+*/
+
+var scan;
+
+var modalTarget = {}; // Store field where the modal will place the selected stuff
+let modal = new bootstrap.Modal($('#modal'), { keyboard: true });
+var modalClose;
+
+$('#modal').on('hidden.bs.modal', function (evt) {
+    $(this).find('.modal-body').html('');
+    $(this).find('.modal-title').html('');
+    if (typeof modalClose === "function") {
+        modalClose();
+    }
+});
+
+async function openModal(params) {
+    modalTarget = params.target;
+    modalClose = params.close;
+    modal.toggle();
+}

+ 394 - 468
public/dist/script.js

@@ -6,22 +6,6 @@ var user_config = {
     allways_ajax: true
 };
 
-function log(message, importance = 0) {
-    if (user_config.log === 0) {
-        return;
-    }
-
-    if (importance === 0) {
-        console.log("LOG:: |" + message + "|");
-    }
-    if (importance === 1) {
-        console.log(message);
-    }
-    if (importance === 2) {
-        alert("LOG:: |" + message + "|");
-    }
-}
-
 function isDefined(data) {
     if (typeof data === 'undefined') {
         return false;
@@ -35,418 +19,26 @@ function definedOr(data, value = '') {
         return value;
     } else {
         return data;
+    }
 }
-}
-
-//============================== Generic Template Functions
-
-function revalidate_screen() {
-    $('[data-format]').each(function () {
-        $(this).mask($(this).data('format'), {});
-    });
-
-    //$('[data-toggle="popover"]').popover();
-
-    $('select').each(function () {
-        if (typeof $(this).data('value') !== "undefined" && $(this).data('value') !== '') {
-            $(this).val($(this).data('value'));
-        }
-    });
-
-    $('.datepicker').each(function () {
-        $(this).datepicker({
-            format: "dd/mm/yyyy",
-            todayBtn: "linked",
-            clearBtn: true,
-            autoclose: true,
-            todayHighlight: true
-        });
-    });
-
-    $('.selectpicker').each(function () {
-        $(this).select2({
-            liveSearch: true
-        });
-    });
-    
-    $(".wysiwyg").each(function () {
-        $(this).trumbowyg();
-    });
-    
-    $(".form-control-range").each(function(i, item){
-        $(item).on('change', function(item, i){
-            $(item.currentTarget)
-                    .parent()
-                    .find('.range-monitor')
-                    .html(item.currentTarget.value + "%");
-        })
-    });
-
-    $('.popup-toggle').each(() => {
-        var template = '<div class="modal-dialog"> <div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal"> X </button><h4 class="modal-title">Modal Header</h4></div><div class="modal-body">{{aaa}}</div><div class="modal-footer"><button type="button" class="btn btn-default" data-dismiss="modal">Close</button></div></div>';
-        if ($(this).hasClass('processed')) {
-            return true;
-        }
-        $(this).addClass('processed');
-        $(this).on('click', function (e) {
-            e.preventDefault();
-            $.ajax({
-                method: 'GET',
-                url: $(this).data('source')
-            }).done(function (msg) {
-                template = template.replace('{{aaa}}', msg);
-                $('#modal').html(template).modal('show');
-                revalidate_screen();
-            });
-        });
-        $('#modal').on('shown.bs.modal', function () {
-            revalidate_screen();
-            $(this).find('.datatable-anchor').focus();
-        });
-    });
-
-    $('.remote-popup').each((i, element) => {
-
-        if ($(element).hasClass('processed')) {
-            return true;
-        }
-
-        var instance = $(element);
-        var number = $(element).find('.remote-popup-number');
-        var button = $(element).find('button');
-        var label = $(element).find('.remote-popup-label');
-
-        searchRemote = (value = null) => {
-            if (value == null) {
-                value = $(number).val();
-            }
-            $.ajax({
-                method: 'GET',
-                url: $(instance).data('relay') + '/' + value
-            }).done(function (msg) {
-                $(label).val(msg.name);
-            }).fail(function () {
-                $(number).val('');
-                $(label).val('');
-            });
-        }
-
-        remotePopup = (source) => {
-            $($('#modal')).off();
-            var template = '<div class="modal-dialog"> <div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal"> X </button><h4 class="modal-title">Modal Header</h4></div><div class="modal-body">{{aaa}}</div><div class="modal-footer"><button type="button" class="btn btn-default" data-dismiss="modal">Close</button></div></div>';
-            $.ajax({
-                method: 'GET',
-                url: source
-            }).done(function (msg) {
-                template = template.replace('{{aaa}}', msg);
-                $('#modal').html(template).modal('show');
-                $('#modal').on('hide.bs.modal', () => {
-                    $(number).val($("#modal .selected").data('info').id);
-                    searchRemote();
-                });
-                revalidate_screen();
-            });
-        };
-
-        $(button).on('click', () => {
-            remotePopup($(instance).data('relay') + '/' + $(instance).data('mode'));
-        });
-
-        $(number).on('keyup', (e) => {
-            if (e.keyCode == 112) {
-                remotePopup($(instance).data('relay') + '/' + $(instance).data('mode'));
-            }
-        });
 
-        $(number).on('focusout', () => {
-            console.log($(number).val() == '');
-            if ($(number).val() == '') {
-                $(label).val('');
-                return;
-            }
-            searchRemote($(number).val());
-        });
-        
-        if($(number).val() != ''){
-            searchRemote( $(number).val() )
-        }
-        
-        /*console.log($(element))
-        console.log(number);
-        console.log(button);
-        console.log(label);*/
-        
-        $(element).addClass('processed');
-        
-    });
-
-    $('.live-selectpicker').each(function () {
-
-        $(this).select2({
-            liveSearch: true
-        });
-
-        var object = $(this);
-        var source = definedOr($(this).data('source'), false);
-        var placeholder = definedOr($(this).data('placeholder'));
-        var filter_name = definedOr($(this).data('filter'));
-        var value = definedOr($(this).data('value'));
-
-        if (!source) {
-            return;
-        }
-        object.ajax = {
-            "url": source,
-            "data": function (params) {
-                var query = {
-                    "name": params.value
-                }
-            }
-        };
-        /*$(this).ajaxSelectPicker({
-         ajax: {
-         url: source + "/combo_data",
-         method: 'GET',
-         data: {
-         nome: '{{{q}}}',
-         filter: function() {
-         if (filter_name === '') {
-         return ''
-         }
-         return $("[name='" + filter_name + "'] option:selected").val();
-         }
-         }
-         },
-         locale: {
-         emptyTitle: placeholder
-         },
-         preprocessData: function(data) {
-         var registers = [];
-         registers.push({
-         'value': '0',
-         'text': 'Selecione'
-         });
-         for (var i in data) {
-         registers.push({
-         'value': data[i].id,
-         'text': data[i].nome
-         });
-         }
-         return registers;
-         },
-         preserveSelected: true
-         });*/
-    });
-
-    /*===========================================*/
-
-    $('.icon-colapser').on('click', function () {
-        $(this).parent().parent().find('.panel-collapse').collapse('toggle');
-    });
-
-    /*$('form').each(function () {
-     $(this).validator();
-     });*/
-
-    $('.data-table').each(function () {
-        if ($(this).hasClass('processed')) {
-            return;
-        }
-        var wrapper = $(this);
-        var table_anchor = $(this).find('a');
-        var table = $(this).find('table');
-
-        var str = '<thead> <tr class="header">';
-        for (var i in table.data('columns')) {
-            if (typeof table.data('columns')[i].name === 'undefined') {
-                str = str + '<th>' + table.data('columns')[i].data + "</th>";
-            } else {
-                str = str + '<th>' + table.data('columns')[i].name + "</th>";
-            }
-        }
-        str += '<th>*</th>';
-        str += "</tr> </thead>";
-        $(table).html(str);
-        var datatable = $(table).DataTable({
-            'createdRow': function (row, data) {
-                $(row).attr('data-info', JSON.stringify(data));
-                var content = '';
-                if (typeof $(table).data('update') != 'undefined') {
-                    content += '<a href="' + $(table).data('update') + '"> <i class="fa fa-pencil-square"></i> </a>'
-                }
-                if (typeof $(table).data('delete') != 'undefined') {
-                    content += '<a href="' + $(table).data('delete') + '"> <i class="fa fa-trash"></i> </a>'
-                }
-                if (typeof $(table).data('purge') != 'undefined') {
-                    content += '<a href="' + $(table).data('purge') + '"> <i class="fa fa-minus-square"></i> </a>'
-                }
-
-                $(row).append('<td>' + content + '</td>');
-            },
-            "drawCallback": function (settings) {
-                if ($(wrapper).hasClass('selectable')) {
-                    $($(table).find('tr')[1]).addClass('selected');
-                    if (!$(wrapper).hasClass('processed')) {
-                        $(table_anchor).focus();
-                    }
-                }
-            },
-            "initComplete": function (settings, json) {
-                $(wrapper).addClass('processed');
-            },
-            processing: true,
-            serverSide: true,
-            searchDelay: 800,
-            ajax: {'url': table.data('source'), 'type': 'POST'},
-            columns: table.data('columns')
-        });
-
-        var search = $(this).find('input');
-
-        $(search).on('keyup', function (e) {
-            if (e.keyCode == 13) {
-                $(table_anchor).focus();
-            }
-        });
-
-        if ($(wrapper).hasClass('selectable')) {
-            $(this).on('contextmenu', 'tr', function () {
-
-            });
-
-            $(this).on('click', 'tr', function () {
-                $(table_anchor).focus();
-                if ($(this).hasClass('selected')) {
-                    $(this).removeClass('selected');
-                    return;
-                }
-                $(this).parent().find('tr').each(function () {
-                    $(this).removeClass('selected');
-                });
-                $(this).addClass('selected');
-            });
-
-            $(table_anchor).on('focus', function () {
-                $('body').addClass('no-scroll');
-                $($(table).find('tr')[1]).addClass('selected');
-            });
-
-            $(table_anchor).on('focusout', function () {
-                $('body').removeClass('no-scroll');
-                $(table).find('tr').each((i, value) => {
-                    $(value).removeClass('selected');
-                });
-            });
-
-            $(table_anchor).on('keypress', function (e) {
-
-            });
-
-            $(table_anchor).on('keyup', function (e) {
-
-                e.preventDefault();
-
-                if (e.keyCode == 70) {
-                    $(search).focus();
-                }
-
-                if (e.keyCode == 112) {
-                    ajax_call($(this).data('insert'));
-                }
-
-                if (e.keyCode == 113) {
-                    id = $(table).find('.selected').data('info').id;
-                    ajax_call($(this).data('insert') + '/' + id);
-                }
-
-                if (e.keyCode == 39 && e.ctrlKey) {
-                    datatable.page('last').draw('page');
-                }
-                if (e.keyCode == 37 && e.ctrlKey) {
-                    datatable.page('first').draw('page');
-                    $($(table).find('tr')[1]).addClass('selected');
-                }
-                if (e.keyCode == 37) { //left
-                    datatable.page('previous').draw('page');
-                    $($(table).find('tr')[1]).addClass('selected');
-                }
-                if (e.keyCode == 39) { //right
-                    datatable.page('next').draw('page');
-                    $($(table).find('tr')[1]).addClass('selected');
-                }
-                if (e.keyCode == 38) { //up
-                    var last = null;
-                    var line = null;
-
-                    $(table).find('tr').each((i, value) => {
-                        if ($(value).hasClass('selected')) {
-                            ;
-                            line = $(value)
-                            return false;
-                        }
-                        last = $(value)
-                    });
-                    if ($(last).hasClass('header')) {
-                        datatable.page('previous').draw('page');
-                    }
-                    if (line != null) {
-                        $(line).removeClass('selected');
-                        $(last).addClass('selected');
-                    }
-
-                }
-                if (e.keyCode == 40) { //up
-                    var next = false;
-
-                    $(table).find('tr').each((i, value) => {
-                        if (next) {
-                            $(value).addClass('selected');
-                            next = false;
-                            return false;
-                        }
-                        if ($(value).hasClass('selected')) {
-                            next = true;
-                            $(value).removeClass('selected');
-                        }
-                    });
-                    if (next) {
-                        datatable.page('next').draw('page');
-                    }
-                }
-                if (e.keyCode == 13) {
-                    if ($(this).parent().parent().hasClass('modal-body')) {
-                        $(this).parent().parent()
-                                .parent().parent()
-                                .parent().modal('hide');
-                        //console.log($(this).parent().find('.selected').data('info'));
-                    }
-                }
-            })
-        }
-    });
-
-    popover_help();
+function setIfNotEmpty(location, value) {
+    if (value != '') {
+        $(location).val(value);
+    }
 }
 
-/*===========================================*/
-
-$('.remote-element').each(function () {
-
-    var element = $(this);
-    var source = $(this).data('source');
-    var value = $(this).data('value');
-
-    $.ajax({
-        method: "GET",
-        url: source,
-        data: {value: value}
-    }).done(function (msg) {
-        $(element).html(msg);
-    });
-
-});
-
-//============================== Template Boot
+/*
+ * ============================== Template Boot
+ *   _______                   _       _
+ *  |__   __|                 | |     | |
+ *     | | ___ _ __ ___  _ __ | | __ _| |_ ___
+ *     | |/ _ \ '_ ` _ \| '_ \| |/ _` | __/ _ \
+ *     | |  __/ | | | | | |_) | | (_| | ||  __/
+ *     |_|\___|_| |_| |_| .__/|_|\__,_|\__\___|
+ *                      | |
+ *                      |_|
+*/
 
 /* Função de aparecer ou desaparecer o menu lateral */
 $(".menu-toggle").on('click', function (e) {
@@ -471,9 +63,19 @@ $(".menu-toggle").on('contextmenu', function (e) {
 
 $('#side-menu').metisMenu();
 
-revalidate_screen();
+/*
+ * ============================== - MouseTrap
+ *  __  __                   _______
+ * |  \/  |                 |__   __|
+ * | \  / | ___  _   _ ___  ___| |_ __ __ _ _ __
+ * | |\/| |/ _ \| | | / __|/ _ \ | '__/ _` | '_ \
+ * | |  | | (_) | |_| \__ \  __/ | | | (_| | |_) |
+ * |_|  |_|\___/ \__,_|___/\___|_|_|  \__,_| .__/
+ *                                         | |
+ *                                         |_|
+ *
+*/
 
-//============================== - MouseTrap
 /* Atalho, Ao apertar alt, foca no primeiro ítem do menu lateral */
 Mousetrap.bind('alt', function (e) {
     e.preventDefault();
@@ -501,7 +103,7 @@ Mousetrap.bind("ctrl+shift+f", function (e) {
 function popover_help() {
     $('input').each(function () {
         Mousetrap($(this)[0]).bind('ctrl+f1', function () {
-            //alert(10);    
+            //alert(10);
         });
     })
 }
@@ -540,8 +142,24 @@ $(".search-nav >input").on("keyup", function () {
     }
 });
 
-//============================== Ajax Page Handler
-$('a').on('click', function (e) {
+/*
+ * ============================== - Ajax Page Handler
+ *           _              _____
+ *     /\   (_)            |  __ \
+ *    /  \   _  __ ___  __ | |__) |_ _  __ _  ___  ___
+ *   / /\ \ | |/ _` \ \/ / |  ___/ _` |/ _` |/ _ \/ __|
+ *  / ____ \| | (_| |>  <  | |  | (_| | (_| |  __/\__ \
+ * /_/    \_\ |\__,_/_/\_\ |_|   \__,_|\__, |\___||___/
+ *         _/ |                         __/ |
+ *        |__/                         |___/
+*/
+
+
+//==============================
+//===      Link clicks
+//==============================
+$('body').on('click', 'a', function (e) {
+
     if (!user_config.allways_ajax) {
         return true;
     }
@@ -550,13 +168,13 @@ $('a').on('click', function (e) {
     var method = $(this).data('method');
 
     if (typeof target === 'undefined' ||
-            target === '' ||
-            target === '#' ||
-            target == 'javascript:void(0)') {
+        target === '' ||
+        target === '#' ||
+        target == 'javascript:void(0)') {
         return;
     }
 
-    if (method === 'reload') {
+    if (method === 'reload' || method === 'follow') {
         return true;
     }
 
@@ -566,48 +184,356 @@ $('a').on('click', function (e) {
         method = 'GET';
     }
 
-    $('#progress').removeClass('hidden');
-
-    $.ajax({
-        method: method,
-        url: target
-    }).done(function (msg) {
-        $('#content').html(msg);
-        history.replaceState({}, '', target);
-    }).fail(function () {
-        alert('fail');
-    }).always(function () {
-        $('#progress').addClass('hidden')
-        revalidate_screen();
+    asyncRedirect(target, method);
+
+});
+
+//==============================
+//===    Form submissions
+//==============================
+$('body').on('submit', 'form', async function (e) {
+
+    var formAjax = true;
+
+    if (formAjax == false) {
+        return true;
+    }
+
+    e.preventDefault();
+
+    let request = await fetch(e.target.action, {
+        method: e.target.method,
+        body: JSON.stringify($(this).serialize()).replace(/^"+|"+$/g, ''),
+        headers: {
+            'Content-Type': 'application/x-www-form-urlencoded',
+            'X-Requested-With': 'fetch'
+        }
     });
+
+    let responseJson = await request.json();
+
+    if (!request.ok) {
+
+        $('#toast-container').bootstrapToastWrapper({
+            'type': 'danger',
+            'title': 'Erro',
+            'body': responseJson,
+            'timeout': 5000
+        });
+
+    } else {
+
+        $('#toast-container').bootstrapToastWrapper({
+            'type': 'success',
+            'title': 'Sucesso',
+            'body': 'Ação bem sucedida',
+            'timeout': 5000
+        });
+
+        if (responseJson.location) {
+            asyncRedirect(responseJson.location, 'GET');
+        }
+    }
 });
 
-function ajax_call(target) {
-    $('#progress').removeClass('hidden');
+/*
+ *  Ao sair do campo digitável de um valor buscavel. Executa a busca
+*/
+$('#content').on('blur', '[data-search] input', function (e) {
+    val = $(this).val();
+    if (val == "") { return; }
+
+    el = $(this);
+    elwrap = $(this).parent().parent();
+
+    url = $(this).parent().parent().data('search');
+    fields = $(this).parent().parent().data('searchfields').split('+');
 
-    $.ajax({
+    fetch(url + val, {
         method: 'GET',
-        url: target
-    }).done(function (msg) {
-        $('#content').html(msg);
-        history.replaceState({}, '', target);
-    }).fail(function () {
-        alert('fail');
-    }).always(function () {
-        $('#progress').addClass('hidden')
-        revalidate_screen();
+        headers: {
+            'Content-Type': 'application/x-www-form-urlencoded',
+            'X-Requested-With': 'fetch'
+        }
+    }).then(function (response) {
+        let json = response.json();
+        return json;
+    }).then(function (json) {
+
+        if (json == null) {
+            $(this).val('');
+            $($(elwrap).find('input')[1]).val("");
+            return;
+        }
+
+        var fieldData = "";
+        for (value in fields) {
+            fieldData += json[fields[value]] + " ";
+        }
+        $($(elwrap).find('input')[1]).val(fieldData);
+        $(this).find('input').trigger('filled', json);
+        //$(e).trigger('filled', json);
+        //console.log();
+    });
+});
+
+
+// Revalidate screen
+function revalidate_screen(location) {
+
+    $(location).find('[data-mask]').each(function () {
+        if ($(this).data('maskreverse') == false) {
+
+        } else {
+            var params = {
+                reverse: true
+            }
+        }
+
+        if ($(this).data('maskcomplete')) {
+            params.onComplete = window[$(this).data('maskcomplete')]
+        }
+
+        $(this).mask($(this).data('mask'), params);
+
+        $(this).on('filled', { 'params': params }, function (e) {
+            $(this).mask($(this).data('mask').mask);
+            $(this).mask($(this).data('mask').mask, params);
+        });
+
+    });
+
+    /*$(location).find('.remoteFill').each(function(i, el){
+        $(el).on('click', function(){
+            $(this).remoteFill();
+        })
+    });*/
+
+    //$('[data-toggle="popover"]').popover();
+
+    $(location).find('.remote-element').each(async function () {
+        var element = $(this);
+        var source = $(this).data('source');
+        var value = $(this).data('value');
+        source = source + '?value=' + value;
+        await asyncFill(source, 'GET', element, revalidate_screen, element);
+    });
+
+    $(location).find('.remote-datatable').each(async function () {
+        var element = $(this);
+        var source = $(this).data('source');
+        var value = $(this).data('value');
+        await asyncFill(source, 'GET', element, datatableInplaceBoot, $(this));
+    });
+
+    setSelectValues(location);
+    datatableBasicBoot();
+
+    $('.icon-colapser').on('click', function () {
+        $(this).parent().parent().find('.panel-collapse').collapse('toggle');
+    });
+
+    $(location).find('[data-tablesearch]').on('click', async function (e) {
+        await asyncFill(
+            $(e.currentTarget).data('tablesearch'),
+            'GET',
+            $('#modal .modal-body'),
+            datatableBasicBoot,
+            function (el) {
+                $(el).on('click', 'button', function (ee) {
+                    $($(modalTarget).find('input')[0]).val($(ee.currentTarget).data('id')).trigger('blur');
+                    modal.toggle();
+                })
+            });
+
+        await openModal({
+            'target': $(e.currentTarget).parent().parent().parent(),
+            'source': $(e.currentTarget).data('search')
+        });
+    });
+
+    $(location).find('[data-tablesearchadd]').on('click', async function (e) {
+        await asyncFill(
+            $(e.currentTarget).data('tablesearchadd') + '/table',
+            'GET',
+            $('#modal .modal-body'),
+            datatableBasicBoot,
+            async function (el) {
+                await $(el).on('click', 'button', async function (ee) {
+                    modalTarget.trigger('added', $(ee.target).data('id'));
+                    modal.toggle();
+                })
+            });
+
+        await openModal({
+            'target': $(e.currentTarget).parent().parent().find('.list-group'),
+            'source': $(e.currentTarget).data('search')
+        });
+    });
+
+    $(location).find('[data-ean] button').on('click', function (e) {
+
+        $('#modal .modal-body').html('<div id="reader" width="600px"></div>');
+
+        function onScanSuccess(decodedText, decodedResult) {
+            // handle the scanned code as you like, for example:
+            $(this).parent().find('input').val(decodedText);
+            myModal.hide();
+        }
+
+        scan = new Html5QrcodeScanner(
+            "reader",
+            { fps: 10, qrbox: { width: 250, height: 250 } },
+            /* verbose= */ false);
+
+        scan.render(onScanSuccess);
+
+        openModal({
+            'target': $(e.currentTarget).parent().parent().find('.list-group'),
+            'source': $(e.currentTarget).data('search'),
+            'close': function () {
+                scan.stop();
+            }
+        });
+
     });
+
+    /*
+     * Campos que se autopreenchem quando o valor é buscado
+     */
+    $(location).find('[data-listener]').each(function (el, i) {
+        var element = $(this);
+        let selector = "[name='" + $(this).data('listener') + "']";
+        let key = $(this).data('listenervalue');
+        $(selector).on('filled blur', function (e, data, data1) {
+            console.log($(this));
+        });
+    });
+
+    /* TODO create validation rules */
+    $('#content').find('form').each(function () {
+        //$(this).validator();
+    });
+
+    popover_help();
 }
 
-function open_popup(source) {
-    var template = '<div class="modal-dialog"> <div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal"> X </button><h4 class="modal-title">Modal Header</h4></div><div class="modal-body">{{aaa}}</div><div class="modal-footer"><button type="button" class="btn btn-default" data-dismiss="modal">Close</button></div></div>';
-    $.ajax({
-        method: 'GET',
-        url: source
-    }).done(function (msg) {
-        //alert(msg);
-        template = template.replace('{{aaa}}', msg);
-        $('#modal').html(template).modal('show');
-        revalidate_screen();
+/*
+ * ================================================
+ *   _____        _        _        _     _
+ *  |  __ \      | |      | |      | |   | |
+ *  | |  | | __ _| |_ __ _| |_ __ _| |__ | | ___  ___
+ *  | |  | |/ _` | __/ _` | __/ _` | '_ \| |/ _ \/ __|
+ *  | |__| | (_| | || (_| | || (_| | |_) | |  __/\__ \
+ *  |_____/ \__,_|\__\__,_|\__\__,_|_.__/|_|\___||___/
+ *
+ */
+
+function datatableBasicBoot(param) {
+    $('.datatable').each(function (i, el) {
+
+        var columns = [];
+
+        $(this).find('thead').find('th').each(function (i, el) {
+            columns.push({ 'data': $(el).data('field') });
+        });
+
+        var ajax = {
+            "url": $(el).data('src'),
+            'type': 'POST',
+        }
+
+        $(el).DataTable({
+            "processing": true,
+            "serverSide": true,
+            "ajax": ajax,
+            "columns": columns
+        });
+
+        param(el);
     });
 }
+
+function datatableInplaceBoot(location = '#content', param = function () { }) {
+    $(location).find('.datatable').each(function (i, el) {
+
+        var columns = [];
+
+        $(this).find('thead').find('th').each(function (i, el) {
+            columns.push({ 'data': $(el).data('field') });
+        });
+
+        var ajax = {
+            "url": $(el).data('src'),
+            'type': 'POST',
+        }
+
+        $(el).DataTable({
+            "processing": true,
+            "serverSide": true,
+            "ajax": ajax,
+            "columns": columns
+        });
+
+        param(el);
+    });
+}
+
+function datatableRemoteLoad() {
+
+}
+
+/*
+ * ================================================
+ *   _____      _           _
+ *  / ____|    | |         | |
+ * | (___   ___| | ___  ___| |_ ___
+ *  \___ \ / _ \ |/ _ \/ __| __/ __|
+ *  ____) |  __/ |  __/ (__| |_\__ \
+ * |_____/ \___|_|\___|\___|\__|___/
+ *
+*/
+
+function setSelectValues(select, value) {
+    if ($(select).prop('nodeName') == 'SELECT') {
+        setSelectValue(select, $(select).data('value'));
+    } else {
+        $(select).find('select').each(function (i, el) {
+            if (typeof $(this).data('value') !== "undefined" && $(this).data('value') !== '') {
+                setSelectValue($(this), $(this).data('value'))
+            }
+        });
+    }
+}
+
+function setSelectValue(select, value) {
+    $(select).find('option').each(function (i, el) {
+        $(el).attr('selected', false);
+        if ($(el).val() == value) {
+            $(el).attr('selected', true);
+        }
+    });
+}
+
+function setSelectName(select, value) {
+    $(select).find('select').each(function (i, el) {
+        if (typeof $(this).data('value') !== "undefined" && $(this).data('value') !== '') {
+            setSelectName($(this), $(this).data('value'))
+        }
+    });
+}
+
+function setSelectName(select, value) {
+    $(select).find('option').each(function (i, el) {
+        $(el).attr('selected', false);
+        if ($(el).html() == value) {
+            $(el).attr('selected', true);
+        }
+    });
+}
+
+$('#content').on('reloaded', function () {
+    revalidate_screen('#content');
+});
+
+revalidate_screen('body');