Proyectos de Subversion Moodle

Rev

Autoría | Ultima modificación | Ver Log |

{"version":3,"file":"form-display-errors.min.js","sources":["../src/form-display-errors.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Custom form error event handler to manipulate the bootstrap markup and show\n * nicely styled errors in an mform.\n *\n * @module     theme_boost/form-display-errors\n * @copyright  2016 Damyon Wiese <damyon@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core_form/events'], function($, FormEvent) {\n    let focusedAlready = false;\n    return {\n        /**\n         * Enhance the supplied element to handle form field errors.\n         *\n         * @method\n         * @param {String} elementid\n         * @listens event:formFieldValidationFailed\n         */\n        enhance: function(elementid) {\n            var element = document.getElementById(elementid);\n            if (!element) {\n                // Some elements (e.g. static) don't have a form field.\n                // Hence there is no validation. So, no setup required here.\n                return;\n            }\n\n            element.addEventListener(FormEvent.eventTypes.formFieldValidationFailed, e => {\n                const msg = e.detail.message;\n                e.preventDefault();\n\n                var parent = $(element).closest('.fitem');\n                var feedback = parent.find('.form-control-feedback');\n                const feedbackId = feedback.attr('id');\n\n                // Get current aria-describedby value.\n                let describedBy = $(element).attr('aria-describedby');\n                if (typeof describedBy === \"undefined\") {\n                    describedBy = '';\n                }\n                // Split aria-describedby attribute into an array of IDs if necessary.\n                let describedByIds = [];\n                if (describedBy.length) {\n                    describedByIds = describedBy.split(\" \");\n                }\n                // Find the the feedback container in the aria-describedby attribute.\n                const feedbackIndex = describedByIds.indexOf(feedbackId);\n\n                // Sometimes (atto) we have a hidden textarea backed by a real contenteditable div.\n                if (($(element).prop(\"tagName\") == 'TEXTAREA') && parent.find('[contenteditable]').length > 0) {\n                    element = parent.find('[contenteditable]');\n                }\n                if (msg !== '') {\n                    parent.addClass('has-danger');\n                    parent.data('client-validation-error', true);\n                    $(element).addClass('is-invalid');\n                    // Append the feedback ID to the aria-describedby attribute if it doesn't exist yet.\n                    if (feedbackIndex === -1) {\n                        describedByIds.push(feedbackId);\n                        $(element).attr('aria-describedby', describedByIds.join(\" \"));\n                    }\n                    $(element).attr('aria-invalid', true);\n                    feedback.html(msg);\n                    feedback.show();\n\n                    // If we haven't focused anything yet, focus this one.\n                    if (!focusedAlready) {\n                        element.scrollIntoView({behavior: \"smooth\", block: \"center\"});\n                        focusedAlready = true;\n                        setTimeout(()=> {\n                            // Actual focus happens later in case we need to do this in response to\n                            // a change event which happens in the middle of changing focus.\n                            element.focus({preventScroll: true});\n                            // Let it focus again next time they submit the form.\n                            focusedAlready = false;\n                        }, 0);\n                    }\n\n                } else {\n                    if (parent.data('client-validation-error') === true) {\n                        parent.removeClass('has-danger');\n                        parent.data('client-validation-error', false);\n                        $(element).removeClass('is-invalid');\n                        // If the aria-describedby attribute contains the error container's ID, remove it.\n                        if (feedbackIndex > -1) {\n                            describedByIds.splice(feedbackIndex, 1);\n                        }\n                        // Check the remaining element IDs in the aria-describedby attribute.\n                        if (describedByIds.length) {\n                            // If there's at least one, combine them with a blank space and update the aria-describedby attribute.\n                            describedBy = describedByIds.join(\" \");\n                            // Put back the new describedby attribute.\n                            $(element).attr('aria-describedby', describedBy);\n                        } else {\n                            // If there's none, remove the aria-describedby attribute.\n                            $(element).removeAttr('aria-describedby');\n                        }\n                        $(element).attr('aria-invalid', false);\n                        feedback.hide();\n                    }\n                }\n            });\n\n            var form = element.closest('form');\n            if (form && !('boostFormErrorsEnhanced' in form.dataset)) {\n                form.addEventListener('submit', function() {\n                    var visibleError = $('.form-control-feedback:visible');\n                    if (visibleError.length) {\n                        visibleError[0].focus();\n                    }\n                });\n                form.dataset.boostFormErrorsEnhanced = 1;\n            }\n        }\n    };\n});\n"],"names":["define","$","FormEvent","focusedAlready","enhance","elementid","element","document","getElementById","addEventListener","eventTypes","formFieldValidationFailed","e","msg","detail","message","preventDefault","parent","closest","feedback","find","feedbackId","attr","describedBy","describedByIds","length","split","feedbackIndex","indexOf","prop","addClass","data","push","join","html","show","scrollIntoView","behavior","block","setTimeout","focus","preventScroll","removeClass","splice","removeAttr","hide","form","dataset","visibleError","boostFormErrorsEnhanced"],"mappings":";;;;;;;;AAuBAA,yCAAO,CAAC,SAAU,qBAAqB,SAASC,EAAGC,eAC3CC,gBAAiB,QACd,CAQHC,QAAS,SAASC,eACVC,QAAUC,SAASC,eAAeH,cACjCC,SAMLA,QAAQG,iBAAiBP,UAAUQ,WAAWC,2BAA2BC,UAC/DC,IAAMD,EAAEE,OAAOC,QACrBH,EAAEI,qBAEEC,OAAShB,EAAEK,SAASY,QAAQ,UAC5BC,SAAWF,OAAOG,KAAK,gCACrBC,WAAaF,SAASG,KAAK,UAG7BC,YAActB,EAAEK,SAASgB,KAAK,yBACP,IAAhBC,cACPA,YAAc,QAGdC,eAAiB,GACjBD,YAAYE,SACZD,eAAiBD,YAAYG,MAAM,YAGjCC,cAAgBH,eAAeI,QAAQP,YAGV,YAA9BpB,EAAEK,SAASuB,KAAK,YAA6BZ,OAAOG,KAAK,qBAAqBK,OAAS,IACxFnB,QAAUW,OAAOG,KAAK,sBAEd,KAARP,KACAI,OAAOa,SAAS,cAChBb,OAAOc,KAAK,2BAA2B,GACvC9B,EAAEK,SAASwB,SAAS,eAEG,IAAnBH,gBACAH,eAAeQ,KAAKX,YACpBpB,EAAEK,SAASgB,KAAK,mBAAoBE,eAAeS,KAAK,OAE5DhC,EAAEK,SAASgB,KAAK,gBAAgB,GAChCH,SAASe,KAAKrB,KACdM,SAASgB,OAGJhC,iBACDG,QAAQ8B,eAAe,CAACC,SAAU,SAAUC,MAAO,WACnDnC,gBAAiB,EACjBoC,YAAW,KAGPjC,QAAQkC,MAAM,CAACC,eAAe,IAE9BtC,gBAAiB,IAClB,MAIwC,IAA3Cc,OAAOc,KAAK,6BACZd,OAAOyB,YAAY,cACnBzB,OAAOc,KAAK,2BAA2B,GACvC9B,EAAEK,SAASoC,YAAY,cAEnBf,eAAiB,GACjBH,eAAemB,OAAOhB,cAAe,GAGrCH,eAAeC,QAEfF,YAAcC,eAAeS,KAAK,KAElChC,EAAEK,SAASgB,KAAK,mBAAoBC,cAGpCtB,EAAEK,SAASsC,WAAW,oBAE1B3C,EAAEK,SAASgB,KAAK,gBAAgB,GAChCH,SAAS0B,eAKjBC,KAAOxC,QAAQY,QAAQ,QACvB4B,QAAU,4BAA6BA,KAAKC,WAC5CD,KAAKrC,iBAAiB,UAAU,eACxBuC,aAAe/C,EAAE,kCACjB+C,aAAavB,QACbuB,aAAa,GAAGR,WAGxBM,KAAKC,QAAQE,wBAA0B"}