Browse Source

ext-7.4 引入一半,没有完成
datetimefield 做了一半,没有完成

luoyifan 3 years ago
parent
commit
13bfe6eba7
100 changed files with 46182 additions and 0 deletions
  1. 106 0
      assets/ext-7.4.0.42/classic/classic/.sencha/test/Ext.cmd.api.adapter.js
  2. 300 0
      assets/ext-7.4.0.42/classic/classic/.sencha/test/test-impl.xml
  3. 2 0
      assets/ext-7.4.0.42/classic/classic/Readme.md
  4. 506 0
      assets/ext-7.4.0.42/classic/classic/build.xml
  5. 3 0
      assets/ext-7.4.0.42/classic/classic/index.js
  6. 76 0
      assets/ext-7.4.0.42/classic/classic/overrides/GlobalEvents.js
  7. 204 0
      assets/ext-7.4.0.42/classic/classic/overrides/Positionable.js
  8. 60 0
      assets/ext-7.4.0.42/classic/classic/overrides/Progress.js
  9. 233 0
      assets/ext-7.4.0.42/classic/classic/overrides/Widget.js
  10. 122 0
      assets/ext-7.4.0.42/classic/classic/overrides/app/Application.js
  11. 30 0
      assets/ext-7.4.0.42/classic/classic/overrides/app/ViewController.js
  12. 10 0
      assets/ext-7.4.0.42/classic/classic/overrides/app/domain/Component.js
  13. 13 0
      assets/ext-7.4.0.42/classic/classic/overrides/app/domain/View.js
  14. 3841 0
      assets/ext-7.4.0.42/classic/classic/overrides/dom/Element.js
  15. 118 0
      assets/ext-7.4.0.42/classic/classic/overrides/dom/Helper.js
  16. 455 0
      assets/ext-7.4.0.42/classic/classic/overrides/event/Event.js
  17. 155 0
      assets/ext-7.4.0.42/classic/classic/overrides/event/publisher/Dom.js
  18. 27 0
      assets/ext-7.4.0.42/classic/classic/overrides/event/publisher/Gesture.js
  19. 34 0
      assets/ext-7.4.0.42/classic/classic/overrides/form/field/Checkbox.js
  20. 41 0
      assets/ext-7.4.0.42/classic/classic/overrides/form/field/Radio.js
  21. 7 0
      assets/ext-7.4.0.42/classic/classic/overrides/init.js
  22. 13 0
      assets/ext-7.4.0.42/classic/classic/overrides/list/AbstractTreeItem.js
  23. 35 0
      assets/ext-7.4.0.42/classic/classic/overrides/list/Tree.js
  24. 110 0
      assets/ext-7.4.0.42/classic/classic/overrides/list/TreeItem.js
  25. 244 0
      assets/ext-7.4.0.42/classic/classic/overrides/mixin/Focusable.js
  26. 67 0
      assets/ext-7.4.0.42/classic/classic/overrides/plugin/Abstract.js
  27. 136 0
      assets/ext-7.4.0.42/classic/classic/overrides/scroll/Scroller.js
  28. 73 0
      assets/ext-7.4.0.42/classic/classic/overrides/sparkline/Base.js
  29. 75 0
      assets/ext-7.4.0.42/classic/classic/package.json
  30. 39 0
      assets/ext-7.4.0.42/classic/classic/sass/example/fashion.html
  31. 345 0
      assets/ext-7.4.0.42/classic/classic/src/Action.js
  32. 7313 0
      assets/ext-7.4.0.42/classic/classic/src/Component.js
  33. 255 0
      assets/ext-7.4.0.42/classic/classic/src/ComponentLoader.js
  34. 604 0
      assets/ext-7.4.0.42/classic/classic/src/Editor.js
  35. 440 0
      assets/ext-7.4.0.42/classic/classic/src/ElementLoader.js
  36. 444 0
      assets/ext-7.4.0.42/classic/classic/src/EventManager.js
  37. 10 0
      assets/ext-7.4.0.42/classic/classic/src/Gadget.js
  38. 342 0
      assets/ext-7.4.0.42/classic/classic/src/Img.js
  39. 654 0
      assets/ext-7.4.0.42/classic/classic/src/LoadMask.js
  40. 450 0
      assets/ext-7.4.0.42/classic/classic/src/ProgressBar.js
  41. 29 0
      assets/ext-7.4.0.42/classic/classic/src/Responsive.js
  42. 14 0
      assets/ext-7.4.0.42/classic/classic/src/ResponsiveWidget.js
  43. 808 0
      assets/ext-7.4.0.42/classic/classic/src/ZIndexManager.js
  44. 2280 0
      assets/ext-7.4.0.42/classic/classic/src/button/Button.js
  45. 246 0
      assets/ext-7.4.0.42/classic/classic/src/button/Cycle.js
  46. 116 0
      assets/ext-7.4.0.42/classic/classic/src/button/Manager.js
  47. 642 0
      assets/ext-7.4.0.42/classic/classic/src/button/Segmented.js
  48. 379 0
      assets/ext-7.4.0.42/classic/classic/src/button/Split.js
  49. 227 0
      assets/ext-7.4.0.42/classic/classic/src/container/ButtonGroup.js
  50. 2492 0
      assets/ext-7.4.0.42/classic/classic/src/container/Container.js
  51. 394 0
      assets/ext-7.4.0.42/classic/classic/src/container/DockingContainer.js
  52. 225 0
      assets/ext-7.4.0.42/classic/classic/src/container/Monitor.js
  53. 145 0
      assets/ext-7.4.0.42/classic/classic/src/container/Viewport.js
  54. 78 0
      assets/ext-7.4.0.42/classic/classic/src/dashboard/Column.js
  55. 454 0
      assets/ext-7.4.0.42/classic/classic/src/dashboard/Dashboard.js
  56. 291 0
      assets/ext-7.4.0.42/classic/classic/src/dashboard/DropZone.js
  57. 196 0
      assets/ext-7.4.0.42/classic/classic/src/dashboard/Panel.js
  58. 201 0
      assets/ext-7.4.0.42/classic/classic/src/dashboard/Part.js
  59. 334 0
      assets/ext-7.4.0.42/classic/classic/src/dd/DD.js
  60. 212 0
      assets/ext-7.4.0.42/classic/classic/src/dd/DDProxy.js
  61. 196 0
      assets/ext-7.4.0.42/classic/classic/src/dd/DDTarget.js
  62. 1166 0
      assets/ext-7.4.0.42/classic/classic/src/dd/DragDrop.js
  63. 1531 0
      assets/ext-7.4.0.42/classic/classic/src/dd/DragDropManager.js
  64. 484 0
      assets/ext-7.4.0.42/classic/classic/src/dd/DragSource.js
  65. 777 0
      assets/ext-7.4.0.42/classic/classic/src/dd/DragTracker.js
  66. 147 0
      assets/ext-7.4.0.42/classic/classic/src/dd/DragZone.js
  67. 146 0
      assets/ext-7.4.0.42/classic/classic/src/dd/DropTarget.js
  68. 291 0
      assets/ext-7.4.0.42/classic/classic/src/dd/DropZone.js
  69. 139 0
      assets/ext-7.4.0.42/classic/classic/src/dd/Registry.js
  70. 313 0
      assets/ext-7.4.0.42/classic/classic/src/dd/ScrollManager.js
  71. 206 0
      assets/ext-7.4.0.42/classic/classic/src/dd/StatusProxy.js
  72. 92 0
      assets/ext-7.4.0.42/classic/classic/src/dom/ButtonElement.js
  73. 187 0
      assets/ext-7.4.0.42/classic/classic/src/dom/Layer.js
  74. 24 0
      assets/ext-7.4.0.42/classic/classic/src/enums.js
  75. 66 0
      assets/ext-7.4.0.42/classic/classic/src/event/publisher/MouseEnterLeave.js
  76. 252 0
      assets/ext-7.4.0.42/classic/classic/src/flash/Component.js
  77. 1307 0
      assets/ext-7.4.0.42/classic/classic/src/form/Basic.js
  78. 564 0
      assets/ext-7.4.0.42/classic/classic/src/form/CheckboxGroup.js
  79. 14 0
      assets/ext-7.4.0.42/classic/classic/src/form/CheckboxManager.js
  80. 206 0
      assets/ext-7.4.0.42/classic/classic/src/form/FieldAncestor.js
  81. 362 0
      assets/ext-7.4.0.42/classic/classic/src/form/FieldContainer.js
  82. 759 0
      assets/ext-7.4.0.42/classic/classic/src/form/FieldSet.js
  83. 118 0
      assets/ext-7.4.0.42/classic/classic/src/form/Label.js
  84. 1142 0
      assets/ext-7.4.0.42/classic/classic/src/form/Labelable.js
  85. 483 0
      assets/ext-7.4.0.42/classic/classic/src/form/Panel.js
  86. 416 0
      assets/ext-7.4.0.42/classic/classic/src/form/RadioGroup.js
  87. 28 0
      assets/ext-7.4.0.42/classic/classic/src/form/RadioManager.js
  88. 332 0
      assets/ext-7.4.0.42/classic/classic/src/form/action/Action.js
  89. 36 0
      assets/ext-7.4.0.42/classic/classic/src/form/action/DirectAction.js
  90. 104 0
      assets/ext-7.4.0.42/classic/classic/src/form/action/DirectLoad.js
  91. 107 0
      assets/ext-7.4.0.42/classic/classic/src/form/action/DirectSubmit.js
  92. 138 0
      assets/ext-7.4.0.42/classic/classic/src/form/action/Load.js
  93. 36 0
      assets/ext-7.4.0.42/classic/classic/src/form/action/StandardSubmit.js
  94. 345 0
      assets/ext-7.4.0.42/classic/classic/src/form/action/Submit.js
  95. 1259 0
      assets/ext-7.4.0.42/classic/classic/src/form/field/Base.js
  96. 781 0
      assets/ext-7.4.0.42/classic/classic/src/form/field/Checkbox.js
  97. 2761 0
      assets/ext-7.4.0.42/classic/classic/src/form/field/ComboBox.js
  98. 864 0
      assets/ext-7.4.0.42/classic/classic/src/form/field/Date.js
  99. 248 0
      assets/ext-7.4.0.42/classic/classic/src/form/field/Display.js
  100. 0 0
      assets/ext-7.4.0.42/classic/classic/src/form/field/Field.js

+ 106 - 0
assets/ext-7.4.0.42/classic/classic/.sencha/test/Ext.cmd.api.adapter.js

@@ -0,0 +1,106 @@
+Ext.cmd.api.adapter = {
+
+    testResults: [],
+    isRunning: false,
+    resultBufferSize: 100,
+    api: Ext.cmd.api,
+
+    setCurrentScript: function(name) {
+        // no-op, managed by Ext.Boot.currentFile
+    },
+
+    getCurrentScript: function() {
+        return this.api.getCurrentScript(Ext.Boot.currentFile);
+    },
+
+    getSpecStructure: function(spec) {
+        var structure = {
+            hash: '' + spec.id,
+            fileName: spec.fileName,
+            description: spec.description
+        };
+        return structure;
+    },
+
+    getSuiteStructure: function(suite) {
+        var structure = {
+                hash: '' + suite.id,
+                fileName: suite.fileName,
+                suites: [],
+                specs: [],
+                description: suite.description
+            },
+            specs = suite.specs_,
+            spLen = specs.length, spec, sp,
+            suites = suite.suites_,
+            suLen = suites.length, suite, su;
+
+        for(su = 0; su < suLen; su++) {
+            suite = suites[su];
+            structure.suites.push(this.getSuiteStructure(suite));
+        }
+
+        for(sp = 0; sp < spLen; sp++) {
+            spec = specs[sp];
+            structure.specs.push(this.getSpecStructure(spec));
+        }
+
+        return structure;
+    },
+
+    reportTestStructure: function() {
+        var runner = jasmine.getEnv().currentRunner_,
+            suites = runner.topLevelSuites(),
+            slen = suites.length, suite, s,
+            structure = [];
+
+        for(s = 0; s < slen; s++) {
+            suite = suites[s];
+            structure.push(this.getSuiteStructure(suite));
+        }
+        this.api.addTestSuites(structure);
+    },
+
+    executeTests: function() {
+        this.isRunning = true;
+        jasmine.setOptions(this.api.jsonOptions);
+        jasmine.initDebug();
+        jasmine.getEnv().addReporter(new SenchaTestRunner.Reporter());
+        jasmine.getEnv().execute();
+    },
+
+    flushTestResults: function() {
+        if(this.testResults.length > 0) {
+            var results = this.testResults;
+            this.testResults = [];
+            this.api.reportTestResults(results);
+        }
+    },
+
+    onTestResult: function(result) {
+        this.testResults.push(result);
+        if(this.testResults.length >= this.resultBufferSize) {
+            this.flushTestResults();
+        }
+    },
+
+    captureCoverage: function() {
+        var coverageObj = window['__coverage__'];
+        if(coverageObj) {
+            this.api.addTestCoverage(coverageObj);
+        }
+    },
+
+    onTestsDone: function(success) {
+        var me = this;
+        me.isRunning = false;
+        if(success === undefined) {
+            me.success = true;
+        } else {
+            me.success = success;
+        }
+        me.flushTestResults();
+        me.captureCoverage();
+        this.api.stopWorkItem(me.success);
+    }
+};

+ 300 - 0
assets/ext-7.4.0.42/classic/classic/.sencha/test/test-impl.xml

@@ -0,0 +1,300 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+********************************** DO NOT EDIT **********************************
+
+This file will be replaced during upgrades so DO NOT EDIT this file. If you need to
+adjust the process, reading and understanding this file is the first step.
+
+In most cases, the adjustments can be achieved by setting properties or providing one
+of the "hooks" in the form of a "-before-" or "-after-" target. Whenever possible, look
+for one of these solutions.
+
+Failing that, you can copy whole targets to your build.xml file and it will overrride
+the target provided here. Doing that can create problems for upgrading to newer
+versions of Cmd so it is not recommended but it will be easier to manage than editing
+this file in most cases.
+-->
+<project name="cmd-test">
+    <target name="-before-test-init"/>
+    <target name="-test-init">
+        <condition property="environment.dir" value="${app.dir}">
+            <isset property="${app.dir}"/>
+        </condition>
+
+        <property name="environment.dir" value="${package.dir}"/>
+        <property name="cmd-test.specs.dir" value="${environment.dir}/test/specs"/>
+        <property name="cmd-test.specs.test-json" value="${cmd-test.specs.dir}/../test.json"/>
+        <available file="${cmd-test.specs.test-json}" property="cmd-test.available"/>
+    </target>
+    <target name="-after-test-init"/>
+    <target name="test-init"
+            depends="init,-before-test-init,-test-init,-after-test-init"/>
+
+    <target name="-before-test-console"/>
+    <target name="-test-console" depends="test-bootstrap">
+        <echo>Launching Sencha Test Console</echo>
+        <echo>using cmd.dir : ${cmd.dir}</echo>
+        <x-sencha-command
+                dir="cmd-test.specs.dir">
+            <property name="cmd-test.run.launch-browser" 
+                      value="${cmd-test.run.launch-browser}"/>
+            test
+                console
+                    -configFile
+                    ${cmd-test.specs.test-json}
+        </x-sencha-command>
+    </target>
+    <target name="-after-test-console"/>
+    <target name="test-console"
+            depends="test-init,-before-test-console,-test-console,-after-test-console"
+            description="Run tests"/>
+
+    <target name="-before-test-run"/>
+    <target name="-test-run" depends="test-bootstrap">
+        <echo>Launching Sencha Test Runner</echo>
+        <echo>using cmd.dir : ${cmd.dir}</echo>
+        <x-sencha-command
+                dir="cmd-test.specs.dir">
+            test
+                run
+                    -configFile
+                    ${cmd-test.specs.test-json}
+        </x-sencha-command>
+    </target>
+    <target name="-after-test-run"/>
+    <target name="test-run"
+            depends="test-init,-before-test-run,-test-run,-after-test-run"
+            description="Run tests"/>
+
+
+    <target name="-before-test-bootstrap"/>
+    <target name="-test-bootstrap" if="${cmd-test.available}">
+        <local name="local.runner.dir"/>
+        <local name="console.runner.dir"/>
+        <local name="specfiles.list"/>
+        <local name="specfiles.start-test"/>
+        <local name="base.path"/>
+
+        <property name="local.runner.dir" value="${environment.dir}/test/local"/>
+        <property name="console.runner.dir" value="${environment.dir}/test/specs"/>
+
+        <property name="base.path" value="${local.runner.dir}"/>
+        <property name="bootstrap.specs.file" value="../bootstrap-specs.js"/>
+
+        <!--Comment this line out to skip including bootstrap metadata for the test files-->
+        <property name="scan.test.files" value="true"/>
+        
+        <if>
+            <x-is-true value="${scan.test.files}"/>
+            <then>
+                <x-compile refid="${compiler.ref.id}">
+                    <![CDATA[
+                        save
+                            current
+                        and
+                        classpath
+                            +new
+                             -name=specs
+                             -path=${package.dir}/../../packages/core/test/specs
+                        and
+                        classpath
+                             -name=specs
+                             -path=${package.dir}/test/specs
+                        and
+                        classpath
+                             -name=specs
+                             -path=${package.dir}/../../packages/charts/test/specs
+                        and
+                        classpath
+                             -name=specs
+                             -path=${package.dir}/../../packages/charts/test/specs-classic
+                        and
+                        classpath
+                             -name=specs
+                             -path=${package.dir}/../../packages/ux/test/specs
+                        and
+                        classpath
+                             -name=specs
+                             -path=${package.dir}/../../packages/ux/test/classic/specs
+                        and
+                        classpath
+                             -name=specs
+                             -path=${package.dir}/../../../packages/d3/test/specs
+                        and
+                        classpath
+                             -name=specs
+                             -path=${package.dir}/../../../packages/d3/test/specs-classic
+                        and
+                        classpath
+                             -name=specs
+                             -path=${package.dir}/../../../packages/pivot/test/specs
+                        and
+                        classpath
+                             -name=specs
+                             -path=${package.dir}/../../../packages/pivot/test/classic/specs
+                        and
+                        classpath
+                             -name=specs
+                             -path=${package.dir}/../../../packages/exporter/test/specs
+                        and
+                        classpath
+                             -name=specs
+                             -path=${package.dir}/../../../packages/exporter/test/classic/specs
+                        and
+                        include
+                             -all
+                    ]]>
+                </x-compile>
+            </then>
+        </if>
+
+
+
+        <x-bootstrap file="${base.path}/../bootstrap.js"
+                     basedir="${base.path}"
+                     coreFilesFile="${base.path}/../bootstrap-files.js"
+                     classMetadataFile="${base.path}/../bootstrap-data.js"
+                     overridesFile="${base.path}/../bootstrap-data.js"
+                     includeBoot="true"
+                     includeManifest="true"
+                     includeCoreFiles="true"
+                     appendCoreFiles="false"
+                     includeMetadata="false"
+                     appendClassMetadata="false"
+                     appendOverrides="true"
+                     overrideExcludeTags="">
+<![CDATA[
+Ext.Boot.loadSync([
+    "../bootstrap-files.js",
+    "../bootstrap-data.js"
+]);
+Ext.Boot.load("../bootstrap-launch.js");
+]]>
+         </x-bootstrap>
+        <if>
+            <x-is-true value="${scan.test.files}"/>
+            <then>
+                <x-compile refid="${compiler.ref.id}">
+                    restore
+                    current
+                </x-compile>
+            </then>
+        </if>
+
+        <!--
+        for the local runner, we also need to include all spec files in the bootstrap
+        info
+        -->
+        <x-script-def name="x-load-specs">
+            <attribute name="base"/>
+            <attribute name="property"/>
+            <attribute name="configprop"/>
+            <attribute name="startscriptprop"/>
+            <attribute name="startscriptpath"/>
+            <script src="${cmd.dir}/ant/ant-util.js"/>
+            <![CDATA[
+                    importPackage(com.sencha.util);
+                    importPackage(com.sencha.logging);
+                    var logger = SenchaLogManager.getLogger(),
+					specDir = project.getProperty('cmd-test.specs.dir') + '',
+                    propName = attributes.get("property") + '',
+                    basePath = attributes.get("base") + '',
+                    configPropName = attributes.get("configprop"),
+                    config = readConfig(joinPath(specDir, '../test.json')),
+                    getScriptFiles = function(path, basePath) {
+                        var converted = [],
+                            files = FileUtil.getAllFilesByExtension(path, ".js"),
+                            length = files.size(), file, f,
+                            relPath;
+                        for(f = 0; f < length; f++) {
+                            file = files.get(f);
+                            logger.debug("getting relpath from {} to {}", basePath, file);
+                            relPath = PathUtil.getRelativePath(basePath, file);
+                            relPath = PathUtil.convertPathCharsToUnix(relPath);
+                            converted.push('"' + relPath + '"');
+                        }
+                        return converted;
+                    },
+                    shuffle = function(input, factor) {
+                        if (!factor)
+                            return input;
+                            
+                        var i, f,
+                            reverse = factor < 0,
+                            output = [];
+                        factor = Math.abs(factor);
+                        for (f = 0; f < factor; f++) {
+                            for (i = f; i < input.length; i = i + factor) {
+                                output.push(input[i]);
+                            }
+                        }
+                        return reverse ? output.reverse() : output;
+                    },
+                    files = config[configPropName].src || [],
+                    shuffleFactor = config[configPropName].shuffle || 0, 
+                    len = files.length, file, f,
+                    relPath,
+                    converted = [],
+                    shuffled = [];
+                    
+                    for(f = 0; f < len; f++) {
+                        file = files[f];
+                        if(!PathUtil.isAbsolute(file)) {
+                            file = PathUtil.join(specDir, file);
+                        }
+                        file = PathUtil.getCanonicalPath(file);
+                        converted = converted.concat(getScriptFiles(file, basePath));
+                    }
+
+                    // FileUtil.getAllFilesByExtension returns files in a different order
+                    // depending on OS.  This sort ensures the files are always ordered the same.
+                    converted.sort(function(a, b) {
+                        return (a < b) ? -1 : (a > b) ? 1 : 0
+                    });
+                    shuffled = shuffle(converted, shuffleFactor);
+                    project.setNewProperty(propName, StringUtil.join(shuffled, ',\n'));
+                    
+                    var frameworkDir = project.getProperty('framework.dir'),
+                        startScriptProp = attributes.get('startscriptprop'),
+                        startScriptPath = attributes.get('startscriptpath');
+                    
+                    relPath = PathUtil.getRelativePath(basePath, frameworkDir + '/' + startScriptPath);
+                    relPath = PathUtil.convertPathCharsToUnix(relPath);
+                    
+                    project.setNewProperty(startScriptProp, relPath);
+                ]]>
+        </x-script-def>
+        
+        <!-- startscriptpath is relative to framework root -->
+        <x-load-specs base="${local.runner.dir}" property="specfiles.list" configprop="specs"
+                      startscriptprop="specfiles.start-test"
+                      startscriptpath="test/shared/start-tests.js"/>
+        
+        <echo file="${local.runner.dir}/${bootstrap.specs.file}">
+<![CDATA[
+(function() {
+    var url = [
+${specfiles.list}
+        ];
+
+    if (top.Test && top.Test.Options && top.Test.Options.getCurrentChunk) {
+        url = top.Test.Options.getCurrentChunk(url);
+    }
+
+    Ext.Boot.load({
+        charset: "UTF-8",
+        url: url,
+        success: function() {
+            Ext.Boot.load("${specfiles.start-test}");
+        }
+    });
+})();
+]]>
+        </echo>
+    </target>
+    <target name="-after-test-bootstrap"/>
+    <target name="test-bootstrap"
+            depends="test-init,-before-test-bootstrap,-test-bootstrap,-after-test-bootstrap"
+            description="Re-generate the bootstrap info for local and console test harnesses"/>
+
+</project>

+ 2 - 0
assets/ext-7.4.0.42/classic/classic/Readme.md

@@ -0,0 +1,2 @@
+# classic - Read Me
+

+ 506 - 0
assets/ext-7.4.0.42/classic/classic/build.xml

@@ -0,0 +1,506 @@
+<?xml version="1.0" encoding="utf-8"?>
+<project name="classic" default=".help">
+    <!--
+    The build-impl.xml file imported here contains the guts of the build process. It is
+    a great idea to read that file to understand how the process works, but it is best to
+    limit your changes to this file.
+    -->
+    <script language="javascript">
+        <![CDATA[
+            var dir = project.getProperty("basedir"),
+                cmdDir = project.getProperty("cmd.dir"),
+                cmdLoaded = project.getReference("senchaloader");
+            
+            if (!cmdLoaded) {
+                function echo(message, file) {
+                    var e = project.createTask("echo");
+                    e.setMessage(message);
+                    if (file) {
+                        e.setFile(file);
+                    }
+                    e.execute();
+                };
+
+                if (!cmdDir) {
+                    
+                    function exec(args) {
+                        var process = java.lang.Runtime.getRuntime().exec(args),
+                            input = new java.io.BufferedReader(new java.io.InputStreamReader(process.getInputStream())),
+                            headerFound = false,
+                            line;
+
+                        while (line = input.readLine()) {
+                            line = line + '';
+                            java.lang.System.out.println(line);
+                            if (line.indexOf("Sencha Cmd") > -1) {
+                                headerFound = true;
+                            }
+                            else if (headerFound && !cmdDir) {
+                                cmdDir = line;
+                                project.setProperty("cmd.dir", cmdDir);
+                            }
+                        }
+                        process.waitFor();
+                        return !!cmdDir;
+                    }
+                    
+                    if (!exec(["sencha", "which"])) {
+                        var tmpFile = "tmp.sh";
+                        echo("source ~/.bash_profile; sencha " + whichArgs.join(" "), tmpFile);
+                        exec(["/bin/sh", tmpFile]);
+                        new java.io.File(tmpFile)['delete'](); 
+                    }
+                }
+            }
+            
+            if (cmdDir && !project.getTargets().containsKey("init-cmd")) {
+                var importTask = project.createTask("import");
+                importTask.setOwningTarget(self.getOwningTarget());
+                importTask.setLocation(self.getLocation());
+                importTask.setFile(cmdDir + "/ant/build/package/build-impl.xml");
+                importTask.execute();
+            }
+        ]]>
+    </script>
+    <import file="${basedir}/.sencha/test/test-impl.xml"/>
+
+    <target name="-js" depends="init">
+
+        <local name="manifest.wrapper"/>
+        <local name="concat.options"/>
+
+        <property name="concat.options">
+            -remove-text-references=false
+            -optimize-string-references=false
+            -remove-requirement-nodes=false
+        </property>
+
+        <property name="manifest.wrapper"><![CDATA[
+var Ext = Ext || {};
+(function(manifest){
+    if(!Ext.manifest) {
+        Ext.manifest = manifest;
+    } else {
+        for(var name in manifest) {
+            Ext.manifest[name] = manifest[name];
+        }
+    }
+})]]></property>
+
+        <echo file="${build.dir}/ext-debug.js" message="${manifest.wrapper}"/>
+        <echo file="${build.dir}/ext.js" message="${manifest.wrapper}"/>
+
+        <property name="build.optimize"><![CDATA[
+            optimize
+                -css-prefix=true
+                -call-parent=true
+                -define-rewrite=true
+                -include-metadata=false
+        ]]></property>
+
+        <property name="build.compress"><![CDATA[
+             #+closure
+        ]]></property>
+
+        <!--
+        Ext JS produces a few additional flavors of compiled code, so we just reject the
+        provided build.compile.command property and substitute our own.
+        -->
+        <x-compile refid="${compiler.ref.id}">
+            <![CDATA[
+                -ignore=diag
+
+                    exclude
+                        -all
+                    and
+                    include
+                        +recursive
+                        -includeUses=false
+                        -class=Ext.Loader
+                    and
+                    include
+                        -tag=overrides
+                    and
+                    save
+                        corefiles
+                    and
+                    include
+                        -tag=package-core,package-classic
+                    and
+                    save
+                        allfiles
+                    and
+
+                # Build *-debug.js files - these have all "debug" conditional code active
+                # for use in development mode.
+
+                -options=debug:true
+                    restore
+                        allfiles
+                    and
+                    concatenate
+                        ${concat.options}
+                        -output-file=${build.dir}/ext-all-rtl-debug.js
+                    and
+
+
+                    exclude
+                        -namespace=Ext.rtl
+                    and
+
+                    concatenate
+                        ${concat.options}
+                        -output-file=${build.dir}/ext-all-debug.js
+                    and
+
+                    exclude
+                        -set=corefiles
+                    and
+                    metadata
+                        +append
+                        -tpl=({0});
+                        -info=AppManifest
+                        -basePath=${build.dir}
+                        +bootRelative
+                        -excludeDisabled=true
+                        -output-file=${build.dir}/ext-debug.js
+                    and
+                    metadata
+                        +append
+                        -tpl=({0});
+                        -info=AppManifest
+                        -basePath=${build.dir}
+                        +bootRelative
+                        -excludeDisabled=true
+                        -output-file=${build.dir}/ext.js
+                    and
+
+                    restore
+                        corefiles
+                    and
+
+                    concatenate
+                        +append
+                        ${concat.options}
+                        -output-file=${build.dir}/ext-debug.js
+                    and
+                    concatenate
+                        +append
+                        ${concat.options}
+                        ${build.compress}
+                        -output-file=${build.dir}/ext.js
+                    and
+
+                # Optimize and compress the builds
+                -options=debug:false
+                    restore
+                        allfiles
+                    and
+
+                    ${build.optimize}
+                    and
+
+                    concatenate
+                        ${concat.options}
+                        ${build.compress}
+                        -output-file=${build.dir}/ext-all-rtl.js
+                    and
+
+                    exclude
+                        -namespace=Ext.rtl
+                    and
+                    concatenate
+                        ${concat.options}
+                        ${build.compress}
+                        -output-file=${build.dir}/ext-all.js
+                    and
+            ]]>
+        </x-compile>
+
+        <if>
+            <not><isset property="skip.post.compress"/></not>
+            <then>
+                <for list="ext,ext-all,ext-all-rtl" param="file">
+                    <sequential>
+                        <x-echo>Compressing ${build.dir}/@{file}.js</x-echo>
+                        <x-compress-js srcfile="${build.dir}/@{file}.js"/>
+                    </sequential>
+                </for>
+            </then>
+        </if>
+    </target>
+
+    <target name="perf">
+        <property name="skip.post.compress" value="1"/>
+    </target>
+
+    <target name="calendar" depends="init">
+        <x-compile refid="${compiler.ref.id}">
+            <![CDATA[
+            classpath
+                +new
+                -name=calendar
+                -path=${framework.dir}/../packages/calendar/classic/src
+            and
+            classpath
+                -name=calendar
+                -path=${framework.dir}/../packages/calendar/src
+            and
+            classpath
+                -name=calendar
+                -path=${framework.dir}/../packages/calendar/classic/overrides
+                -tags=overrides
+            and
+            classpath
+                -name=calendar
+                -path=${framework.dir}/../packages/calendar/overrides
+                -tags=overrides
+            and
+            include
+                -all
+        ]]>
+        </x-compile>
+    </target>
+
+    <target name="charts" depends="init">
+        <x-compile refid="${compiler.ref.id}">
+            <![CDATA[
+            classpath
+                +new
+                -name=charts
+                -path=${framework.dir}/packages/charts/classic/src
+            and
+            classpath
+                -name=charts
+                -path=${framework.dir}/packages/charts/src
+            and
+            classpath
+                -name=charts
+                -path=${framework.dir}/packages/charts/classic/overrides
+                -tags=overrides
+            and
+            classpath
+                -name=charts
+                -path=${framework.dir}/packages/charts/overrides
+                -tags=overrides
+            and
+            include
+                -all
+        ]]>
+        </x-compile>
+    </target>
+
+    <target name="d3" depends="init">
+        <x-compile refid="${compiler.ref.id}">
+            <![CDATA[
+            classpath
+                +new
+                -name=d3
+                -path=${framework.dir}/../packages/d3/classic/src
+            and
+            classpath
+                -name=d3
+                -path=${framework.dir}/../packages/d3/src
+            and
+            classpath
+                -name=d3
+                -path=${framework.dir}/../packages/d3/classic/overrides
+                -tags=overrides
+            and
+            classpath
+                -name=d3
+                -path=${framework.dir}/../packages/d3/overrides
+                -tags=overrides
+            and
+            include
+                -all
+        ]]>
+        </x-compile>
+    </target>
+
+    <target name="ux" depends="init">
+        <x-compile refid="${compiler.ref.id}">
+            <![CDATA[
+            classpath
+                +new
+                -name=ux
+                -path=${framework.dir}/packages/ux/classic/src
+            and
+            classpath
+                -name=ux
+                -path=${framework.dir}/packages/ux/src
+            and
+            classpath
+                -name=ux
+                -path=${framework.dir}/packages/ux/classic/overrides
+                -tags=overrides
+            and
+            classpath
+                -name=ux
+                -path=${framework.dir}/packages/ux/overrides
+                -tags=overrides
+            and
+            include
+                -all
+        ]]>
+        </x-compile>
+    </target>
+
+    <target name="exporter" depends="init">
+        <x-compile refid="${compiler.ref.id}">
+            <![CDATA[
+            classpath
+                +new
+                -name=exporter
+                -path=${framework.dir}/../packages/exporter/classic/src
+            and
+            classpath
+                -name=exporter
+                -path=${framework.dir}/../packages/exporter/src
+            and
+            classpath
+                -name=exporter
+                -path=${framework.dir}/../packages/exporter/classic/overrides
+                -tags=overrides
+            and
+            classpath
+                -name=exporter
+                -path=${framework.dir}/../packages/exporter/overrides
+                -tags=overrides
+            and
+            include
+                -all
+        ]]>
+        </x-compile>
+    </target>
+
+    <target name="pivot" depends="init">
+        <x-compile refid="${compiler.ref.id}">
+            <![CDATA[
+            classpath
+                +new
+                -name=pivot
+                -path=${framework.dir}/../packages/pivot/classic/src
+            and
+            classpath
+                -name=pivot
+                -path=${framework.dir}/../packages/pivot/src
+            and
+            classpath
+                -name=pivot
+                -path=${framework.dir}/../packages/pivot/classic/overrides
+                -tags=overrides
+            and
+            classpath
+                -name=pivot
+                -path=${framework.dir}/../packages/pivot/overrides
+                -tags=overrides
+            and
+            include
+                -all
+        ]]>
+        </x-compile>
+    </target>
+
+    <target name="pivot-d3" depends="init,pivot,d3">
+        <x-compile refid="${compiler.ref.id}">
+            <![CDATA[
+            classpath
+                +new
+                -name=pivot-d3
+                -path=${framework.dir}/../packages/pivot-d3/classic/src
+            and
+            classpath
+                -name=pivot-d3
+                -path=${framework.dir}/../packages/pivot-d3/src
+            and
+            classpath
+                -name=pivot-d3
+                -path=${framework.dir}/../packages/pivot-d3/classic/overrides
+                -tags=overrides
+            and
+            classpath
+                -name=pivot-d3
+                -path=${framework.dir}/../packages/pivot-d3/overrides
+                -tags=overrides
+            and
+            include
+                -all
+        ]]>
+        </x-compile>
+    </target>
+
+    <target name="core-bootstrap" depends="init">
+        <local name="base.path"/>
+        <property name="base.path" value="${framework.dir}"/>
+
+        <delete file="${base.path}/bootstrap-manifest.js"/>
+
+        <x-compile refid="${compiler.ref.id}">
+            <![CDATA[
+                include
+                    -all
+                and
+                exclude
+                    +recursive
+                    -class=Ext.Loader
+                and
+                metadata
+                    -tpl=var Ext = Ext || '{' '}'; Ext.manifest = {0};
+                    -info=AppManifest
+                    -basePath=${base.path}
+                    +append
+                    +bootRelative
+                    -output-file=${base.path}/bootstrap-manifest.js
+            ]]>
+        </x-compile>
+
+        <x-bootstrap file="${base.path}/bootstrap.js"
+                     basedir="${base.path}"
+                     coreFilesFile="${base.path}/bootstrap-files.js"
+                     classMetadataFile="${base.path}/bootstrap-data.js"
+                     overridesFile="${base.path}/bootstrap-data.js"
+                     includeBoot="true"
+                     includeCoreFiles="true"
+                     appendCoreFiles="false"
+                     appendClassMetadata="false"
+                     appendOverrides="true"
+                     coreFilesJsonpTpl="Ext.Boot.loadSyncBasePrefix"
+                     loaderConfigJsonpTpl="Ext.Loader.addBaseUrlClassPathMappings"
+                     overrideTpl="Ext.Loader.loadScriptsSyncBasePrefix"
+                     overrideTplType="jsonp"
+                     overrideExcludeTags="">
+<![CDATA[
+Ext.Boot.loadSyncBasePrefix([
+    "bootstrap-manifest.js",
+    "bootstrap-files.js"
+]);
+]]>
+        </x-bootstrap>
+
+        <!--
+        Duplicate the "ext.js" dev-mode bootstrap file to the other deployed names
+        -->
+        <for list="ext,ext-all,ext-all-rtl" param="part1">
+            <sequential>
+                <for list=".,-debug." param="part2">
+                    <sequential>
+                        <local name="out"/>
+                        <property name="out" value="@{part1}@{part2}js"/>
+                        <echo>Generating ${out}</echo>
+                        <copy file="${base.path}/bootstrap.js" tofile="${base.path}/${out}"
+                              overwrite="true"/>
+                        <replace file="${base.path}/${out}"
+                                 token="bootstrapper"
+                                 value="bootstrapper :: GENERATED COPY! Edit &quot;core/bootstrap.js&quot;"/>
+                    </sequential>
+                </for>
+            </sequential>
+        </for>
+        <delete file="${base.path}/bootstrap.js"/>
+    </target>
+
+    <target name="bootstrap"
+            description="*** Regenerate files needed by standalone examples and unit tests ***"
+            depends="calendar,charts,d3,ux,exporter,pivot,pivot-d3,core-bootstrap,test-bootstrap"/>
+</project>

+ 3 - 0
assets/ext-7.4.0.42/classic/classic/index.js

@@ -0,0 +1,3 @@
+// This file was intentionally left blank.
+// This file is used by require.resolve to property locate this module.
+

+ 76 - 0
assets/ext-7.4.0.42/classic/classic/overrides/GlobalEvents.js

@@ -0,0 +1,76 @@
+// @tag core
+
+/**
+ * @class Ext.GlobalEvents
+ */
+Ext.define('Ext.overrides.GlobalEvents', {
+    override: 'Ext.GlobalEvents',
+
+    /**
+     * @event resumelayouts
+     * Fires after global layout processing has been resumed in {@link
+     * Ext.Component#resumeLayouts}.
+     */
+
+    attachListeners: function() {
+        var me = this,
+            docElement, bufferedFn;
+
+        // In IE9- when using legacy onresize event via attachEvent or onresize property,
+        // the event may fire for *content size changes* as well as actual document view
+        // size changes. See this: https://msdn.microsoft.com/en-us/library/ms536959(v=vs.85).aspx
+        // and this: http://stackoverflow.com/questions/1852751/window-resize-event-firing-in-internet-explorer
+        // The amount of these events firing all at once can be entirely staggering, and they
+        // often happen during layouts so we have to be über careful to execute as few JavaScript
+        // statements as possible to improve overall framework performance.
+        if (Ext.isIE8) {
+            docElement = Ext.getDoc().dom.documentElement;
+            bufferedFn = Ext.Function.createBuffered(me.fireResize, me.resizeBuffer, me);
+
+            Ext.getWin().dom.attachEvent('onresize', function() {
+                if (docElement.clientWidth !== Ext.GlobalEvents.curWidth ||
+                    docElement.clientHeight !== Ext.GlobalEvents.curHeight) {
+                    bufferedFn();
+                }
+            });
+        }
+
+        me.callParent();
+    },
+
+    deprecated: {
+        5: {
+            methods: {
+                addListener: function(ename, fn, scope, options, order, caller, eventOptions) {
+                    var name,
+                        readyFn;
+
+                    // The "ready" event was removed from Ext.globalEvents in 5.0 in favor of
+                    // Ext.onReady().  This function adds compatibility for the ready event
+
+                    if (ename === 'ready') {
+                        readyFn = fn;
+                    }
+                    else if (typeof ename !== 'string') {
+                        for (name in ename) {
+                            if (name === 'ready') {
+                                readyFn = ename[name];
+                            }
+                        }
+                    }
+
+                    if (readyFn) {
+                        //<debug>
+                        Ext.log.warn("Ext.on('ready', fn) is deprecated.  " +
+                                     "Please use Ext.onReady(fn) instead.");
+                        //</debug>
+
+                        Ext.onReady(readyFn);
+                    }
+
+                    this.callParent([ename, fn, scope, options, order, caller, eventOptions]);
+                }
+            }
+        }
+    }
+});

+ 204 - 0
assets/ext-7.4.0.42/classic/classic/overrides/Positionable.js

@@ -0,0 +1,204 @@
+/**
+ * @class Ext.util.Positionable
+ */
+Ext.define('Ext.overrides.util.Positionable', {
+    override: 'Ext.util.Positionable',
+
+    /**
+     * @method alignTo
+     * @param {Ext.util.Positionable/HTMLElement/String} anchorToEl The Positionable,
+     * HTMLElement, or id of the element to align to.
+     * @param {String} [alignment="tl-bl?"] The position to align to
+     * @param {Number[]} [offsets] Offset the positioning by [x, y]
+     * @param {Boolean/Object} [animate] true for the default animation or a standard
+     * Element animation config object
+     * @return {Ext.util.Positionable} this
+     */
+
+    /**
+     * @method anchorTo
+     * Anchors an element to another element and realigns it when the window is resized.
+     * @param {Ext.util.Positionable/HTMLElement/String} anchorToEl The Positionable,
+     * HTMLElement, or id of the element to align to.
+     * @param {String} [alignment="tl-bl?"] The position to align to
+     * @param {Number[]} [offsets] Offset the positioning by [x, y]
+     * @param {Boolean/Object} [animate] true for the default animation or a standard
+     * Element animation config object
+     * @param {Boolean/Number} [monitorScroll=50] True to monitor body scroll and
+     * reposition. If this parameter is a number, it is used as the buffer delay in
+     * milliseconds.
+     * @param {Function} [callback] The function to call after the animation finishes
+     * @return {Ext.util.Positionable} this
+     */
+    anchorTo: function(anchorToEl, alignment, offsets, animate, monitorScroll, callback) {
+        var me = this,
+            scroll = !Ext.isEmpty(monitorScroll),
+            action = function() {
+                me.mixins.positionable.alignTo.call(me, anchorToEl, alignment, offsets, animate);
+                Ext.callback(callback, me);
+            },
+            anchor = me.getAnchor();
+
+        // previous listener anchor, remove it
+        me.removeAnchor();
+        Ext.apply(anchor, {
+            fn: action,
+            scroll: scroll
+        });
+
+        Ext.on('resize', action, null);
+
+        if (scroll) {
+            Ext.getWin().on('scroll', action, null,
+                            { buffer: !isNaN(monitorScroll) ? monitorScroll : 50 });
+        }
+
+        action(); // align immediately
+
+        return me;
+    },
+
+    getAnchor: function() {
+        var el = this.el,
+            data, anchor;
+
+        if (!el || !el.dom) {
+            return;
+        }
+
+        data = el.getData();
+        anchor = data._anchor;
+
+        if (!anchor) {
+            anchor = data._anchor = {};
+        }
+
+        return anchor;
+    },
+
+    alignTo: function(element, position, offsets, /* private (documented in ext) */ animate) {
+        var me = this,
+            el = me.el,
+            newMaxHeight,
+            newRegion;
+
+        // Release any height constraint prior to aligning if we are shrinkwrap height.
+        if (me.isComponent && me.getSizeModel().height.shrinkWrap) {
+            if (me.maxHeight) {
+                me.setMaxHeight(null);
+            }
+
+            newMaxHeight = true;
+        }
+
+        newRegion = me.getAlignToRegion(element, position, offsets, me.minHeight || 150);
+        me.setXY([newRegion.x, newRegion.y], el.anim && !!animate ? el.anim(animate) : false);
+
+        // Impose calculated height constraint.
+        if (newMaxHeight && (newMaxHeight = newRegion.getHeight()) !== me.getHeight()) {
+            me.setMaxHeight(newMaxHeight);
+        }
+
+        return me;
+    },
+
+    /**
+     * @method move
+     * Move the element relative to its current position.
+     * @param {String} direction Possible values are:
+     *
+     * - `"l"` (or `"left"`)
+     * - `"r"` (or `"right"`)
+     * - `"t"` (or `"top"`, or `"up"`)
+     * - `"b"` (or `"bottom"`, or `"down"`)
+     *
+     * @param {Number} distance How far to move the element in pixels
+     * @param {Boolean/Object} [animate] true for the default animation or a standard
+     * Element animation config object
+     */
+
+    /**
+     * Remove any anchor to this element. See {@link #anchorTo}.
+     * @return {Ext.util.Positionable} this
+     */
+    removeAnchor: function() {
+        var anchor = this.getAnchor();
+
+        if (anchor && anchor.fn) {
+            Ext.un('resize', anchor.fn);
+
+            if (anchor.scroll) {
+                Ext.getWin().on('scroll', anchor.fn);
+            }
+
+            delete anchor.fn;
+        }
+
+        return this;
+    },
+
+    /**
+     * @method setBox
+     * Sets the element's box. If animate is true then x, y, width, and height will be
+     * animated concurrently.
+     * @param {Object} box The box to fill {x, y, width, height}
+     * @param {Boolean/Object} [animate] true for the default animation or a standard
+     * Element animation config object
+     * @return {Ext.util.Positionable} this
+     */
+    setBox: function(box, animate) {
+        var me = this;
+
+        if (box.isRegion) {
+            box = {
+                x: box.left,
+                y: box.top,
+                width: box.right - box.left,
+                height: box.bottom - box.top
+            };
+        }
+
+        if (animate) {
+            me.constrainBox(box);
+            me.animate(Ext.applyIf({
+                to: box,
+                listeners: {
+                    afteranimate: Ext.Function.bind(me.afterSetPosition, me, [box.x, box.y])
+                }
+            }, animate));
+        }
+        else {
+            me.callParent([box]);
+        }
+
+        return me;
+    }
+
+    /**
+     * @method setX
+     * Sets the X position of the DOM element based on page coordinates.
+     * @param {Number} x The X position
+     * @param {Boolean/Object} [animate] True for the default animation, or a standard
+     * Element animation config object
+     * @return {Ext.util.Positionable} this
+     */
+
+    /**
+     * @method setXY
+     * Sets the position of the DOM element in page coordinates.
+     * @param {Number[]} pos Contains X & Y [x, y] values for new position (coordinates
+     * are page-based)
+     * @param {Boolean/Object} [animate] True for the default animation, or a standard
+     * Element animation config object
+     * @return {Ext.util.Positionable} this
+     */
+
+    /**
+     * @method setY
+     * Sets the Y position of the DOM element based on page coordinates.
+     * @param {Number} y The Y position
+     * @param {Boolean/Object} [animate] True for the default animation, or a standard
+     * Element animation config object
+     * @return {Ext.util.Positionable} this
+     */
+});

+ 60 - 0
assets/ext-7.4.0.42/classic/classic/overrides/Progress.js

@@ -0,0 +1,60 @@
+/**
+ * @class Ext.Progress
+ *
+ *     @example
+ *     Ext.create({
+ *         xtype: 'grid',
+ *         title: 'Simpsons',
+ *         store: {
+ *             data: [
+ *                 { name: 'Lisa', progress: .159 },
+ *                 { name: 'Bart', progress: .216 },
+ *                 { name: 'Homer', progress: .55 },
+ *                 { name: 'Maggie', progress: .167 },
+ *                 { name: 'Marge', progress: .145 }
+ *             ]
+ *         },
+ *         columns: [
+ *             { text: 'Name',  dataIndex: 'name' },
+ *             {
+ *                 text: 'Progress',
+ *                 xtype: 'widgetcolumn',
+ *                 width: 120,
+ *                 dataIndex: 'progress',
+ *                 widget: {
+ *                     xtype: 'progress'
+ *                 }
+ *             }
+ *         ],
+ *         height: 200,
+ *         width: 400,
+ *         renderTo: Ext.getBody()
+ *     });
+ */
+
+Ext.define('Ext.overrides.Progress', {
+    override: 'Ext.Progress',
+
+    config: {
+        ui: 'default'
+    },
+
+    updateWidth: function(width, oldWidth) {
+        var me = this;
+
+        me.callParent([width, oldWidth]);
+        width -= me.element.getBorderWidth('lr');
+        me.backgroundEl.setWidth(width);
+        me.textEl.setWidth(width);
+    },
+
+    privates: {
+        startBarAnimation: function(o) {
+            this.barEl.animate(o);
+        },
+
+        stopBarAnimation: function() {
+            this.barEl.stopAnimation();
+        }
+    }
+});

+ 233 - 0
assets/ext-7.4.0.42/classic/classic/overrides/Widget.js

@@ -0,0 +1,233 @@
+/**
+ * @class Ext.Widget
+ */
+Ext.define('Ext.overrides.Widget', {
+    override: 'Ext.Widget',
+
+    uses: [
+        'Ext.Component',
+        'Ext.layout.component.Auto'
+    ],
+
+    $configStrict: false,
+
+    isComponent: true,
+
+    liquidLayout: true,
+
+    // in Ext JS the rendered flag is set as soon as a component has its element.  Since
+    // widgets always have an element when constructed, they are always considered to be
+    // "rendered"
+    rendered: true,
+
+    rendering: true,
+
+    config: {
+        renderTo: null
+    },
+
+    constructor: function(config) {
+        var me = this,
+            renderTo;
+
+        me.callParent([config]);
+
+        // initialize the component layout
+        me.getComponentLayout();
+        renderTo = me.getRenderTo();
+
+        if (renderTo) {
+            me.render(renderTo);
+        }
+    },
+
+    addClsWithUI: function(cls) {
+        this.el.addCls(cls);
+    },
+
+    afterComponentLayout: Ext.emptyFn,
+
+    updateLayout: function() {
+        var owner = this.getRefOwner();
+
+        if (owner) {
+            owner.updateLayout();
+        }
+    },
+
+    destroy: function() {
+        var me = this,
+            ownerCt = me.ownerCt;
+
+        if (ownerCt && ownerCt.remove) {
+            ownerCt.remove(me, false);
+        }
+
+        me.callParent();
+    },
+
+    finishRender: function() {
+        this.rendering = false;
+
+        this.initBindable();
+        this.initKeyMap();
+    },
+
+    getAnimationProps: function() {
+        // see Ext.util.Animate mixin
+        return {};
+    },
+
+    getComponentLayout: function() {
+        var me = this,
+            layout = me.componentLayout;
+
+        if (!layout) {
+            layout = me.componentLayout = new Ext.layout.component.Auto();
+            layout.setOwner(me);
+        }
+
+        return layout;
+    },
+
+    getEl: function() {
+        return this.element;
+    },
+
+    /**
+     * @private
+     * Needed for when widget is rendered into a grid cell. The class to add to the cell element.
+     * @member Ext.Widget
+     */
+    getTdCls: function() {
+        return Ext.baseCSSPrefix + this.getTdType() + '-' + (this.ui || 'default') + '-cell';
+    },
+
+    /**
+     * @private
+     * Partner method to {@link #getTdCls}.
+     *
+     * Returns the base type for the component. Defaults to return `this.xtype`, but
+     * All derived classes of {@link Ext.form.field.Text TextField} can return the type 'textfield',
+     * and all derived classes of {@link Ext.button.Button Button} can return the type 'button'
+     * @member Ext.Widget
+     */
+    getTdType: function() {
+        return this.xtype;
+    },
+
+    getItemId: function() {
+        // needed by ComponentQuery
+        return this.itemId || this.id;
+    },
+
+    getSizeModel: function() {
+        return Ext.Component.prototype.getSizeModel.apply(this, arguments);
+    },
+
+    onAdded: function(container, pos, instanced) {
+        var me = this;
+
+        me.ownerCt = container;
+
+        me.onInheritedAdd(me, instanced);
+
+        // this component is no longer detached from the body
+        me.isDetached = false;
+    },
+
+    onRemoved: function(destroying) {
+        this.onInheritedRemove(destroying);
+
+        this.ownerCt = this.ownerLayout = null;
+    },
+
+    parseBox: function(box) {
+        return Ext.Element.parseBox(box);
+    },
+
+    removeClsWithUI: function(cls) {
+        this.el.removeCls(cls);
+    },
+
+    render: function(container, position) {
+        var me = this,
+            element = me.element,
+            proto = Ext.Component.prototype,
+            nextSibling;
+
+        if (!me.ownerCt || me.floating) {
+            if (Ext.scopeCss) {
+                element.addCls(proto.rootCls);
+            }
+
+            element.addCls(proto.borderBoxCls);
+        }
+
+        if (position) {
+            nextSibling = container.childNodes[position];
+
+            if (nextSibling) {
+                Ext.fly(container).insertBefore(element, nextSibling);
+
+                return;
+            }
+        }
+
+        Ext.fly(container).appendChild(element);
+        me.finishRender();
+    },
+
+    setPosition: function(x, y) {
+        this.el.setLocalXY(x, y);
+    },
+
+    up: function() {
+        return Ext.Component.prototype.up.apply(this, arguments);
+    },
+
+    isAncestor: function() {
+        return Ext.Component.prototype.isAncestor.apply(this, arguments);
+    },
+
+    onFocusEnter: function() {
+        return Ext.Component.prototype.onFocusEnter.apply(this, arguments);
+    },
+
+    onFocusLeave: function() {
+        return Ext.Component.prototype.onFocusLeave.apply(this, arguments);
+    },
+
+    isLayoutChild: function(candidate) {
+        var ownerCt = this.ownerCt;
+
+        return ownerCt ? (ownerCt === candidate || ownerCt.isLayoutChild(candidate)) : false;
+    },
+
+    privates: {
+        doAddListener: function(name, fn, scope, options, order, caller, manager) {
+            if (name === 'painted' || name === 'resize') {
+                this.element.doAddListener(name, fn, scope || this, options, order);
+            }
+
+            this.callParent([name, fn, scope, options, order, caller, manager]);
+        },
+
+        doRemoveListener: function(name, fn, scope) {
+            if (name === 'painted' || name === 'resize') {
+                this.element.doRemoveListener(name, fn, scope);
+            }
+
+            this.callParent([name, fn, scope]);
+        }
+    }
+
+}, function(Cls) {
+    var prototype = Cls.prototype;
+
+    if (Ext.isIE9m) {
+        // Since IE8/9 don't not support Object.defineProperty correctly we can't add the reference
+        // nodes on demand, so we just fall back to adding all references up front.
+        prototype.addElementReferenceOnDemand = prototype.addElementReference;
+    }
+});

+ 122 - 0
assets/ext-7.4.0.42/classic/classic/overrides/app/Application.js

@@ -0,0 +1,122 @@
+/**
+ * @class Ext.app.Application
+ */
+
+Ext.define('Ext.overrides.app.Application', {
+    override: 'Ext.app.Application',
+    uses: [
+        'Ext.tip.QuickTipManager'
+    ],
+
+    // @cmd-auto-dependency {aliasPrefix: "view.", mvc: true, requires: ["Ext.plugin.Viewport"]}
+    /**
+     * @cfg {Boolean/String} [autoCreateViewport=false]
+     * @deprecated 5.1 Instead use {@link #mainView}
+     * @member Ext.app.Application
+     */
+    autoCreateViewport: false,
+
+    config: {
+        /**
+         * @cfg {Boolean} enableQuickTips
+         * @deprecated 6.2.0 Use {@link #quickTips}.
+         */
+        enableQuickTips: null
+    },
+
+    /**
+     * @cfg {Boolean} quickTips
+     * True to automatically set up Ext.tip.QuickTip support.
+     *
+     * @since 6.2.0
+     */
+    quickTips: true,
+
+    updateEnableQuickTips: function(enableQuickTips) {
+        this.setQuickTips(enableQuickTips);
+    },
+
+    applyMainView: function(mainView) {
+        var view, proto, config, protoPlugins, configPlugins;
+
+        if (typeof mainView === 'string') {
+            view = this.getView(mainView);
+            config = {};
+        }
+        else {
+            config = mainView;
+            view = Ext.ClassManager.getByConfig(mainView);
+        }
+
+        proto = view.prototype;
+
+        if (!proto.isViewport) {
+            // Need to copy over any plugins defined on the prototype and on the config.
+            protoPlugins = Ext.Array.from(proto.plugins);
+            configPlugins = Ext.Array.from(config.plugins);
+            config = Ext.apply({}, config);
+            config.plugins = ['viewport'].concat(protoPlugins, configPlugins);
+        }
+
+        return view.create(config);
+    },
+
+    getDependencies: function(cls, data, requires) {
+        var Controller = Ext.app.Controller,
+            proto = cls.prototype,
+            namespace = data.$namespace,
+            viewportClass = data.autoCreateViewport;
+
+        if (viewportClass) {
+            //<debug>
+            if (!namespace) {
+                Ext.raise("[Ext.app.Application] Can't resolve namespace for " +
+                    data.$className + ", did you forget to specify 'name' property?");
+            }
+            //</debug>
+
+            if (viewportClass === true) {
+                viewportClass = 'Viewport';
+            }
+            else {
+                requires.push('Ext.plugin.Viewport');
+            }
+
+            Controller.processDependencies(proto, requires, namespace, 'view', viewportClass);
+        }
+    },
+
+    onBeforeLaunch: function() {
+        var me = this,
+            autoCreateViewport = me.autoCreateViewport;
+
+        if (me.getQuickTips()) {
+            me.initQuickTips();
+        }
+
+        if (autoCreateViewport) {
+            me.initViewport();
+        }
+
+        this.callParent(arguments);
+    },
+
+    getViewportName: function() {
+        var name = null,
+            autoCreate = this.autoCreateViewport;
+
+        if (autoCreate) {
+            name = (autoCreate === true) ? 'Viewport' : autoCreate;
+        }
+
+        return name;
+    },
+
+    initViewport: function() {
+        this.setMainView(this.getViewportName());
+    },
+
+    initQuickTips: function() {
+        Ext.tip.QuickTipManager.init();
+    }
+});

+ 30 - 0
assets/ext-7.4.0.42/classic/classic/overrides/app/ViewController.js

@@ -0,0 +1,30 @@
+/**
+ * @class Ext.app.ViewController
+ */
+
+/**
+ * @method beforeRender
+ * @template
+ * Template method called by the owning component's 
+ * {@link Ext.Component#method-beforeRender beforeRender} method.
+ * @param {Ext.Component} component The owner component attached to the 
+ * ViewController
+ */
+
+/**
+ * @method afterRender
+ * @template
+ * Template method called by the owning component's 
+ * {@link Ext.Component#method-afterRender afterRender} method.
+ * @param {Ext.Component} component The owner component attached to the 
+ * ViewController
+ */
+
+/**
+ * @method boxReady
+ * @template
+ * Template method called by the owning component's 
+ * {@link Ext.Component#method-onBoxReady onBoxReady} method.
+ * @param {Ext.Component} component The owner component attached to the 
+ * ViewController
+ */

+ 10 - 0
assets/ext-7.4.0.42/classic/classic/overrides/app/domain/Component.js

@@ -0,0 +1,10 @@
+Ext.define('Ext.overrides.app.domain.Component', {
+    override: 'Ext.app.domain.Component',
+    requires: [
+        'Ext.Component'
+    ]
+}, function(ComponentDomain) {
+    // The core Component domain monitors events on the Ext.Widget class
+    // in Ext Components are not widgets so we need to monitor Ext.Component as well.
+    ComponentDomain.monitor(Ext.Component);
+});

+ 13 - 0
assets/ext-7.4.0.42/classic/classic/overrides/app/domain/View.js

@@ -0,0 +1,13 @@
+Ext.define('Ext.overrides.app.domain.View', {
+    override: 'Ext.app.domain.View',
+    requires: [
+        'Ext.Component'
+    ],
+
+    constructor: function(controller) {
+        this.callParent([controller]);
+        // The base class handles Ext.Widget, which encompasses
+        // component for modern, so we only need the override here.
+        this.monitoredClasses.push(Ext.Component);
+    }
+});

File diff suppressed because it is too large
+ 3841 - 0
assets/ext-7.4.0.42/classic/classic/overrides/dom/Element.js


+ 118 - 0
assets/ext-7.4.0.42/classic/classic/overrides/dom/Helper.js

@@ -0,0 +1,118 @@
+/**
+ * @class Ext.dom.Helper
+ */
+
+Ext.define('Ext.overrides.dom.Helper', (function() {
+    var tableRe = /^(?:table|thead|tbody|tr|td)$/i,
+        tableElRe = /td|tr|tbody|thead/i,
+        ts = '<table>',
+        te = '</table>',
+        tbs = ts + '<tbody>',
+        tbe = '</tbody>' + te,
+        trs = tbs + '<tr>',
+        tre = '</tr>' + tbe;
+
+    return {
+        override: 'Ext.dom.Helper',
+
+        ieInsertHtml: function(where, el, html) {
+            var frag = null;
+
+            // IE's incomplete table implementation: http://www.ericvasilik.com/2006/07/code-karma.html
+            if (Ext.isIE9m && tableRe.test(el.tagName)) {
+                frag = this.insertIntoTable(el.tagName.toLowerCase(), where, el, html);
+            }
+
+            return frag;
+        },
+
+        ieOverwrite: function(el, html) {
+            // IE Inserting HTML into a table/tbody/tr requires extra processing:
+            // http://www.ericvasilik.com/2006/07/code-karma.html
+            if (Ext.isIE9m && tableRe.test(el.tagName)) {
+                // Clearing table elements requires removal of all elements.
+                while (el.firstChild) {
+                    el.removeChild(el.firstChild);
+                }
+
+                if (html) {
+                    return this.insertHtml('afterbegin', el, html);
+                }
+            }
+        },
+
+        ieTable: function(depth, openingTags, htmlContent, closingTags) {
+            var i = -1,
+                el = this.detachedDiv,
+                ns, nx;
+
+            el.innerHTML = [openingTags, htmlContent, closingTags].join('');
+
+            while (++i < depth) {
+                el = el.firstChild;
+            }
+
+            // If the result is multiple siblings, then encapsulate them into one fragment.
+            ns = el.nextSibling;
+
+            if (ns) {
+                ns = el;
+                el = document.createDocumentFragment();
+
+                while (ns) {
+                    nx = ns.nextSibling;
+                    el.appendChild(ns);
+                    ns = nx;
+                }
+            }
+
+            return el;
+        },
+
+        /**
+         * @private
+         * @method insertIntoTable
+         * @member Ext.dom.Helper
+         * workaround for broken table implementation in IE9m
+         * http://www.ericvasilik.com/2006/07/code-karma.html
+         */
+        insertIntoTable: function(tag, where, destinationEl, html) {
+            var node,
+                before,
+                bb = where === 'beforebegin',
+                ab = where === 'afterbegin',
+                be = where === 'beforeend',
+                ae = where === 'afterend';
+
+            if (tag === 'td' && (ab || be) || !tableElRe.test(tag) && (bb || ae)) {
+                return null;
+            }
+
+            /* eslint-disable indent, multiline-ternary, no-multi-spaces */
+            before = bb ? destinationEl
+                   : ae ? destinationEl.nextSibling
+                   : ab ? destinationEl.firstChild
+                   :      null;
+            /* eslint-enable indent, multiline-ternary, no-multi-spaces */
+
+            if (bb || ae) {
+                destinationEl = destinationEl.parentNode;
+            }
+
+            if (tag === 'td' || (tag === 'tr' && (be || ab))) {
+                node = this.ieTable(4, trs, html, tre);
+            }
+            else if (((tag === 'tbody' || tag === 'thead') && (be || ab)) ||
+                    (tag === 'tr' && (bb || ae))) {
+                node = this.ieTable(3, tbs, html, tbe);
+            }
+            else {
+                node = this.ieTable(2, ts, html, te);
+            }
+
+            destinationEl.insertBefore(node, before);
+
+            return node;
+        }
+    };
+})());

+ 455 - 0
assets/ext-7.4.0.42/classic/classic/overrides/event/Event.js

@@ -0,0 +1,455 @@
+/**
+ * @class Ext.event.Event
+ */
+
+Ext.define('Ext.overrides.event.Event', {
+    override: 'Ext.event.Event',
+
+    /**
+     * @method injectEvent
+     * @member Ext.event.Event
+     * Injects a DOM event using the data in this object and (optionally) a new target.
+     * This is a low-level technique and not likely to be used by application code. The
+     * currently supported event types are:
+     * <p><b>HTMLEvents</b></p>
+     * <ul>
+     * <li>load</li>
+     * <li>unload</li>
+     * <li>select</li>
+     * <li>change</li>
+     * <li>submit</li>
+     * <li>reset</li>
+     * <li>resize</li>
+     * <li>scroll</li>
+     * </ul>
+     * <p><b>MouseEvents</b></p>
+     * <ul>
+     * <li>click</li>
+     * <li>dblclick</li>
+     * <li>mousedown</li>
+     * <li>mouseup</li>
+     * <li>mouseover</li>
+     * <li>mousemove</li>
+     * <li>mouseout</li>
+     * </ul>
+     * <p><b>UIEvents</b></p>
+     * <ul>
+     * <li>focusin</li>
+     * <li>focusout</li>
+     * <li>activate</li>
+     * <li>focus</li>
+     * <li>blur</li>
+     * </ul>
+     * @param {Ext.Element/HTMLElement} target (optional) If specified, the target for the event.
+     * This is likely to be used when relaying a DOM event. If not specified, {@link #getTarget}
+     * is used to determine the target.
+     */
+    injectEvent: (function() {
+        var API,
+            dispatchers = {}, // keyed by event type (e.g., 'mousedown')
+            crazyIEButtons;
+
+        // Good reference: http://developer.yahoo.com/yui/docs/UserAction.js.html
+
+        // IE9 has createEvent, but this code causes major problems with htmleditor (it
+        // blocks all mouse events and maybe more). TODO
+
+        if (!Ext.isIE9m && document.createEvent) { // if (DOM compliant)
+            API = {
+                createHtmlEvent: function(doc, type, bubbles, cancelable) {
+                    var event = doc.createEvent('HTMLEvents');
+
+                    event.initEvent(type, bubbles, cancelable);
+
+                    return event;
+                },
+
+                createMouseEvent: function(
+                    doc, type, bubbles, cancelable, detail, clientX, clientY, ctrlKey, altKey,
+                    shiftKey, metaKey, button, relatedTarget) {
+                    var event = doc.createEvent('MouseEvents'),
+                        view = doc.defaultView || window;
+
+                    if (event.initMouseEvent) {
+                        event.initMouseEvent(type, bubbles, cancelable, view, detail,
+                                             clientX, clientY, clientX, clientY, ctrlKey, altKey,
+                                             shiftKey, metaKey, button, relatedTarget);
+                    }
+                    else { // old Safari
+                        event = doc.createEvent('UIEvents');
+                        event.initEvent(type, bubbles, cancelable);
+                        event.view = view;
+                        event.detail = detail;
+                        event.screenX = clientX;
+                        event.screenY = clientY;
+                        event.clientX = clientX;
+                        event.clientY = clientY;
+                        event.ctrlKey = ctrlKey;
+                        event.altKey = altKey;
+                        event.metaKey = metaKey;
+                        event.shiftKey = shiftKey;
+                        event.button = button;
+                        event.relatedTarget = relatedTarget;
+                    }
+
+                    return event;
+                },
+
+                createUIEvent: function(doc, type, bubbles, cancelable, detail) {
+                    var event = doc.createEvent('UIEvents'),
+                        view = doc.defaultView || window;
+
+                    event.initUIEvent(type, bubbles, cancelable, view, detail);
+
+                    return event;
+                },
+
+                fireEvent: function(target, type, event) {
+                    target.dispatchEvent(event);
+                }
+            };
+        }
+        else if (document.createEventObject) { // else if (IE)
+            crazyIEButtons = { 0: 1, 1: 4, 2: 2 };
+
+            API = {
+                createHtmlEvent: function(doc, type, bubbles, cancelable) {
+                    var event = doc.createEventObject();
+
+                    event.bubbles = bubbles;
+                    event.cancelable = cancelable;
+
+                    return event;
+                },
+
+                createMouseEvent: function(
+                    doc, type, bubbles, cancelable, detail, clientX, clientY, ctrlKey, altKey,
+                    shiftKey, metaKey, button, relatedTarget) {
+                    var event = doc.createEventObject();
+
+                    event.bubbles = bubbles;
+                    event.cancelable = cancelable;
+                    event.detail = detail;
+                    event.screenX = clientX;
+                    event.screenY = clientY;
+                    event.clientX = clientX;
+                    event.clientY = clientY;
+                    event.ctrlKey = ctrlKey;
+                    event.altKey = altKey;
+                    event.shiftKey = shiftKey;
+                    event.metaKey = metaKey;
+                    event.button = crazyIEButtons[button] || button;
+                    event.relatedTarget = relatedTarget; // cannot assign to/fromElement
+
+                    return event;
+                },
+
+                createUIEvent: function(doc, type, bubbles, cancelable, detail) {
+                    var event = doc.createEventObject();
+
+                    event.bubbles = bubbles;
+                    event.cancelable = cancelable;
+
+                    return event;
+                },
+
+                fireEvent: function(target, type, event) {
+                    target.fireEvent('on' + type, event);
+                }
+            };
+        }
+
+        //----------------
+        // HTMLEvents
+
+        Ext.Object.each(
+            {
+                load: [false, false],
+                unload: [false, false],
+                select: [true, false],
+                change: [true, false],
+                submit: [true, true],
+                reset: [true, false],
+                resize: [true, false],
+                scroll: [true, false]
+            },
+            function(name, value) {
+                var bubbles = value[0],
+                    cancelable = value[1];
+
+                dispatchers[name] = function(targetEl, srcEvent) {
+                    var e = API.createHtmlEvent(name, bubbles, cancelable);
+
+                    API.fireEvent(targetEl, name, e);
+                };
+            }
+        );
+
+        //----------------
+        // MouseEvents
+
+        function createMouseEventDispatcher(type, detail) {
+            var cancelable = (type !== 'mousemove');
+
+            return function(targetEl, srcEvent) {
+                var xy = srcEvent.getXY(),
+                    e;
+
+                e = API.createMouseEvent(targetEl.ownerDocument, type, true, cancelable,
+                                         detail, xy[0], xy[1], srcEvent.ctrlKey, srcEvent.altKey,
+                                         srcEvent.shiftKey, srcEvent.metaKey, srcEvent.button,
+                                         srcEvent.relatedTarget);
+                API.fireEvent(targetEl, type, e);
+            };
+        }
+
+        Ext.each(
+            ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mousemove', 'mouseout'],
+            function(eventName) {
+                dispatchers[eventName] = createMouseEventDispatcher(eventName, 1);
+            }
+        );
+
+        //----------------
+        // UIEvents
+
+        Ext.Object.each(
+            {
+                focusin: [true, false],
+                focusout: [true, false],
+                activate: [true, true],
+                focus: [false, false],
+                blur: [false, false]
+            },
+            function(name, value) {
+                var bubbles = value[0],
+                    cancelable = value[1];
+
+                dispatchers[name] = function(targetEl, srcEvent) {
+                    var e = API.createUIEvent(targetEl.ownerDocument, name, bubbles, cancelable, 1);
+
+                    API.fireEvent(targetEl, name, e);
+                };
+            });
+
+        //---------
+        if (!API) {
+            // not even sure what ancient browsers fall into this category...
+
+            dispatchers = {}; // never mind all those we just built :P
+
+            API = {};
+        }
+
+        function cannotInject(target, srcEvent) {
+            //<debug>
+            // TODO log something
+            //</debug>
+        }
+
+        return function(target) {
+            var me = this,
+                dispatcher = dispatchers[me.type] || cannotInject,
+                t = target ? (target.dom || target) : me.getTarget();
+
+            dispatcher(t, me);
+        };
+    }()), // call to produce method
+
+    preventDefault: function(browserOnly) {
+        var me = this,
+            event = me.browserEvent,
+            parentEvent = me.parentEvent,
+            unselectable, target, fn;
+
+        // This check is for IE8/9. The event object may have been
+        // invalidated, so we can't delve into the details of it. If so,
+        // just fall out gracefully and don't attempt to do anything.
+        // eslint-disable-next-line valid-typeof
+        if (typeof event.type !== 'unknown') {
+            // In some cases we want to prevent default on the browser event
+            // but keep propagating it through our event system. For example,
+            // in Checkbox selection where the cells with checkboxes should
+            // prevent focusing on mousedown but still fire the click event.
+            if (!browserOnly) {
+                me.defaultPrevented = true;
+            }
+
+            // if the event was created by prototype-chaining a new object to an existing event
+            // instance, we need to make sure the parent event is defaultPrevented as well.
+            if (parentEvent) {
+                parentEvent.defaultPrevented = true;
+            }
+
+            if (event.preventDefault) {
+                event.preventDefault();
+            }
+            else {
+                // The purpose of the code below is for preventDefault to stop focus from
+                // occurring like it does in other modern browsers. This only happens in
+                // IE8/9 when using attachEvent. The use of unselectable seems the most reliable
+                // way to prevent this from happening. We need to use a timeout to restore the
+                // unselectable state because if we don't setting it has no effect. It's important
+                // to set the atrribute to 'on' as opposed to just setting the property on the
+                // DOM element. See the link below for a discussion on the issue:
+                // http://bugs.jquery.com/ticket/10345
+                if (event.type === 'mousedown') {
+                    target = event.target;
+                    unselectable = target.getAttribute('unselectable');
+
+                    if (unselectable !== 'on') {
+                        target.setAttribute('unselectable', 'on');
+
+                        fn = function() {
+                            target.setAttribute('unselectable', unselectable);
+                        };
+
+                        // This function is hard to track, with a potential to be called
+                        // for any HtmlElement in the document. It may be a Fly, it may
+                        // not belong to any Component, and it may even be created by
+                        // 3rd party code that we have no control over and cannot intercept
+                        // the element being destroyed.
+                        // On the other hand, the function is pretty simple, cannot lead
+                        // to memory leaks and is only fired once. So, no harm no foul.
+                        //<debug>
+                        fn.$skipTimerCheck = true;
+                        //</debug>
+
+                        Ext.defer(fn, 1);
+                    }
+                }
+
+                // IE9 and earlier do not support preventDefault
+                event.returnValue = false;
+
+                // Some keys events require setting the keyCode to -1 to be prevented
+                // all ctrl + X and F1 -> F12
+                if (event.ctrlKey || event.keyCode > 111 && event.keyCode < 124) {
+                    event.keyCode = -1;
+                }
+            }
+        }
+
+        return me;
+    },
+
+    deprecated: {
+        '5.0': {
+            methods: {
+                /**
+                 * @method clone
+                 * @member Ext.event.Event
+                 * Clones this event.
+                 * @return {Ext.event.Event} The cloned copy
+                 * @deprecated 5.0.0 This method is deprecated.
+                 */
+                clone: function() {
+                    return new this.self(this.browserEvent, this);
+                }
+            }
+        }
+    }
+}, function() {
+    var Event = this,
+        btnMap;
+
+    //<feature legacyBrowser>
+    if (Ext.isIE9m) {
+        btnMap = {
+            0: 0,
+            1: 0,
+            4: 1,
+            2: 2
+        };
+
+        Event.override({
+            statics: {
+                /**
+                 * @member Ext.event.Event
+                 * When events are attached using IE's attachEvent API instead of
+                 * addEventListener accessing any members of an event object asynchronously
+                 * results in "Member not found" error.  To work around this we fabricate
+                 * our own event object by copying all of its members to a new object.
+                 * @param {Event} browserEvent The native browser event object
+                 * @private
+                 * @static
+                 */
+                enableIEAsync: function(browserEvent) {
+                    var name,
+                        fakeEvent = {};
+
+                    for (name in browserEvent) {
+                        fakeEvent[name] = browserEvent[name];
+                    }
+
+                    return fakeEvent;
+                }
+            },
+
+            constructor: function(event, info, touchesMap, identifiers) {
+                var me = this;
+
+                me.callParent([event, info, touchesMap, identifiers]);
+                me.button = btnMap[event.button];
+
+                if (event.type === 'contextmenu') {
+                    // IE8/9 reports click as 0, so we can at least attempt to infer here
+                    me.button = 2;
+                }
+
+                // IE8 can throw an error when trying to access properties on a browserEvent
+                // object when the event has been buffered or delayed.  Cache them here
+                // so we can access them later.
+                me.toElement = event.toElement;
+                me.fromElement = event.fromElement;
+            },
+
+            mouseLeaveRe: /(mouseout|mouseleave)/,
+            mouseEnterRe: /(mouseover|mouseenter)/,
+
+            /**
+             * @method enableIEAsync
+             * @member Ext.event.Event
+             * @inheritdoc Ext.event.Event#static-method-enableIEAsync
+             * @private
+             */
+            enableIEAsync: function(browserEvent) {
+                this.browserEvent = this.self.enableIEAsync(browserEvent);
+            },
+
+            getRelatedTarget: function(selector, maxDepth, returnEl) {
+                var me = this,
+                    type, target;
+
+                if (!me.relatedTarget) {
+                    type = me.type;
+
+                    if (me.mouseLeaveRe.test(type)) {
+                        target = me.toElement;
+                    }
+                    else if (me.mouseEnterRe.test(type)) {
+                        target = me.fromElement;
+                    }
+
+                    if (target) {
+                        me.relatedTarget = me.self.resolveTextNode(target);
+                    }
+                }
+
+                return me.callParent([selector, maxDepth, returnEl]);
+            }
+        });
+
+        // We place these listeners to capture Tab and Shift-Tab key strokes
+        // and pass this information in the focus/blur event if it happens
+        // between keydown/keyup pair.
+        document.attachEvent('onkeydown', Ext.event.Event.globalTabKeyDown);
+        document.attachEvent('onkeyup', Ext.event.Event.globalTabKeyUp);
+
+        window.attachEvent('onunload', function() {
+            document.detachEvent('onkeydown', Ext.event.Event.globalTabKeyDown);
+            document.detachEvent('onkeyup', Ext.event.Event.globalTabKeyUp);
+        });
+    }
+    //</feature>
+});

+ 155 - 0
assets/ext-7.4.0.42/classic/classic/overrides/event/publisher/Dom.js

@@ -0,0 +1,155 @@
+//<feature legacyBrowser>
+Ext.define('Ext.overrides.event.publisher.Dom', {
+    override: 'Ext.event.publisher.Dom'
+
+}, function(DomPublisher) {
+    var focusEvents = {
+        focus: true,
+        focusin: true,
+        focusout: true,
+        blur: true
+    };
+
+    if (Ext.isIE10m) {
+        DomPublisher.override({
+            isEventBlocked: function(e) {
+                if (!focusEvents[e.type]) {
+                    return this.callParent([e]);
+                }
+
+                // eslint-disable-next-line vars-on-top
+                var body = document.body,
+                    ev = e.browserEvent,
+                    el = Ext.synchronouslyFocusing;
+
+                /* eslint-disable max-len, brace-style */
+                // This horrid hack is necessary to work around the issue with input elements
+                // in IE10m that can fail to focus under certain conditions. See comment in
+                // Ext.dom.Element override.
+                if (el &&
+                    ((ev.type === 'focusout' && (ev.srcElement === el || ev.srcElement === window) && ev.toElement === body) ||
+                     (ev.type === 'focusin' && (ev.srcElement === body || ev.srcElement === window) && ev.fromElement === el &&
+                      ev.toElement === null)))
+                {
+                    return true;
+                }
+                /* eslint-enable max-len, brace-style */
+
+                return false;
+            }
+        });
+    }
+
+    if (Ext.isIE9m) {
+        // eslint-disable-next-line vars-on-top
+        var docElement = document.documentElement,
+            docBody = document.body,
+            prototype = DomPublisher.prototype,
+            onDirectEvent, onDirectCaptureEvent; // eslint-disable-line no-unused-vars
+
+        prototype.target = document;
+        prototype.directBoundListeners = {};
+
+        // This method gets bound to the element scope in addDirectListener so that
+        // the currentTarget can be captured using "this".
+        onDirectEvent = function(e, publisher, capture) {
+            e.target = e.srcElement || window;
+            e.currentTarget = this;
+
+            if (capture) {
+                // Although directly attached capture listeners are not supported in IE9m
+                // we still need to call the handler so at least the event fires.
+                publisher.onDirectCaptureEvent(e);
+            }
+            else {
+                publisher.onDirectEvent(e);
+            }
+        };
+
+        onDirectCaptureEvent = function(e, publisher) {
+            e.target = e.srcElement || window;
+            e.currentTarget = this; // this, not DomPublisher
+            publisher.onDirectCaptureEvent(e);
+        };
+
+        DomPublisher.override({
+            addDelegatedListener: function(eventName) {
+                this.delegatedListeners[eventName] = 1;
+                // Use attachEvent for IE9 and below.  Even though IE9 strict supports
+                // addEventListener, it has issues with using synthetic events.
+                this.target.attachEvent('on' + eventName, this.onDelegatedEvent);
+            },
+
+            removeDelegatedListener: function(eventName) {
+                delete this.delegatedListeners[eventName];
+                this.target.detachEvent('on' + eventName, this.onDelegatedEvent);
+            },
+
+            addDirectListener: function(eventName, element, capture) {
+                var me = this,
+                    dom = element.dom,
+                    // binding the listener to the element allows us to capture the
+                    // "currentTarget" (see onDirectEvent)
+                    boundFn = Ext.Function.bind(onDirectEvent, dom, [me, capture], true),
+                    directBoundListeners = me.directBoundListeners,
+                    handlers = directBoundListeners[eventName] ||
+                               (directBoundListeners[eventName] = {});
+
+                handlers[dom.id] = boundFn;
+
+                // may be called with an SVG element here, which
+                // does not have the attachEvent method on IE 9 strict
+                if (dom.attachEvent) {
+                    dom.attachEvent('on' + eventName, boundFn);
+                }
+                else {
+                    me.callParent([eventName, element, capture]);
+                }
+            },
+
+            removeDirectListener: function(eventName, element, capture) {
+                var dom = element.dom;
+
+                if (dom.detachEvent) {
+                    dom.detachEvent(
+                        'on' + eventName,
+                        this.directBoundListeners[eventName][dom.id]
+                    );
+                }
+                else {
+                    this.callParent([eventName, element, capture]);
+                }
+            },
+
+            doDelegatedEvent: function(e) {
+                e.target = e.srcElement || window;
+
+                if (e.type === 'focusin') {
+                    // IE8 sometimes happen to focus <html> element instead of the body
+                    // eslint-disable-next-line max-len
+                    e.relatedTarget = e.fromElement === docBody || e.fromElement === docElement ? null : e.fromElement;
+                }
+                else if (e.type === 'focusout') {
+                    // eslint-disable-next-line max-len
+                    e.relatedTarget = e.toElement === docBody || e.toElement === docElement ? null : e.toElement;
+                }
+
+                return this.callParent([e]);
+            }
+        });
+
+        // can't capture any events without addEventListener.  Have to have direct
+        // listeners for every event that does not bubble.
+        Ext.apply(prototype.directEvents, prototype.captureEvents);
+
+        // These do not bubble in IE9m so have to attach direct listeners as well.
+        Ext.apply(prototype.directEvents, {
+            change: 1,
+            input: 1,
+            paste: 1
+        });
+
+        prototype.captureEvents = {};
+    }
+});
+//</feature>

+ 27 - 0
assets/ext-7.4.0.42/classic/classic/overrides/event/publisher/Gesture.js

@@ -0,0 +1,27 @@
+//<feature legacyBrowser>
+Ext.define('Ext.overrides.event.publisher.Gesture', {
+    override: 'Ext.event.publisher.Gesture'
+}, function() {
+    if (Ext.isIE9m) {
+        this.override({
+            updateTouches: function(e, isEnd) {
+                var browserEvent = e.browserEvent,
+                    xy = e.getXY();
+
+                // I don't always set pageX and pageY on the event object, but when I do
+                // it's because the Gesture publisher expects an event object that has them.
+                browserEvent.pageX = xy[0];
+                browserEvent.pageY = xy[1];
+                this.callParent([e, isEnd]);
+            },
+
+            doDelegatedEvent: function(e) {
+                // Workaround IE's "Member not found" errors when accessing an event
+                // object asynchronously.  Needed for all gesture handlers because
+                // they use requestAnimationFrame (see enableIEAsync for more details)
+                this.callParent([Ext.event.Event.enableIEAsync(e)]);
+            }
+        });
+    }
+});
+//</feature>

+ 34 - 0
assets/ext-7.4.0.42/classic/classic/overrides/form/field/Checkbox.js

@@ -0,0 +1,34 @@
+/**
+ * @class Ext.form.field.Checkbox
+ */
+Ext.define(null, {
+    override: 'Ext.form.field.Checkbox',
+
+    compatibility: Ext.isIE8,
+
+    // IE8 does not support change event but it has propertychange which is even better
+    changeEventName: 'propertychange',
+
+    onChangeEvent: function(e) {
+        // IE8 propertychange fires for *any* property change but we're only interested in checked
+        // We also don't want to react to propertychange fired as the result of assigning
+        // checked property in setRawValue().
+        if (this.duringSetRawValue || e.browserEvent.propertyName !== 'checked') {
+            return;
+        }
+
+        this.callParent([e]);
+    },
+
+    updateCheckedCls: function(checked) {
+        var me = this,
+            displayEl = me.displayEl;
+
+        me.callParent([checked]);
+
+        // IE8 has a bug with font icons and pseudo-elements
+        if (displayEl && checked !== me.lastValue) {
+            displayEl.repaint();
+        }
+    }
+});

+ 41 - 0
assets/ext-7.4.0.42/classic/classic/overrides/form/field/Radio.js

@@ -0,0 +1,41 @@
+/**
+ * @class Ext.form.field.Radio
+ */
+Ext.define(null, {
+    override: 'Ext.form.field.Radio',
+
+    compatibility: Ext.isIE8,
+
+    getSubTplData: function(fieldData) {
+        var data = this.callParent([fieldData]);
+
+        // Rendering a radio button with checked attribute
+        // will have a curious side effect in IE8: the DOM
+        // node will have checked property set to `true` but
+        // radio group (radios with the same name attribute)
+        // will behave as if no radio is checked in the group;
+        // tabbing into the group will select first or last
+        // button instead of the checked one.
+        // So instead of rendering the attribute we will set
+        // checked value in the DOM after rendering. Apparently
+        // such a tiny nudge is enough for the browser to behave.
+        delete data.checked;
+
+        return data;
+    },
+
+    afterRender: function() {
+        this.callParent();
+
+        if (this.checked) {
+            this.inputEl.dom.checked = true;
+        }
+    },
+
+    onChange: function(newValue, oldValue) {
+        // We don't need to bother updating other radio buttons in IE8
+        // since it will fire propertychange event on any change, not only false -> true.
+        // This is unlike standard compliant browsers, see main class.
+        this.callSuper([newValue, oldValue]);
+    }
+});

+ 7 - 0
assets/ext-7.4.0.42/classic/classic/overrides/init.js

@@ -0,0 +1,7 @@
+// @override Ext
+
+// This file is order extremely early (typically right after Ext.js) due to the
+// above Cmd directive. This ensures that the "modern" and "classic" platform tags
+// are properly set up as soon as possible.
+
+Ext.platformTags.modern = !(Ext.platformTags.classic = Ext.isClassic = true);

+ 13 - 0
assets/ext-7.4.0.42/classic/classic/overrides/list/AbstractTreeItem.js

@@ -0,0 +1,13 @@
+/**
+ * @class Ext.list.AbstractTreeItem
+ */
+
+Ext.define('Ext.overrides.list.AbstractTreeItem', {
+    override: 'Ext.list.AbstractTreeItem',
+
+    // This config is used by TreeIten, however to support the generic API (RootItem),
+    // we need this up here.
+    config: {
+        floated: null
+    }
+});

+ 35 - 0
assets/ext-7.4.0.42/classic/classic/overrides/list/Tree.js

@@ -0,0 +1,35 @@
+/**
+ * @class Ext.list.Tree
+ */
+Ext.define('Ext.overrides.list.Tree', {
+    override: 'Ext.list.Tree',
+
+    canMeasure: true,
+
+    constructor: function(config) {
+        this.callParent([config]);
+
+        // Track size so that we can track the expanded size
+        // for use by the floated state of items when in micro mode.
+        // Browsers where this event is not supported, fall back to a width
+        // of 200px for floated tree items.
+        if (!Ext.isIE8) {
+            this.element.on('resize', 'onElResize', this);
+        }
+    },
+
+    beforeLayout: function() {
+        this.syncIconSize();
+    },
+
+    onElResize: function(el, details) {
+        if (!this.getMicro() && this.canMeasure) {
+            this.expandedWidth = details.width;
+        }
+    },
+
+    privates: {
+        defaultListWidth: 200,
+        expandedWidth: null
+    }
+});

+ 110 - 0
assets/ext-7.4.0.42/classic/classic/overrides/list/TreeItem.js

@@ -0,0 +1,110 @@
+/**
+ * @class Ext.list.TreeItem
+ */
+Ext.define('Ext.overrides.list.TreeItem', {
+    override: 'Ext.list.TreeItem',
+
+    // Implement a setter.
+    // There *is* no "floated" config in Classic.
+    // We're still an inner item, we just get put inside a Container.
+    setFloated: function(floated) {
+        var me = this,
+            el = me.element,
+            placeholder = me.placeholder,
+            node, wasExpanded;
+
+        if (me.treeItemFloated !== floated) {
+            if (floated) {
+                placeholder = el.clone(false, true); // shallow, asDom
+                placeholder.id += '-placeholder'; // avoid duplicate id
+                me.placeholder = Ext.get(placeholder);
+
+                me.wasExpanded = me.getExpanded();
+                me.setExpanded(true);
+
+                el.addCls(me.floatedCls);
+                el.dom.parentNode.insertBefore(placeholder, el.dom);
+
+                me.floater = me.createFloater(); // toolkit-specific
+            }
+            else if (placeholder) {
+                wasExpanded = me.wasExpanded;
+                node = me.getNode();
+                me.setExpanded(wasExpanded);
+
+                if (!wasExpanded && node.isExpanded()) {
+                    // If we have been floating and expanded a child, we may have been
+                    // expanded as part of the ancestors. Attempt to restore state.
+                    me.preventAnimation = true;
+                    node.collapse();
+                    me.preventAnimation = false;
+                }
+
+                me.floater.remove(me, false); // don't destroy
+                el.removeCls(me.floatedCls);
+                placeholder.dom.parentNode.insertBefore(el.dom, placeholder.dom);
+
+                placeholder.destroy();
+                me.floater.destroy();
+
+                me.placeholder = me.floater = null;
+            }
+
+            // Use an internal property name. We are NOT really floated
+            me.treeItemFloated = floated;
+        }
+    },
+
+    getFloated: function() {
+        return this.treeItemFloated;
+    },
+
+    runAnimation: function(animation) {
+        return this.itemContainer.addAnimation(animation);
+    },
+
+    stopAnimation: function(animation) {
+        animation.jumpToEnd();
+    },
+
+    privates: {
+        createFloater: function() {
+            var me = this,
+                owner = me.getOwner(),
+                ownerTree = me.up('treelist'),
+                floater,
+                toolElement = me.getToolElement(),
+                expandedWidth = ownerTree.expandedWidth,
+                defaultListWidth = ownerTree.defaultListWidth;
+
+            if (expandedWidth === null) {
+                expandedWidth = defaultListWidth;
+            }
+
+            me.floater = floater = new Ext.container.Container({
+                cls: ownerTree.self.prototype.element.cls + ' ' +
+                     ownerTree.uiPrefix + ownerTree.getUi() + ' ' +
+                     Ext.baseCSSPrefix + 'treelist-floater',
+                floating: true,
+                // We do not get element resize events on IE8
+                // so fall back to 6.0.1 sizing to 200 wide.
+                width: Ext.isIE8 ? defaultListWidth : (expandedWidth - toolElement.getWidth()),
+                shadow: false,
+                hidden: true,
+                renderTo: Ext.getBody(),
+                listeners: {
+                    element: 'el',
+                    click: function(e) {
+                        return owner.onClick(e);
+                    }
+                }
+            });
+
+            floater.add(me);
+            floater.show();
+            floater.el.alignTo(toolElement, 'tr?');
+
+            return floater;
+        }
+    }
+});

+ 244 - 0
assets/ext-7.4.0.42/classic/classic/overrides/mixin/Focusable.js

@@ -0,0 +1,244 @@
+/**
+ * @class Ext.mixin.Focusable
+ */
+Ext.define('Ext.overrides.mixin.Focusable', {
+    override: 'Ext.Component',
+
+    /**
+     * @cfg {String} [focusCls='focus'] CSS class suffix that will be used to
+     * compose the CSS class name that will be added to Component's {@link #focusClsEl},
+     * and removed when Component blurs.
+     *
+     * **Note** that this is not a full CSS class name; this suffix will be combined
+     * with component's UI class via {@link #addClsWithUI} and {@link #removeClsWithUI} methods.
+     */
+    focusCls: 'focus',
+
+    /**
+     * Try to focus this component.
+     *
+     * If this component is disabled, a close relation will be targeted for focus instead
+     * to keep focus localized for keyboard users.
+     * @param {Mixed} [selectText] If applicable, `true` to also select all the text in this
+     * component, or an array consisting of start and end (defaults to start) position of selection.
+     * @param {Boolean/Number} [delay] Delay the focus this number of milliseconds (true for
+     * 10 milliseconds).
+     * @param {Function} [callback] Only needed if the `delay` parameter is used. A function to call
+     * upon focus.
+     * @param {Function} [scope] Only needed if the `delay` parameter is used. The scope (`this`
+     * reference) in which to execute the callback.
+     * @return {Ext.Component} The focused Component. Usually `this` Component. Some Containers may
+     * delegate focus to a descendant Component ({@link Ext.window.Window Window}s can do this
+     * through their {@link Ext.window.Window#defaultFocus defaultFocus} config option. If this
+     * component is disabled, a closely related component will be focused and that will be returned.
+     */
+    focus: function(selectText, delay, callback, scope) {
+        var me = this,
+            containerScrollTop;
+
+        if ((!me.focusable && !me.isContainer) || me.destroyed || me.destroying) {
+            return me;
+        }
+
+        // If delay is wanted, queue a call to this function.
+        if (delay) {
+            me.getFocusTask().delay(
+                Ext.isNumber(delay) ? delay : 10, me.focus, me,
+                [selectText, false, callback, scope]
+            );
+
+            return me;
+        }
+
+        // An immediate focus call must cancel any outstanding delayed focus calls.
+        me.cancelFocus();
+
+        if (me.floating && me.container && me.container.dom) {
+            containerScrollTop = me.container.dom.scrollTop;
+        }
+
+        // Core Focusable method will return true if focusing was attempted
+        if (me.mixins.focusable.focus.apply(me, arguments) !== false) {
+            if (callback) {
+                Ext.callback(callback, scope);
+            }
+
+            // Focusing a floating Component brings it to the front of its stack.
+            // this is performed by its zIndexManager. Pass preventFocus true to avoid recursion.
+            if (me.floating && containerScrollTop !== undefined) {
+                me.container.dom.scrollTop = containerScrollTop;
+            }
+        }
+
+        return me;
+    },
+
+    /**
+     * Cancel any deferred focus on this component
+     * @protected
+     */
+    cancelFocus: function() {
+        var me = this,
+            task = me.getFocusTask();
+
+        if (task) {
+            task.cancel();
+        }
+    },
+
+    /**
+     * @method
+     * Template method to do any pre-blur processing.
+     * @protected
+     * @param {Ext.event.Event} e The event object
+     */
+    beforeBlur: Ext.emptyFn,
+
+    /**
+     * @method
+     * Template method to do any post-blur processing.
+     * @protected
+     * @param {Ext.event.Event} e The event object
+     */
+    postBlur: Ext.emptyFn,
+
+    /**
+     * @method
+     * Template method to do any pre-focus processing.
+     * @protected
+     * @param {Ext.event.Event} e The event object
+     */
+    beforeFocus: Ext.emptyFn,
+
+    /**
+     * @method
+     * Template method to do any post-focus processing.
+     * @protected
+     * @param {Ext.event.Event} e The event object
+     */
+    postFocus: Ext.emptyFn,
+
+    onFocusEnter: function(e) {
+        var me = this;
+
+        if (me.destroying || me.destroyed) {
+            return;
+        }
+
+        // Focusing must being a floating component to the front.
+        // Only bring to front if this component is not the manager's
+        // topmost component (may be a result of focusOnToFront).
+        if (me.floating && me !== me.zIndexManager.getActive()) {
+            me.toFront(true);
+        }
+
+        me.callParent([e]);
+    },
+
+    destroyFocusable: function() {
+        var me = this;
+
+        // Calling cancelFocus() will assign focusTask property,
+        // which we don't want during destruction
+        if (me.focusTask) {
+            me.focusTask.stop(me.focus, me);
+        }
+
+        me.callParent();
+    },
+
+    privates: {
+        addFocusCls: function(e) {
+            var me = this,
+                focusCls = me.focusCls,
+                el;
+
+            if (focusCls) {
+                el = me.getFocusClsEl(e);
+
+                if (el) {
+                    el.addCls(me.addClsWithUI(focusCls, true));
+                }
+            }
+        },
+
+        removeFocusCls: function(e) {
+            var me = this,
+                focusCls = me.focusCls,
+                el;
+
+            if (focusCls) {
+                el = me.getFocusClsEl(e);
+
+                if (el) {
+                    el.removeCls(me.removeClsWithUI(focusCls, true));
+                }
+            }
+        },
+
+        /**
+         * @private
+         */
+        getFocusTask: function() {
+            if (!this.focusTask) {
+                this.focusTask = Ext.focusTask;
+            }
+
+            return this.focusTask;
+        },
+
+        updateMaskState: function(state, mask) {
+            var me = this,
+                ariaEl = me.ariaEl.dom,
+                skipMask = me.getInherited().disabled && me.getInherited().disableMask,
+                value;
+
+            if (state) {
+                me.disableTabbing();
+
+                if (!skipMask) {
+                    me.setMasked(true);
+                }
+
+                if (ariaEl) {
+                    ariaEl.setAttribute('aria-busy', 'true');
+
+                    // It is possible that ariaEl already has aria-describedby attribute;
+                    // in that case we need to save it to restore later.
+                    value = ariaEl.getAttribute('aria-describedby');
+
+                    if (value) {
+                        me._savedAriaDescribedBy = value;
+                    }
+
+                    ariaEl.setAttribute('aria-describedby', mask.ariaEl.id);
+                }
+            }
+            else {
+                me.enableTabbing();
+
+                if (!skipMask) {
+                    me.setMasked(false);
+                }
+
+                if (ariaEl) {
+                    ariaEl.removeAttribute('aria-busy');
+
+                    value = ariaEl.getAttribute('aria-describedby');
+                    ariaEl.removeAttribute('aria-describedby');
+
+                    if (value === mask.ariaEl.id && me._savedAriaDescribedBy) {
+                        ariaEl.setAttribute('aria-describedby', me._savedAriaDescribedBy);
+                        delete me._savedAriaDescribedBy;
+                    }
+                }
+            }
+        }
+    }
+}, function() {
+    // One global DelayedTask to assign focus
+    // So that the last focus call wins.
+    if (!Ext.focusTask) {
+        Ext.focusTask = new Ext.util.DelayedTask();
+    }
+});

+ 67 - 0
assets/ext-7.4.0.42/classic/classic/overrides/plugin/Abstract.js

@@ -0,0 +1,67 @@
+/**
+ * @class Ext.plugin.Abstract
+ */
+Ext.define('Ext.overrides.plugin.Abstract', {
+    override: 'Ext.plugin.Abstract',
+
+    $configStrict: false,
+    $configPrefixed: false,
+
+    disabled: false,
+
+    /**
+     * @cfg {String|Array} stateEvents
+     * The configured list of stateEvents used to (optionally) participate in Owner Component's
+     * state management.
+     * @member Ext.plugin.Abstract
+     */
+
+    /**
+     * @method
+     * The getState method is invoked by the client Component's State mixin when one or more of the
+     * specified {@link #stateEvents} are raised.
+     *
+     * The supplied implementation is empty. If plugin Subclasses are to (optionally) participate
+     * in the client Component's state management, implementers should provide a suitable method
+     * which returns a state object.
+     * @return {Object} state
+     * @member Ext.plugin.Abstract
+     */
+    getState: null,
+
+    /**
+     * @method
+     * The applyState method is invoked by the client Component's State mixin after initComponent
+     * method has been run for the client.
+     *
+     * The supplied implementation is empty. If plugin Subclasses are to (optionally) participate
+     * in the client Component's state management, implementers should provide a suitable method
+     * to utilize it.
+     * @param {Object} state The current plugin state object to be applied.
+     * @param {Object} allState The current aggregate state of the Component and all plugins.
+     * @member Ext.plugin.Abstract
+     */
+    applyState: null,
+
+    /**
+     * The base implementation just sets the plugin's `disabled` flag to `false`
+     *
+     * Plugin subclasses which need more complex processing may implement an overriding
+     * implementation.
+     * @member Ext.plugin.Abstract
+     */
+    enable: function() {
+        this.disabled = false;
+    },
+
+    /**
+     * The base implementation just sets the plugin's `disabled` flag to `true`
+     *
+     * Plugin subclasses which need more complex processing may implement an overriding
+     * implementation.
+     * @member Ext.plugin.Abstract
+     */
+    disable: function() {
+        this.disabled = true;
+    }
+});

+ 136 - 0
assets/ext-7.4.0.42/classic/classic/overrides/scroll/Scroller.js

@@ -0,0 +1,136 @@
+/**
+ * @class Ext.scroll.Scroller
+ */
+Ext.define(null, {
+    override: 'Ext.scroll.Scroller',
+
+    compatibility: Ext.isIE8,
+
+    privates: {
+        // Important note: this code had to be copied as a whole
+        // because the scrollLeft assignment trickery only works
+        // reliably when it is done within the same function context.
+        doScrollTo: function(x, y, animate) {
+            var me = this,
+                element = me.getScrollElement(),
+                maxPosition, dom, to, xInf, yInf,
+                ret, deferred, callback;
+
+            if (element && !element.destroyed) {
+                dom = element.dom;
+
+                xInf = (x === Infinity);
+                yInf = (y === Infinity);
+
+                if (xInf || yInf) {
+                    maxPosition = me.getMaxPosition();
+
+                    if (xInf) {
+                        x = maxPosition.x;
+                    }
+
+                    if (yInf) {
+                        y = maxPosition.y;
+                    }
+                }
+
+                if (x !== null) {
+                    x = me.convertX(x);
+                }
+
+                if (animate) {
+                    to = {};
+
+                    if (y != null) {
+                        to.scrollTop = y;
+                    }
+
+                    if (x != null) {
+                        to.scrollLeft = x;
+                    }
+
+                    animate = Ext.mergeIf({
+                        to: {
+                            scrollTop: y,
+                            scrollLeft: x
+                        }
+                    }, animate);
+
+                    deferred = new Ext.Deferred();
+                    callback = animate.callback;
+
+                    animate.callback = function() {
+                        if (callback) {
+                            callback.call(animate.scope || Ext.global, arguments);
+                        }
+
+                        // The callback will be called if the element is destroyed
+                        if (me.destroyed) {
+                            deferred.reject();
+                        }
+                        else {
+                            deferred.resolve();
+                        }
+                    };
+
+                    element.animate(animate);
+                    ret = deferred.promise;
+                }
+                else {
+                    // When we need to assign both scrollTop and scrollLeft,
+                    // IE8 might fire scroll event on the first assignment
+                    // but not on the second; that behavior is unlike the other
+                    // browsers which will wait for the second assignment
+                    // to happen before firing the event. This leads to our
+                    // scrollstart event firing prematurely, when the scrolling
+                    // has not actually finished yet.
+                    // To work around that, we ignore the first event and then
+                    // force another one by assigning scrollLeft the second time.
+                    if ((x != null && x !== 0) && y != null) {
+                        me.deferDomScroll = true;
+                    }
+
+                    if (y != null) {
+                        dom.scrollTop = y;
+                    }
+
+                    if (x != null) {
+                        dom.scrollLeft = x;
+                    }
+
+                    if (me.deferDomScroll) {
+                        me.deferDomScroll = false;
+
+                        // Reading the DOM makes sure the second assignment will fire the event.
+                        // eslint-disable-next-line no-unused-expressions
+                        +dom.scrollLeft;
+                        dom.scrollLeft = x;
+                        // eslint-disable-next-line no-unused-expressions
+                        +dom.scrollTop;
+                        dom.scrollTop = y;
+                    }
+
+                    ret = Ext.Deferred.getCachedResolved();
+                }
+
+                // Our position object will need refreshing before returning.
+                me.positionDirty = true;
+            }
+            else {
+                ret = Ext.Deferred.getCachedRejected();
+            }
+
+            return ret;
+        },
+
+        onDomScroll: function() {
+            var me = this;
+
+            if (me.deferDomScroll) {
+                return;
+            }
+
+            me.callParent();
+        }
+    }
+});

+ 73 - 0
assets/ext-7.4.0.42/classic/classic/overrides/sparkline/Base.js

@@ -0,0 +1,73 @@
+/**
+ * @class Ext.sparkline.Base
+ */
+Ext.define('Ext.override.sparkline.Base', {
+    override: 'Ext.sparkline.Base',
+
+    statics: {
+        constructTip: function() {
+            // eslint-disable-next-line dot-notation
+            return new Ext.tip['ToolTip']({
+                id: 'sparklines-tooltip',
+                showDelay: 0,
+                dismissDelay: 0,
+                hideDelay: 400
+            });
+        }
+    },
+
+    onMouseMove: function(e) {
+        this.getSharedTooltip().triggerEvent = e;
+        this.callParent([e]);
+    },
+
+    onMouseLeave: function(e) {
+        this.callParent([e]);
+        this.getSharedTooltip().target = null;
+    },
+
+    privates: {
+        hideTip: function() {
+            var tip = this.getSharedTooltip();
+
+            tip.target = null;
+            tip.hide();
+        },
+
+        showTip: function() {
+            var tip = this.getSharedTooltip();
+
+            tip.target = this.el;
+            tip.onTargetOver(tip.triggerEvent);
+        }
+    }
+}, function(Cls) {
+    // If we are on a VML platform (IE8 - TODO: remove this when that retires)...
+    if (!Ext.supports.Canvas) {
+        Cls.prototype.element = {
+            tag: 'span',
+            reference: 'element',
+            listeners: {
+                mouseenter: 'onMouseEnter',
+                mouseleave: 'onMouseLeave',
+                mousemove: 'onMouseMove'
+            },
+            style: {
+                display: 'inline-block',
+                position: 'relative',
+                overflow: 'hidden',
+                margin: '0px',
+                padding: '0px',
+                verticalAlign: 'top',
+                cursor: 'default'
+            },
+            children: [{
+                tag: 'svml:group',
+                reference: 'groupEl',
+                coordorigin: '0 0',
+                coordsize: '0 0',
+                style: 'position:absolute;width:0;height:0;pointer-events:none'
+            }]
+        };
+    }
+});

+ 75 - 0
assets/ext-7.4.0.42/classic/classic/package.json

@@ -0,0 +1,75 @@
+{
+    "name": "@sencha/ext-classic",
+    "ext-react-name": "@sencha/ext-react-classic",
+    "ext-name": "@sencha/ext-classic",
+    "SenchaExtName": "@sencha/ext-classic",
+    "SenchaExtReactName": "@sencha/ext-react-classic",
+    "version": "7.4.0.42",
+    "sencha": {
+        "name": "classic",
+        "namespace": "Ext",
+        "type": "toolkit",
+        "framework": "ext",
+        "requires": [
+            "core"
+        ],
+        "creator": "Sencha",
+        "summary": "The Classic UI Toolkit",
+        "detailedDescription": "UI components for desktops and legacy browsers",
+        "version": "7.4.0.42",
+        "compatVersion": "7.4.0",
+        "format": "1",
+        "output": "${framework.dir}/build",
+        "local": true,
+        "build": {
+            "dir": "${package.output}"
+        },
+        "sass": {
+            "namespace": "Ext",
+            "etc": "${package.dir}/sass/etc/all.scss",
+            "var": "${package.dir}/sass/var",
+            "src": "${package.dir}/sass/src"
+        },
+        "classpath": "${package.dir}/src",
+        "overrides": "${package.dir}/overrides",
+        "buildOptions": {
+            "classic": true
+        },
+        "example": {
+            "path": [
+                "examples"
+            ]
+        },
+        "subpkgs": {
+            "dir": "${package.dir}/../",
+            "packages": [
+                "ux",
+                "locale",
+                "theme-classic",
+                "theme-gray",
+                "theme-classic-sandbox",
+                "theme-neptune",
+                "theme-neptune-touch",
+                "theme-crisp",
+                "theme-crisp-touch",
+                "aria",
+                "theme-aria",
+                "theme-triton",
+                "theme-graphite",
+                "theme-material"
+            ]
+        },
+        "language": {
+            "js": {
+                "input": {
+                    "version": "ES5"
+                }
+            }
+        },
+        "properties": {
+            "skip.sass": 1,
+            "skip.pkg": 1,
+            "skip.slice": 1
+        }
+    }
+}

+ 39 - 0
assets/ext-7.4.0.42/classic/classic/sass/example/fashion.html

@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+   Copyright (c) 2012-2020. Sencha Inc.
+-->
+<html>
+<head>
+    <title>Ext JS Theme Harness</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
+
+    <!--
+    Load all required links and scripts
+    -->
+    <script type="text/javascript" src="/~cmd/extensions/sencha-fashion/fashion/fashion.js"></script>
+    <script type="text/javascript" src="/~cmd/extensions/sencha-fashion/sass-compiler.js"></script>
+    <script type="text/javascript" src="bootstrap.js"></script>
+
+    <style>
+        .widget-container {
+            margin: 10px;
+            width: 400px;
+            position: relative;
+            overflow: visible;
+        }
+
+        .x-slicer-target,
+        .x-slicer-target * {
+            opacity: 1;
+        }
+
+        /* ensure body does not overlap the rounded corners of framed panel/window when slicing */
+        .x-panel-body,
+        .x-window-body {
+            background: transparent;
+        }
+    </style>
+</head>
+    <body></body>
+</html>

+ 345 - 0
assets/ext-7.4.0.42/classic/classic/src/Action.js

@@ -0,0 +1,345 @@
+/**
+ * An Action encapsulates a shareable, reusable set of properties which define a "clickable"
+ * UI component such as a {@link Ext.button.Button button} or {@link Ext.menu.Item menu item},
+ * or {@link Ext.panel.Panel#tools panel header tool}, or an
+ * {@link Ext.grid.column.Action ActionColumn item}
+ * 
+ * Actions let you share handlers, configuration options and UI updates across any components
+ * which were created using the Action.
+ *
+ * You do not have to create Action instances. They can be configured into Views
+ * using the {@link Ext.container.Container#actions actions} config.
+ *
+ * Use a reference to an Action as the config object for any number of UI Components which share
+ * the same configuration. The Action not only supplies the configuration, but allows all Components
+ * based upon it to have a common set of methods called at once through a single call to the Action.
+ *
+ * Any Component that is to be configured with an Action may support
+ * the following methods:
+ *
+ * - setText(String)
+ * - setIconCls(String)
+ * - setGlyph(String)
+ * - setDisabled(Boolean)
+ * - setVisible(Boolean)
+ * - setHandler(String)
+ *
+ * This allows the Action to control its associated Components. Use a
+ * {@link Ext.container.Container#getAction reference to an Action} to control
+ * all components created from that action.
+ *
+ * Example usage:
+ *
+ *     @example
+ *     Ext.define('ActionsExampleController', {
+ *         extend: 'Ext.app.ViewController',
+ *         alias: 'controller.actionsexample',
+ *
+ *         onOperationClick: function() {
+ *             Ext.Msg.alert('Click', 'Perform the operation');
+ *         },
+ *
+ *         onOperationToggle: function(btn, pressed) {
+ *             // The action controls all UI components created from it.
+ *             this.view.getAction('operation').setDisabled(pressed);
+ *         }
+ *     });
+ *
+ *     Ext.define('ActionsPanel', {
+ *         extend: 'Ext.panel.Panel',
+ *         controller: 'actionsexample',
+ *
+ *         title: 'Actions',
+ *         width: 500,
+ *         height: 300,
+ *
+ *         // Define the shared Action.  Each Component created from these will
+ *         // have the same display text, icon and tooltip, and will invoke the
+ *         // same controller method on click.
+ *         actions: {
+ *             operation: {
+ *                 text: 'Do operation',
+ *                  handler: 'onOperationClick',
+ *                 glyph: 'xf005@FontAwesome',
+ *                 tooltip: 'Perform the operation'
+ *             },
+ *             disableOperation: {
+ *                 text: 'Disable operation',
+ *                 enableToggle: true,
+ *                 toggleHandler: 'onOperationToggle',
+ *                 tooltip: 'Disable the operation'
+ *             }
+ *         },
+ *
+ *         // Actions are interpreted as Buttons by this view.
+ *         // Other descendants such as Menus and Toolbars have
+ *         // their own defaults.
+ *         defaultActionType: 'button',
+ *
+ *         tools: [
+ *             '@operation'
+ *         ],
+ *
+ *         tbar: [
+ *             // Add the Action directly to a toolbar as a menu button
+ *             '@operation',
+ *             {
+ *                 text: 'Action Menu',
+ *                 menu: [
+ *                     // Add the Action to a menu as a text item
+ *                     '@operation'
+ *                 ]
+ *             }, '@disableOperation'
+ *         ],
+ *
+ *         bodyPadding: 10,
+ *         layout: {
+ *             type: 'vbox',
+ *             align: 'stretch'
+ *         },
+ *         items: [
+ *             // Add the Action to the panel body.
+ *             // defaultActionType will ensure it is converted to a Button.
+ *             '@operation'
+ *         ]
+ *     });
+ *
+ *     Ext.QuickTips.init();
+ *     new ActionsPanel({
+ *         renderTo: Ext.getBody()
+ *     });
+ */
+Ext.define('Ext.Action', {
+
+    /**
+     * @cfg {String} [text='']
+     * The text to set for all components configured by this Action.
+     */
+    /**
+     * @cfg glyph
+     * @inheritdoc Ext.panel.Header#cfg-glyph
+     * @since 6.2.0
+     */
+    /**
+     * @cfg iconCls
+     * @localdoc **Note:** The CSS class(es) specifying the background image will apply 
+     * to all components configured by this Action.
+     * @inheritdoc Ext.panel.Header#cfg-iconCls
+     */
+    /**
+     * @cfg {Boolean} [disabled=false]
+     * True to disable all components configured by this Action, false to enable them.
+     */
+    /**
+     * @cfg {Boolean} [hidden=false]
+     * True to hide all components configured by this Action, false to show them.
+     */
+    /**
+     * @cfg {String/Function} handler
+     * The function that will be invoked by each component tied to this Action
+     * when the component's primary event is triggered.
+     */
+    /**
+     * @cfg {String} itemId
+     * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.
+     */
+    /**
+     * @cfg {Object} [scope]
+     * The scope (this reference) in which the {@link #handler} is executed
+     * if specified as a function instead of a named Controller method.
+     * Defaults to the browser window.
+     */
+
+    /**
+     * Creates new Action.
+     * @param {Object} config Config object.
+     */
+    constructor: function(config) {
+        this.initialConfig = config;
+        this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
+        this.items = [];
+    },
+
+    /**
+     * @property {Boolean} isAction
+     * `true` in this class to identify an object as an instantiated Action, or subclass thereof.
+     */
+    isAction: true,
+
+    /**
+     * Sets the text to be displayed by all components configured by this Action.
+     * @param {String} text The text to display
+     */
+    setText: function(text) {
+        this.initialConfig.text = text;
+        this.callEach('setText', [text]);
+    },
+
+    /**
+     * Gets the text currently displayed by all components configured by this Action.
+     */
+    getText: function() {
+        return this.initialConfig.text;
+    },
+
+    /**
+     * Sets the {@link #iconCls icon CSS class} for all components configured by this 
+     * Action.  The class should supply a background image that will be used as the icon 
+     * image.
+     * @param {String} cls The CSS class supplying the icon image
+     */
+    setIconCls: function(cls) {
+        this.initialConfig.iconCls = cls;
+        this.callEach('setIconCls', [cls]);
+    },
+
+    /**
+     * Sets the {@link #glyph glyph} for all components configured by this 
+     * Action.
+     * @param {String} glyph The CSS class supplying the icon image
+     */
+    setGlyph: function(glyph) {
+        this.initialConfig.glyph = glyph;
+        this.callEach('setGlyph', [glyph]);
+    },
+
+    /**
+     * Gets the icon CSS class currently used by all components configured by this Action.
+     */
+    getIconCls: function() {
+        return this.initialConfig.iconCls;
+    },
+
+    /**
+     * Sets the disabled state of all components configured by this Action.  Shortcut method
+     * for {@link #enable} and {@link #disable}.
+     * @param {Boolean} disabled True to disable the component, false to enable it
+     */
+    setDisabled: function(disabled) {
+        this.initialConfig.disabled = disabled;
+        this.callEach('setDisabled', [disabled]);
+    },
+
+    /**
+     * Enables all components configured by this Action.
+     */
+    enable: function() {
+        this.setDisabled(false);
+    },
+
+    /**
+     * Disables all components configured by this Action.
+     */
+    disable: function() {
+        this.setDisabled(true);
+    },
+
+    /**
+     * Returns true if the components using this Action are currently disabled, else returns false.
+     */
+    isDisabled: function() {
+        return this.initialConfig.disabled;
+    },
+
+    /**
+     * Sets the hidden state of all components configured by this Action.  Shortcut method
+     * for `{@link #hide}` and `{@link #show}`.
+     * @param {Boolean} hidden True to hide the component, false to show it.
+     */
+    setHidden: function(hidden) {
+        this.initialConfig.hidden = hidden;
+        this.callEach('setVisible', [!hidden]);
+    },
+
+    /**
+     * Shows all components configured by this Action.
+     */
+    show: function() {
+        this.setHidden(false);
+    },
+
+    /**
+     * Hides all components configured by this Action.
+     */
+    hide: function() {
+        this.setHidden(true);
+    },
+
+    /**
+     * Returns true if the components configured by this Action are currently hidden,
+     * else returns false.
+     */
+    isHidden: function() {
+        return this.initialConfig.hidden;
+    },
+
+    /**
+     * Sets the function that will be called by each Component using this action when its
+     * primary event (usually a click or tap) is triggered.
+     * @param {String/Function} handler The function that will be invoked by the action's components
+     * when clicked. See the `handler` config of the target component for the arguments passed.
+     * @param {Object} [scope] The scope (this reference) in which the function is executed.
+     * Defaults to an encapsulating {@link Ext.app.Controller Controller}, or the Component.
+     */
+    setHandler: function(handler, scope) {
+        this.initialConfig.handler = handler;
+        this.initialConfig.scope = scope;
+        this.callEach('setHandler', [handler, scope]);
+    },
+
+    /**
+     * Executes the specified function once for each Component currently tied to this Action.
+     * The function passed in should accept a single argument that will be an object that supports
+     * the basic Action config/method interface.
+     * @param {Function} fn The function to execute for each component
+     * @param {Object} scope The scope (this reference) in which the function is executed.
+     * Defaults to the Component.
+     */
+    each: function(fn, scope) {
+        Ext.each(this.items, fn, scope);
+    },
+
+    /**
+     * @private
+     */
+    callEach: function(fnName, args) {
+        var items = this.items,
+            i = 0,
+            len = items.length,
+            item;
+
+        Ext.suspendLayouts();
+
+        for (; i < len; i++) {
+            item = items[i];
+            item[fnName].apply(item, args);
+        }
+
+        Ext.resumeLayouts(true);
+    },
+
+    /**
+     * @private
+     */
+    addComponent: function(comp) {
+        this.items.push(comp);
+        comp.on('destroy', this.removeComponent, this);
+    },
+
+    /**
+     * @private
+     */
+    removeComponent: function(comp) {
+        Ext.Array.remove(this.items, comp);
+    },
+
+    /**
+     * Executes this Action manually using the handler function specified in the original config
+     * object or the handler function set with {@link #setHandler}. Any arguments passed to this
+     * function will be passed on to the handler function.
+     * @param {Object...} args Variable number of arguments passed to the handler function
+     */
+    execute: function() {
+        this.initialConfig.handler.apply(this.initialConfig.scope || Ext.global, arguments);
+    }
+});

File diff suppressed because it is too large
+ 7313 - 0
assets/ext-7.4.0.42/classic/classic/src/Component.js


+ 255 - 0
assets/ext-7.4.0.42/classic/classic/src/ComponentLoader.js

@@ -0,0 +1,255 @@
+/**
+ * This class is used to load content via Ajax into a {@link Ext.Component}. In general 
+ * this class will not be instanced directly, rather a loader configuration will be passed to the
+ * constructor of the {@link Ext.Component}.
+ *
+ * ## HTML Renderer
+ *
+ * By default, the content loaded will be processed as raw html. The response text
+ * from the request is taken and added to the component. This can be used in
+ * conjunction with the {@link #scripts} option to execute any inline scripts in
+ * the resulting content. Using this renderer has the same effect as passing the
+ * {@link Ext.Component#html} configuration option.
+ *
+ * ## Data Renderer
+ *
+ * This renderer allows content to be added by using JSON data and a {@link Ext.XTemplate}.
+ * The content received from the response is passed to the {@link Ext.Component#update} method.
+ * This content is run through the attached {@link Ext.Component#tpl} and the data is added to
+ * the Component. Using this renderer has the same effect as using the {@link Ext.Component#data}
+ * configuration in conjunction with a {@link Ext.Component#tpl}.
+ *
+ * ## Component Renderer
+ *
+ * This renderer can only be used with a {@link Ext.container.Container} and subclasses. It allows
+ * for Components to be loaded remotely into a Container. The response is expected to be
+ * a single/series of {@link Ext.Component} configuration objects. When the response is received,
+ * the data is decoded and then passed to {@link Ext.container.Container#method-add}. Using this
+ * renderer has the same effect as specifying the {@link Ext.container.Container#cfg-items}
+ * configuration on a Container.
+ *
+ * ## Custom Renderer
+ *
+ * A custom function can be passed to handle any other special case, see the {@link #renderer}
+ * option.
+ *
+ * ## Example Usage
+ *
+ *     var cmp = Ext.create('Ext.Component', {
+ *         renderTo: Ext.getBody(),
+ *         tpl: '{firstName} - {lastName}',
+ *         loader: {
+ *             url: 'myPage.php',
+ *             renderer: 'data',
+ *             params: {
+ *                 userId: 1
+ *             }
+ *         }
+ *     });
+ *
+ *     // call the loader manually (or use autoLoad:true instead)
+ *     cmp.getLoader().load();
+ */
+Ext.define('Ext.ComponentLoader', {
+    extend: 'Ext.ElementLoader',
+
+    statics: {
+        Renderer: {
+            Data: function(loader, response, active) {
+                var success = true;
+
+                try {
+                    loader.getTarget().update(Ext.decode(response.responseText));
+                }
+                catch (e) {
+                    success = false;
+                }
+
+                return success;
+            },
+
+            Component: function(loader, response, active) {
+                var success = true,
+                    target = loader.getTarget(),
+                    items = [];
+
+                //<debug>
+                if (!target.isContainer) {
+                    Ext.raise({
+                        target: target,
+                        msg: 'Components can only be loaded into a container'
+                    });
+                }
+                //</debug>
+
+                try {
+                    items = Ext.decode(response.responseText);
+                }
+                catch (e) {
+                    success = false;
+                }
+
+                if (success) {
+                    target.suspendLayouts();
+
+                    if (active.removeAll) {
+                        target.removeAll();
+                    }
+
+                    target.add(items);
+                    target.resumeLayouts(true);
+                }
+
+                return success;
+            }
+        }
+    },
+
+    /**
+     * @cfg {Ext.Component/String} target The target {@link Ext.Component} for the loader.
+     * If a string is passed it will be looked up via the id.
+     */
+    target: null,
+
+    /**
+     * @cfg {Boolean/Object} loadOnRender
+     * `true` to have the loader make a request when the {@link #target} is rendered. If the target
+     * is already rendered, a load will take place immediately.
+     * This argument can also be a set of options that will be passed to {@link #method-load} when
+     * it is called.
+     */
+    loadOnRender: false,
+
+    /**
+     * @cfg {Boolean/Object} loadMask True or a {@link Ext.LoadMask} configuration to enable masking
+     * during loading.
+     */
+    loadMask: false,
+
+    /**
+     * @cfg {Boolean} scripts True to parse any inline script tags in the response. This only used
+     * when using the html {@link #renderer}. The scripts will be executed with the target Component
+     * as the scope (`this` reference).
+     */
+
+    /**
+     * @cfg {Object} [rendererScope=`this`]
+     * The scope (`this` reference)to execute the {@link #renderer} function in. If the
+     * {@link #scripts} option is `true`, *inline* script source (not scripts with a `src`
+     * attribute) is also executed in this scope.
+     * Defaults to this Component.
+     */
+
+    /**
+     * @cfg {String/Function} renderer
+     *
+     * The type of content that is to be loaded into, which can be one of 3 types:
+     * 
+     * + **html**: Loads raw html content, see {@link Ext.Component#html}
+     * + **data**: Loads raw html content, see {@link Ext.Component#data}
+     * + **component**: Loads child {Ext.Component} instances. This option is only valid when used
+     * with a Container.
+     * 
+     * Alternatively, you can pass a function which is called with the following parameters.
+     * 
+     * + loader - Loader instance
+     * + response - The server response
+     * + active - The active request
+     * 
+     * The function must return false is loading is not successful. Below is a sample of using
+     * a custom renderer:
+     *
+     *     new Ext.Component({
+     *         loader: {
+     *             url: 'myPage.php',
+     *             renderer: function(loader, response, active) {
+     *                 var text = response.responseText;
+     *                 loader.getTarget().setHtml('The response is ' + text);
+     *                 return true;
+     *             }
+     *         }
+     *     });
+     *
+     */
+    renderer: 'html',
+
+    /**
+     * Set a {Ext.Component} as the target of this loader. Note that if the target is changed,
+     * any active requests will be aborted.
+     * @param {String/Ext.Component} target The component to be the target of this loader.
+     * If a string is passed it will be looked up via its id.
+     */
+    setTarget: function(target) {
+        var me = this;
+
+        if (Ext.isString(target)) {
+            target = Ext.getCmp(target);
+        }
+
+        if (me.target && me.target !== target) {
+            me.abort();
+        }
+
+        me.target = target;
+
+        if (target && me.loadOnRender) {
+            if (target.rendered) {
+                me.doLoadOnRender();
+            }
+            else {
+                me.mon(target, 'render', me.doLoadOnRender, me);
+            }
+        }
+    },
+
+    doLoadOnRender: function() {
+        var loadOnRender = this.loadOnRender;
+
+        this.load(Ext.isObject(loadOnRender) ? loadOnRender : null);
+    },
+
+    removeMask: function() {
+        this.target.setLoading(false);
+    },
+
+    /**
+     * Add the mask on the target
+     * @private
+     * @param {Boolean/Object} mask The mask configuration
+     */
+    addMask: function(mask) {
+        this.target.setLoading(mask);
+    },
+
+    setOptions: function(active, options) {
+        active.removeAll = Ext.isDefined(options.removeAll) ? options.removeAll : this.removeAll;
+        active.rendererScope = options.rendererScope || this.rendererScope || this.target;
+    },
+
+    /**
+     * Gets the renderer to use
+     * @private
+     * @param {String/Function} renderer The renderer to use
+     * @return {Function} A rendering function to use.
+     */
+    getRenderer: function(renderer) {
+        var renderers;
+
+        if (Ext.isFunction(renderer)) {
+            return renderer;
+        }
+
+        renderers = this.statics().Renderer;
+
+        switch (renderer) {
+            case 'component':
+                return renderers.Component;
+
+            case 'data':
+                return renderers.Data;
+
+            default:
+                return Ext.ElementLoader.Renderer.Html;
+        }
+    }
+});

+ 604 - 0
assets/ext-7.4.0.42/classic/classic/src/Editor.js

@@ -0,0 +1,604 @@
+/**
+ * The Editor class is used to provide inline editing for elements on the page. The editor
+ * is backed by a {@link Ext.form.field.Field} that will be displayed to edit the underlying
+ * content. The editor is a floating Component, when the editor is shown it is automatically
+ * aligned to display over the top of the bound element it is editing. The Editor contains several
+ * options for how to handle key presses:
+ *
+ * - {@link #completeOnEnter}
+ * - {@link #cancelOnEsc}
+ * - {@link #swallowKeys}
+ *
+ * It also has options for how to use the value once the editor has been activated:
+ *
+ * - {@link #revertInvalid}
+ * - {@link #ignoreNoChange}
+ * - {@link #updateEl}
+ *
+ * Sample usage:
+ * 
+ *     @example
+ *     var form = Ext.create('Ext.form.Panel', {
+ *         renderTo: Ext.getBody(),
+ *         width: 380,
+ *         height: 400,
+ *         title: 'User Details',
+ *         bodyPadding: 10,
+ *         items: [{
+ *             html: 'Double-Click on the header title, this, or the field label to edit',
+ *             height:30
+ *         },{
+ *             fieldLabel: 'First Name',
+ *             name: 'firstname',
+ *             xtype: 'textfield'
+ *         }]
+ *     });
+ *     
+ *     var editor = new Ext.Editor({
+ *         // update the innerHTML of the bound element 
+ *         // when editing completes
+ *         updateEl: true,
+ *         alignment: 'l-l',
+ *         autoSize: {
+ *             width: 'boundEl'
+ *         },
+ *         field: {
+ *             xtype: 'textfield'
+ *         }
+ *     });
+ *     
+ *     form.header.getTitle().textEl.on('dblclick', function(e, t) {
+ *         editor.startEdit(t);
+ *     });
+ *     
+ *     form.getTargetEl().on('dblclick', function(e, t) {
+ *         editor.startEdit(t);
+ *         // Manually focus, since clicking on the label will focus the text field
+ *         editor.field.focus(50, true);
+ *     });
+ *
+ * {@img Ext.Editor/Ext.Editor.png Ext.Editor component}
+ *
+ */
+Ext.define('Ext.Editor', {
+    extend: 'Ext.container.Container',
+    xtype: 'editor',
+
+    requires: ['Ext.layout.container.Editor'],
+
+    layout: 'editor',
+
+    /**
+    * @cfg {Ext.form.field.Field} field
+    * The Field object (or descendant) or config object for field
+    */
+
+    /**
+     * @cfg {Boolean} allowBlur
+     * True to {@link #completeEdit complete the editing process} if in edit mode when focus exits
+     * from this Editor's hierarchy.
+     */
+    allowBlur: true,
+
+    /**
+     * @cfg {Boolean/Object} autoSize
+     * True for the editor to automatically adopt the size of the underlying field. Otherwise,
+     * an object can be passed to indicate where to get each dimension. The available properties
+     * are 'boundEl' and 'field'. If a dimension is not specified, it will use the underlying
+     * height/width specified on the editor object.
+     * Examples:
+     *
+     *     autoSize: true // The editor will be sized to the height/width of the field
+     *
+     *     height: 21,
+     *     autoSize: {
+     *         width: 'boundEl' // The width will be determined by the width of the boundEl,
+     *                          // the height from the editor (21)
+     *     }
+     *
+     *     autoSize: {
+     *         width: 'field', // Width from the field
+     *         height: 'boundEl' // Height from the boundEl
+     *     }
+     */
+
+    /**
+     * @cfg {Boolean} revertInvalid
+     * True to automatically revert the field value and cancel the edit when the user completes
+     * an edit and the field validation fails
+     */
+    revertInvalid: true,
+
+    /**
+     * @cfg {Boolean} [ignoreNoChange=false]
+     * True to skip the edit completion process (no save, no events fired) if the user completes
+     * an edit and the value has not changed. Applies only to string values - edits for other
+     * data types will never be ignored.
+     */
+
+    /**
+     * @cfg {Boolean} [hideEl=true]
+     * False to keep the bound element visible while the editor is displayed
+     */
+
+    /**
+     * @cfg {Object} value
+     * The data value of the underlying field
+     */
+    value: '',
+
+    /**
+     * @cfg {String} alignment
+     * The position to align to (see {@link Ext.util.Positionable#alignTo} for more details).
+     */
+    alignment: 'c-c?',
+
+    /**
+     * @cfg {Number[]} offsets
+     * The offsets to use when aligning (see {@link Ext.util.Positionable#alignTo} for more details.
+     */
+    offsets: [0, 0],
+
+    /**
+     * @cfg {Boolean/String} shadow
+     * "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop" for bottom-right shadow.
+     */
+    shadow: 'frame',
+
+    /**
+     * @cfg {Boolean} constrain
+     * True to constrain the editor to the viewport
+     */
+    constrain: false,
+
+    /**
+     * @cfg {Boolean} swallowKeys
+     * Handle the keydown/keypress events so they don't propagate
+     */
+    swallowKeys: true,
+
+    /**
+     * @cfg {Boolean} completeOnEnter
+     * True to complete the edit when the enter key is pressed.
+     */
+    completeOnEnter: true,
+
+    /**
+     * @cfg {Boolean} cancelOnEsc
+     * True to cancel the edit when the escape key is pressed.
+     */
+    cancelOnEsc: true,
+
+    /**
+     * @cfg {Boolean} updateEl
+     * True to update the innerHTML of the bound element when the update completes
+     */
+    updateEl: false,
+
+    // Do not participate in the ZIndexManager's focus switching operations.
+    // When an editor is hidden, the ZIndexManager will not automatically activate
+    // the last visible floater on the stack.
+    focusOnToFront: false,
+
+    /**
+     * @cfg {String/HTMLElement/Ext.dom.Element} [parentEl=document.body]
+     * An element to render to.
+     */
+
+    baseCls: Ext.baseCSSPrefix + 'editor',
+
+    /**
+     * @property {Boolean} editing
+     * True if this editor is currently active.
+     * @readonly
+     */
+    editing: false,
+
+    /**
+     * @event beforestartedit
+     * Fires when editing is initiated, but before the value changes.  Editing can be canceled
+     * by returning `false` from the handler of this event.
+     * @param {Ext.Editor} this
+     * @param {Ext.dom.Element} boundEl The underlying element bound to this editor
+     * @param {Object} value The field value being set
+     */
+
+    /**
+     * @event startedit
+     * Fires when this editor is displayed
+     * @param {Ext.Editor} this
+     * @param {Ext.dom.Element} boundEl The underlying element bound to this editor
+     * @param {Object} value The starting field value
+     */
+
+    /**
+     * @event beforecomplete
+     * Fires after a change has been made to the field, but before the change is reflected in the
+     * underlying field. Saving the change to the field can be canceled by returning `false`
+     * from the handler of this event. Note that if the value has not changed and
+     * ignoreNoChange = true, the editing will still end but this event will not fire since no edit
+     * actually occurred.
+     * @param {Ext.Editor} this
+     * @param {Object} value The current field value
+     * @param {Object} startValue The original field value
+     */
+
+    /**
+     * @event complete
+     * Fires after editing is complete and any changed value has been written to the underlying
+     * field.
+     * @param {Ext.Editor} this
+     * @param {Object} value The current field value
+     * @param {Object} startValue The original field value
+     */
+
+    /**
+     * @event canceledit
+     * Fires after editing has been canceled and the editor's value has been reset.
+     * @param {Ext.Editor} this
+     * @param {Object} value The user-entered field value that was discarded
+     * @param {Object} startValue The original field value that was set back into the editor after
+     * cancel
+     */
+
+    /**
+     * @event specialkey
+     * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.
+     * You can check {@link Ext.event.Event#getKey} to determine which key was pressed.
+     * @param {Ext.Editor} this
+     * @param {Ext.form.field.Field} field The field attached to this editor
+     * @param {Ext.event.Event} event The event object
+     */
+
+    preventDefaultAlign: true,
+    useBoundValue: true,
+    specialKeyDelay: 1,
+
+    initComponent: function() {
+        var me = this,
+            field = me.field = Ext.ComponentManager.create(me.field || {}, 'textfield');
+
+        field.msgTarget = field.msgTarget || 'qtip';
+
+        me.mon(field, {
+            scope: me,
+            specialkey: me.onSpecialKey
+        });
+
+        if (field.grow) {
+            me.mon(field, 'autosize', me.onFieldAutosize, me, { delay: 1 });
+        }
+
+        me.floating = {
+            constrain: me.constrain
+        };
+
+        me.items = field;
+
+        me.callParent();
+    },
+
+    onAdded: function(container) {
+        // Editors are floaters and shouldn't have an ownerCt, so use ownerCmp as
+        // the upward link.
+        this.ownerCmp = container;
+    },
+
+    /**
+     * @private
+     */
+    onFieldAutosize: function() {
+        this.updateLayout();
+    },
+
+    afterRender: function(ct, position) {
+        var me = this,
+            field = me.field,
+            inputEl = field.inputEl;
+
+        me.callParent(arguments);
+
+        // Ensure the field doesn't get submitted as part of any form
+        if (inputEl) {
+            inputEl.dom.name = '';
+
+            if (me.swallowKeys) {
+                inputEl.swallowEvent([
+                    'keypress', // *** Opera
+                    'keydown'   // *** all other browsers
+                ]);
+            }
+        }
+    },
+
+    /**
+     * @private
+     */
+    onSpecialKey: function(field, event) {
+        var me = this,
+            key = event.getKey(),
+            complete = me.completeOnEnter && key === event.ENTER,
+            cancel = me.cancelOnEsc && key === event.ESC,
+            task = me.specialKeyTask;
+
+        if (complete || cancel) {
+            event.stopEvent();
+
+            if (!task) {
+                me.specialKeyTask = task = new Ext.util.DelayedTask();
+            }
+
+            // Must defer this slightly to prevent exiting edit mode before the field's own
+            // key nav can handle the enter key, e.g. selecting an item in a combobox list
+            task.delay(me.specialKeyDelay, complete ? me.completeEdit : me.cancelEdit, me);
+
+            //<debug>
+            // Makes unit testing easier
+            if (me.specialKeyDelay === 0) {
+                task.cancel();
+
+                if (complete) {
+                    me.completeEdit();
+                }
+                else {
+                    me.cancelEdit();
+                }
+            }
+            //</debug>
+        }
+
+        me.fireEvent('specialkey', me, field, event);
+    },
+
+    /**
+     * Starts the editing process and shows the editor.
+     * @param {String/HTMLElement/Ext.dom.Element} el The element to edit
+     * @param {String} value (optional) A value to initialize the editor with. If a value
+     * is not provided, it defaults to the innerHTML of el.
+     * @param doFocus (private)
+     * @param isResuming (private)
+     */
+    startEdit: function(el, value, doFocus, isResuming) {
+        var me = this,
+            field = me.field,
+            dom, ownerCt, renderTo, delay;
+
+        if (!isResuming) {
+            me.completeEdit(true);
+        }
+
+        me.boundEl = Ext.get(el);
+        dom = me.boundEl.dom;
+
+        if (me.useBoundValue && !Ext.isDefined(value)) {
+            value = Ext.String.trim(dom.textContent || dom.innerText || dom.innerHTML);
+        }
+
+        if (me.fireEvent('beforestartedit', me, me.boundEl, value) !== false) {
+            if (me.context) {
+                // Grab the value again, may have changed in beforestartedit
+                value = me.context.value;
+            }
+
+            // If NOT configured with a renderTo, render to the ownerCt's element
+            // Being floating, we do not need to use the actual layout's target.
+            // Indeed, it's better if we do not so that we do not interfere with layout's
+            // child management.
+            Ext.suspendLayouts();
+
+            if (!me.rendered) {
+                ownerCt = me.ownerCt;
+                renderTo = me.renderTo || (ownerCt && ownerCt.getEl()) || Ext.getBody();
+                Ext.fly(renderTo).position();
+                me.renderTo = renderTo;
+            }
+
+            me.startValue = value;
+            me.show();
+            me.realign(true);
+
+            // temporarily suspend events on field to prevent the "change" event from firing
+            // when resetOriginalValue() and setValue() are called
+            if (!isResuming) {
+                field.suspendEvents();
+                field.setValue(value);
+                field.resetOriginalValue();
+                field.resumeEvents();
+            }
+
+            if (doFocus !== false) {
+                // Set a delay parameter to true to prevent the cursor from jumping 
+                // after focus for IE: https://sencha.jira.com/browse/EXTJS-26698
+                delay = Ext.isIE ? true : false;
+
+                // Use maximum 32 bit signed integer for setSelectionRange start value. Any
+                // higher value causes an issue with IE/Edge/Safari by selecting text when 
+                // selectOnFocus is false.
+                // https://sencha.jira.com/browse/EXTJS-26698
+                field.focus(field.selectOnFocus ? true : [Ext.Number.MAX_32BIT_INTEGER], delay);
+            }
+
+            if (field.autoSize) {
+                field.autoSize();
+            }
+
+            Ext.resumeLayouts(true);
+            me.toggleBoundEl(false);
+            me.editing = true;
+        }
+    },
+
+    /**
+     * Realigns the editor to the bound field based on the current alignment config value.
+     * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound
+     * element.
+     */
+    realign: function(autoSize) {
+        var me = this;
+
+        if (autoSize === true) {
+            me.updateLayout();
+        }
+
+        me.alignTo(me.boundEl, me.alignment, me.offsets);
+    },
+
+    /**
+     * Ends the editing process, persists the changed value to the underlying field, and hides
+     * the editor.
+     * @param {Boolean} [remainVisible=false] Override the default behavior and keep the editor
+     * visible after edit
+     */
+    completeEdit: function(remainVisible) {
+        var me = this,
+            field = me.field,
+            startValue = me.startValue,
+            cancel = me.context && me.context.cancel,
+            value;
+
+        if (!me.editing) {
+            return;
+        }
+
+        // Assert combo values first
+        if (field.assertValue) {
+            field.assertValue();
+        }
+
+        value = me.getValue();
+
+        if (!field.isValid()) {
+            if (me.revertInvalid !== false) {
+                me.cancelEdit(remainVisible);
+            }
+
+            return;
+        }
+
+        if (me.ignoreNoChange && !field.didValueChange(value, startValue)) {
+            me.onEditComplete(remainVisible);
+
+            return;
+        }
+
+        if (me.fireEvent('beforecomplete', me, value, startValue) !== false) {
+            // Grab the value again, may have changed in beforecomplete
+            value = me.getValue();
+
+            if (me.updateEl && me.boundEl) {
+                me.boundEl.setHtml(value);
+            }
+
+            me.onEditComplete(remainVisible, cancel);
+            me.fireEvent('complete', me, value, startValue);
+        }
+    },
+
+    onShow: function() {
+        var me = this;
+
+        me.callParent(arguments);
+        me.fireEvent('startedit', me, me.boundEl, me.startValue);
+    },
+
+    /**
+     * Cancels the editing process and hides the editor without persisting any changes. The field
+     * value will be reverted to the original starting value.
+     * @param {Boolean} [remainVisible=false] Override the default behavior and keep the editor
+     * visible after cancel
+     */
+    cancelEdit: function(remainVisible) {
+        var me = this,
+            startValue = me.startValue,
+            field = me.field,
+            value;
+
+        if (me.editing) {
+            if (field) {
+                value = me.editedValue = me.getValue();
+
+                // temporarily suspend events on field to prevent the "change" event from firing
+                // when setValue() is called
+                field.suspendEvents();
+                me.setValue(startValue);
+                field.resumeEvents();
+            }
+
+            me.onEditComplete(remainVisible, true);
+            me.fireEvent('canceledit', me, value, startValue);
+
+            delete me.editedValue;
+        }
+    },
+
+    /**
+     * @private
+     */
+    onEditComplete: function(remainVisible, canceling) {
+        this.editing = false;
+
+        if (remainVisible !== true) {
+            this.hide();
+            this.toggleBoundEl(true);
+        }
+    },
+
+    onFocusLeave: function(e) {
+        var me = this;
+
+        if (me.allowBlur === true && me.editing) {
+            me.completeEdit();
+        }
+
+        me.callParent([e]);
+    },
+
+    onHide: function() {
+        var me = this,
+            field = me.field;
+
+        if (me.editing) {
+            me.completeEdit();
+        }
+        else if (field.collapse) {
+            field.collapse();
+        }
+
+        me.callParent(arguments);
+    },
+
+    /**
+     * Gets the data value of the editor
+     * @return {Object} The data value
+     */
+    getValue: function() {
+        return this.field.getValue();
+    },
+
+    /**
+     * Sets the data value of the editor
+     * @param {Object} value Any valid value supported by the underlying field
+     */
+    setValue: function(value) {
+        this.field.setValue(value);
+    },
+
+    toggleBoundEl: function(visible) {
+        if (this.hideEl !== false) {
+            this.boundEl.setVisible(visible);
+        }
+    },
+
+    doDestroy: function() {
+        var me = this,
+            task = me.specialKeyTask;
+
+        if (task) {
+            task.cancel();
+        }
+
+        Ext.destroy(me.field);
+
+        me.callParent();
+    }
+});

+ 440 - 0
assets/ext-7.4.0.42/classic/classic/src/ElementLoader.js

@@ -0,0 +1,440 @@
+/**
+ * A class used to load remote content to an Element. Sample usage:
+ *
+ *     Ext.get('el').load({
+ *         url: 'myPage.php',
+ *         scripts: true,
+ *         params: {
+ *             id: 1
+ *         }
+ *     });
+ *
+ * In general this class will not be instanced directly, rather the
+ * {@link Ext.dom.Element#method-load} method will be used.
+ */
+Ext.define('Ext.ElementLoader', {
+    mixins: [
+        'Ext.util.Observable'
+    ],
+
+    uses: [
+        'Ext.data.Connection',
+        'Ext.Ajax'
+    ],
+
+    statics: {
+        Renderer: {
+            Html: function(loader, response, active) {
+                loader.getTarget().setHtml(
+                    response.responseText, active.scripts === true, active.callback,
+                    active.rendererScope
+                );
+
+                return true;
+            }
+        }
+    },
+
+    /**
+     * @cfg {String} url (required)
+     * The url to retrieve the content from.
+     */
+    url: null,
+
+    /**
+     * @cfg {Object} params
+     * Any params to be attached to the Ajax request. These parameters will
+     * be overridden by any params in the load options.
+     */
+    params: null,
+
+    /**
+     * @cfg {Object} baseParams Params that will be attached to every request. These parameters
+     * will not be overridden by any params in the load options.
+     */
+    baseParams: null,
+
+    /**
+     * @cfg {Boolean/Object} autoLoad
+     * `true` to have the loader make a request as soon as it is created.
+     * This argument can also be a set of options that will be passed to {@link #method-load}
+     * when it is called.
+     */
+    autoLoad: false,
+
+    /**
+     * @cfg {HTMLElement/Ext.dom.Element/String} target
+     * The target element for the loader. It can be the DOM element, the id or an
+     * {@link Ext.dom.Element}.
+     */
+    target: null,
+
+    /**
+     * @cfg {Boolean/String} loadMask
+     * True or a string to show when the element is loading.
+     */
+    loadMask: false,
+
+    /**
+     * @cfg {Object} ajaxOptions
+     * Any additional options to be passed to the request, for example timeout or headers.
+     */
+    ajaxOptions: null,
+
+    /**
+     * @cfg {Boolean} scripts
+     * True to parse any inline script tags in the response.
+     */
+    scripts: false,
+
+    /**
+     * @cfg {Function/String} success
+     * A function to be called when a load request is successful.
+     * Will be called with the following config parameters:
+     *
+     * - this - The ElementLoader instance.
+     * - response - The response object.
+     * - options - Ajax options.
+     * 
+     * @controllable
+     */
+
+    /**
+     * @cfg {Function/String} failure A function to be called when a load request fails.
+     * Will be called with the following config parameters:
+     *
+     * - this - The ElementLoader instance.
+     * - response - The response object.
+     * - options - Ajax options.
+     * 
+     * @controllable
+     */
+
+    /**
+     * @cfg {Function/String} callback A function to be called when a load request finishes.
+     * Will be called with the following config parameters:
+     *
+     * - this - The ElementLoader instance.
+     * - success - True if successful request.
+     * - response - The response object.
+     * - options - Ajax options.
+     * 
+     * @controllable
+     */
+
+    /**
+     * @cfg {Object} scope
+     * The scope to execute the {@link #success} and {@link #failure} functions in.
+     */
+
+    /**
+     * @cfg {Function} renderer
+     * A custom function to render the content to the element. The function should
+     * return false if the renderer could not be applied. The passed parameters are:
+     *
+     * - The loader
+     * - The response
+     * - The active request
+     */
+
+    /**
+     * @cfg {Object} rendererScope
+     * The scope to execute the {@link #renderer} function in.
+     */
+
+    /**
+     * @property {Boolean} isLoader
+     * `true` in this class to identify an object as an instantiated ElementLoader,
+     * or subclass thereof.
+     */
+    isLoader: true,
+
+    /**
+     * @event beforeload
+     * Fires before a load request is made to the server.
+     * Returning false from an event listener can prevent the load
+     * from occurring.
+     * @param {Ext.ElementLoader} this
+     * @param {Object} options The options passed to the request
+     */
+
+    /**
+     * @event exception
+     * Fires after an unsuccessful load.
+     * @param {Ext.ElementLoader} this
+     * @param {Object} response The response from the server
+     * @param {Object} options The options passed to the request
+     */
+
+    /**
+     * @event load
+     * Fires after a successful load.
+     * @param {Ext.ElementLoader} this
+     * @param {Object} response The response from the server
+     * @param {Object} options The options passed to the request
+     */
+
+    constructor: function(config) {
+        var me = this,
+            autoLoad;
+
+        //<debug>
+        me.callParent([config]);
+        //</debug>
+
+        me.mixins.observable.constructor.call(me, config);
+
+        me.setTarget(me.target);
+
+        if (me.autoLoad) {
+            autoLoad = me.autoLoad;
+
+            if (autoLoad === true) {
+                autoLoad = null;
+            }
+
+            me.load(autoLoad);
+        }
+    },
+
+    /**
+     * Sets an {@link Ext.dom.Element} as the target of this loader.
+     * Note that if the target is changed, any active requests will be aborted.
+     * @param {String/HTMLElement/Ext.dom.Element} target The element or its ID.
+     */
+    setTarget: function(target) {
+        var me = this;
+
+        target = Ext.get(target);
+
+        if (me.target && me.target !== target) {
+            me.abort();
+        }
+
+        me.target = target;
+    },
+
+    /**
+     * Returns the target of this loader.
+     * @return {Ext.Component} The target or null if none exists.
+     */
+    getTarget: function() {
+        return this.target || null;
+    },
+
+    /**
+     * Aborts the active load request
+     */
+    abort: function() {
+        var active = this.active;
+
+        if (active !== undefined) {
+            Ext.Ajax.abort(active.request);
+
+            if (active.mask) {
+                this.removeMask();
+            }
+
+            delete this.active;
+        }
+    },
+
+    /**
+     * Removes the mask on the target
+     * @private
+     */
+    removeMask: function() {
+        this.target.unmask();
+    },
+
+    /**
+     * Adds the mask on the target
+     * @private
+     * @param {Boolean/Object} mask The mask configuration
+     */
+    addMask: function(mask) {
+        this.target.mask(mask === true ? null : mask);
+    },
+
+    /**
+     * Loads new data from the server.
+     * @param {Object} options The options for the request. They can be any configuration option
+     * that can be specified for the class, with the exception of the target option. Note that any
+     * options passed to the method will override any class defaults.
+     */
+    load: function(options) {
+        if (this.destroying || this.destroyed) {
+            return;
+        }
+
+        //<debug>
+        if (!this.target) {
+            Ext.raise('A valid target is required when loading content for ' + this.id);
+        }
+        //</debug>
+
+        options = Ext.apply({}, options);
+
+        // eslint-disable-next-line vars-on-top
+        var me = this,
+            mask = Ext.isDefined(options.loadMask) ? options.loadMask : me.loadMask,
+            params = Ext.apply({}, options.params),
+            ajaxOptions = Ext.apply({}, options.ajaxOptions),
+            callback = options.callback || me.callback,
+            scope = options.scope || me.scope || me;
+
+        Ext.applyIf(ajaxOptions, me.ajaxOptions);
+        Ext.applyIf(options, ajaxOptions);
+
+        Ext.applyIf(params, me.params);
+        Ext.apply(params, me.baseParams);
+
+        Ext.applyIf(options, {
+            url: me.url
+        });
+
+        //<debug>
+        if (!options.url) {
+            Ext.raise('You must specify the URL from which content should be loaded');
+        }
+        //</debug>
+
+        Ext.apply(options, {
+            scope: me,
+            params: params,
+            callback: me.onComplete
+        });
+
+        if (me.fireEvent('beforeload', me, options) === false) {
+            return;
+        }
+
+        if (mask) {
+            me.addMask(mask);
+        }
+
+        me.active = {
+            options: options,
+            mask: mask,
+            scope: scope,
+            callback: callback,
+            success: options.success || me.success,
+            failure: options.failure || me.failure,
+            renderer: options.renderer || me.renderer,
+            scripts: Ext.isDefined(options.scripts) ? options.scripts : me.scripts
+        };
+
+        me.active.request = Ext.Ajax.request(options);
+        me.setOptions(me.active, options);
+    },
+
+    /**
+     * @method
+     * Sets any additional options on the active request
+     * @private
+     * @param {Object} active The active request
+     * @param {Object} options The initial options
+     */
+    setOptions: function(active, options) {
+        active.rendererScope = options.rendererScope || this.rendererScope || this;
+    },
+
+    /**
+     * Parses the response after the request completes
+     * @private
+     * @param {Object} options Ajax options
+     * @param {Boolean} success Success status of the request
+     * @param {Object} response The response object
+     */
+    onComplete: function(options, success, response) {
+        var me = this,
+            active = me.active,
+            rendererScope,
+            scope;
+
+        if (active) {
+            scope = active.scope;
+            rendererScope = active.rendererScope;
+
+            if (success) {
+                // eslint-disable-next-line max-len
+                success = me.getRenderer(active.renderer).call(rendererScope, me, response, active) !== false;
+            }
+
+            if (success) {
+                Ext.callback(active.success, scope, [me, response, options]);
+                me.fireEvent('load', me, response, options);
+            }
+            else {
+                Ext.callback(active.failure, scope, [me, response, options]);
+                me.fireEvent('exception', me, response, options);
+            }
+
+            Ext.callback(active.callback, scope, [me, success, response, options]);
+
+            if (active.mask) {
+                me.removeMask();
+            }
+        }
+
+        delete me.active;
+    },
+
+    /**
+     * Gets the renderer to use
+     * @private
+     * @param {String/Function} renderer The renderer to use
+     * @return {Function} A rendering function to use.
+     */
+    getRenderer: function(renderer) {
+        if (Ext.isFunction(renderer)) {
+            return renderer;
+        }
+
+        return this.statics().Renderer.Html;
+    },
+
+    /**
+     * Automatically refreshes the content over a specified period.
+     * @param {Number} interval The interval to refresh in ms.
+     * @param {Object} options (optional) The options to pass to the load method.
+     * See {@link #method-load}
+     */
+    startAutoRefresh: function(interval, options) {
+        var me = this;
+
+        me.stopAutoRefresh();
+
+        me.autoRefresh = Ext.interval(function() {
+            me.load(options);
+        }, interval);
+    },
+
+    /**
+     * Clears any auto refresh. See {@link #startAutoRefresh}.
+     */
+    stopAutoRefresh: function() {
+        Ext.uninterval(this.autoRefresh);
+        this.autoRefresh = null;
+    },
+
+    /**
+     * Checks whether the loader is automatically refreshing. See {@link #startAutoRefresh}.
+     * @return {Boolean} True if the loader is automatically refreshing
+     */
+    isAutoRefreshing: function() {
+        return !!this.autoRefresh;
+    },
+
+    /**
+     * Destroys the loader. Any active requests will be aborted.
+     */
+    destroy: function() {
+        var me = this;
+
+        me.stopAutoRefresh();
+        me.abort();
+
+        me.callParent();
+    }
+});

+ 444 - 0
assets/ext-7.4.0.42/classic/classic/src/EventManager.js

@@ -0,0 +1,444 @@
+/**
+ * @class Ext.EventManager
+ * Registers event handlers on DOM elements.
+ * 
+ * This class is deprecated.  Please use the Ext.dom.Element api to attach listeners to
+ * DOM Elements.  For example:
+ * 
+ *     var element = Ext.get('myId');
+ *     
+ *     element.on('click', function(e) {
+ *         // event handling logic here
+ *     });
+ *
+ * @singleton
+ * @deprecated 5.0.0 Please use the Ext.dom.Element api to attach listeners to DOM Elements
+ */
+Ext.define('Ext.EventManager', {
+    singleton: true,
+
+    mouseLeaveRe: /(mouseout|mouseleave)/,
+    mouseEnterRe: /(mouseover|mouseenter)/,
+
+    /**
+     * Appends an event handler to an element.  The shorthand version {@link #on} is equivalent.
+     * Typically you will use {@link Ext.dom.Element#addListener} directly on an Element in favor of
+     * calling this version.
+     *
+     * {@link Ext.EventManager#on} is an alias for {@link Ext.EventManager#addListener}.
+     *
+     * @param {String/Ext.dom.Element/HTMLElement/Window} element The html element or id to assign
+     * the event handler to.
+     *
+     * @param {String} eventName The name of the event to listen for.
+     * May also be an object who's property names are event names.
+     *
+     * @param {Function/String} [fn] The handler function the event invokes. A String parameter
+     * is assumed to be method name in `scope` object, or Element object if no scope is provided.
+     * @param {Ext.event.Event} fn.event The {@link Ext.event.Event EventObject} describing
+     * the event.
+     * @param {Ext.dom.Element} fn.target The Element which was the target of the event.
+     * Note that this may be filtered by using the `delegate` option.
+     * @param {Object} fn.options The options object from the addListener call.
+     *
+     * @param {Object} [scope] The scope (`this` reference) in which the handler function
+     * is executed. Defaults to the Element.
+     *
+     * @param {Object} [options] An object containing handler configuration properties.
+     * This may contain any of the following properties (See {@link Ext.dom.Element#addListener}
+     * for examples of how to use these options.):
+     * @param {Object} options.scope The scope (`this` reference) in which the handler function
+     * is executed. Defaults to the Element.
+     * @param {String} options.delegate A simple selector to filter the target or look for
+     * a descendant of the target. See {@link Ext.dom.Query} for information about simple selectors.
+     * @param {Boolean} options.stopEvent True to stop the event. That is stop propagation,
+     * and prevent the default action.
+     * @param {Boolean} options.preventDefault True to prevent the default action
+     * @param {Boolean} options.stopPropagation True to prevent event propagation
+     * @param {Boolean} options.normalized False to pass a browser event to the handler function
+     * instead of an Ext.event.Event
+     * @param {Number} options.delay The number of milliseconds to delay the invocation of the
+     * handler after te event fires.
+     * @param {Boolean} options.single True to add a handler to handle just the next firing of the
+     * event, and then remove itself.
+     * @param {Number} options.buffer Causes the handler to be scheduled to run in an
+     * {@link Ext.util.DelayedTask} delayed by the specified number of milliseconds. If the event
+     * fires again within that time, the original handler is *not* invoked, but the new handler
+     * is scheduled in its place.
+     * @param {Ext.dom.Element} options.target Only call the handler if the event was fired
+     * on the target Element, *not* if the event was bubbled up from a child node.
+     * @param {Boolean} options.capture `true` to initiate capture which will fire the listeners
+     * on the target Element *before* any descendant Elements. Normal events start with the target
+     * element and propagate upward to ancestor elements, whereas captured events propagate
+     * from the top of the DOM downward to descendant elements. This option is the same
+     * as the useCapture parameter in the javascript addEventListener method.
+     */
+    addListener: function(element, eventName, fn, scope, options) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager is deprecated. " +
+                     "Use Ext.dom.Element#addListener to attach an event listener.");
+        //</debug>
+
+        Ext.get(element).addListener(eventName, fn, scope, options);
+    },
+
+    /**
+     * Adds a listener to be notified when the browser window is resized and provides resize event
+     * buffering (100 milliseconds), passes new viewport width and height to handlers.
+     * @param {Function} fn      The handler function the window resize event invokes.
+     * @param {Object}   scope   The scope (<code>this</code> reference) in which the handler
+     * function executes. Defaults to the browser window.
+     * @param {Boolean}  [options] Options object as passed to {@link Ext.dom.Element#addListener}
+     * @deprecated 5.0.0 Use {@link Ext#method-on Ext.on}('resize', fn) to attach a window resize
+     * listener.
+     */
+    onWindowResize: function(fn, scope, options) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager is deprecated. " +
+                     "Use Ext.on('resize', fn) to attach a window resize listener.");
+        //</debug>
+
+        Ext.GlobalEvents.on('resize', fn, scope, options);
+    },
+
+    /**
+     * Adds a listener to be notified when the browser window is unloaded.
+     * @param {Function} fn      The handler function the window unload event invokes.
+     * @param {Object}   scope   The scope (<code>this</code> reference) in which the handler
+     * function executes. Defaults to the browser window.
+     * @param {Boolean}  options Options object as passed to {@link Ext.dom.Element#addListener}
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    onWindowUnload: function(fn, scope, options) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager is deprecated. " +
+                     "Use Ext.getWin().on('unload', fn) to attach a window unload listener.");
+        //</debug>
+
+        Ext.getWin().on('unload', fn, scope, options);
+    },
+
+    /**
+     * Recursively removes all previous added listeners from an element and its children.
+     * Typically you will use {@link Ext.dom.Element#clearListeners} directly on an Element
+     * in favor of calling this method.
+     * @param {String/Ext.dom.Element/HTMLElement/Window} element The id or html element from which
+     * to remove all event handlers.
+     * @param {String} eventName (optional) The name of the event.
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    purgeElement: function(element, eventName) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager is deprecated. " +
+                     "Call clearListeners() on a Ext.dom.Element to remove all listeners.");
+        //</debug>
+
+        Ext.get(element).clearListeners();
+    },
+
+    /**
+     * Removes all event handers from an element.  Typically you will use {@link
+     * Ext.dom.Element#clearListeners} directly on an Element in favor of calling this method.
+     * @param {String/Ext.dom.Element/HTMLElement/Window} element The id or html element from which
+     * to remove all event handlers.
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    removeAll: function(element) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager is deprecated. " +
+                     "Call clearListeners() on a Ext.dom.Element to remove all listeners.");
+        //</debug>
+
+        Ext.get(element).clearListeners();
+    },
+
+    /**
+     * Removes an event handler from an element.  The shorthand version {@link #un} is equivalent.
+     * Typically you will use {@link Ext.dom.Element#removeListener} directly on an Element in favor
+     * of calling this version.
+     *
+     * {@link Ext.EventManager#on} is an alias for {@link Ext.EventManager#addListener}.
+     *
+     * @param {String/Ext.dom.Element/HTMLElement/Window} element The id or html element from which
+     * to remove the listener.
+     * @param {String} eventName The name of the event.
+     * @param {Function} fn The handler function to remove. **This must be a reference to the
+     * function passed into the {@link #addListener} call.**
+     * @param {Object} [scope] If a scope (`this` reference) was specified when the listener
+     * was added, then this must refer to the same object.
+     * @param {Object} [options]
+     */
+    removeListener: function(element, eventName, fn, scope, options) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager is deprecated. " +
+                     "Use Ext.dom.Element#removeListener to remove an event listener.");
+        //</debug>
+
+        Ext.get(element).removeListener(eventName, fn, scope, options);
+    },
+
+    /**
+     * Removes the passed window resize listener.
+     * @param {Function} fn        The method the event invokes
+     * @param {Object}   [scope]  The scope of handler
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    removeResizeListener: function(fn, scope) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager is deprecated. " +
+                     "Use Ext.on('resize', fn) to detach a window resize listener.");
+        //</debug>
+
+        Ext.GlobalEvents.un('resize', fn, scope);
+    },
+
+    /**
+     * Removes the passed window unload listener.
+     * @param {Function} fn        The method the event invokes
+     * @param {Object}   [scope]  The scope of handler
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    removeUnloadListener: function(fn, scope) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager is deprecated. " +
+                     "Use Ext.getWin().un('unload', fn) to detach a window unload listener.");
+        //</debug>
+
+        Ext.getWin().un('unload', fn, scope);
+    },
+
+    /**
+     * Stop the event (preventDefault and stopPropagation)
+     * @param {Event} event The event to stop
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    stopEvent: function(event) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager.stopEvent() is deprecated. " +
+                     "Call stopEvent() directly on the Ext.event.Event instance instead.");
+        //</debug>
+
+        this.stopPropagation(event);
+        this.preventDefault(event);
+    },
+
+    /**
+     * Cancels bubbling of the event.
+     * @param {Event} event The event to stop bubbling.
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    stopPropagation: function(event) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager.stopPropagation() is deprecated. " +
+                     "Call stopPropagation() directly on the Ext.event.Event instance instead.");
+        //</debug>
+
+        event = event.browserEvent || event;
+
+        if (event.stopPropagation) {
+            event.stopPropagation();
+        }
+        else {
+            event.cancelBubble = true;
+        }
+    },
+
+    /**
+     * Prevents the browsers default handling of the event.
+     * @param {Event} event The event to prevent the default
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    preventDefault: function(event) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager.preventDefault() is deprecated. " +
+                     "Call preventDefault() directly on the Ext.event.Event instance instead.");
+        //</debug>
+
+        event = event.browserEvent || event;
+
+        if (event.preventDefault) {
+            event.preventDefault();
+        }
+        else {
+            event.returnValue = false;
+
+            // Some keys events require setting the keyCode to -1 to be prevented
+            try {
+                // all ctrl + X and F1 -> F12
+                if (event.ctrlKey || event.keyCode > 111 && event.keyCode < 124) {
+                    event.keyCode = -1;
+                }
+            }
+            catch (e) {
+                // see this outdated document http://support.microsoft.com/kb/934364/en-us
+                // for more info
+            }
+        }
+    },
+
+    /**
+     * Get the id of the element. If one has not been assigned, automatically assign it.
+     * @param {HTMLElement/Ext.dom.Element} element The element to get the id for.
+     * @return {String} id
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    getId: function(element) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager.getId() is deprecated. " +
+                     "Call Ext.get() to assign ids to elements.");
+        //</debug>
+
+        element = Ext.get(element);
+
+        return element.id;
+    },
+
+    /**
+     * Gets the related target from the event.
+     * @param {Object} event The event
+     * @return {HTMLElement} The related target.
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    getRelatedTarget: function(event) {
+        var target;
+
+        //<debug>
+        Ext.log.warn("Ext.EventManager.getRelatedTarget() is deprecated. " +
+                     "Call getRelatedTarget() directly on the Ext.event.Event instance instead.");
+        //</debug>
+
+        event = event.browserEvent || event;
+        target = event.relatedTarget;
+
+        if (!target) {
+            if (this.mouseLeaveRe.test(event.type)) {
+                target = event.toElement;
+            }
+            else if (this.mouseEnterRe.test(event.type)) {
+                target = event.fromElement;
+            }
+        }
+
+        return this.resolveTextNode(target);
+    },
+
+    /**
+     * Gets the x coordinate from the event
+     * @param {Object} event The event
+     * @return {Number} The x coordinate
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    getPageX: function(event) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager.getPageX() is deprecated. " +
+                     "Call getX() directly on the Ext.event.Event instance instead.");
+        //</debug>
+
+        return this.getPageXY(event)[0];
+    },
+
+    /**
+     * Gets the x & y coordinate from the event
+     * @param {Object} event The event
+     * @return {Number[]} The x/y coordinate
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    getPageXY: function(event) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager.getPageXY() is deprecated. " +
+                     "Call getXY() directly on the Ext.event.Event instance instead.");
+        //</debug>
+
+        event = event.browserEvent || event;
+
+        // eslint-disable-next-line vars-on-top
+        var x = event.pageX,
+            y = event.pageY,
+            docEl = document.documentElement,
+            body = document.body;
+
+        // pageX/pageY not available (undefined, not null), use clientX/clientY instead
+        if (!x && x !== 0) {
+            x = event.clientX + (docEl && docEl.scrollLeft || body && body.scrollLeft || 0) -
+                (docEl && docEl.clientLeft || body && body.clientLeft || 0);
+            y = event.clientY + (docEl && docEl.scrollTop || body && body.scrollTop || 0) -
+                (docEl && docEl.clientTop || body && body.clientTop || 0);
+        }
+
+        return [x, y];
+    },
+
+    /**
+     * Gets the y coordinate from the event
+     * @param {Object} event The event
+     * @return {Number} The y coordinate
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    getPageY: function(event) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager.getPageY() is deprecated. " +
+                     "Call getY() directly on the Ext.event.Event instance instead.");
+        //</debug>
+
+        return this.getPageXY(event)[1];
+    },
+
+    /**
+     * Gets the target of the event.
+     * @param {Object} event The event
+     * @return {HTMLElement} target
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    getTarget: function(event) {
+        //<debug>
+        Ext.log.warn("Ext.EventManager.getTarget() is deprecated. " +
+                     "Call getTarget() directly on the Ext.event.Event instance instead.");
+        //</debug>
+
+        event = event.browserEvent || event;
+
+        return Ext.EventManager.resolveTextNode(event.target || event.srcElement);
+    },
+
+    // technically no need to browser sniff this, however it makes
+    // no sense to check this every time, for every event, whether
+    // the string is equal.
+    /**
+     * @method
+     * Resolve any text nodes accounting for browser differences.
+     * @private
+     * @param {HTMLElement} node The node
+     * @return {HTMLElement} The resolved node
+     * @deprecated 5.0.0 This method is deprecated.
+     */
+    resolveTextNode: Ext.isGecko
+        ? function(node) {
+            var s;
+
+            if (node) {
+                // work around firefox bug, https://bugzilla.mozilla.org/show_bug.cgi?id=101197
+                s = HTMLElement.prototype.toString.call(node);
+
+                if (s !== '[xpconnect wrapped native prototype]' && s !== '[object XULElement]') {
+                    return node.nodeType === 3 ? node.parentNode : node;
+                }
+            }
+        }
+        : function(node) {
+            return node && node.nodeType === 3 ? node.parentNode : node;
+        }
+}, function(EventManager) {
+    /**
+     * @method on
+     * @member Ext.EventManager
+     * @inheritdoc Ext.EventManager#method-addListener
+     */
+    EventManager.on = EventManager.addListener;
+
+    /**
+     * @method un
+     * @member Ext.EventManager
+     * @inheritdoc Ext.EventManager#method-removeListener
+     */
+    EventManager.un = EventManager.removeListener;
+});

+ 10 - 0
assets/ext-7.4.0.42/classic/classic/src/Gadget.js

@@ -0,0 +1,10 @@
+/**
+ * @class Ext.Gadget
+ * @extend Ext.Widget
+ *
+ * `Ext.Gadget` is not actually a class but simply an alternate class name for `Ext.Widget`. It
+ * is used primarily for writing cross-toolkit widgets.
+ *
+ * In the modern toolkit, `Ext.Gadget` is an alternate class name for Ext.Component in order
+ * to allow gadgets to be used as `items` in an Ext.Container.
+ */

+ 342 - 0
assets/ext-7.4.0.42/classic/classic/src/Img.js

@@ -0,0 +1,342 @@
+/**
+ * Simple helper class for easily creating image components. This renders an image tag to
+ * the DOM with the configured src.
+ *
+ * {@img Ext.Img/Ext.Img.png Ext.Img component}
+ *
+ * ## Example usage:
+ *
+ *     var changingImage = Ext.create('Ext.Img', {
+ *         src: 'http://www.sencha.com/img/20110215-feat-html5.png',
+ *         width: 184,
+ *         height: 90,
+ *         renderTo: Ext.getBody()
+ *     });
+ *
+ *     // change the src of the image programmatically
+ *     changingImage.setSrc('http://www.sencha.com/img/20110215-feat-perf.png');
+ *
+ * By default, only an img element is rendered and that is this component's primary
+ * {@link Ext.Component#getEl element}. If the {@link Ext.Component#autoEl} property
+ * is other than 'img' (the default), the a child img element will be added to the primary
+ * element. This can be used to create a wrapper element around the img.
+ *
+ * ## Wrapping the img in a div:
+ *
+ *     var wrappedImage = Ext.create('Ext.Img', {
+ *         src: 'http://www.sencha.com/img/20110215-feat-html5.png',
+ *         autoEl: 'div', // wrap in a div
+ *         renderTo: Ext.getBody()
+ *     });
+ *
+ * ## Using a glyph
+ *
+ *     var glyphImage = Ext.create('Ext.Img', {
+ *         glyph: 'xf015@FontAwesome',     // the "home" icon
+ *         renderTo: Ext.getBody()
+ *     });
+ *
+ * ## Image Dimensions
+ *
+ * You should include height and width dimensions for any image owned by a parent 
+ * container.  By omitting dimensions, an owning container will not know how to 
+ * size and position the image in the initial layout.
+ */
+Ext.define('Ext.Img', {
+    extend: 'Ext.Component',
+    alias: ['widget.image', 'widget.imagecomponent'],
+    requires: [
+        'Ext.Glyph'
+    ],
+
+    /**
+     * @cfg autoEl
+     * @inheritdoc
+     */
+    autoEl: 'img',
+
+    /**
+     * @cfg baseCls
+     * @inheritdoc
+     */
+    baseCls: Ext.baseCSSPrefix + 'img',
+
+    config: {
+        /**
+         * @cfg {String} src
+         * The source of this image. See {@link Ext#resolveResource} for details on
+         * locating application resources.
+         * @accessor
+         */
+        src: null,
+
+        /**
+         * @cfg glyphorig
+         * @inheritdoc Ext.panel.Header#cfg-glyph
+         */
+        /**
+         * @cfg {Number/String} glyph
+         * A numeric unicode character code to serve as the image.  If this option is used
+         * The image will be rendered using a div with innerHTML set to the html entity
+         * for the given character code.  The default font-family for glyphs can be set
+         * globally using {@link Ext#setGlyphFontFamily Ext.setGlyphFontFamily()}. Alternatively,
+         * this config option accepts a string with the charCode and font-family separated by
+         * the `@` symbol. For example '65@My Font Family'.
+         */
+        glyph: null
+    },
+
+    /**
+     * @cfg {String} alt
+     * The descriptive text for non-visual UI description.
+     */
+    alt: '',
+
+    /**
+     * @cfg {String} title
+     * Specifies additional information about the image.
+     */
+    title: '',
+
+    /**
+     * @cfg {String} imgCls
+     * Optional CSS classes to add to the img element.
+     */
+    imgCls: '',
+
+    /**
+     * @property maskOnDisable
+     * @inheritdoc
+     */
+    maskOnDisable: false,
+
+    applySrc: function(src) {
+        return src && Ext.resolveResource(src);
+    },
+
+    getElConfig: function() {
+        var me = this,
+            autoEl = me.autoEl,
+            config = me.callParent(),
+            glyph = me.glyph,
+            img;
+
+        // We were configured with a glyph, then this is a div with a single char content
+        if (glyph) {
+            config.tag = 'div';
+            config.html = glyph.character;
+            config.style = config.style || {};
+            config.style.fontFamily = glyph.fontFamily;
+
+            // A glyph is a graphic which is not an <img> tag so it should have
+            // the corresponding role for Accessibility interface to recognize
+            config.role = 'img';
+        }
+        // The default; an img element
+        else if (autoEl === 'img' || (Ext.isObject(autoEl) && autoEl.tag === 'img')) {
+            img = config;
+        }
+        // It is sometimes helpful (like in a panel header icon) to have the img wrapped
+        // by a div. If our autoEl is not 'img' then we just add an img child to the el.
+        else {
+            config.cn = [img = {
+                tag: 'img',
+                id: me.id + '-img'
+            }];
+        }
+
+        if (img) {
+            if (me.imgCls) {
+                img.cls = (img.cls ? img.cls + ' ' : '') + me.imgCls;
+            }
+
+            img.src = me.src || Ext.BLANK_IMAGE_URL;
+        }
+
+        if (me.alt) {
+            (img || config).alt = me.alt;
+        }
+        else {
+            // Images that do not have alt attribute can't be properly announced
+            // by screen readers. In best case they will be silently skipped;
+            // in worst case screen reader will announce data url. Yes, that very long
+            // base-64 encoded string. :/
+            // That will make the application totally unusable for blind people.
+            (img || config).alt = '';
+
+            //<debug>
+            Ext.log.warn('For WAI-ARIA compliance, IMG elements SHOULD have an alt attribute.');
+            //</debug>
+        }
+
+        if (me.title) {
+            (img || config).title = me.title;
+        }
+
+        return config;
+    },
+
+    onRender: function() {
+        var me = this,
+            autoEl = me.autoEl,
+            el;
+
+        me.callParent(arguments);
+
+        el = me.el;
+
+        if (autoEl === 'img' || (Ext.isObject(autoEl) && autoEl.tag === 'img')) {
+            me.imgEl = el;
+        }
+        else {
+            me.imgEl = el.getById(me.id + '-img');
+        }
+    },
+
+    doDestroy: function() {
+        var me = this,
+            imgEl = me.imgEl;
+
+        // Only clean up when the img is a child, otherwise it will get handled
+        // by the element destruction in the parent
+        if (imgEl && me.el !== imgEl) {
+            imgEl.destroy();
+        }
+
+        me.imgEl = null;
+
+        me.callParent();
+    },
+
+    getTitle: function() {
+        return this.title;
+    },
+
+    /**
+     * Updates the {@link #title} of the image.
+     * @param {String} title
+     */
+    setTitle: function(title) {
+        var me = this,
+            imgEl = me.imgEl;
+
+        me.title = title || '';
+
+        if (imgEl) {
+            imgEl.dom.title = title || '';
+        }
+    },
+
+    afterComponentLayout: function(width, height, oldWidth, oldHeight) {
+        var heightModel = this.getSizeModel().height,
+            h;
+
+        // If we have our height set, then size the glyph as requested to make image scalable.
+        if ((heightModel.calculated || heightModel.configured) && height && this.glyph) {
+            h = height + 'px';
+            this.setStyle({
+                'line-height': h,
+                'font-size': h
+            });
+        }
+
+        this.callParent([width, height, oldWidth, oldHeight]);
+    },
+
+    getAlt: function() {
+        return this.alt;
+    },
+
+    /**
+     * Updates the {@link #alt} of the image.
+     * @param {String} alt
+     */
+    setAlt: function(alt) {
+        var me = this,
+            imgEl = me.imgEl;
+
+        me.alt = alt || '';
+
+        if (imgEl) {
+            imgEl.dom.alt = alt || '';
+        }
+    },
+
+    _naturalSize: null,
+
+    /**
+     * Returns the size of the image as an object.
+     * @return {Object} The size and aspect ratio of the image.
+     * @return {Number} return.aspect The aspect ration of the image (`width / height`).
+     * @return {Number} return.height The height of the image.
+     * @return {Number} return.width The width of the image.
+     * @since 6.2.0
+     */
+    getNaturalSize: function() {
+        var me = this,
+            img = me.imgEl,
+            naturalSize = me._naturalSize,
+            style, w, h;
+
+        if (img && !naturalSize) {
+            img = img.dom;
+
+            me._naturalSize = naturalSize = {
+                width: w = img.naturalWidth,
+                height: img.naturalHeight
+            };
+
+            if (!w) {
+                style = img.style;
+
+                w = style.width;
+                h = style.height;
+
+                // As long as the width/height styles are "auto", the IMG dom element
+                // will have "width" and "height" properties that are the natural size.
+                style.width = style.height = 'auto';
+
+                naturalSize.width = img.width;
+                naturalSize.height = img.height;
+
+                style.width = w;
+                style.height = h;
+            }
+
+            naturalSize.aspect = naturalSize.width / naturalSize.height;
+        }
+
+        return naturalSize;
+    },
+
+    updateSrc: function(src) {
+        var imgEl = this.imgEl;
+
+        if (imgEl) {
+            imgEl.dom.src = src || Ext.BLANK_IMAGE_URL;
+        }
+    },
+
+    applyGlyph: function(glyph, oldGlyph) {
+        if (glyph) {
+            if (!glyph.isGlyph) {
+                glyph = new Ext.Glyph(glyph);
+            }
+
+            if (glyph.isEqual(oldGlyph)) {
+                glyph = undefined;
+            }
+        }
+
+        return glyph;
+    },
+
+    updateGlyph: function(glyph, oldGlyph) {
+        var el = this.el;
+
+        if (el) {
+            el.dom.innerHTML = glyph.character;
+            el.setStyle(glyph.getStyle());
+        }
+    }
+});

+ 654 - 0
assets/ext-7.4.0.42/classic/classic/src/LoadMask.js

@@ -0,0 +1,654 @@
+/**
+ * A modal, floating Component which may be shown above a specified {@link Ext.Component Component}
+ * while loading data. When shown, the configured owning Component will be covered with a modality
+ * mask, and the LoadMask's {@link #msg} will be displayed centered, accompanied by a spinner image.
+ *
+ * If the {@link #store} config option is specified, the masking will be automatically shown
+ * and then hidden synchronized with the Store's loading process.
+ *
+ * Because this is a floating Component, its z-index will be managed by the global
+ * {@link Ext.WindowManager ZIndexManager} object, and upon show, it will place itsef at the top
+ * of the hierarchy.
+ *
+ * Example usage:
+ *
+ *     @example
+ *     var myPanel = new Ext.panel.Panel({
+ *         renderTo : document.body,
+ *         height   : 100,
+ *         width    : 200,
+ *         title    : 'Foo'
+ *     });
+ *
+ *     var myMask = new Ext.LoadMask({
+ *         msg    : 'Please wait...',
+ *         target : myPanel
+ *     });
+ *
+ *     myMask.show();
+ */
+Ext.define('Ext.LoadMask', {
+    extend: 'Ext.Component',
+    alias: 'widget.loadmask',
+
+    mixins: [
+        'Ext.util.StoreHolder'
+    ],
+
+    uses: ['Ext.data.StoreManager'],
+
+    /**
+     * @property {Boolean} isLoadMask
+     * `true` in this class to identify an object as an instantiated LoadMask, or subclass thereof.
+     */
+    isLoadMask: true,
+
+    /**
+     * @cfg {Ext.Component} target The Component you wish to mask. The the mask will be
+     * automatically sized upon Component resize, and the message box will be kept centered.
+     */
+
+    /**
+     * @cfg {Ext.data.Store} store
+     * Optional Store to which the mask is bound. The mask is displayed when a load request
+     * is issued, and hidden on either load success, or load fail.
+     */
+
+    /**
+     * @cfg {String} [msg="Loading..."]
+     * The text to display in a centered loading message box.
+     * @locale
+     */
+    msg: 'Loading...',
+
+    msgCls: Ext.baseCSSPrefix + 'mask-loading',
+
+    msgWrapCls: Ext.baseCSSPrefix + 'mask-msg',
+
+    /**
+     * @cfg {Boolean} [useMsg=true]
+     * Whether or not to use a loading message class or simply mask the bound element.
+     */
+    useMsg: true,
+
+    /**
+     * @cfg {Boolean} [useTargetEl=false]
+     * True to mask the {@link Ext.Component#getTargetEl targetEl} of the bound Component.
+     * By default, the {@link Ext.Component#getEl el} will be masked.
+     */
+    useTargetEl: false,
+
+    /**
+     * @cfg {Boolean} shim `true` to enable an iframe shim for this LoadMask to keep
+     * windowed objects from showing through.
+     */
+
+    /**
+     * @private
+     */
+    cls: Ext.baseCSSPrefix + 'mask',
+    componentCls: Ext.baseCSSPrefix + 'border-box',
+
+    ariaRole: 'progressbar',
+    focusable: true,
+    tabIndex: 0,
+
+    childEls: [
+        'msgWrapEl',
+        'msgEl',
+        'msgTextEl'
+    ],
+
+    /* eslint-disable indent, max-len */
+    renderTpl: [
+        '<div id="{id}-msgWrapEl" data-ref="msgWrapEl" class="{[values.$comp.msgWrapCls]}" role="presentation">',
+            '<div id="{id}-msgEl" data-ref="msgEl" class="{[values.$comp.msgCls]} ',
+                Ext.baseCSSPrefix, 'mask-msg-inner {childElCls}" role="presentation">',
+                '<div id="{id}-msgTextEl" data-ref="msgTextEl" class="',
+                    Ext.baseCSSPrefix, 'mask-msg-text',
+                    '{childElCls}" role="presentation">{msg}</div>',
+            '</div>',
+        '</div>'
+    ],
+    /* eslint-enable indent, max-len */
+
+    maskOnDisable: false,
+
+    /**
+     * @private
+     */
+    skipLayout: true,
+
+    /**
+     * Creates new LoadMask.
+     * @param {Object} [config] The config object.
+     */
+    constructor: function(config) {
+        var me = this,
+            comp;
+
+        if (arguments.length === 2) {
+            //<debug>
+            if (Ext.isDefined(Ext.global.console)) {
+                Ext.global.console.warn(
+                    'Ext.LoadMask: LoadMask now uses a standard 1 arg constructor: ' +
+                    'use the target config'
+                );
+            }
+            //</debug>
+
+            comp = me.target = config;
+            config = arguments[1];
+        }
+        else {
+            comp = config.target;
+        }
+
+        //<debug>
+        if (config.maskCls) {
+            Ext.log.warn('Ext.LoadMask property maskCls is deprecated, use msgWrapCls instead');
+            config.msgWrapCls = config.msgWrapCls || config.maskCls;
+        }
+        //</debug>
+
+        // Must apply configs early so that renderTo can be calculated correctly.
+        me.callParent([config]);
+
+        // Target is a Component
+        if (comp.isComponent) {
+            me.ownerCt = comp;
+            me.hidden = true;
+
+            // Ask the component which element should be masked.
+            // Most will not have an answer, in which case this returns the document body
+            // Ext.view.Table for example returns the el of its owning Panel.
+            me.renderTo = me.getMaskTarget();
+            me.external = me.renderTo === Ext.getBody();
+            me.bindComponent(comp);
+        }
+        // Element support to be deprecated
+        else {
+            //<debug>
+            if (Ext.isDefined(Ext.global.console)) {
+                Ext.global.console.warn(
+                    'Ext.LoadMask: LoadMask for elements has been deprecated, ' +
+                    'use Ext.dom.Element.mask & Ext.dom.Element.unmask');
+            }
+            //</debug>
+
+            comp = Ext.get(comp);
+            me.isElement = true;
+            me.renderTo = me.target;
+        }
+
+        me.render(me.renderTo);
+
+        if (me.store) {
+            me.bindStore(me.store, true);
+        }
+    },
+
+    initRenderData: function() {
+        var result = this.callParent(arguments);
+
+        result.msg = this.msg || '';
+
+        return result;
+    },
+
+    onRender: function() {
+        this.callParent(arguments);
+
+        // In versions prior to 5.1, maskEl was rendered outside of the
+        // LoadMask's main el and had a reference to it; we keep this
+        // reference for backwards compatibility.
+        this.maskEl = this.el;
+    },
+
+    bindComponent: function(comp) {
+        var me = this,
+            listeners = {
+                scope: this,
+                resize: me.sizeMask
+            };
+
+        if (me.external) {
+            listeners.added = me.onComponentAdded;
+            listeners.removed = me.onComponentRemoved;
+
+            if (comp.floating) {
+                listeners.move = me.sizeMask;
+                me.activeOwner = comp;
+            }
+            else if (comp.ownerCt) {
+                me.onComponentAdded(comp.ownerCt);
+            }
+        }
+
+        me.mon(comp, listeners);
+
+        // Subscribe to the observer that manages the hierarchy
+        // Only needed if we had to be rendered outside of the target
+        if (me.external) {
+            me.mon(Ext.GlobalEvents, {
+                show: me.onContainerShow,
+                hide: me.onContainerHide,
+                expand: me.onContainerExpand,
+                collapse: me.onContainerCollapse,
+                scope: me
+            });
+        }
+    },
+
+    onComponentAdded: function(owner) {
+        var me = this;
+
+        delete me.activeOwner;
+        me.floatParent = owner;
+
+        if (!owner.floating) {
+            owner = owner.up('[floating]');
+        }
+
+        if (owner) {
+            me.activeOwner = owner;
+            me.mon(owner, 'move', me.sizeMask, me);
+            me.mon(owner, 'tofront', me.onOwnerToFront, me);
+        }
+        else {
+            me.preventBringToFront = true;
+        }
+
+        owner = me.floatParent.ownerCt;
+
+        if (me.rendered && me.isVisible() && owner) {
+            me.floatOwner = owner;
+            me.mon(owner, 'afterlayout', me.sizeMask, me, { single: true });
+        }
+    },
+
+    onComponentRemoved: function(owner) {
+        var me = this,
+            activeOwner = me.activeOwner,
+            floatOwner = me.floatOwner;
+
+        if (activeOwner) {
+            me.mun(activeOwner, 'move', me.sizeMask, me);
+            me.mun(activeOwner, 'tofront', me.onOwnerToFront, me);
+        }
+
+        if (floatOwner) {
+            me.mun(floatOwner, 'afterlayout', me.sizeMask, me);
+        }
+
+        delete me.activeOwner;
+        delete me.floatOwner;
+    },
+
+    afterRender: function() {
+        var me = this;
+
+        me.callParent(arguments);
+
+        // In IE8-11, clicking on an inner msgEl will focus it, despite
+        // it having no tabindex attribute and thus being canonically
+        // non-focusable. Placing unselectable="on" attribute will make
+        // it unfocusable but will also prevent clicks from focusing
+        // the parent element. We want clicks within the mask's main el
+        // to focus it, hence the workaround.
+        if (Ext.isIE) {
+            me.el.on('mousedown', me.onMouseDown, me);
+        }
+
+        // This LoadMask shares the DOM and may be tipped out by the use of innerHTML
+        // Ensure the element does not get garbage collected from under us.
+        this.el.skipGarbageCollection = true;
+    },
+
+    onMouseDown: function(e) {
+        var el = this.el;
+
+        if (e.within(el)) {
+            e.preventDefault();
+            el.focus();
+        }
+    },
+
+    onOwnerToFront: function(owner, zIndex) {
+        this.el.setStyle('zIndex', zIndex + 1);
+    },
+
+    // Only called if we are rendered external to the target.
+    // Best we can do is show.
+    onContainerShow: function(container) {
+        if (!this.isHierarchicallyHidden()) {
+            this.onComponentShow();
+        }
+    },
+
+    // Only called if we are rendered external to the target.
+    // Best we can do is hide.
+    onContainerHide: function(container) {
+        if (this.isHierarchicallyHidden()) {
+            this.onComponentHide();
+        }
+    },
+
+    // Only called if we are rendered external to the target.
+    // Best we can do is show.
+    onContainerExpand: function(container) {
+        if (!this.isHierarchicallyHidden()) {
+            this.onComponentShow();
+        }
+    },
+
+    // Only called if we are rendered external to the target.
+    // Best we can do is hide.
+    onContainerCollapse: function(container) {
+        if (this.isHierarchicallyHidden()) {
+            this.onComponentHide();
+        }
+    },
+
+    onComponentHide: function() {
+        var me = this;
+
+        if (me.rendered && me.isVisible()) {
+            me.hide();
+            me.showNext = true;
+        }
+    },
+
+    onComponentShow: function() {
+        if (this.showNext) {
+            this.show();
+        }
+
+        delete this.showNext;
+    },
+
+    /**
+     * @private
+     * Called when this LoadMask's Component is resized. The toFront method rebases and resizes
+     * the modal mask.
+     */
+    sizeMask: function() {
+        var me = this,
+            // Need to use the closest floating component (if it exists) as the basis
+            // for our z-index positioning
+            target = me.activeOwner || me.target,
+            boxTarget = me.external ? me.getOwner().el : me.getMaskTarget(),
+            zIndex;
+
+        if (me.rendered && me.isVisible()) {
+            // Only need to move and size the message wrap if we are outside of
+            // the masked element.
+            // If we are inside, it will be left:0;top:0;width:100%;height:100% by default
+            if (me.external) {
+                if (!me.isElement && target.floating) {
+                    zIndex = target.el.getZIndex();
+
+                    if (!isNaN(zIndex)) {
+                        me.onOwnerToFront(target, zIndex);
+                    }
+                }
+
+                me.el.setSize(boxTarget.getSize()).alignTo(boxTarget, 'tl-tl');
+            }
+
+            // Always need to center the message wrap
+            me.msgWrapEl.center(me.el);
+        }
+    },
+
+    /**
+     * Changes the data store bound to this LoadMask.
+     * @param {Ext.data.Store} store The store to bind to this LoadMask
+     * @param [initial]
+     */
+    bindStore: function(store, initial) {
+        var me = this;
+
+        // If the server returns a failure, and the proxy fires an exception instead of
+        // loading the store, the mask must clear.
+        Ext.destroy(me.proxyListeners);
+
+        me.mixins.storeholder.bindStore.apply(me, arguments);
+        store = me.store;
+
+        if (store) {
+            // Skip ChainedStores to the store that does the loading
+            while (store.getSource) {
+                store = store.getSource();
+            }
+
+            if (!store.loadsSynchronously()) {
+                me.proxyListeners = store.getProxy().on({
+                    exception: me.onLoad,
+                    scope: me,
+                    destroyable: true
+                });
+            }
+
+            if (store.isLoading()) {
+                me.onBeforeLoad();
+            }
+        }
+    },
+
+    getStoreListeners: function(store) {
+        var onLoad = this.onLoad,
+            beforeLoad = this.onBeforeLoad,
+            result = {
+                // Fired when a range is requested for rendering that is not in the cache
+                cachemiss: beforeLoad,
+
+                // Fired when a range for rendering which was previously missing from the cache
+                // is loaded. buffer so that scrolling and store filling has settled,
+                // and the results have been rendered.
+                cachefilled: {
+                    fn: onLoad,
+                    buffer: 100
+                }
+            };
+
+        // Only need to mask on load if the proxy is asynchronous - ie: Ajax/JsonP
+        if (!store.loadsSynchronously()) {
+            result.beforeload = beforeLoad;
+            result.load = onLoad;
+        }
+
+        return result;
+    },
+
+    onDisable: function() {
+        this.callParent(arguments);
+
+        if (this.loading) {
+            this.onLoad();
+        }
+    },
+
+    getOwner: function() {
+        return this.ownerCt || this.ownerCmp || this.floatParent;
+    },
+
+    getMaskTarget: function() {
+        var owner = this.getOwner();
+
+        if (this.isElement) {
+            return this.target;
+        }
+
+        return this.useTargetEl ? owner.getTargetEl() : (owner.getMaskTarget() || Ext.getBody());
+    },
+
+    /**
+     * @private
+     */
+    onBeforeLoad: function() {
+        var me = this,
+            owner = me.getOwner(),
+            origin;
+
+        if (!me.disabled) {
+            me.loading = true;
+
+            // If the owning Component has not been laid out, defer so that the ZIndexManager
+            // gets to read its laid out size when sizing the modal mask
+            if (owner.componentLayoutCounter) {
+                me.maybeShow();
+            }
+            else {
+                // The code below is a 'run-once' interceptor.
+                origin = owner.afterComponentLayout;
+
+                owner.afterComponentLayout = function() {
+                    owner.afterComponentLayout = origin;
+                    origin.apply(owner, arguments);
+                    me.maybeShow();
+                };
+            }
+        }
+    },
+
+    maybeShow: function() {
+        var me = this,
+            owner = me.getOwner(),
+            ownerVisible;
+
+        // Owner could be detached
+        ownerVisible = owner.isVisible(true) && (!me.isComponent || owner.el.isVisible(true));
+
+        if (!ownerVisible) {
+            me.showNext = true;
+        }
+        else if (me.loading && owner.rendered) {
+            me.show();
+        }
+    },
+
+    hide: function() {
+        var me = this,
+            ownerCt = me.ownerCt;
+
+        me.target.removeCls(Ext.baseCSSPrefix + "masked");
+
+        // Element support to be deprecated
+        if (me.isElement) {
+            ownerCt.unmask();
+            me.fireEvent('hide', this);
+
+            return;
+        }
+
+        // Could be already nulled while destroying
+        if (ownerCt) {
+            ownerCt.updateMaskState(false, me);
+        }
+
+        delete me.showNext;
+
+        return me.callParent(arguments);
+    },
+
+    show: function() {
+        var me = this;
+
+        me.target.addCls(Ext.baseCSSPrefix + "masked");
+
+        // Element support to be deprecated
+        if (me.isElement) {
+            me.ownerCt.mask(this.useMsg ? this.msg : '', this.msgCls);
+            me.fireEvent('show', this);
+
+            return;
+        }
+
+        return me.callParent(arguments);
+    },
+
+    afterShow: function() {
+        var me = this,
+            ownerCt = me.ownerCt;
+
+        me.loading = true;
+        me.callParent(arguments);
+
+        ownerCt.updateMaskState(true, me);
+
+        // Owner's disabled tabbing will also make the mask
+        // untabbable since it is rendered within the target
+        me.el.restoreTabbableState();
+
+        me.syncMaskState();
+    },
+
+    /**
+     * Synchronizes the visible state of the mask with the configuration settings such
+     * as {@link #msgWrapCls}, {@link #msg}, sizes the mask to occlude the target element
+     * or Component and focuses the mask.
+     * @private
+     */
+    syncMaskState: function() {
+        var me = this,
+            ownerCt = me.ownerCt,
+            el = me.el;
+
+        if (me.isVisible()) {
+            // Allow dynamic setting of msgWrapCls
+            if (me.hasOwnProperty('msgWrapCls')) {
+                el.dom.className = me.msgWrapCls;
+            }
+
+            if (me.useMsg) {
+                me.msgTextEl.setHtml(me.msg);
+                me.ariaEl.dom.setAttribute('aria-valuetext', me.msg);
+            }
+            else {
+                // Only the mask is visible if useMsg is false
+                me.msgWrapEl.hide();
+            }
+
+            if (me.shim || Ext.useShims) {
+                el.enableShim(null, true);
+            }
+            else {
+                // Just in case me.shim was changed since last time we were shown (by
+                // Component#setLoading())
+                el.disableShim();
+            }
+
+            // If owner contains focus, focus this.
+            // Component level onHide processing takes care of focus reversion on hide.
+            if (ownerCt.el.contains(Ext.Element.getActiveElement())) {
+                me.focus();
+            }
+
+            me.sizeMask();
+        }
+    },
+
+    /**
+     * @private
+     */
+    onLoad: function() {
+        this.loading = false;
+        this.hide();
+    },
+
+    doDestroy: function() {
+        var me = this;
+
+        // We don't have a real ownerCt, so clear it out here to prevent
+        // spurious warnings when we are destroyed
+        me.ownerCt = null;
+        me.bindStore(null);
+
+        if (me.isElement) {
+            me.ownerCt.unmask();
+        }
+
+        me.callParent();
+    }
+});

+ 450 - 0
assets/ext-7.4.0.42/classic/classic/src/ProgressBar.js

@@ -0,0 +1,450 @@
+/**
+ * An updateable progress bar component. The progress bar supports two different modes: manual
+ * and automatic.
+ *
+ * In manual mode, you are responsible for showing, updating (via {@link #updateProgress})
+ * and clearing the progress bar as needed from your own code. This method is most appropriate
+ * when you want to show progress throughout an operation that has predictable points of interest
+ * at which you can update the control.
+ *
+ * In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely,
+ * only clearing it once the operation is complete. You can optionally have the progress bar
+ * wait for a specific amount of time and then clear itself. Automatic mode is most appropriate
+ * for timed operations or asynchronous operations in which you have no need for indicating
+ * intermediate progress.
+ *
+ *     @example
+ *     var p = Ext.create('Ext.ProgressBar', {
+ *        renderTo: Ext.getBody(),
+ *        width: 300
+ *     });
+ *
+ *     // Wait for 5 seconds, then update the status el (progress bar will auto-reset)
+ *     p.wait({
+ *         interval: 500, //bar will move fast!
+ *         duration: 50000,
+ *         increment: 15,
+ *         text: 'Updating...',
+ *         scope: this,
+ *         fn: function(){
+ *             p.updateText('Done!');
+ *         }
+ *     });
+ */
+Ext.define('Ext.ProgressBar', {
+    extend: 'Ext.Component',
+    xtype: 'progressbar',
+
+    mixins: [
+        'Ext.ProgressBase'
+    ],
+
+    requires: [
+        'Ext.Template',
+        'Ext.CompositeElement',
+        'Ext.TaskManager',
+        'Ext.layout.component.ProgressBar'
+    ],
+
+    uses: ['Ext.fx.Anim'],
+
+    /**
+     * @cfg {String/HTMLElement/Ext.dom.Element} textEl
+     * The element to render the progress text to (defaults to the progress bar's internal
+     * text element)
+     */
+
+    /**
+     * @cfg {String} id
+     * The progress bar element's id (defaults to an auto-generated id)
+     */
+
+    /**
+     * @cfg {String} [baseCls='x-progress']
+     * The base CSS class to apply to the progress bar's wrapper element.
+     */
+    baseCls: Ext.baseCSSPrefix + 'progress',
+
+    /**
+     * @cfg {Boolean/Object} animate
+     * True to animate the progress bar during transitions, or an animation configuration
+     * (see the {@link #method-animate} method for details).
+     */
+    animate: false,
+
+    /**
+     * @cfg {String} text
+     * The text shown in the progress bar.
+     */
+    text: '',
+
+    /**
+     * @private
+     */
+    waitTimer: null,
+
+    childEls: [
+        'bar'
+    ],
+
+    defaultBindProperty: 'value',
+
+    /* eslint-disable indent, max-len */
+    renderTpl: [
+        '<tpl if="internalText">',
+            '<div class="{baseCls}-text {baseCls}-text-back" role="presentation">{text}</div>',
+        '</tpl>',
+        '<div id="{id}-bar" data-ref="bar" class="{baseCls}-bar {baseCls}-bar-{ui}" role="presentation" style="width:{percentage}%">',
+            '<tpl if="internalText">',
+                '<div class="{baseCls}-text" role="presentation">',
+                    '<div role="presentation">{text}</div>',
+                '</div>',
+            '</tpl>',
+        '</div>'
+    ],
+    /* eslint-enable indent, max-len */
+
+    componentLayout: 'progressbar',
+
+    ariaRole: 'progressbar',
+    focusable: true,
+    tabIndex: 0,
+
+    autoEl: {
+        'aria-valuemin': '0',
+        'aria-valuenow': '0',
+        'aria-valuemax': '100'
+    },
+
+    /**
+     * @event update
+     * Fires after each update interval
+     * @param {Ext.ProgressBar} this
+     * @param {Number} value The current progress value
+     * @param {String} text The current progress text
+     */
+
+    initRenderData: function() {
+        var me = this,
+            value = me.value || 0,
+            data;
+
+        data = me.callParent();
+
+        return Ext.apply(data, {
+            internalText: !me.hasOwnProperty('textEl'),
+            text: me.text || Math.round(value * 100) + '%',
+            percentage: value * 100
+        });
+    },
+
+    onRender: function() {
+        var me = this;
+
+        me.callParent(arguments);
+
+        // External text display
+        if (me.textEl) {
+            me.textEl = Ext.get(me.textEl);
+            me.updateText(me.text);
+        }
+        // Inline text display
+        else {
+            // This produces a composite w/2 el's (which is why we cannot use childEls or
+            // renderSelectors):
+            me.textEl = me.el.select('.' + me.baseCls + '-text');
+        }
+    },
+
+    afterRender: function() {
+        var me = this;
+
+        me.callParent(arguments);
+
+        if (me.text) {
+            me.ariaEl.dom.setAttribute('aria-valuetext', me.text);
+        }
+    },
+
+    updateValue: function(value) {
+        this.updateProgress(value);
+    },
+
+    /**
+     * Updates the progress bar value, and optionally its text.
+     * 
+     * If the text argument is not specified, then the {@link #textTpl} will be used to generate
+     * the text. If there is no `textTpl`, any existing text value will be unchanged. To blank out
+     * existing text, pass `""`.
+     *
+     * Note that even if the progress bar value exceeds 1, it will never automatically reset --
+     * you are responsible for determining when the progress is complete and
+     * calling {@link #reset} to clear and/or hide the control.
+     * @param {Number} [value=0] A floating point value between 0 and 1 (e.g., .5)
+     * @param {String} [text=''] The string to display in the progress text element
+     * @param {Boolean} [animate=false] Whether to animate the transition of the progress bar.
+     * If this value is not specified, the default for the class is used
+     * @return {Ext.ProgressBar} this
+     */
+    updateProgress: function(value, text, animate) {
+        var me = this,
+            oldValue = me.value,
+            textTpl = me.getTextTpl();
+
+        value = value || 0;
+
+        // Ensure value is not undefined.
+        me.value = value || (value = 0);
+
+        // Empty string (falsy) must blank out the text as per docs.
+        if (text != null) {
+            me.autoText = false;
+            me.updateText(text);
+        }
+        // Generate text using template and progress values.
+        else if (textTpl) {
+            me.autoText = false;
+            me.updateText(textTpl.apply({
+                value: value,
+                percent: value * 100
+            }));
+        }
+        else if (!me.text && me.autoText !== false) {
+            me.autoText = true;
+            me.updateText(Math.round(value * 100) + '%');
+        }
+        // Text was set the previous time but not this time. We can't
+        // deduce what it should be just from the value so need to
+        // reset aria-valuetext because it is no longer valid.
+        else if (me.text && me.ariaEl.dom) {
+            me.ariaEl.dom.removeAttribute('aria-valuetext');
+        }
+
+        if (me.rendered && !me.destroyed) {
+            if (animate === true || (animate !== false && me.animate)) {
+                me.bar.stopAnimation();
+                me.bar.animate(Ext.apply({
+                    from: {
+                        width: (oldValue * 100) + '%'
+                    },
+                    to: {
+                        width: (value * 100) + '%'
+                    }
+                }, me.animate));
+            }
+            else {
+                me.bar.setStyle('width', (value * 100) + '%');
+            }
+
+            me.ariaEl.dom.setAttribute('aria-valuenow', Math.round(value * 100));
+        }
+
+        me.fireEvent('update', me, value, text);
+
+        return me;
+    },
+
+    /**
+     * Updates the progress bar text. If specified, textEl will be updated, otherwise
+     * the progress bar itself will display the updated text.
+     * @param {String} [text=''] The string to display in the progress text element
+     * @return {Ext.ProgressBar} this
+     */
+    updateText: function(text) {
+        var me = this;
+
+        if (!me.autoText) {
+            me.text = text;
+        }
+
+        if (me.rendered) {
+            me.textEl.setHtml(text);
+
+            if (!me.autoText) {
+                me.ariaEl.dom.setAttribute('aria-valuetext', text);
+            }
+            else {
+                me.ariaEl.dom.removeAttribute('aria-valuetext');
+            }
+        }
+
+        return me;
+    },
+
+    applyText: function(text) {
+        this.updateText(text);
+    },
+
+    getText: function() {
+        return this.text;
+    },
+
+    /**
+     * Initiates an auto-updating progress bar. A duration can be specified, in which case
+     * the progress bar will automatically reset after a fixed amount of time and optionally call
+     * a callback function if specified. If no duration is passed in, then the progress bar will run
+     * indefinitely and must be manually cleared by calling {@link #reset}.
+     *
+     * Example usage:
+     *
+     *     var p = new Ext.ProgressBar({
+     *        renderTo: 'my-el'
+     *     });
+     *
+     *     // Wait for 5 seconds, then update the status el (progress bar will auto-reset)
+     *     var p = Ext.create('Ext.ProgressBar', {
+     *        renderTo: Ext.getBody(),
+     *        width: 300
+     *     });
+     *
+     *     // Wait for 5 seconds, then update the status el (progress bar will auto-reset)
+     *     p.wait({
+     *        interval: 500, // bar will move fast!
+     *        duration: 50000,
+     *        increment: 15,
+     *        text: 'Updating...',
+     *        scope: this,
+     *        fn: function() {
+     *           p.updateText('Done!');
+     *        }
+     *     });
+     *
+     *     // Or update indefinitely until some async action completes, then reset manually
+     *     p.wait();
+     *     myAction.on('complete', function() {
+     *         p.reset();
+     *         p.updateText('Done!');
+     *     });
+     *
+     * @param {Object} config (optional) Configuration options
+     * @param {Number} config.duration The length of time in milliseconds that the progress bar
+     * should run before resetting itself (defaults to undefined, in which case it will run
+     * indefinitely until reset is called)
+     * @param {Number} config.interval The length of time in milliseconds between each progress
+     * update (defaults to 1000 ms)
+     * @param {Boolean} config.animate Whether to animate the transition of the progress bar.
+     * If this value is not specified, the default for the class is used.
+     * @param {Number} config.increment The number of progress update segments to display within
+     * the progress bar (defaults to 10).  If the bar reaches the end and is still updating, it will
+     * automatically wrap back to the beginning.
+     * @param {String} config.text Optional text to display in the progress bar element
+     * (defaults to '').
+     * @param {Function} config.fn A callback function to execute after the progress bar finishes
+     * auto-updating. The function will be called with no arguments. This function will be ignored
+     * if duration is not specified since in that case the progress bar can only be stopped
+     * programmatically, so any required function should be called by the same code after it resets
+     * the progress bar.
+     * @param {Object} config.scope The scope that is passed to the callback function (only applies
+     * when duration and fn are both passed).
+     * @return {Ext.ProgressBar} this
+     */
+    wait: function(config) {
+        var me = this,
+            scope;
+
+        if (!me.waitTimer) {
+            scope = me;
+            config = config || {};
+
+            if (config.text != null) {
+                me.autoText = false;
+            }
+
+            me.updateText(config.text);
+
+            me.waitTimer = Ext.TaskManager.start({
+                run: function(i) {
+                    var inc = config.increment || 10;
+
+                    i -= 1;
+                    me.updateProgress(((((i + inc) % inc) + 1) * (100 / inc)) * 0.01, null,
+                                      config.animate);
+                },
+                interval: config.interval || 1000,
+                duration: config.duration,
+                onStop: function() {
+                    if (config.fn) {
+                        config.fn.apply(config.scope || me);
+                    }
+
+                    me.reset();
+                },
+                scope: scope
+            });
+        }
+
+        return me;
+    },
+
+    /**
+     * Returns true if the progress bar is currently in a {@link #wait} operation
+     * @return {Boolean} True if waiting, else false
+     */
+    isWaiting: function() {
+        return this.waitTimer !== null;
+    },
+
+    /**
+     * Resets the progress bar value to 0 and text to empty string. If hide = true,
+     * the progress bar will also be hidden (using the {@link #hideMode} property internally).
+     * @param {Boolean} [hide=false] True to hide the progress bar.
+     * @return {Ext.ProgressBar} this
+     */
+    reset: function(hide) {
+        var me = this;
+
+        me.updateProgress(0);
+        me.clearTimer();
+
+        if (hide === true) {
+            me.hide();
+        }
+
+        if (me.rendered) {
+            me.ariaEl.dom.removeAttribute('aria-valuetext');
+        }
+
+        return me;
+    },
+
+    /**
+     * @private
+     */
+    clearTimer: function() {
+        var me = this;
+
+        if (me.waitTimer) {
+            me.waitTimer.onStop = null; // prevent recursion
+            Ext.TaskManager.stop(me.waitTimer);
+            me.waitTimer = null;
+        }
+    },
+
+    doDestroy: function() {
+        var me = this,
+            bar = me.bar,
+            nodes, el, i, len;
+
+        me.clearTimer();
+
+        if (me.rendered) {
+            if (me.textEl.isComposite) {
+                // Clean up Element references created by the layout
+                nodes = me.textEl.slice();
+
+                for (i = 0, len = nodes.length; i < len; i++) {
+                    el = Ext.get(nodes[i]);
+                    el.destroy();
+                }
+            }
+
+            Ext.destroyMembers(me, 'textEl', 'progressBar');
+
+            if (bar && me.animate) {
+                bar.stopAnimation();
+            }
+        }
+
+        me.callParent();
+    }
+});

+ 29 - 0
assets/ext-7.4.0.42/classic/classic/src/Responsive.js

@@ -0,0 +1,29 @@
+/**
+ * This is an override, not a class. To use `Ext.Responsive` you simply require it:
+ *
+ *      Ext.application({
+ *          requires: [
+ *              'Ext.Responsive'
+ *          ],
+ *
+ *          // ...
+ *      });
+ *
+ * Once required, this override mixes in {@link Ext.mixin.Responsive} into `Ext.Component`
+ * and `Ext.Widget` so that these classes both gain the
+ * {@link Ext.mixin.Responsive#cfg!responsiveConfig responsiveConfig} and
+ * {@link Ext.mixin.Responsive#cfg!responsiveFormulas responsiveFormulas} configs.
+ * @since 6.7.0
+ */
+Ext.define('Ext.Responsive', {
+    override: 'Ext.Component',
+
+    mixins: [
+        'Ext.mixin.Responsive'
+    ],
+
+    requires: [
+        // Also an override, so it will drop out if Ext.Widget isn't used
+        'Ext.ResponsiveWidget'
+    ]
+});

+ 14 - 0
assets/ext-7.4.0.42/classic/classic/src/ResponsiveWidget.js

@@ -0,0 +1,14 @@
+/**
+ * The counterpart to `Ext.Responsive` for `Ext.Widget`. This override is required by
+ * `Ext.Responsive` but will only be included if `Ext.Widget` is also used.
+ *
+ * @since 6.7.0
+ * @private
+ */
+Ext.define('Ext.ResponsiveWidget', {
+    override: 'Ext.Widget',
+
+    mixins: [
+        'Ext.mixin.Responsive'
+    ]
+});

+ 808 - 0
assets/ext-7.4.0.42/classic/classic/src/ZIndexManager.js

@@ -0,0 +1,808 @@
+/**
+ * A class that manages a group of {@link Ext.Component#cfg-floating} Components and 
+ * provides z-order management, and Component activation behavior, including masking 
+ * below the active (topmost) Component.
+ *
+ * {@link Ext.Component#cfg-floating Floating} Components which are rendered directly 
+ * into the document (such as {@link Ext.window.Window Window}s) which are 
+ * {@link Ext.Component#method-show show}n are managed by a
+ * {@link Ext.WindowManager global instance}.
+ *
+ * {@link Ext.Component#cfg-floating Floating} Components which are descendants of 
+ * {@link Ext.Component#cfg-floating floating} *Containers* (for example a 
+ * {@link Ext.view.BoundList BoundList} within an {@link Ext.window.Window Window},
+ * or a {@link Ext.menu.Menu Menu}), are managed by a ZIndexManager owned by that floating
+ * Container. Therefore ComboBox dropdowns within Windows will have managed z-indices guaranteed
+ * to be correct, relative to the Window.
+ */
+Ext.define('Ext.ZIndexManager', {
+    alternateClassName: 'Ext.WindowGroup',
+
+    requires: [
+        'Ext.util.SorterCollection',
+        'Ext.util.FilterCollection',
+        'Ext.GlobalEvents'
+    ],
+
+    statics: {
+        zBase: 9000,
+        activeCounter: 0
+    },
+
+    reflowSuspended: 0,
+
+    /**
+     * @private
+     */
+    constructor: function(container) {
+        var me = this;
+
+        me.id = Ext.id(null, 'zindex-mgr-');
+
+        // The stack is a collection sorted on the incrementing activeCounter ascending,
+        // so recently active components sort to the top.
+        // The component's alwaysOnTop flag takes priority in the sort order and
+        // cause the component to gravitate to the correct end of the stack.
+        me.zIndexStack = new Ext.util.Collection({
+            sorters: {
+                sorterFn: function(comp1, comp2) {
+                    var ret = (comp1.alwaysOnTop || 0) - (comp2.alwaysOnTop || 0);
+
+                    if (!ret) {
+                        ret = comp1.getActiveCounter() - comp2.getActiveCounter();
+                    }
+
+                    return ret;
+                }
+            },
+            filters: {
+                filterFn: function(comp) {
+                    return comp.isVisible();
+                }
+            }
+        });
+
+        // zIndexStack will call into this class on key lifecycle events if methods exist here.
+        // Specifically, we implement onCollectionSort which is called by Component's updaters
+        // for activeCounter and alwaysOnTop.
+        me.zIndexStack.addObserver(me);
+        me.front = null;
+        me.sortCount = 0;
+
+        // Listen for global component hiding and showing.
+        // onComponentShowHide only reacts if we are managing the component.
+        me.globalListeners = Ext.GlobalEvents.on({
+            // The 'beforehide' global event is a non-vetoable event fired before the component
+            // is hidden. We use this to sort the remaining visible components, and unmask
+            // if the hiding component is the sole modal.
+            beforehide: me.onComponentShowHide,
+            show: me.onComponentShowHide,
+            scope: me,
+            destroyable: true
+        });
+
+        if (container) {
+
+            // This is the ZIndexManager for an Ext.container.Container, base its zseed
+            // on the zIndex of the Container's element
+            if (container.isContainer) {
+                me.resizeListeners = container.on({
+                    resize: me.onContainerResize,
+                    scope: me,
+                    destroyable: true
+                });
+
+                me.zseed = Ext.Number.from(
+                    me.rendered ? container.getEl().getStyle('zIndex') : undefined,
+                    me.getNextZSeed()
+                );
+
+                // The containing element we will be dealing with (eg masking) is the content target
+                me.targetEl = container.getTargetEl();
+                me.container = container;
+            }
+            // This is the ZIndexManager for a DOM element
+            else {
+                me.resizeListeners = Ext.on({
+                    resize: me.onContainerResize,
+                    scope: me,
+                    destroyable: true
+                });
+
+                me.zseed = me.getNextZSeed();
+                me.targetEl = Ext.get(container);
+            }
+        }
+        // No container passed means we are the global WindowManager. Our target is the doc body.
+        // DOM must be ready to collect that ref.
+        else {
+            me.zseed = me.getNextZSeed();
+
+            Ext.onInternalReady(function() {
+                // We need to use lowest possible priority here to give enough time
+                // for layouts to run and resize if we're masking a contained component
+                me.resizeListeners = Ext.on({
+                    resize: me.scheduleContainerResize,
+                    scope: me,
+                    destroyable: true,
+                    priority: -10000
+                });
+
+                me.targetEl = Ext.getBody();
+            });
+        }
+    },
+
+    // Required to be an Observer of a Collection
+    getId: function() {
+        return this.id;
+    },
+
+    getNextZSeed: function() {
+        return (Ext.ZIndexManager.zBase += 10000);
+    },
+
+    setBase: function(baseZIndex) {
+        this.zseed = baseZIndex;
+
+        return this.onCollectionSort();
+    },
+
+    onCollectionSort: function() {
+        var me = this,
+            oldFront = me.front,
+            zIndex = me.zseed,
+            a = me.zIndexStack.getRange(),
+            len = a.length,
+            i, comp, topModal, topFocusable, topMost,
+            doFocus = !oldFront || oldFront.isVisible();
+
+        me.sortCount++;
+
+        for (i = 0; i < len; i++) {
+            comp = a[i];
+
+            if (comp.destroying || comp.destroyed) {
+                continue;
+            }
+
+            // Setting the zIndex of a Component returns the topmost zIndex consumed by
+            // that Component.
+            // If it's just a plain floating Component such as a BoundList, then the
+            // return value is the passed value plus 10, ready for the next item.
+            // If a floating *Container* has its zIndex set, it re-orders its managed
+            // floating children, starting from that new base, and returns a value 10000 above
+            // the highest zIndex which it allocates.
+            zIndex = comp.setZIndex(zIndex);
+
+            // Only register a new topmost to activate if we find one that is visible
+            // Unfiltered panels with hidden:true can end up here during an animated hide process
+            // When the hidden flag is set, and the ghost show operation kicks the ZIndexManager's
+            // sort.
+            if (!comp.hidden) {
+                topMost = comp;
+
+                // Track topmost visible modal so we can place the modal mask just below it.
+                // Any prior focusable ones just became not focusable - they'll be below our mask.
+                if (comp.modal) {
+                    topModal = comp;
+                    topFocusable = null;
+                }
+
+                // Track topmost focusable floater which is above all modals.
+                // Unfocusable things like tooltips and toasts may be above it
+                // but they do not matter, the topmost *focusable* must be focused.
+                if (doFocus && (comp.isFocusable(true) && (comp.modal || comp.focusOnToFront))) {
+                    topFocusable = comp;
+                }
+            }
+        }
+
+        // Sort resulted in a different topmost focusable.
+        if (topFocusable && topFocusable !== oldFront && !topFocusable.preventFocusOnActivate) {
+            topFocusable.onFocusTopmost();
+        }
+
+        // If we encountered a modal in our reassigment, ensure our modal mask is just below it.
+        if (topModal) {
+            // If it's the same topmost, then just ensure the
+            // correct z-index and size of mask.
+            if (topModal === me.topModal) {
+                me.syncModalMask(topModal);
+            }
+            // If it's a new top, we must re-show the mask because of tabbability resets.
+            else {
+                me.showModalMask(topModal);
+            }
+        }
+        else {
+            me.hideModalMask();
+        }
+
+        // Inform components of change in to of stack.
+        if (topMost !== me.topMost) {
+            if (me.topMost) {
+                // This one has been bumped from top.
+                me.topMost.onZIndexChange(false);
+            }
+
+            if (topMost) {
+                // This one is now at the top.
+                topMost.onZIndexChange(true);
+            }
+        }
+
+        // Cache the top of the stack
+        me.front = topFocusable;
+        me.topModal = topModal;
+        me.topMost = topMost;
+
+        // Ensure the top-most component is the front
+        if (!me.front && me.topMost) {
+            me.front = me.topMost;
+        }
+
+        return zIndex;
+    },
+
+    /**
+     * @private
+     * Called from {@link Ext.util.Floating} updater methods when a config which affects
+     * the stack order is updated in a Component.
+     *
+     * eg {@link Ext.Component#alwaysOnTop alwaysOnTop} or
+     * {@link Ext.Component#activeCounter activeCounter}
+     */
+    onComponentUpdate: function(comp) {
+        if (!this.reflowSuspended && this.zIndexStack.contains(comp)) {
+            this.zIndexStack.sort();
+        }
+    },
+
+    suspendReflow: function() {
+        this.reflowSuspended++;
+    },
+
+    resumeReflow: function(flush) {
+        if (this.reflowSuspended && ! --this.reflowSuspended) {
+            if (flush) {
+                this.zIndexStack.sort();
+            }
+        }
+    },
+
+    onComponentReady: function(comp) {
+        if (!this.reflowSuspended && comp.toFrontOnShow && comp.isVisible()) {
+            this.zIndexStack.itemChanged(comp, 'hidden');
+            this.zIndexStack.sort();
+        }
+    },
+
+    /**
+     * @private
+     * Called when the global hide and show events are fired. If it is one of our components,
+     * we must re-sort.
+     */
+    onComponentShowHide: function(comp) {
+        var me = this,
+            zIndexStack = me.zIndexStack,
+            sortCount = me.sortCount;
+
+        // If component has hidden, it will be filtered out, so we have to look in Collection's
+        // source if it's there.
+        if (comp.isFloating() && !me.hidingAll &&
+            (zIndexStack.getSource() || zIndexStack).contains(comp)) {
+            if (me.tempHidden) {
+                Ext.Array.remove(me.tempHidden, comp);
+            }
+
+            zIndexStack.beginUpdate();
+
+            // Showing. If it should go to front on show; nudge the active
+            // counter which will cause a stack sort.
+            if (comp.isVisible()) {
+                if (comp.toFrontOnShow) {
+                    zIndexStack.itemChanged(comp, 'hidden');
+                    comp.setActiveCounter(++Ext.ZIndexManager.activeCounter);
+                }
+            }
+
+            // Hiding
+            else {
+                zIndexStack.itemChanged(comp, 'hidden');
+            }
+
+            // We must update the frontmost according to the new stack order
+            // even if there has been no sort (Collection will not autosort if only one member)
+            zIndexStack.endUpdate();
+
+            if (me.sortCount === sortCount && !me.reflowSuspended) {
+                me.onCollectionSort();
+            }
+        }
+    },
+
+    /**
+     * Registers a floating {@link Ext.Component} with this ZIndexManager. This should not
+     * need to be called under normal circumstances. Floating Components (such as Windows,
+     * BoundLists and Menus) are automatically registered with a
+     * {@link Ext.Component#zIndexManager zIndexManager} at render time.
+     *
+     * Where this may be useful is moving Windows between two ZIndexManagers. For example,
+     * to bring the Ext.MessageBox dialog under the same manager as the Desktop's
+     * ZIndexManager in the desktop sample app:
+     *
+     *     MyDesktop.getDesktop().getManager().register(Ext.MessageBox);
+     *
+     * @param {Ext.Component} comp The Component to register.
+     */
+    register: function(comp) {
+        var me = this;
+
+        if (comp.zIndexManager) {
+            comp.zIndexManager.unregister(comp);
+        }
+
+        comp.zIndexManager = me;
+
+        if (!comp.rendered) {
+            // Checking for rendered as opposed to hide/show is important because
+            // it's still possible to render a floating component and have it be visible.
+            // Since rendered isn't a global event, we need to react individually on each
+            // component and update the state in the collection after render.
+            // It is important to use boxready for floated components, because reordering the
+            // z-index stack during render can cause reflows. For components with liquid layouts,
+            // we must use afterrender because they don't participate in layouts
+            comp.on(me.getReadyEvent(comp), me.onComponentReady, me, { single: true });
+        }
+
+        me.zIndexStack.add(comp);
+    },
+
+    /**
+     * Unregisters a {@link Ext.Component} from this ZIndexManager. This should not
+     * need to be called. Components are automatically unregistered upon destruction.
+     * See {@link #register}.
+     * @param {Ext.Component} comp The Component to unregister.
+     */
+    unregister: function(comp) {
+        var me = this;
+
+        delete comp.zIndexManager;
+        comp.un(me.getReadyEvent(comp), me.onComponentReady, me);
+        me.zIndexStack.remove(comp);
+
+        me.onCollectionSort();
+    },
+
+    /**
+     * Gets a registered Component by id.
+     * @param {String/Object} id The id of the Component or a {@link Ext.Component} instance
+     * @return {Ext.Component}
+     */
+    get: function(id) {
+        return id.isComponent ? id : this.zIndexStack.get(id);
+    },
+
+    /**
+     * Brings the specified Component to the front of any other active Components in this
+     * ZIndexManager.
+     * @param {String/Object} comp The id of the Component or a {@link Ext.Component} instance.
+     * @param {Boolean} preventFocus Pass `true` to prevent the component being focused when moved
+     * to front.
+     * @return {Boolean} True if the component was brought to the front, else false
+     * if it was already in front, or another component remains at the front due to configuration
+     * (eg {@link Ext.util.Floating#alwaysOnTop}, or if the component was not found.
+     */
+    bringToFront: function(comp, preventFocus) {
+        var me = this,
+            zIndexStack = me.zIndexStack,
+            oldFront = zIndexStack.last(),
+            newFront, preventFocusSetting;
+
+        comp = me.get(comp);
+
+        // Refuse to perform this operation if we do not own the passed component.
+        if (!comp) {
+            return false;
+        }
+
+        preventFocusSetting = comp.preventFocusOnActivate;
+
+        // The onCollectionSorted reaction to the setting of activeCounter will focus by default.
+        // Prevent it if requested.
+        comp.preventFocusOnActivate = preventFocus;
+        comp.setActiveCounter(++Ext.ZIndexManager.activeCounter);
+        comp.preventFocusOnActivate = preventFocusSetting;
+        newFront = zIndexStack.last();
+
+        // Return true if the passed component was moved to the front
+        // and was not already at the front
+        return (newFront === comp && newFront !== oldFront);
+    },
+
+    /**
+     * Sends the specified Component to the back of other active Components in this ZIndexManager.
+     * @param {String/Object} comp The id of the Component or a {@link Ext.Component} instance
+     * @return {Ext.Component} The Component
+     */
+    sendToBack: function(comp) {
+        comp = this.get(comp);
+
+        if (comp) {
+            comp.setActiveCounter(0);
+        }
+
+        return comp || null;
+    },
+
+    /**
+     * Hides all Components managed by this ZIndexManager.
+     */
+    hideAll: function() {
+        var me = this,
+            all = me.zIndexStack.getRange(),
+            len = all.length,
+            i;
+
+        me.hidingAll = true;
+
+        for (i = 0; i < len; i++) {
+            all[i].hide();
+        }
+
+        me.hidingAll = false;
+        me.hideModalMask();
+        me.front = null;
+    },
+
+    /**
+     * @private
+     * Temporarily hides all currently visible managed Components. This is for when
+     * dragging a Window which may manage a set of floating descendants in its ZIndexManager;
+     * they should all be hidden just for the duration of the drag.
+     */
+    hide: function() {
+        var me = this,
+            activeElement = Ext.Element.getActiveElement(),
+            all = me.zIndexStack.getRange(),
+            len = all.length,
+            comp, i;
+
+        // If any of the components contained focus, we must restore it on show.
+        me.focusRestoreElement = null;
+        (me.tempHidden || (me.tempHidden = [])).length = 0;
+
+        for (i = 0; i < len; i++) {
+            comp = all[i];
+
+            // Only hide currently visible floaters
+            if (comp.isVisible()) {
+                if (comp.el.contains(activeElement)) {
+                    me.focusRestoreElement = activeElement;
+                }
+
+                comp.el.hide();
+                comp.pendingShow = comp.hidden = true;
+                me.tempHidden.push(comp);
+            }
+        }
+    },
+
+    /**
+     * @private
+     * Restores temporarily hidden managed Components to visibility.
+     */
+    show: function() {
+        var me = this,
+            tempHidden = me.tempHidden,
+            len = tempHidden ? tempHidden.length : 0,
+            comp, i;
+
+        for (i = 0; i < len; i++) {
+            comp = tempHidden[i];
+            comp.hidden = false;
+
+            if (comp.pendingShow) {
+                comp.el.show();
+                comp.pendingShow = false;
+                comp.setPosition(comp.x, comp.y);
+                comp.onFloatShow();
+            }
+            // An attempt at hiding while temp hidden
+            // has cleared the pendingShow flag. Hide it
+            // properly with full event flow now.
+            else {
+                comp.hide();
+            }
+        }
+
+        me.tempHidden = null;
+
+        if (me.focusRestoreElement) {
+            me.focusRestoreElement.focus();
+        }
+    },
+
+    /**
+     * Gets the currently-active Component in this ZIndexManager.
+     * @return {Ext.Component} The active Component
+     */
+    getActive: function() {
+        return this.zIndexStack.last();
+    },
+
+    /**
+     * Returns zero or more Components in this ZIndexManager using the custom search function passed
+     * to this method. The function should accept a single {@link Ext.Component} reference
+     * as its only argument and should return true if the Component matches the search criteria,
+     * otherwise it should return false.
+     * @param {Function} fn The search function
+     * @param {Object} [scope] The scope (`this` reference) in which the function is executed.
+     * Defaults to the Component being tested. That gets passed to the function if not specified.
+     * @return {Array} An array of zero or more matching floating components.
+     */
+    getBy: function(fn, scope) {
+        return this.zIndexStack.filterBy(fn, scope).getRange();
+    },
+
+    /**
+     * Executes the specified function once for every Component in this ZIndexManager, passing each
+     * Component as the only parameter. Returning false from the function will stop the iteration.
+     * @param {Function} fn The function to execute for each item
+     * @param {Object} [scope] The scope (this reference) in which the function
+     * is executed. Defaults to the current Component in the iteration.
+     */
+    each: function(fn, scope) {
+        this.zIndexStack.each(fn, scope);
+    },
+
+    /**
+     * Executes the specified function once for every Component in this ZIndexManager, passing each
+     * Component as the only parameter. Returning false from the function will stop the iteration.
+     * The components are passed to the function starting at the bottom and proceeding to the top.
+     * @param {Function} fn The function to execute for each item
+     * @param {Object} scope (optional) The scope (this reference) in which the function
+     * is executed. Defaults to the current Component in the iteration.
+     */
+    eachBottomUp: function(fn, scope) {
+        var stack = this.zIndexStack.getRange(),
+            len = stack.length,
+            comp, i;
+
+        for (i = 0; i < len; i++) {
+            comp = stack[i];
+
+            if (comp.isComponent && fn.call(scope || comp, comp) === false) {
+                return;
+            }
+        }
+    },
+
+    /**
+     * Executes the specified function once for every Component in this ZIndexManager, passing each
+     * Component as the only parameter. Returning false from the function will stop the iteration.
+     * The components are passed to the function starting at the top and proceeding to the bottom.
+     * @param {Function} fn The function to execute for each item
+     * @param {Object} [scope] The scope (this reference) in which the function
+     * is executed. Defaults to the current Component in the iteration.
+     */
+    eachTopDown: function(fn, scope) {
+        var stack = this.zIndexStack.getRange(),
+            comp, i;
+
+        for (i = stack.length; i-- > 0;) {
+            comp = stack[i];
+
+            if (comp.isComponent && fn.call(scope || comp, comp) === false) {
+                return;
+            }
+        }
+    },
+
+    destroy: function() {
+        var me = this,
+            stack = me.zIndexStack.getRange(),
+            len = stack.length,
+            i;
+
+        for (i = 0; i < len; i++) {
+            Ext.destroy(stack[i]);
+        }
+
+        Ext.destroy(me.mask, me.maskShim, me.zIndexStack, me.globalListeners, me.resizeListeners);
+
+        me.callParent();
+    },
+
+    privates: {
+        getMaskBox: function() {
+            var maskTarget = this.mask.maskTarget;
+
+            if (maskTarget.dom === document.body) {
+                // If we're masking the body, subtract the border/padding
+                // so we don't cause scrollbar.
+                return {
+                    height: Math.max(
+                        document.body.scrollHeight, Ext.dom.Element.getDocumentHeight()
+                    ),
+                    width: Math.max(document.body.scrollWidth, Ext.dom.Element.getDocumentWidth()),
+                    x: 0,
+                    y: 0
+                };
+            }
+            else {
+                return maskTarget.getBox();
+            }
+        },
+
+        getReadyEvent: function(c) {
+            return c.liquidLayout ? 'afterrender' : 'boxready';
+        },
+
+        scheduleContainerResize: function() {
+            // The reason we're scheduling resize handler here is to allow Responsive mixin
+            // to fire events and run layouts that may affect the size of the modal mask.
+            // Responsive will request animation frame on browser window resize event,
+            // we do likewise here to minimize flicker.
+            if (!this.containerResizeTimer) {
+                this.containerResizeTimer = Ext.raf(this.onContainerResize, this);
+            }
+        },
+
+        onContainerResize: function() {
+            var me = this,
+                mask = me.mask,
+                maskShim = me.maskShim,
+                viewSize;
+
+            me.containerResizeTimer = null;
+
+            if (mask && mask.isVisible()) {
+                // At the new container size, the mask might be *causing* the scrollbar,
+                // so to find the valid client size to mask, we must temporarily unmask
+                // the parent node.
+                mask.hide();
+
+                if (maskShim) {
+                    maskShim.hide();
+                }
+
+                viewSize = me.getMaskBox();
+
+                if (maskShim) {
+                    maskShim.setSize(viewSize);
+                    maskShim.show();
+                }
+
+                mask.setSize(viewSize);
+                mask.show();
+            }
+        },
+
+        onMaskMousedown: function(e) {
+            // Focus frontmost modal, do not allow mousedown to focus mask.
+            if (this.topModal) {
+                this.topModal.focus();
+                e.preventDefault();
+            }
+        },
+
+        onMaskClick: function() {
+            var front = this.topModal,
+                methodName;
+
+            if (front) {
+                // Fire a maskclick event. Allow the onward processing by the maskClickAction method
+                // to be vetoed by a false return value.
+                if (!front.hasListeners.maskclick ||
+                    front.fireEvent('maskclick', front) !== false) {
+                    // We call whatever method 'maskClickAction' points to.
+                    // By default, Windows have 'focus'. If we encounter other
+                    // classes without that property, default to 'focus'
+                    methodName = front.maskClickAction || 'focus';
+                    front[methodName]();
+                }
+            }
+        },
+
+        showModalMask: function(comp) {
+            var me = this,
+                compEl = comp.el,
+                maskTarget = comp.floatParent ? comp.floatParent.getEl() : comp.container,
+                mask = me.mask;
+
+            if (!mask) {
+                // Create the mask at zero size so that it does not affect upcoming
+                // target measurements.
+                me.mask = mask = Ext.getBody().createChild({
+                    //<debug>
+                    // tell the spec runner to ignore this element when checking if the dom is clean
+                    'data-sticky': true,
+                    //</debug>
+
+                    role: 'presentation',
+                    cls: Ext.baseCSSPrefix + 'mask ' + Ext.baseCSSPrefix + 'border-box',
+                    style: 'height:0;width:0'
+                });
+
+                mask.setVisibilityMode(Ext.Element.DISPLAY);
+
+                mask.on({
+                    mousedown: me.onMaskMousedown,
+                    click: me.onMaskClick,
+                    scope: me
+                });
+            }
+
+            // If the mask is already shown, hide it before showing again
+            // to ensure underlying elements' tabbability is restored
+            else {
+                me.hideModalMask();
+            }
+
+            mask.maskTarget = maskTarget;
+
+            // Since there is no fast and reliable way to find elements above or below
+            // a given z-index, we just cheat and prevent tabbable elements within the
+            // topmost component from being made untabbable.
+            maskTarget.saveTabbableState({
+                excludeRoot: compEl
+            });
+
+            // Size and zIndex stack the mask (and its shim)
+            me.syncModalMask(comp);
+        },
+
+        syncModalMask: function(comp) {
+            var me = this,
+                zIndex = comp.el.getZIndex() - 4,
+                mask = me.mask,
+                shim = me.maskShim,
+                viewSize = me.getMaskBox();
+
+            if (shim) {
+                shim.setZIndex(zIndex);
+                shim.show();
+                shim.setBox(viewSize);
+            }
+
+            mask.setZIndex(zIndex);
+            mask.show();
+            mask.setBox(viewSize);
+        },
+
+        hideModalMask: function() {
+            var mask = this.mask,
+                maskShim = this.maskShim;
+
+            if (mask && mask.isVisible()) {
+                mask.maskTarget.restoreTabbableState();
+
+                mask.maskTarget = undefined;
+                mask.hide();
+
+                if (maskShim) {
+                    maskShim.hide();
+                }
+            }
+        }
+    }
+}, function() {
+    /**
+     * @class Ext.WindowManager
+     * @extends Ext.ZIndexManager
+     *
+     * The default global floating Component group that is available automatically.
+     *
+     * This manages instances of floating Components which were rendered programatically without
+     * being added to a {@link Ext.container.Container Container}, and for floating Components
+     * which were added into non-floating Containers.
+     * 
+     * *Floating* Containers create their own instance of ZIndexManager, and floating Components
+     * added at any depth below there are managed by that ZIndexManager.
+     *
+     * @singleton
+     */
+    Ext.WindowManager = Ext.WindowMgr = new this();
+});

File diff suppressed because it is too large
+ 2280 - 0
assets/ext-7.4.0.42/classic/classic/src/button/Button.js


+ 246 - 0
assets/ext-7.4.0.42/classic/classic/src/button/Cycle.js

@@ -0,0 +1,246 @@
+
+/**
+ * A specialized SplitButton that contains a menu of {@link Ext.menu.CheckItem} elements. The button
+ * automatically cycles through each menu item on click, raising the button's {@link #change} event
+ * (or calling the button's {@link #changeHandler} function, if supplied) for the active menu item.
+ * Clicking on the arrow section of the button displays the dropdown menu just like a normal
+ * SplitButton.
+ * Example usage:
+ *
+ *     @example
+ *     Ext.create('Ext.button.Cycle', {
+ *         showText: true,
+ *         prependText: 'View as ',
+ *         renderTo: Ext.getBody(),
+ *         menu: {
+ *             id: 'view-type-menu',
+ *             items: [{
+ *                 text: 'text only',
+ *                 iconCls: 'view-text',
+ *                 checked: true
+ *             },{
+ *                 text: 'HTML',
+ *                 iconCls: 'view-html'
+ *             }]
+ *         },
+ *         changeHandler: function(cycleBtn, activeItem) {
+ *             Ext.Msg.alert('Change View', activeItem.text);
+ *         }
+ *     });
+ */
+Ext.define('Ext.button.Cycle', {
+    extend: 'Ext.button.Split',
+    alternateClassName: 'Ext.CycleButton',
+    alias: 'widget.cycle',
+
+    /**
+     * @cfg {Object[]} items
+     * An array of {@link Ext.menu.CheckItem} **config** objects to be used when creating
+     * the button's menu items (e.g., `{text:'Foo', iconCls:'foo-icon'}`)
+     * 
+     * @deprecated 4.0 Use the {@link #cfg-menu} config instead. All menu items will be created as
+     * {@link Ext.menu.CheckItem CheckItems}.
+     */
+
+    /**
+     * @cfg {Boolean} [showText=false]
+     * True to display the active item's text as the button text. The Button will show its
+     * configured {@link #text} if this config is omitted.
+     */
+
+    /**
+     * @cfg {String} [prependText='']
+     * A static string to prepend before the active item's text when displayed as the button's text
+     * (only applies when showText = true).
+     */
+
+    /**
+     * @cfg {Function/String} [changeHandler=undefined]
+     * A callback function that will be invoked each time the active menu item in the button's menu
+     * has changed. If this callback is not supplied, the SplitButton will instead fire the
+     * {@link #change} event on active item change. The changeHandler function will be called with
+     * the following argument list: (SplitButton this, Ext.menu.CheckItem item)
+     * @controllable
+     */
+
+    /**
+     * @cfg {String} forceIcon
+     * A css class which sets an image to be used as the static icon for this button. This icon will
+     * always be displayed regardless of which item is selected in the dropdown list. This overrides
+     * the default behavior of changing the button's icon to match the selected item's icon
+     * on change.
+     */
+
+    /**
+     * @cfg {Number/String} forceGlyph
+     * The charCode to be used as the static icon for this button.  This icon will always be
+     * displayed regardless of which item is selected in the dropdown list. This override
+     * the default behavior of changing the button's icon to match the selected item's icon
+     * on change. This property expects a format consistent with that of {@link #glyph}
+     */
+
+    /**
+     * @property {Ext.menu.Menu} menu
+     * The {@link Ext.menu.Menu Menu} object used to display the
+     * {@link Ext.menu.CheckItem CheckItems} representing the available choices.
+     */
+
+    /**
+     * @event change
+     * Fires after the button's active menu item has changed. Note that if a {@link #changeHandler}
+     * function is set on this CycleButton, it will be called instead on active item change and this
+     * change event will not be fired.
+     * @param {Ext.button.Cycle} this
+     * @param {Ext.menu.CheckItem} item The menu item that was selected
+     */
+
+    /**
+     * @private
+     */
+    getButtonText: function(item) {
+        var me = this,
+            text = '';
+
+        if (item && me.showText === true) {
+            if (me.prependText) {
+                text += me.prependText;
+            }
+
+            text += item.text;
+
+            return text;
+        }
+
+        return me.text;
+    },
+
+    /**
+     * Sets the button's active menu item.
+     * @param {Ext.menu.CheckItem} item The item to activate
+     * @param {Boolean} [suppressEvent=false] True to prevent the {@link #change} event and
+     * {@link #changeHandler} from firing.
+     */
+    setActiveItem: function(item, suppressEvent) {
+        var me = this,
+            changeHandler = me.changeHandler,
+            forceIcon = me.forceIcon,
+            forceGlyph = me.forceGlyph;
+
+        me.settingActive = true;
+
+        if (!Ext.isObject(item)) {
+            item = me.menu.getComponent(item);
+        }
+
+        if (item) {
+            me.setText(me.getButtonText(item));
+            me.setIconCls(forceIcon ? forceIcon : item.iconCls);
+            me.setGlyph(forceGlyph ? forceGlyph : item.glyph);
+
+            me.activeItem = item;
+
+            if (!item.checked) {
+                item.setChecked(true, false);
+            }
+
+            if (!suppressEvent) {
+                if (changeHandler) {
+                    Ext.callback(changeHandler, me.scope, [me, item], 0, me);
+                }
+
+                me.fireEvent('change', me, item);
+            }
+        }
+
+        me.settingActive = false;
+    },
+
+    /**
+     * Gets the currently active menu item.
+     * @return {Ext.menu.CheckItem} The active item
+     */
+    getActiveItem: function() {
+        return this.activeItem;
+    },
+
+    /**
+     * @private
+     */
+    initComponent: function() {
+        var me = this,
+            checked = 0,
+            items, i, iLen, item;
+
+        //<debug>
+        // Ext JS Cycle buttons are implemented in a way that clashes with WAI-ARIA requirements,
+        // so we warn the developer about that.
+        Ext.ariaWarn(
+            me,
+            "Using Cycle buttons is not recommended in accessible " +
+            "applications, because their behavior conflicts " +
+            "with accessibility best practices. See WAI-ARIA 1.0 " +
+            "Authoring guide: http://www.w3.org/TR/wai-aria-practices/#menubutton"
+        );
+        //</debug>
+
+        // Allow them to specify a menu config which is a standard Button config.
+        // Remove direct use of "items" in 5.0.
+        items = (me.menu.items || []).concat(me.items || []);
+
+        me.menu = Ext.applyIf({
+            cls: Ext.baseCSSPrefix + 'cycle-menu',
+            items: []
+        }, me.menu);
+
+        iLen = items.length;
+
+        // Convert all items to CheckItems
+        for (i = 0; i < iLen; i++) {
+            item = items[i];
+
+            item = Ext.applyIf({
+                group: me.id,
+                itemIndex: i,
+                checkHandler: me.checkHandler,
+                scope: me,
+                checked: item.checked || false
+            }, item);
+
+            me.menu.items.push(item);
+
+            if (item.checked) {
+                checked = i;
+            }
+        }
+
+        me.itemCount = me.menu.items.length;
+
+        me.callParent(arguments);
+
+        me.on('click', me.toggleSelected, me);
+        me.setActiveItem(checked, true);
+    },
+
+    /**
+     * @private
+     */
+    checkHandler: function(item, pressed) {
+        if (pressed && !this.settingActive) {
+            this.setActiveItem(item);
+        }
+    },
+
+    /**
+     * This is normally called internally on button click, but can be called externally to advance
+     * the button's active item programmatically to the next one in the menu. If the current item
+     * is the last one in the menu the active item will be set to the first item in the menu.
+     */
+    toggleSelected: function() {
+        var me = this,
+            m = me.menu,
+            checkItem;
+
+        checkItem = me.activeItem.next(':not([disabled])') || m.items.getAt(0);
+        checkItem.setChecked(true);
+    }
+});

+ 116 - 0
assets/ext-7.4.0.42/classic/classic/src/button/Manager.js

@@ -0,0 +1,116 @@
+/**
+ * @private
+ */
+Ext.define('Ext.button.Manager', {
+    singleton: true,
+
+    alternateClassName: 'Ext.ButtonToggleManager',
+
+    groups: {},
+
+    pressedButton: null,
+
+    init: function() {
+        var me = this;
+
+        if (!me.initialized) {
+            Ext.getDoc().on({
+                mouseup: me.onDocumentMouseUp,
+                scope: me
+            });
+
+            me.initialized = true;
+        }
+    },
+
+    // Called by buton instances.
+    // Track the button which was mousedowned upon so that the next *document* mouseup
+    // can be delivered to it in case mouse is moved outside of button element.
+    onButtonMousedown: function(button, e) {
+        var pressed = this.pressedButton;
+
+        if (pressed && !pressed.destroying && !pressed.destroyed) {
+            pressed.onMouseUp(e);
+        }
+
+        this.pressedButton = button;
+    },
+
+    onDocumentMouseUp: function(e) {
+        var pressed = this.pressedButton;
+
+        if (pressed && !pressed.destroying && !pressed.destroyed) {
+            pressed.onMouseUp(e);
+            this.pressedButton = null;
+        }
+    },
+
+    toggleGroup: function(btn, state) {
+        var g, i, length;
+
+        if (state) {
+            g = this.groups[btn.toggleGroup];
+
+            for (i = 0, length = g.length; i < length; i++) {
+                if (g[i] !== btn) {
+                    g[i].toggle(false);
+                }
+            }
+        }
+    },
+
+    register: function(btn) {
+        var me = this,
+            groups = this.groups,
+            group = groups[btn.toggleGroup];
+
+        me.init();
+
+        if (!btn.toggleGroup) {
+            return;
+        }
+
+        if (!group) {
+            group = groups[btn.toggleGroup] = [];
+        }
+
+        group.push(btn);
+        btn.on('toggle', me.toggleGroup, me);
+    },
+
+    unregister: function(btn) {
+        if (!btn.toggleGroup) {
+            return;
+        }
+
+        // eslint-disable-next-line vars-on-top
+        var me = this,
+            group = me.groups[btn.toggleGroup];
+
+        if (group) {
+            Ext.Array.remove(group, btn);
+            btn.un('toggle', me.toggleGroup, me);
+        }
+    },
+
+    /**
+     * Gets the pressed button in the passed group or null
+     * @param {String} groupName
+     * @return {Ext.button.Button}
+     */
+    getPressed: function(groupName) {
+        var group = this.groups[groupName],
+            i = 0,
+            len;
+
+        if (group) {
+            for (len = group.length; i < len; i++) {
+                if (group[i].pressed === true) {
+                    return group[i];
+                }
+            }
+        }
+
+        return null;
+    }
+});

+ 642 - 0
assets/ext-7.4.0.42/classic/classic/src/button/Segmented.js

@@ -0,0 +1,642 @@
+/**
+ * SegmentedButton is a container for a group of {@link Ext.button.Button Button}s.  You 
+ * may populate the segmented button's children by adding buttons to the items config.
+ * The segmented  button's children enjoy the same customizations as regular buttons, such as 
+ * menu, tooltip, etc.  You can see usages of the various configuration
+ * possibilities in the example below.
+ *
+ *     @example preview 
+ *     Ext.create('Ext.button.Segmented', {            
+ *          renderTo: Ext.getBody(),
+ *          allowMultiple: true,
+ *          items: [{
+ *               text: 'Segment Item 1',
+ *               menu: [{
+ *                   text: 'Menu Item 1'
+ *               }]
+ *          },{
+ *               text: 'Segment Item 2',
+ *               tooltip: 'My custom tooltip'
+ *          },{
+ *               text: 'Segment Item 3'
+ *          }],
+ *          listeners: {
+ *               toggle: function(container, button, pressed) {
+ *                    console.log("User toggled the '" + button.text + "' button: " +
+ *                                (pressed ? 'on' : 'off'));
+ *               }
+ *          }
+ *     });
+ * 
+ */
+Ext.define('Ext.button.Segmented', {
+    extend: 'Ext.container.Container',
+    xtype: 'segmentedbutton',
+
+    requires: [
+        'Ext.button.Button',
+        'Ext.layout.container.SegmentedButton'
+    ],
+
+    config: {
+        /**
+         * @cfg {Boolean} allowDepress
+         * Allow toggling the pressed state of each button.
+         * Only applicable when {@link #allowMultiple} is `false`.
+         */
+        allowDepress: false,
+
+        /**
+         * @cfg {Boolean} allowMultiple
+         * Allow multiple pressed buttons.
+         */
+        allowMultiple: false,
+
+        /**
+         * @cfg {Boolean} forceSelection
+         * If {@link #allowMultiple} is `true`, this config may be set to `true` to indicate that
+         * at least one button in the set must remain pressed at all times.
+         *
+         * If no {@link #value} is configured, and no child buttons are configured `pressed`,
+         * the first child button is set `pressed: true`
+         */
+        forceSelection: false,
+
+        /**
+         * @cfg {Boolean} allowToggle
+         * True to enable pressed/not pressed toggling.
+         */
+        allowToggle: true,
+
+        /**
+         * @cfg {Boolean} vertical
+         * True to align the buttons vertically
+         */
+        vertical: false,
+
+        /**
+         * @cfg {String} defaultUI
+         * Default {@link Ext.Component#ui ui} to use for buttons in this segmented button.
+         * Buttons can override this default by specifying their own UI
+         */
+        defaultUI: 'default'
+    },
+
+    beforeRenderConfig: {
+        /**
+         * @cfg {String/Number/String[]/Number[]} value
+         * @accessor
+         * The value of this button.  When {@link #allowMultiple} is `false`, value is a
+         * String or Number.  When {@link #allowMultiple} is `true`, value is an array
+         * of values.  A value corresponds to a child button's {@link Ext.button.Button#value
+         * value}, or its index if no child button values match the given value.
+         *
+         * Using the `value` config of the child buttons with single toggle:
+         *
+         *     @example
+         *     var button = Ext.create('Ext.button.Segmented', {
+         *         renderTo: Ext.getBody(),
+         *         value: 'optTwo', // begin with "Option Two" selected
+         *         items: [{
+         *             text: 'Option One',
+         *             value: 'optOne'
+         *         }, {
+         *             text: 'Option Two',
+         *             value: 'optTwo'
+         *         }, {
+         *             text: 'Option Three',
+         *             value:  'optThree'
+         *         }]
+         *     });
+         *
+         *     console.log(button.getValue()); // optTwo
+         *
+         *     // Sets the value to optOne, and sets the pressed state of the "Option One" button
+         *     button.setValue('optOne');
+         *
+         *     console.log(button.getValue()); // optOne
+         *
+         * Using multiple toggle, and index-based values:
+         *
+         *     @example
+         *     var button = Ext.create('Ext.button.Segmented', {
+         *         renderTo: Ext.getBody(),
+         *         allowMultiple: true
+         *         value: [1, 2], // begin with "Option Two" and "Option Three" selected
+         *         items: [{
+         *             text: 'Option One'
+         *         }, {
+         *             text: 'Option Two'
+         *         }, {
+         *             text: 'Option Three'
+         *         }]
+         *     });
+         *
+         *     // Sets value to [0, 2], and sets pressed state of "Option One" and "Option Three"
+         *     button.setValue([0, 2]);
+         *
+         *     console.log(button.getValue()); // [0, 2]
+         *
+         *     // Remove all pressed buttons, and set value to null
+         *     button.setValue(null);
+         */
+        value: undefined
+    },
+
+    /**
+     * @property defaultBindProperty
+     * @inheritdoc
+     */
+    defaultBindProperty: 'value',
+
+    /**
+     * @cfg publishes
+     * @inheritdoc
+     */
+    publishes: ['value'],
+
+    /**
+     * @cfg twoWayBindable
+     * @inheritdoc
+     */
+    twoWayBindable: ['value'],
+
+    /**
+     * @cfg layout
+     * @inheritdoc
+     */
+    layout: 'segmentedbutton',
+
+    /**
+     * @cfg defaultType
+     * @inheritdoc
+     */
+    defaultType: 'button',
+
+    /**
+     * @property maskOnDisable
+     * @inheritdoc
+     */
+    maskOnDisable: false,
+
+    isSegmentedButton: true,
+
+    /**
+     * @cfg baseCls
+     * @inheritdoc
+     */
+    baseCls: Ext.baseCSSPrefix + 'segmented-button',
+
+    itemCls: Ext.baseCSSPrefix + 'segmented-button-item',
+
+    /**
+     * @private
+     */
+    _firstCls: Ext.baseCSSPrefix + 'segmented-button-first',
+
+    /**
+     * @private
+     */
+    _lastCls: Ext.baseCSSPrefix + 'segmented-button-last',
+
+    /**
+     * @private
+     */
+    _middleCls: Ext.baseCSSPrefix + 'segmented-button-middle',
+
+    /**
+     * @event toggle
+     * Fires when any child button's pressed state has changed.
+     * @param {Ext.button.Segmented} this
+     * @param {Ext.button.Button} button The toggled button.
+     * @param {Boolean} isPressed `true` to indicate if the button was pressed.
+     */
+
+    /**
+     * @event change
+     * Fires when any child button's pressed state has changed and caused the value to change.
+     * @param {Ext.button.Segmented} this
+     * @param {Array} newValue The new value.
+     * @param {Array} oldValue The old value.
+     */
+
+    applyValue: function(value, oldValue) {
+        var me = this,
+            allowMultiple = me.getAllowMultiple(),
+            buttonValue, button, values, oldValues, items, i, ln, hasPressed;
+
+        values = (value instanceof Array) ? value : (value == null) ? [] : [value];
+        oldValues = (oldValue instanceof Array) ? oldValue : (oldValue == null) ? [] : [oldValue];
+
+        // Set a flag to tell our toggle listener not to respond to the buttons' toggle
+        // events while we are applying the value.
+        me._isApplyingValue = true;
+
+        if (!me.rendered) {
+            // first time - add values of buttons with an initial config of pressed:true
+            items = me.items.items;
+
+            for (i = items.length - 1; i >= 0; i--) {
+                button = items[i];
+
+                // If we've got back to zero with no pressed buttons and have forceSelection,
+                // then make button zero pressed.
+                if (me.forceSelection && !i && !hasPressed) {
+                    button.pressed = true;
+                }
+
+                if (button.pressed) {
+                    hasPressed = true;
+                    buttonValue = button.value;
+
+                    if (buttonValue == null) {
+                        buttonValue = me.items.indexOf(button);
+                    }
+
+                    // We're looping backwards, unshift the values into the front of the array
+                    if (!Ext.Array.contains(values, buttonValue)) {
+                        values.unshift(buttonValue);
+                    }
+                }
+            }
+        }
+
+        ln = values.length;
+
+        //<debug>
+        if (ln > 1 && !allowMultiple) {
+            Ext.raise('Cannot set multiple values when allowMultiple is false');
+        }
+        //</debug>
+
+        // press all buttons corresponding to the values
+        for (i = 0; i < ln; i++) {
+            value = values[i];
+            button = me._lookupButtonByValue(value);
+
+            if (button) {
+                buttonValue = button.value;
+
+                if ((buttonValue != null) && buttonValue !== value) {
+                    // button has a value, but it was matched by index.
+                    // transform the index into the button value
+                    values[i] = buttonValue;
+                }
+
+                if (!button.pressed) {
+                    button.setPressed(true);
+                }
+            }
+            //<debug>
+            else {
+                // no matched button. fail.
+                Ext.raise("Invalid value '" + value + "' for segmented button: '" + me.id + "'");
+            }
+            //</debug>
+        }
+
+        value = allowMultiple ? values : ln ? values[0] : null;
+
+        // unpress buttons for the old values, if they do not exist in the new values array
+        for (i = 0, ln = oldValues.length; i < ln; i++) {
+            oldValue = oldValues[i];
+
+            if (!Ext.Array.contains(values, oldValue)) {
+                me._lookupButtonByValue(oldValue).setPressed(false);
+            }
+        }
+
+        me._isApplyingValue = false;
+
+        return value;
+    },
+
+    updateValue: function(value, oldValue) {
+        var me = this,
+            same;
+
+        if (me.hasListeners.change) {
+            if (value && oldValue && me.getAllowMultiple()) {
+                same = Ext.Array.equals(value, oldValue);
+            }
+
+            if (!same) {
+                me.fireEvent('change', me, value, oldValue);
+            }
+        }
+    },
+
+    beforeRender: function() {
+        var me = this;
+
+        me.addCls(me.baseCls + me._getClsSuffix());
+        me._syncItemClasses(true);
+
+        me.callParent();
+    },
+
+    onAdd: function(item) {
+        var me = this,
+            syncItemClasses = '_syncItemClasses';
+
+        //<debug>
+        // eslint-disable-next-line vars-on-top, one-var
+        var items = me.items.items,
+            ln = items.length,
+            i = 0,
+            value, defaultUI;
+
+        if (item.ui === 'default' && !item.hasOwnProperty('ui')) {
+            defaultUI = me.getDefaultUI();
+
+            if (defaultUI !== 'default') {
+                item.ui = defaultUI;
+            }
+        }
+
+        for (; i < ln; i++) {
+            if (items[i] !== item) {
+                value = items[i].value;
+
+                if (value != null && value === item.value) {
+                    Ext.raise("Segmented button '" + me.id +
+                              "' cannot contain multiple items with value: '" + value + "'");
+                }
+            }
+        }
+        //</debug>
+
+        me.mon(item, {
+            hide: syncItemClasses,
+            show: syncItemClasses,
+            beforetoggle: '_onBeforeItemToggle',
+            toggle: '_onItemToggle',
+            scope: me
+        });
+
+        if (me.getAllowToggle()) {
+            item.enableToggle = true;
+
+            if (!me.getAllowMultiple()) {
+                item.toggleGroup = me.getId();
+                item.allowDepress = me.getAllowDepress();
+            }
+        }
+
+        item.addCls(me.itemCls + me._getClsSuffix());
+        me._syncItemClasses();
+
+        me.callParent([item]);
+    },
+
+    onRemove: function(item) {
+        var me = this;
+
+        item.removeCls(me.itemCls + me._getClsSuffix());
+        me._syncItemClasses();
+
+        me.callParent([item]);
+    },
+
+    beforeLayout: function() {
+        if (Ext.isChrome) {
+            // workaround for a chrome bug with table-layout:fixed elements where the element
+            // is layed out with 0 width, for example, in the following test case, without
+            // this workaround the segmented button has 0 width in chrome:
+            //
+            //     Ext.create({
+            //        renderTo: document.body,
+            //            xtype: 'toolbar',
+            //            items: [{
+            //            xtype: 'segmentedbutton',
+            //            items: [{
+            //                text: 'Foo'
+            //            }]
+            //        }]
+            //    });
+            //
+            // reading offsetWidth corrects the issue.
+
+            // eslint-disable-next-line no-unused-expressions
+            this.el.dom.offsetWidth;
+        }
+
+        this.callParent();
+    },
+
+    updateDefaultUI: function(defaultUI) {
+        var items = this.items,
+            item, i, ln;
+
+        if (this.rendered) {
+            Ext.raise(
+                "Changing the ui config of a segmented button after render is not supported."
+            );
+        }
+        else if (items) {
+            if (items.items) { // Mixed collection already created
+                items = items.items;
+            }
+
+            for (i = 0, ln = items.length; i < ln; i++) {
+                item = items[i];
+
+                if (item.ui === 'default' && defaultUI !== 'default' &&
+                    !item.hasOwnProperty('ui')) {
+                    items[i].ui = defaultUI;
+                }
+            }
+        }
+    },
+
+    //<debug>
+    updateAllowDepress: function(newAllowDepress, oldAllowDepress) {
+        if (this.rendered && (newAllowDepress !== oldAllowDepress)) {
+            Ext.raise("Changing the allowDepress config of a segmented button after render " +
+                      "is not supported.");
+        }
+    },
+
+    updateAllowMultiple: function(newAllowMultiple, oldAllowMultiple) {
+        if (this.rendered && (newAllowMultiple !== oldAllowMultiple)) {
+            Ext.raise("Changing the allowMultiple config of a segmented button after render " +
+                      "is not supported.");
+        }
+    },
+
+    updateAllowToggle: function(newAllowToggle, oldAllowToggle) {
+        if (this.rendered && (newAllowToggle !== oldAllowToggle)) {
+            Ext.raise("Changing the allowToggle config of a segmented button after render " +
+                      "is not supported.");
+        }
+    },
+
+    updateVertical: function(newVertical, oldVertical) {
+        if (this.rendered && (newVertical !== oldVertical)) {
+            Ext.raise("Changing the orientation of a segmented button after render " +
+                      "is not supported.");
+        }
+    },
+    //</debug>
+
+    privates: {
+        _getClsSuffix: function() {
+            return this.getVertical() ? '-vertical' : '-horizontal';
+        },
+
+        // rtl hook
+        _getFirstCls: function() {
+            return this._firstCls;
+        },
+
+        // rtl hook
+        _getLastCls: function() {
+            return this._lastCls;
+        },
+
+        /**
+         * Looks up a child button by its value
+         * @private
+         * @param {String/Number} value The button's value or index
+         * @return {Ext.button.Button}
+         */
+        _lookupButtonByValue: function(value) {
+            var items = this.items.items,
+                ln = items.length,
+                i = 0,
+                button = null,
+                buttonValue, btn;
+
+            for (; i < ln; i++) {
+                btn = items[i];
+                buttonValue = btn.value;
+
+                if ((buttonValue != null) && buttonValue === value) {
+                    button = btn;
+                    break;
+                }
+            }
+
+            if (!button && typeof value === 'number') {
+                // no button matched by value, assume value is an index
+                button = items[value];
+            }
+
+            return button;
+        },
+
+        _onBeforeItemToggle: function(button, pressed) {
+            // If we allow multiple selections, and we are forcing a selection, and we are
+            // unpressing and we only have one value, then veto this. we are not allowing
+            // the selection length to fall to zero.
+            if (this.allowMultiple && this.forceSelection && !pressed &&
+                this.getValue().length === 1) {
+                return false;
+            }
+        },
+
+        /**
+         * Handles the "toggle" event of the child buttons.
+         * @private
+         * @param {Ext.button.Button} button
+         * @param {Boolean} pressed
+         */
+        _onItemToggle: function(button, pressed) {
+            if (this._isApplyingValue) {
+                return;
+            }
+
+            // eslint-disable-next-line vars-on-top
+            var me = this,
+                Array = Ext.Array,
+                allowMultiple = me.allowMultiple,
+                buttonValue = (button.value != null) ? button.value : me.items.indexOf(button),
+                value = me.getValue(),
+                valueIndex;
+
+            if (allowMultiple) {
+                valueIndex = Array.indexOf(value, buttonValue);
+            }
+
+            if (pressed) {
+                if (allowMultiple) {
+                    if (valueIndex === -1) {
+                        // We must not mutate our value property here
+                        value = Array.slice(value);
+                        value.push(buttonValue);
+                    }
+                }
+                else {
+                    value = buttonValue;
+                }
+            }
+            else {
+                if (allowMultiple) {
+                    if (valueIndex > -1) {
+                        // We must not mutate our value property here
+                        value = Array.slice(value);
+                        value.splice(valueIndex, 1);
+                    }
+                }
+                else if (value === buttonValue) {
+                    value = null;
+                }
+            }
+
+            me.setValue(value);
+
+            me.fireEvent('toggle', me, button, pressed);
+        },
+
+        /**
+         * Synchronizes the "first", "last", and "middle" css classes when buttons are
+         * added, removed, shown, or hidden
+         * @private
+         * @param {Boolean} force force sync even if not rendered.
+         */
+        _syncItemClasses: function(force) {
+            var me = this,
+                firstCls, middleCls, lastCls, items, ln, visibleItems, item, i;
+
+            if (!force && !me.rendered) {
+                return;
+            }
+
+            firstCls = me._getFirstCls();
+            middleCls = me._middleCls;
+            lastCls = me._getLastCls();
+            items = me.items.items;
+            ln = items.length;
+            visibleItems = [];
+
+            for (i = 0; i < ln; i++) {
+                item = items[i];
+
+                if (!item.hidden) {
+                    visibleItems.push(item);
+                }
+            }
+
+            ln = visibleItems.length;
+
+            // remove all existing classes from visible items
+            for (i = 0; i < ln; i++) {
+                visibleItems[i].removeCls([ firstCls, middleCls, lastCls ]);
+            }
+
+            // do not add any classes if there is only one item (no border removal needed)
+            if (ln > 1) {
+                // add firstCls to the first visible button
+                visibleItems[0].addCls(firstCls);
+
+                // add middleCls to all visible buttons in between
+                for (i = 1; i < ln - 1; i++) {
+                    visibleItems[i].addCls(middleCls);
+                }
+
+                // add lastCls to the first visible button
+                visibleItems[ln - 1].addCls(lastCls);
+            }
+        }
+    }
+});

+ 379 - 0
assets/ext-7.4.0.42/classic/classic/src/button/Split.js

@@ -0,0 +1,379 @@
+/**
+ * A split button that provides a built-in dropdown arrow that can fire an event separately
+ * from the default click event of the button. Typically this would be used to display a dropdown
+ * menu that provides additional options to the primary button action, but any custom handler
+ * can provide the arrowclick implementation.
+ * Example usage:
+ *
+ *     @example
+ *     // display a dropdown menu:
+ *     Ext.create('Ext.button.Split', {
+ *         renderTo: Ext.getBody(),
+ *         text: 'Options',
+ *         // handle a click on the button itself
+ *         handler: function() {
+ *             alert("The button was clicked");
+ *         },
+ *         menu: new Ext.menu.Menu({
+ *             items: [
+ *                 // these will render as dropdown menu items when the arrow is clicked:
+ *                 {text: 'Item 1', handler: function(){ alert("Item 1 clicked"); }},
+ *                 {text: 'Item 2', handler: function(){ alert("Item 2 clicked"); }}
+ *             ]
+ *         })
+ *     });
+ *
+ * Instead of showing a menu, you can provide any type of custom functionality you want when
+ * the dropdown arrow is clicked:
+ *
+ *     Ext.create('Ext.button.Split', {
+ *         renderTo: 'button-ct',
+ *         text: 'Options',
+ *         handler: optionsHandler,
+ *         arrowHandler: myCustomHandler
+ *     });
+ *
+ */
+Ext.define('Ext.button.Split', {
+    extend: 'Ext.button.Button',
+    alternateClassName: 'Ext.SplitButton',
+    alias: 'widget.splitbutton',
+
+    isSplitButton: true,
+
+    /**
+     * @cfg {Function/String} arrowHandler
+     * A function called when the arrow button is clicked (can be used instead of click event)
+     * @cfg {Ext.button.Split} arrowHandler.this
+     * @cfg {Event} arrowHandler.e The click event.
+     * @controllable
+     */
+
+    /**
+     * @cfg {String} arrowTooltip
+     * The title attribute of the arrow.
+     */
+
+    /**
+     * @cfg {Boolean} [separateArrowStyling=false] If enabled, arrow element mouseover,
+     * click, and focus events will be handled separately from main element and
+     * corresponding hover, pressed, and focused states will be added separately
+     * to main element and arrow element, respectively.
+     *
+     * This requires theme support for extended states (see Graphite theme).
+     *
+     * @since 6.6.0
+     * @private
+     */
+    separateArrowStyling: false,
+
+    /**
+     * @private
+     */
+    arrowCls: 'split',
+    split: true,
+
+    componentCls: Ext.baseCSSPrefix + 'split-button',
+
+    /**
+     * @event arrowclick
+     * Fires when this button's arrow is clicked.
+     * @param {Ext.button.Split} this
+     * @param {Event} e The click event.
+     */
+
+    // It is possible to use both menu and arrowHandler with a Split button, which is confusing
+    // and will clash with WAI-ARIA requirements. So we check that and warn if need be.
+    // Unfortunately this won't work with arrowclick event that can be subscribed to
+    // dynamically but we don't want to run these checks at run time so there's a limit
+    // to what we can do about it.
+    //<debug>
+    initComponent: function() {
+        var me = this;
+
+        // Don't warn if we're under the slicer. Only check hasListeners of the component
+        // instance; there could be listeners on the EventBus inherited via prototype.
+        if (me.menu && (me.arrowHandler || me.hasListeners.hasOwnProperty('arrowclick'))) {
+            Ext.ariaWarn(
+                me,
+                "Using both menu and arrowHandler config options in Split buttons " +
+                "leads to confusing user experience and conflicts with accessibility " +
+                "best practices. See WAI-ARIA 1.0 Authoring guide: " +
+                "http://www.w3.org/TR/wai-aria-practices/#menubutton"
+            );
+        }
+
+        me.callParent();
+    },
+    //</debug>
+
+    getTemplateArgs: function() {
+        var me = this,
+            ariaAttr, data;
+
+        data = me.callParent();
+
+        if (me.disabled) {
+            data.tabIndex = null;
+        }
+
+        ariaAttr = me.ariaArrowElAttributes || {};
+
+        ariaAttr['aria-hidden'] = !!me.hidden;
+        ariaAttr['aria-disabled'] = !!me.disabled;
+
+        if (me.arrowTooltip) {
+            ariaAttr['aria-label'] = me.arrowTooltip;
+        }
+        else {
+            ariaAttr['aria-labelledby'] = me.id;
+        }
+
+        data.arrowElAttributes = ariaAttr;
+
+        return data;
+    },
+
+    onRender: function() {
+        var me = this,
+            el;
+
+        me.callParent();
+
+        el = me.getFocusEl();
+
+        if (el) {
+            el.on({
+                scope: me,
+                focus: me.onMainElFocus,
+                blur: me.onMainElBlur
+            });
+        }
+
+        el = me.arrowEl;
+
+        if (el) {
+            el.dom.setAttribute('data-componentid', me.id);
+            el.setVisibilityMode(Ext.dom.Element.DISPLAY);
+
+            el.on({
+                scope: me,
+                focus: me.onArrowElFocus,
+                blur: me.onArrowElBlur
+            });
+        }
+    },
+
+    /**
+     * Sets this button's arrow click handler.
+     * @param {Function} handler The function to call when the arrow is clicked.
+     * @param {Object} scope (optional) Scope for the function passed above.
+     */
+    setArrowHandler: function(handler, scope) {
+        this.arrowHandler = handler;
+        this.scope = scope;
+    },
+
+    onMouseDown: function(e) {
+        var me = this;
+
+        if (me.separateArrowStyling && !me.disabled && e.button === 0 &&
+            me.isWithinTrigger(e)) {
+            e.preventDefault();
+            me.arrowEl.focus();
+
+            Ext.button.Manager.onButtonMousedown(me, e);
+            me.addCls(me._arrowPressedCls);
+        }
+        else {
+            me.callParent([e]);
+        }
+    },
+
+    onMouseUp: function(e) {
+        var me = this;
+
+        if (me.separateArrowStyling && !me.destroyed && e.button === 0 &&
+            me.isWithinTrigger(e)) {
+            me.removeCls(me._arrowPressedCls);
+        }
+        else {
+            me.callParent([e]);
+        }
+    },
+
+    onMenuTriggerOver: function(e) {
+        var me = this;
+
+        if (me.separateArrowStyling && !me.disabled) {
+            me.addCls(me._arrowOverCls);
+        }
+
+        me.callParent([e]);
+    },
+
+    onMenuTriggerOut: function(e) {
+        var me = this;
+
+        if (me.separateArrowStyling && !me.disabled) {
+            me.removeCls(me._arrowOverCls);
+        }
+
+        me.callParent([e]);
+    },
+
+    /**
+     * @private
+     */
+    onClick: function(e) {
+        var me = this,
+            arrowKeydown = e.type === 'keydown' && e.target === me.arrowEl.dom;
+
+        me.doPreventDefault(e);
+
+        if (!me.disabled) {
+            if (arrowKeydown || me.isWithinTrigger(e)) {
+                // Force prevent default here, if we click on the arrow part
+                // we want to trigger the menu, not any link if we have it
+                e.preventDefault();
+                me.maybeShowMenu(e);
+                me.fireEvent("arrowclick", me, e);
+
+                if (me.arrowHandler) {
+                    me.arrowHandler.call(me.scope || me, me, e);
+                }
+            }
+            else {
+                me.doToggle();
+                me.fireHandler(e);
+            }
+        }
+    },
+
+    enable: function(silent) {
+        var me = this,
+            arrowEl = me.arrowEl;
+
+        me.callParent([silent]);
+
+        // May not be rendered yet
+        if (arrowEl) {
+            arrowEl.dom.setAttribute('tabIndex', me.tabIndex);
+            arrowEl.dom.setAttribute('aria-disabled', 'false');
+        }
+    },
+
+    disable: function(silent) {
+        var me = this,
+            arrowEl = me.arrowEl;
+
+        me.callParent([silent]);
+
+        // May not be rendered yet
+        if (arrowEl) {
+            arrowEl.dom.removeAttribute('tabIndex');
+            arrowEl.dom.setAttribute('aria-disabled', 'true');
+        }
+    },
+
+    afterHide: function(cb, scope) {
+        this.callParent([cb, scope]);
+        this.arrowEl.dom.setAttribute('aria-hidden', 'true');
+    },
+
+    afterShow: function(animateTarget, cb, scope) {
+        this.callParent([animateTarget, cb, scope]);
+        this.arrowEl.dom.setAttribute('aria-hidden', 'false');
+    },
+
+    privates: {
+        isFocusing: function(e) {
+            var me = this,
+                from = e.fromElement,
+                to = e.toElement,
+                focusEl = me.focusEl && me.focusEl.dom,
+                arrowEl = me.arrowEl && me.arrowEl.dom;
+
+            if (me.focusable) {
+                if (to === focusEl) {
+                    return from === arrowEl ? false : true;
+                }
+                else if (to === arrowEl) {
+                    return from === focusEl ? false : true;
+                }
+
+                return true;
+            }
+
+            return false;
+        },
+
+        isBlurring: function(e) {
+            var me = this,
+                from = e.fromElement,
+                to = e.toElement,
+                focusEl = me.focusEl && me.focusEl.dom,
+                arrowEl = me.arrowEl && me.arrowEl.dom;
+
+            if (me.focusable) {
+                if (from === focusEl) {
+                    return to === arrowEl ? false : true;
+                }
+                else if (from === arrowEl) {
+                    return to === focusEl ? false : true;
+                }
+
+                return true;
+            }
+
+            return false;
+        },
+
+        // We roll our own focus style handling for Split button, see below
+        getFocusClsEl: Ext.privateFn,
+
+        onMainElFocus: function(e) {
+            this.el.addCls(this._focusCls);
+        },
+
+        onMainElBlur: function(e) {
+            this.el.removeCls(this._focusCls);
+        },
+
+        onArrowElFocus: function(e) {
+            this.el.addCls(this._arrowFocusCls);
+        },
+
+        onArrowElBlur: function() {
+            this.el.removeCls(this._arrowFocusCls);
+        },
+
+        setTabIndex: function(newTabIndex) {
+            this.callParent([newTabIndex]);
+
+            // May not be rendered yet
+            if (this.arrowEl) {
+                this.arrowEl.set({ tabIndex: newTabIndex });
+            }
+        },
+
+        // This and below are called by the setMenu method in the parent class.
+        _addSplitCls: function() {
+            var arrowEl = this.arrowEl;
+
+            this.callParent();
+
+            arrowEl.dom.setAttribute('tabIndex', this.tabIndex);
+            arrowEl.setVisible(true);
+        },
+
+        _removeSplitCls: function() {
+            var arrowEl = this.arrowEl;
+
+            this.callParent();
+
+            arrowEl.dom.removeAttribute('tabIndex');
+            arrowEl.setVisible(false);
+        }
+    }
+});

+ 227 - 0
assets/ext-7.4.0.42/classic/classic/src/container/ButtonGroup.js

@@ -0,0 +1,227 @@
+/**
+ * Provides a container for arranging a group of related Buttons in a tabular manner.
+ *
+ *     @example
+ *     Ext.create('Ext.panel.Panel', {
+ *         title: 'Panel with ButtonGroup',
+ *         width: 300,
+ *         height:200,
+ *         renderTo: document.body,
+ *         bodyPadding: 10,
+ *         html: 'HTML Panel Content',
+ *         tbar: [{
+ *             xtype: 'buttongroup',
+ *             columns: 3,
+ *             title: 'Clipboard',
+ *             items: [{
+ *                 text: 'Paste',
+ *                 scale: 'large',
+ *                 rowspan: 3,
+ *                 iconCls: 'add',
+ *                 iconAlign: 'top',
+ *                 cls: 'btn-as-arrow'
+ *             },{
+ *                 xtype:'splitbutton',
+ *                 text: 'Menu Button',
+ *                 scale: 'large',
+ *                 rowspan: 3,
+ *                 iconCls: 'add',
+ *                 iconAlign: 'top',
+ *                 arrowAlign:'bottom',
+ *                 menu: [{ text: 'Menu Item 1' }]
+ *             },{
+ *                 xtype:'splitbutton', text: 'Cut', iconCls: 'add16',
+ *                 menu: [{ text: 'Cut Menu Item' }]
+ *             },{
+ *                 text: 'Copy', iconCls: 'add16'
+ *             },{
+ *                 text: 'Format', iconCls: 'add16'
+ *             }]
+ *         }]
+ *     });
+ *
+ */
+Ext.define('Ext.container.ButtonGroup', {
+    extend: 'Ext.panel.Panel',
+    alias: 'widget.buttongroup',
+    alternateClassName: 'Ext.ButtonGroup',
+
+    requires: [
+        'Ext.layout.container.Table'
+    ],
+
+    /**
+     * @cfg {Number} columns
+     * The `columns` configuration property passed to the {@link #layout configured layout manager}.
+     * See {@link Ext.layout.container.Table#columns}.
+     */
+
+    /**
+     * @cfg baseCls
+     * @inheritdoc
+     */
+    baseCls: Ext.baseCSSPrefix + 'btn-group',
+
+    /**
+     * @cfg layout
+     * @inheritdoc
+     */
+    layout: {
+        type: 'table'
+    },
+
+    /**
+     * @cfg defaultType
+     * @inheritdoc
+     */
+    defaultType: 'button',
+
+    /**
+     * @cfg frame
+     * @inheritdoc
+     */
+    frame: true,
+
+    /**
+     * @cfg {String} defaultButtonUI
+     * A default {@link Ext.Component#ui ui} to use for {@link Ext.button.Button Button} items
+     */
+
+    /**
+     * @cfg frameHeader
+     * @inheritdoc
+     */
+    frameHeader: false,
+
+    /**
+     * @cfg {String} titleAlign
+     * The alignment of the title text within the available space between the icon and the tools.
+     */
+    titleAlign: 'center',
+
+    noTitleCls: 'notitle',
+
+    bodyAriaRole: 'toolbar',
+
+    /**
+     * @property focusableContainerEl
+     * @inheritdoc
+     */
+    focusableContainerEl: 'body',
+
+    /**
+     * @cfg focusableContainer
+     * @inheritdoc
+     */
+    focusableContainer: true,
+
+    initComponent: function() {
+        // Copy the component's columns config to the layout if specified
+        var me = this,
+            cols = me.columns;
+
+        if (cols) {
+            me.layout = Ext.apply({ columns: cols }, me.layout);
+        }
+
+        if (!me.title) {
+            me.addClsWithUI(me.noTitleCls);
+        }
+
+        me.callParent();
+    },
+
+    /**
+     * @private
+     */
+    onBeforeAdd: function(component) {
+        if (component.isButton) {
+            if (this.defaultButtonUI && component.ui === 'default' &&
+                !component.hasOwnProperty('ui')) {
+                component.ui = this.defaultButtonUI;
+            }
+            else {
+                component.ui = component.ui + '-toolbar';
+            }
+        }
+
+        this.callParent(arguments);
+    },
+
+    beforeRender: function() {
+        var me = this,
+            ariaAttr;
+
+        me.callParent();
+
+        // If header is off we need to set aria-label
+        if (me.afterHeaderInit && !me.header && me.title) {
+            ariaAttr = me.bodyAriaRenderAttributes || (me.bodyAriaRenderAttributes = {});
+            ariaAttr['aria-label'] = me.title;
+        }
+    },
+
+    updateHeader: function(force) {
+        var me = this,
+            bodyEl = me.body,
+            header, ariaAttr;
+
+        me.callParent([force]);
+
+        header = me.header;
+
+        if (header) {
+            if (bodyEl) {
+                bodyEl.dom.setAttribute('aria-labelledby', header.id + '-title-textEl');
+                bodyEl.dom.removeAttribute('aria-label');
+            }
+            else {
+                ariaAttr = me.bodyAriaRenderAttributes || (me.bodyAriaRenderAttributes = {});
+                ariaAttr['aria-labelledby'] = header.id + '-title-textEl';
+                delete ariaAttr['aria-label'];
+            }
+        }
+        else if (me.title) {
+            if (bodyEl) {
+                bodyEl.dom.setAttribute('aria-label', me.title);
+                bodyEl.dom.removeAttribute('aria-labelledby');
+            }
+            else {
+                ariaAttr = me.bodyAriaRenderAttributes || (me.bodyAriaRenderAttributes = {});
+                ariaAttr['aria-label'] = me.title;
+                delete ariaAttr['aria-labelledby'];
+            }
+        }
+    },
+
+    privates: {
+        applyDefaults: function(c) {
+            if (!Ext.isString(c)) {
+                c = this.callParent(arguments);
+            }
+
+            return c;
+        }
+    }
+
+    /**
+     * @cfg {Array} tools
+     * @private
+     */
+    /**
+     * @cfg {Boolean} collapsible
+     * @private
+     */
+    /**
+     * @cfg {Boolean} collapseMode
+     * @private
+     */
+    /**
+     * @cfg {Boolean} animCollapse
+     * @private
+     */
+    /**
+     * @cfg {Boolean} closable
+     * @private
+     */
+});

File diff suppressed because it is too large
+ 2492 - 0
assets/ext-7.4.0.42/classic/classic/src/container/Container.js


+ 394 - 0
assets/ext-7.4.0.42/classic/classic/src/container/DockingContainer.js

@@ -0,0 +1,394 @@
+/**
+ *
+ */
+Ext.define('Ext.container.DockingContainer', {
+    requires: ['Ext.util.MixedCollection', 'Ext.Element' ],
+
+    isDockingContainer: true,
+
+    /**
+     * @event dockedadd
+     * Fires when any {@link Ext.Component} is added or inserted as a docked item.
+     * @param {Ext.panel.Panel} this
+     * @param {Ext.Component} component The component being added
+     * @param {Number} index The index at which the component will be added docked items collection
+     */
+
+    /**
+     * @event dockedremove
+     * Fires when any {@link Ext.Component} is removed from the docked items.
+     * @param {Ext.panel.Panel} this
+     * @param {Ext.Component} component The component being removed
+     */
+
+    /**
+     * @cfg {Object} defaultDockWeights
+     * This object holds the default weights applied to dockedItems that have no weight.
+     * These start with a weight of 1, to allow negative weights to insert before top items
+     * and are odd numbers so that even weights can be used to get between different dock orders.
+     *
+     * To make default docking order match border layout, do this:
+     *
+     *      Ext.panel.Panel.prototype.defaultDockWeights = { top: 1, bottom: 3, left: 5, right: 7 };
+     *
+     * Changing these defaults as above or individually on this object will effect all Panels.
+     * To change the defaults on a single panel, you should replace the entire object:
+     *
+     *      initComponent: function() {
+     *          // NOTE: Don't change members of defaultDockWeights since the object is shared.
+     *          this.defaultDockWeights = { top: 1, bottom: 3, left: 5, right: 7 };
+     *
+     *          this.callParent();
+     *      }
+     *
+     * To change only one of the default values, you do this:
+     *
+     *      initComponent: function() {
+     *          // NOTE: Don't change members of defaultDockWeights since the object is shared.
+     *          this.defaultDockWeights = Ext.applyIf({ top: 10 }, this.defaultDockWeights);
+     * 
+     *          this.callParent();
+     *      }
+     */
+    defaultDockWeights: {
+        top: { render: 1, visual: 1 },
+        left: { render: 3, visual: 5 },
+        right: { render: 5, visual: 7 },
+        bottom: { render: 7, visual: 3 }
+    },
+
+    /**
+     * @private
+     * Values to decide which side of the body element docked items must go
+     * This overides any weight. A left/top will *always* sort before a right/bottom
+     * regardless of any weight value. Weights sort at either side of the "body" dividing point.
+     */
+    dockOrder: {
+        top: -1,
+        left: -1,
+        right: 1,
+        bottom: 1
+    },
+
+    /**
+     * @private
+     * Number of dock 'left' and 'right' items.
+     */
+    horizontalDocks: 0,
+
+    /**
+     * Adds docked item(s) to the container.
+     *
+     * @param {Object/Object[]} items The Component or array of components to add. The components
+     * must include a 'dock' parameter on each component to indicate where it should be docked
+     * ('top', 'right', 'bottom', 'left').
+     * @param {Number} [pos] The index at which the Component will be added
+     * @return {Ext.Component[]} The added components.
+     */
+    addDocked: function(items, pos) {
+        var me = this,
+            rendered = me.rendered,
+            i = 0,
+            dockedItems = me.dockedItems,
+            lastIndex = dockedItems.getCount(),
+            index, instanced,
+            item, length;
+
+        items = me.prepareItems(items);
+        length = items.length;
+
+        if (rendered) {
+            Ext.suspendLayouts();
+        }
+
+        if (pos === undefined) {
+            pos = lastIndex;
+        }
+        else {
+            pos = Math.min(pos, lastIndex);
+        }
+
+        for (; i < length; i++) {
+            item = items[i];
+
+            if (item.isDetached) {
+                item.reattachToBody();
+            }
+
+            item.dock = item.dock || 'top';
+
+            if (item.dock === 'left' || item.dock === 'right') {
+                me.horizontalDocks++;
+            }
+
+            index = pos + i;
+            dockedItems.insert(index, item);
+
+            instanced = !!item.instancedCmp;
+            delete item.instancedCmp;
+
+            item.onAdded(me, index, instanced);
+            delete item.$initParent;
+
+            if (me.onDockedAdd !== Ext.emptyFn) {
+                me.onDockedAdd(item);
+            }
+
+            if (me.hasListeners.dockedadd) {
+                me.fireEvent('dockedadd', me, item, index);
+            }
+        }
+
+        if (me.rendered) {
+            me.updateLayout();
+            Ext.resumeLayouts(true);
+        }
+
+        return items;
+    },
+
+    destroyDockedItems: function() {
+        var dockedItems = this.dockedItems,
+            c;
+
+        if (dockedItems) {
+            while ((c = dockedItems.first())) {
+                this.removeDocked(c, {
+                    destroy: true
+                });
+            }
+        }
+    },
+
+    doRenderDockedItems: function(out, renderData, after) {
+        // Careful! This method is bolted on to the frameTpl and renderTpl so all we get for
+        // context is the renderData! The "this" pointer is either the frameTpl or the
+        // renderTpl instance!
+
+        var me = renderData.$comp,
+            layout = me.componentLayout,
+            // eslint-disable-next-line no-unused-vars
+            tabGuard = me.tabGuard && me.lookupTpl('tabGuardTpl'),
+            items, tree;
+
+        if (layout.getDockedItems) {
+            items = layout.getDockedItems('render', !after);
+            tree = items && layout.getItemsRenderTree(items);
+
+            if (tree) {
+                Ext.DomHelper.generateMarkup(tree, out);
+            }
+        }
+    },
+
+    /**
+     * Finds a docked component by id, itemId or position. Also see {@link #getDockedItems}
+     * @param {String/Number} comp The id, itemId or position of the docked component
+     * (see {@link Ext.container.Container#getComponent getComponent} for details)
+     * @return {Ext.Component} The docked component (if found)
+     */
+    getDockedComponent: function(comp) {
+        if (Ext.isObject(comp)) {
+            comp = comp.getItemId();
+        }
+
+        return this.dockedItems.get(comp);
+    },
+
+    /**
+     * Retrieves an array of all currently docked Components.
+     *
+     * For example to find a toolbar that has been docked at top:
+     *
+     *     panel.getDockedItems('toolbar[dock="top"]');
+     *
+     * @param {String} selector A {@link Ext.ComponentQuery ComponentQuery} selector string
+     * to filter the returned items.
+     * @param {Boolean} beforeBody An optional flag to limit the set of items to only those
+     * before the body (true) or after the body (false). All components are returned by default.
+     * @return {Ext.Component[]} The array of docked components meeting the specified criteria.
+     */
+    getDockedItems: function(selector, beforeBody) {
+        var dockedItems = this.getComponentLayout().getDockedItems('render', beforeBody);
+
+        if (selector && dockedItems.length) {
+            dockedItems = Ext.ComponentQuery.query(selector, dockedItems);
+        }
+
+        return dockedItems;
+    },
+
+    getDockingRefItems: function(deep, containerItems) {
+        // deep fetches the docked items and their descendants using '*' and then '* *'
+        var selector = deep && '*,* *',
+            // start with only the top/left docked items (and maybe their children)
+            dockedItems = this.getDockedItems(selector, true),
+            items;
+
+        // push container items (and maybe their children) after top/left docked items:
+        dockedItems.push.apply(dockedItems, containerItems);
+
+        // push right/bottom docked items (and maybe their children) after container items:
+        items = this.getDockedItems(selector, false);
+        dockedItems.push.apply(dockedItems, items);
+
+        return dockedItems;
+    },
+
+    /**
+     * @protected
+     * Initializes an Item Collection for docked items to be inserted into.  If items
+     * already exist, they will be added to the new collection.
+     */
+    initDockingItems: function() {
+        var me = this,
+            items = me.dockedItems;
+
+        if (!items || !items.isMixedCollection) {
+            me.dockedItems = new Ext.util.ItemCollection();
+
+            if (items) {
+                me.addDocked(items);
+            }
+        }
+    },
+
+    /**
+     * Inserts docked item(s) to the panel at the indicated position.
+     * @param {Number} pos The index at which the Component will be inserted
+     * @param {Object/Object[]} items The Component or array of components to add. The components
+     * must include a 'dock' paramater on each component to indicate where it should be docked
+     * ('top', 'right', 'bottom', 'left').
+     */
+    insertDocked: function(pos, items) {
+        this.addDocked(items, pos);
+    },
+
+    // Placeholder empty functions
+    /**
+     * @method
+     * Invoked after a docked item is added to the Panel.
+     * @param {Ext.Component} component
+     * @template
+     * @protected
+     */
+    onDockedAdd: Ext.emptyFn,
+    /**
+     * @method
+     * Invoked after a docked item is removed from the Panel.
+     * @param {Ext.Component} component
+     * @template
+     * @protected
+     */
+    onDockedRemove: Ext.emptyFn,
+
+    /**
+     * Removes the docked item from the panel.
+     * @param {Ext.Component} item The Component to remove.
+     * @param {Boolean/Object} [flags] Pass `true` to destroy the item or an
+     * object with multiple options. If not passed, {@link #cfg!autoDestroy} will
+     * determine if the item is destroyed.
+     * @param {Boolean} [flags.destroy] Pass `true` to destroy the item.
+     * @param {Boolean} [flags.detach] Pass `true` to put the item in the
+     * {@link Ext#getDetachedBody detachedBody element}.
+     */
+    removeDocked: function(item, flags) {
+        var me = this,
+            layout, hasLayout, doDestroy, doDetach;
+
+        if (!me.dockedItems.contains(item)) {
+            return item;
+        }
+
+        // Ensure the flags are set correctly 
+        if (flags == null) {
+            doDestroy = me.autoDestroy;
+        }
+        else if (typeof flags === 'boolean') {
+            doDestroy = flags;
+        }
+        else {
+            doDestroy = ('destroy' in flags) && flags.destroy;
+            doDetach = ('detach' in flags) && flags.detach;
+        }
+
+        if (item.dock === 'left' || item.dock === 'right') {
+            me.horizontalDocks--;
+        }
+
+        layout = me.componentLayout;
+        hasLayout = layout && me.rendered;
+
+        if (hasLayout) {
+            layout.onRemove(item);
+        }
+
+        me.dockedItems.remove(item);
+
+        // destroying flag is true if the removal is taking place as part of destruction,
+        // OR if removal is intended to *cause* destruction
+        if (!item.destroyed) {
+            item.onRemoved(item.destroying || doDestroy);
+        }
+
+        me.onDockedRemove(item);
+
+        if (doDestroy) {
+            item.destroy();
+        }
+        else if (!me.destroyed) {
+            if (hasLayout) {
+                // not destroying, make any layout related removals
+                layout.afterRemove(item);
+            }
+
+            if (doDetach && item.rendered) {
+                item.detachFromBody();
+            }
+        }
+
+        if (me.hasListeners.dockedremove) {
+            me.fireEvent('dockedremove', me, item);
+        }
+
+        if (!me.destroying) {
+            me.updateLayout();
+        }
+
+        return item;
+    },
+
+    /**
+     * Moves a docked item to a different side.
+     * @param {Ext.Component} item
+     * @param {'top'/'right'/'bottom'/'left'} side
+     * @private
+     */
+    moveDocked: function(item, side) {
+        var me = this;
+
+        if (me.rendered) {
+            Ext.suspendLayouts();
+        }
+
+        me.removeDocked(item, {
+            destroy: false,
+            detach: true
+        });
+
+        item.dock = side;
+        me.addDocked(item);
+
+        if (me.rendered) {
+            if (item.frame) {
+                item.updateFrame();
+            }
+
+            Ext.resumeLayouts(true);
+        }
+    },
+
+    setupDockingRenderTpl: function(renderTpl) {
+        renderTpl.renderDockedItems = this.doRenderDockedItems;
+    }
+});

+ 225 - 0
assets/ext-7.4.0.42/classic/classic/src/container/Monitor.js

@@ -0,0 +1,225 @@
+/**
+ * This is a utility class for being able to track all items of a particular type
+ * inside any level at a container. This can be used in favour of bubbling add/remove events
+ * which can add a large perf cost when implemented globally
+ * @private
+ */
+Ext.define('Ext.container.Monitor', {
+    target: null,
+    selector: '',
+
+    scope: null,
+    addHandler: null,
+    removeHandler: null,
+    invalidateHandler: null,
+
+    clearPropertiesOnDestroy: false,
+    clearPrototypeOnDestroy: false,
+
+    disabled: 0,
+
+    constructor: function(config) {
+        Ext.apply(this, config);
+    },
+
+    destroy: function() {
+        this.unbind();
+
+        this.callParent();
+    },
+
+    bind: function(target) {
+        var me = this;
+
+        me.target = target;
+        target.on('beforedestroy', me.disable, me);
+        me.onContainerAdd(target);
+    },
+
+    unbind: function() {
+        var me = this,
+            target = me.target;
+
+        if (target && !target.destroying && !target.destroyed) {
+            me.onContainerRemove(target, target);
+            target.un('beforedestroy', me.disable, me);
+        }
+
+        me.items = Ext.destroy(me.items);
+    },
+
+    disable: function() {
+        ++this.disabled;
+    },
+
+    enable: function() {
+        if (this.disabled > 0) {
+            --this.disabled;
+        }
+    },
+
+    handleAdd: function(ct, comp) {
+        if (!this.disabled) {
+            if (Ext.ComponentQuery.is(comp, this.selector)) {
+                this.onItemAdd(comp.ownerCt, comp);
+            }
+
+            if (comp.isQueryable) {
+                this.onContainerAdd(comp);
+            }
+        }
+    },
+
+    onItemAdd: function(ct, comp) {
+        var me = this,
+            items = me.items,
+            handler = me.addHandler;
+
+        if (!me.disabled) {
+            if (handler) {
+                handler.call(me.scope || comp, comp);
+            }
+
+            if (items) {
+                items.add(comp);
+            }
+        }
+
+        // This is a temporary hack until we refactor Forms
+        // and kill off Ext.container.Monitor
+        comp.clearPropertiesOnDestroy = comp.clearPrototypeOnDestroy = false;
+    },
+
+    onItemRemove: function(ct, comp) {
+        var me = this,
+            items = me.items,
+            handler = me.removeHandler;
+
+        if (!me.disabled) {
+            if (handler) {
+                handler.call(me.scope || comp, comp);
+            }
+
+            if (items) {
+                items.remove(comp);
+            }
+        }
+    },
+
+    onContainerAdd: function(ct, preventChildren) {
+        var me = this,
+            items, len,
+            i, comp;
+
+        if (ct.isContainer) {
+            ct.on({
+                scope: me,
+                add: me.handleAdd,
+                dockedadd: me.handleAdd,
+                remove: me.handleRemove,
+                dockedremove: me.handleRemove
+            });
+        }
+
+        // Means we've been called by a parent container so the selector
+        // matchers have already been processed
+        if (preventChildren !== true) {
+            items = ct.query(me.selector);
+
+            for (i = 0, len = items.length; i < len; ++i) {
+                comp = items[i];
+                me.onItemAdd(comp.ownerCt, comp);
+            }
+        }
+
+        items = ct.query('>container');
+
+        for (i = 0, len = items.length; i < len; ++i) {
+            me.onContainerAdd(items[i], true);
+        }
+
+        // This is a temporary hack until we refactor Forms
+        // and kill off Ext.container.Monitor
+        ct.clearPropertiesOnDestroy = ct.clearPrototypeOnDestroy = false;
+    },
+
+    handleRemove: function(ct, comp) {
+        var me = this;
+
+        // During a destroy we don't want to maintain any of this information,
+        // so typically we'll be disabled here
+        if (!me.disabled) {
+            if (Ext.ComponentQuery.is(comp, me.selector)) {
+                me.onItemRemove(ct, comp);
+            }
+
+            if (comp.isQueryable) {
+                me.onContainerRemove(ct, comp);
+            }
+        }
+    },
+
+    onContainerRemove: function(ct, comp) {
+        var me = this,
+            items, i, len, item;
+
+        // If it's not a container, it means it's a queryable that isn't a container.
+        // For example a button with a menu
+        if (!comp.destroyed && comp.isContainer) {
+            me.removeCtListeners(comp);
+
+            if (!comp.destroying) {
+                items = comp.query(me.selector);
+
+                for (i = 0, len = items.length; i < len; ++i) {
+                    item = items[i];
+                    me.onItemRemove(item.ownerCt, item);
+                }
+
+                items = comp.query('container');
+
+                for (i = 0, len = items.length; i < len; ++i) {
+                    me.removeCtListeners(items[i]);
+                }
+            }
+        }
+
+        // comp destroying, or we need to invalidate the collection
+        me.invalidateItems(true);
+    },
+
+    removeCtListeners: function(ct) {
+        var me = this;
+
+        ct.un({
+            scope: me,
+            add: me.handleAdd,
+            dockedadd: me.handleAdd,
+            remove: me.handleRemove,
+            dockedremove: me.handleRemove
+        });
+    },
+
+    getItems: function() {
+        var me = this,
+            items = me.items;
+
+        if (!items) {
+            items = me.items = new Ext.util.MixedCollection();
+            items.addAll(me.target.query(me.selector));
+        }
+
+        return items;
+    },
+
+    invalidateItems: function(triggerHandler) {
+        var me = this,
+            handler = me.invalidateHandler;
+
+        if (triggerHandler && handler) {
+            handler.call(me.scope || me, me);
+        }
+
+        me.items = Ext.destroy(me.items);
+    }
+});

+ 145 - 0
assets/ext-7.4.0.42/classic/classic/src/container/Viewport.js

@@ -0,0 +1,145 @@
+/**
+ * A specialized container representing the viewable application area (the browser viewport).
+ *
+ * The Viewport renders itself to the document body, and automatically sizes itself to the size of
+ * the browser viewport and manages window resizing. There may only be one Viewport created
+ * in a page.
+ *
+ * Like any {@link Ext.container.Container Container}, a Viewport will only perform sizing
+ * and positioning on its child Components if you configure it with a {@link #layout}.
+ *
+ * A Common layout used with Viewports is {@link Ext.layout.container.Border border layout},
+ * but if the required layout is simpler, a different layout should be chosen.
+ *
+ * For example, to simply make a single child item occupy all available space, use
+ * {@link Ext.layout.container.Fit fit layout}.
+ *
+ * To display one "active" item at full size from a choice of several child items, use
+ * {@link Ext.layout.container.Card card layout}.
+ *
+ * Inner layouts are available because all {@link Ext.panel.Panel Panel}s
+ * added to the Viewport, either through its {@link #cfg-items}, or the {@link #method-add}
+ * method of any of its child Panels may themselves have a layout.
+ *
+ * The Viewport does not provide scrolling, so child Panels within the Viewport should provide
+ * for scrolling if needed using the {@link #scrollable} config.
+ *
+ * An example showing a classic application border layout:
+ *
+ *     @example
+ *     Ext.create('Ext.container.Viewport', {
+ *         layout: 'border',
+ *         items: [{
+ *             region: 'north',
+ *             html: '<h1 class="x-panel-header">Page Title</h1>',
+ *             border: false,
+ *             margin: '0 0 5 0'
+ *         }, {
+ *             region: 'west',
+ *             collapsible: true,
+ *             title: 'Navigation',
+ *             width: 150
+ *             // could use a TreePanel or AccordionLayout for navigational items
+ *         }, {
+ *             region: 'south',
+ *             title: 'South Panel',
+ *             collapsible: true,
+ *             html: 'Information goes here',
+ *             split: true,
+ *             height: 100,
+ *             minHeight: 100
+ *         }, {
+ *             region: 'east',
+ *             title: 'East Panel',
+ *             collapsible: true,
+ *             split: true,
+ *             width: 150
+ *         }, {
+ *             region: 'center',
+ *             xtype: 'tabpanel', // TabPanel itself has no title
+ *             activeTab: 0,      // First tab active by default
+ *             items: {
+ *                 title: 'Default Tab',
+ *                 html: 'The first tab\'s content. Others may be added dynamically'
+ *             }
+ *         }]
+ *     });
+ *
+ * Alternatively you can turn any normal Container (or Component) into a Viewport using
+ * the `{@link Ext.plugin.Viewport viewport plugin}`.
+ */
+Ext.define('Ext.container.Viewport', {
+    extend: 'Ext.container.Container',
+
+    requires: [
+        'Ext.plugin.Viewport',
+        'Ext.Responsive'
+    ],
+
+    alias: 'widget.viewport',
+    alternateClassName: 'Ext.Viewport',
+
+    /**
+     * @property {Boolean} isViewport
+     * `true` in this class to identify an object as an instantiated Viewport, or subclass thereof.
+     * @readonly
+     */
+
+    /**
+     * @cfg {Number} [maxUserScale=10]
+     * The maximum zoom scale. Only applicable for touch devices. Set this to 1 to
+     * disable zooming.
+     */
+
+    // Privatize config options which, if used, would interfere with the
+    // correct operation of the Viewport as the sole manager of the
+    // layout of the document body.
+
+    /**
+     * @cfg {Boolean} allowDomMove
+     * @private
+     */
+
+    /**
+     * @cfg {String/HTMLElement/Ext.dom.Element} renderTo
+     * Always renders to document body.
+     * @private
+     */
+
+    /**
+     * @cfg {Number} height
+     * Sets itself to viewport width.
+     * @private
+     */
+
+    /**
+     * @cfg {Number} width
+     * Sets itself to viewport height.
+     * @private
+     */
+
+    /**
+     * @cfg scrollable
+     * @hide
+     */
+
+    ariaRole: 'application',
+
+    responsiveConfig: true,
+
+    privates: {
+        updateResponsiveState: function() {
+            // By providing this method we are in sync with the layout suspend/resume as
+            // well as other changes to configs that need to happen during this pulse of
+            // size change.
+
+            // Since we are not using the Viewport plugin beyond applying its methods on
+            // to our prototype, we need to be Responsive ourselves and call this here:
+            this.handleViewportResize();
+
+            this.mixins.responsive.updateResponsiveState.call(this);
+        }
+    }
+}, function() {
+    Ext.plugin.Viewport.decorate(this);
+});

+ 78 - 0
assets/ext-7.4.0.42/classic/classic/src/dashboard/Column.js

@@ -0,0 +1,78 @@
+/**
+ * This class manages columns in a `Dashboard`. The primary role here is the `defaultType`
+ * config which points to `Ext.dashboard.Panel` and the self-destruct mechanism to get
+ * rid of empty columns.
+ * @protected
+ */
+Ext.define('Ext.dashboard.Column', {
+    extend: 'Ext.container.Container',
+    xtype: 'dashboard-column',
+
+    requires: [
+        'Ext.layout.container.Anchor',
+        'Ext.dashboard.Panel'
+    ],
+
+    layout: 'anchor',
+
+    isDashboardColumn: true,
+
+    defaultType: 'dashboard-panel',
+
+    cls: Ext.baseCSSPrefix + 'dashboard-column',
+
+    synthetic: true, // not user-defined
+
+    onRemove: function(dashPanel, isDestroying) {
+        var me = this,
+            ownerCt = me.ownerCt,
+            remainingSiblings,
+            numRemaining,
+            columnWidth,
+            totalColumnWidth = 0,
+            i;
+
+        // If we've just emptied this column.
+        if (ownerCt && me.items.getCount() === 0) {
+            // Collect remaining column siblings of the same row, when this one has gone.
+            remainingSiblings = Ext.Array.filter(
+                ownerCt.query('>' + me.xtype + '[rowIndex=' + me.rowIndex + ']'),
+                function(c) {
+                    return c !== me;
+                }
+            );
+
+            numRemaining = remainingSiblings.length;
+
+            // If this column is not destroyed, then remove this column (unless it is the last one!)
+            if (!me.destroying && !me.destroyed) {
+                ownerCt.remove(me);
+
+                // Down to just one column; it must take up full width
+                if (numRemaining === 1) {
+                    remainingSiblings[0].columnWidth = 1;
+                }
+                // If more than one remaining sibling, redistribute columnWidths proportionally
+                // so that they still total 1.0
+                else {
+                    for (i = 0; i < numRemaining; i++) {
+                        totalColumnWidth += remainingSiblings[i].columnWidth || 0;
+                    }
+
+                    for (i = 0; i < numRemaining; i++) {
+                        columnWidth = remainingSiblings[i].columnWidth;
+                        remainingSiblings[i].columnWidth =
+                            Math.floor(columnWidth / totalColumnWidth * 100) / 100;
+                    }
+                }
+
+                // Needed if user is *closing* the last portlet in a column as opposed
+                // to just dragging it to another place.
+                // The destruction will not force a layout
+                if (isDestroying) {
+                    ownerCt.updateLayout();
+                }
+            }
+        }
+    }
+});

+ 454 - 0
assets/ext-7.4.0.42/classic/classic/src/dashboard/Dashboard.js

@@ -0,0 +1,454 @@
+/**
+ * This class manages a drag-drop Dashboard similar to the legacy Ext JS Portal example.
+ * The user-directed layout of the Dashboard is preserved the Ext JS `stateful` mechanism
+ * to preserve potentially dynamic user sizing and collapsed states as well as order of
+ * items in their columns.
+ */
+Ext.define('Ext.dashboard.Dashboard', {
+    extend: 'Ext.panel.Panel',
+    xtype: 'dashboard',
+
+    requires: [
+        'Ext.layout.container.Dashboard',
+        'Ext.dashboard.DropZone',
+        'Ext.dashboard.Column',
+        'Ext.dashboard.Part'
+    ],
+
+    isDashboard: true,
+
+    cls: Ext.baseCSSPrefix + 'dashboard',
+
+    bodyCls: Ext.baseCSSPrefix + 'dashboard-body',
+
+    defaultType: 'dashboard-column',
+
+    scrollable: true,
+
+    layout: {
+        type: 'dashboard'
+    },
+
+    stateful: false,
+
+    idSeed: 1,
+
+    config: {
+        /**
+         * @cfg {Object} parts
+         * An object keyed by `id` for the parts that can be created for this `Dashboard`.
+         */
+        parts: null
+    },
+
+    renderConfig: {
+        /**
+         * @cfg {Number} maxColumns
+         * The maximum number of visible columns.
+         * @accessor
+         */
+        maxColumns: 4
+    },
+
+    /**
+     * @cfg {Number[]} columnWidths
+     * An array designating the width of columns in your dashboard's default state as described
+     * by the {@link #cfg-defaultContent} property. For example:
+     *
+     *     columnWidths: [
+     *        0.35,
+     *        0.40,
+     *        0.25
+     *     ]
+     *    
+     * As you can see, this array contains the default widths for the 3 columns in the dashboard's 
+     * initial view. The column widths should total to an integer value, typically 1 as shown
+     * above. When column widths exceed 1, they will be wrapped effectively creating "rows". This
+     * means that if your column widths add up to more than 1, you would still want the first few
+     * to total 1 to ensure that the first row fills the dashboard space. This applies whenever
+     * the column widths extend past an integer value.
+     * 
+     * **Note:** columnWidths will not be utilized if there is stateful information that 
+     * dictates different user saved column widths.
+     */
+
+    /**
+     * @cfg {Object[]} defaultContent
+     * An array of {@link Ext.dashboard.Part part} configuration objects that define your
+     * dashboard's default state. These should not be confused with component configurations.
+     *
+     * Each config object should also include:
+     *
+     * + `type` - The type of {@link Ext.dashboard.Part part} that you want to be generated.
+     * + `columnIndex` - The column position in which the {@link Ext.dashboard.Part part} should
+     * reside.
+     * + `height` - The desired height of the {@link Ext.dashboard.Part part} to be generated.
+     *
+     * The remaining properties are specific to your part's config object. For example:      
+     *
+     *       defaultContent: [{
+     *           type: 'rss',
+     *           columnIndex: 0,
+     *           height: 500,
+     *           feedUrl: 'http://feeds.feedburner.com/extblog'
+     *       }, {
+     *           type: 'stockTicker',
+     *           columnIndex: 1,
+     *           height: 300
+     *       }, {
+     *           type: 'stocks',
+     *           columnIndex: 1,
+     *           height: 300
+     *       }, {
+     *           type: 'rss',
+     *           columnIndex: 2,
+     *           height: 350,
+     *           feedUrl: 'http://rss.cnn.com/rss/edition.rss'
+     *       }]
+     *
+     * Default column widths are defined by {@link #cfg-columnWidths} and not in these
+     * part config objects.
+     * 
+     * **Note:** defaultContent will not be utilized if there is stateful information that 
+     * dictates different user saved positioning and componentry.
+     */
+
+    /**
+     * @event validatedrop
+     */
+
+    /**
+     * @event beforedragover
+     */
+
+    /**
+     * @event dragover
+     */
+
+    /**
+     * @event beforedrop
+     */
+
+    /**
+     * @event drop
+     */
+
+    initComponent: function() {
+        var me = this;
+
+        me.callParent();
+        me.addStateEvents('remove');
+    },
+
+    applyParts: function(parts, collection) {
+        var id, part;
+
+        if (!collection) {
+            collection = new Ext.util.Collection({
+                decoder: Ext.Factory.part
+            });
+        }
+
+        for (id in parts) {
+            part = parts[id];
+
+            if (Ext.isString(part)) {
+                part = {
+                    type: part
+                };
+            }
+
+            part.id = id;
+            part.dashboard = this;
+            collection.add(part);
+        }
+
+        return collection;
+    },
+
+    /**
+     * @private
+     */
+    getPart: function(type) {
+        var parts = this.getParts();
+
+        return parts.getByKey(type);
+    },
+
+    addNew: function(type, columnIndex, beforeAfter) {
+        var me = this,
+            part = me.getPart(type);
+
+        part.displayForm(null, null, function(config) {
+            config.type = type;
+            me.addView(config, columnIndex, beforeAfter);
+        });
+    },
+
+    addView: function(instance, columnIndex, beforeAfter) {
+        var me = this,
+            // We are only concerned with columns (ignore splitters).
+            items = me.query('dashboard-column'),
+            count = items.length,
+            index = columnIndex || 0,
+            view = instance.id ? instance : me.createView(instance),
+            columnWidths = me.columnWidths,
+            column;
+
+        if (!count) {
+            // if the layout is empty, assert a full initially
+            column = me.add(0, me.createColumn({
+                columnWidth: (Ext.isArray(columnWidths) ? columnWidths[0] : 1)
+            }));
+
+            items = [column];
+            count = 1;
+        }
+
+        if (index >= count) {
+            index = count - 1;
+            beforeAfter = 1; // after
+        }
+
+        if (!beforeAfter) {
+            column = items[index];
+
+            if (column) {
+                return column.add(view);
+            }
+        }
+
+        if (beforeAfter > 0) {
+            // after...
+            ++index;
+        }
+
+        column = me.createColumn();
+
+        if (columnWidths) {
+            column.columnWidth = columnWidths[index] || (columnWidths[index] = 1);
+        }
+
+        if (!column.items) {
+            column.items = [];
+        }
+
+        column.items.push(view);
+        column = me.add(column);
+
+        return column.items.first();
+    },
+
+    createColumn: function(config) {
+        var cycle = this.cycleLayout;
+
+        return Ext.apply({
+            items: [],
+            bubbleEvents: ['add', 'childmove', 'resize'],
+            listeners: {
+                expand: cycle,
+                collapse: cycle,
+                scope: this
+            }
+        }, config);
+    },
+
+    createView: function(config) {
+        var me = this,
+            type = config.type,
+            part = me.getPart(type),
+            view = part.createView(config);
+
+        if (!view.id) {
+            view.id = me.id + '_' + type + (me.idSeed++);
+        }
+
+        view.bubbleEvents = Ext.Array.from(view.bubbleEvents).concat(['expand', 'collapse']);
+        view.stateful = me.stateful;
+
+        view.listeners = {
+            removed: this.onItemRemoved,
+            scope: this
+        };
+
+        return view;
+    },
+
+    initEvents: function() {
+        this.callParent();
+
+        this.dd = new Ext.dashboard.DropZone(this, this.dropConfig);
+    },
+
+    /**
+     * Readjust column/splitter heights for collapsing child panels
+     * @private
+     */
+    cycleLayout: function() {
+        this.updateLayout();
+    },
+
+    doDestroy: function() {
+        if (this.dd) {
+            Ext.destroy(this.dd);
+        }
+
+        this.callParent();
+    },
+
+    //-------------------------------------------------
+    // State and Item Persistence
+
+    applyState: function(state) {
+        delete state.items;
+
+        this.callParent([state]);
+
+        // eslint-disable-next-line vars-on-top
+        var me = this,
+            columnWidths = state.columnWidths,
+            items = me.items.items,
+            length = items.length,
+            columnLength = columnWidths ? columnWidths.length : 0,
+            i;
+
+        // Splitters have not been inserted so the length is sans-splitter
+        if (columnLength) {
+            me.columnWidths = [];
+
+            for (i = 0; i < length; ++i) {
+                me.columnWidths.push(
+                    items[i].columnWidth = (i < columnLength) ? columnWidths[i] : (1 / length)
+                );
+            }
+        }
+    },
+
+    getState: function() {
+        var me = this,
+            columnWidths = [],
+            items = me.items.items,
+            state = me.callParent() || {},
+            length = items.length,
+            i, item;
+
+        for (i = 0; i < length; ++i) {
+            if (!(item = items[i]).isSplitter) {
+                columnWidths.push(item.columnWidth);
+            }
+        }
+
+        state.idSeed = me.idSeed;
+        state.items = me.serializeItems();
+
+        // only overwrite column widths if they are defined in the state
+        if (columnWidths.length) {
+            state.columnWidths = me.columnWidths = columnWidths;
+        }
+        // no column widths are defined from the state, let's remove it so any defaults
+        // can be used instead
+        else {
+            delete state.columnWidths;
+        }
+
+        return state;
+    },
+
+    initItems: function() {
+        var me = this,
+            defaultContent = me.defaultContent,
+            state;
+
+        if (me.stateful) {
+            state = Ext.state.Manager.get(me.getStateId());
+            defaultContent = (state && state.items) || defaultContent;
+        }
+
+        if (!me.items && defaultContent) {
+            me.items = me.deserializeItems(defaultContent);
+        }
+
+        me.callParent();
+    },
+
+    deserializeItems: function(serialized) {
+        var me = this,
+            length = serialized.length,
+            columns = [],
+            columnWidths = me.columnWidths,
+            maxColumns = me.getMaxColumns(),
+            column, columnIndex, columnWidth, i, item, partConfig;
+
+        for (i = 0; i < length; ++i) {
+            partConfig = serialized[i];
+            columnIndex = Math.min(partConfig.columnIndex || 0, maxColumns - 1);
+            delete partConfig.columnIndex;
+
+            if (!(column = columns[columnIndex])) {
+                columns[columnIndex] = column = me.createColumn();
+
+                columnWidth = columnWidths && columnWidths[columnIndex];
+
+                if (columnWidth) {
+                    column.columnWidth = columnWidth;
+                }
+            }
+
+            item = me.createView(partConfig);
+            column.items.push(item);
+        }
+
+        for (i = 0, length = columns.length; i < length; ++i) {
+            column = columns[i];
+
+            if (!column.columnWidth) {
+                column.columnWidth = 1 / length;
+            }
+        }
+
+        return columns;
+    },
+
+    serializeItem: function(item) {
+        return Ext.apply({
+            type: item.part.id,
+            id: item.id,
+            columnIndex: item.columnIndex
+        }, item._partConfig);
+    },
+
+    serializeItems: function() {
+        var me = this,
+            items = me.items.items,
+            length = items.length,
+            ret = [],
+            columnIndex = 0,
+            child, childItems, i, item, j, k;
+
+        for (i = 0; i < length; ++i) {
+            item = items[i];
+
+            if (!item.isSplitter) {
+                childItems = item.items.items;
+
+                for (j = 0, k = childItems.length; j < k; ++j) {
+                    child = childItems[j];
+                    child.columnIndex = columnIndex;
+                    ret.push(me.serializeItem(child));
+                }
+
+                ++columnIndex;
+            }
+        }
+
+        return ret;
+    },
+
+    onItemRemoved: function(item, column) {
+        // Removing items from a Dashboard is a persistent action, so we must remove the
+        // state data for it or leak it.
+        if (item.stateful && !item.isMoving) {
+            Ext.state.Manager.clear(item.getStateId());
+        }
+    }
+});

+ 291 - 0
assets/ext-7.4.0.42/classic/classic/src/dashboard/DropZone.js

@@ -0,0 +1,291 @@
+/**
+ * Internal class that manages drag/drop for the `Dashboard`.
+ * @private
+ */
+Ext.define('Ext.dashboard.DropZone', {
+    extend: 'Ext.dd.DropTarget',
+
+    ddScrollConfig: {
+        vthresh: 75,
+        hthresh: -1,
+        animate: true,
+        increment: 200
+    },
+
+    containerScroll: true,
+
+    // This causes overflow to go hidden during the drag so that we don't cause panels to
+    // wrap by triggering overflow.
+    overClass: Ext.baseCSSPrefix + 'dashboard-dd-over',
+
+    constructor: function(dashboard, cfg) {
+        this.dashboard = dashboard;
+        dashboard.body.ddScrollConfig = this.ddScrollConfig;
+
+        this.callParent([dashboard.body, cfg]);
+    },
+
+    getOverEvent: function(dd, e, data) {
+        var dashboard = this.dashboard,
+            dbody = dashboard.body,
+            items = dashboard.items.items,
+            bodyBox = dbody.getBox(),
+            count = items.length,
+            xy = e.getXY(),
+            orginalX = xy[0] - bodyBox.x + dbody.getScrollLeft(),
+            orginalY = xy[1] - bodyBox.y + dbody.getScrollTop(),
+            x = orginalX,
+            y = orginalY,
+            yOffset = 0,
+            rowIterationIndex = 0,
+            over = {
+                columnIndex: 0,
+                column: null,
+                dashboard: dashboard,
+                above: null,
+                extensible: false,
+                beforeAfter: 0,
+                data: data,
+                panel: data.panel,
+                rawEvent: e,
+                source: dd,
+                status: this.dropAllowed
+            },
+            t, ht, i, k, item, w, h, childCount, childItems, childItem;
+
+        for (i = 0; i < count; i += 2) {
+            item = items[i];
+
+            if (rowIterationIndex !== item.rowIndex) {
+                rowIterationIndex = item.rowIndex;
+                x = orginalX;
+
+                if (rowIterationIndex > 0) {
+                    y -= yOffset;
+                    yOffset = 0;
+                }
+            }
+
+            w = item.lastBox.width;
+            h = item.lastBox.height;
+
+            if (yOffset <= h) {
+                yOffset = h;
+            }
+
+            if (items[i + 1]) {
+                // This is for splitter
+                w += items[i + 1].lastBox.width;
+            }
+
+            if (e.within(item.el)) {
+                over.columnIndex = i;
+                over.column = item;
+                over.extensible = this.isRowExtensible(item.rowIndex);
+
+                t = Math.min(80, w * 0.2);
+                over.beforeAfter = t = (over.extensible && ((x < t) ? -1 : ((x > w - t) ? 1 : 0)));
+
+                if (!t || !over.extensible) {
+                    childItems = item.items.items;
+
+                    // if we are not on an edge OR reached maxColumns
+                    // (which means "insert the panel in between the columns"),
+                    // we need to dig one more level down
+                    for (k = 0, childCount = childItems.length; k < childCount; ++k) {
+                        childItem = childItems[k];
+                        ht = childItem.el.getHeight();
+
+                        if (y < ht / 2) {
+                            // if mouse is above the current child's top, Y coord, it
+                            // is considered as "above" the previous child
+                            over.above = childItem;
+
+                            break;
+                        }
+
+                        y -= ht;
+                    }
+
+                }
+
+                break;
+            }
+
+            x -= w;
+        }
+
+        return over;
+    },
+
+    notifyOver: function(dd, e, data) {
+        var me = this,
+            dashboard = me.dashboard,
+            hasListeners = dashboard.hasListeners,
+            over = me.getOverEvent(dd, e, data),
+            colEl = over.column && over.column.el,
+            proxy = dd.proxy,
+            aboveItem = over.above,
+            width = 0,
+            proxyProxy, colWidth, padding;
+
+        data.lastOver = over;
+
+        if ((!hasListeners.validatedrop || dashboard.fireEvent('validatedrop', over) !== false) &&
+            (!hasListeners.beforedragover || dashboard.fireEvent('beforedragover', over) !== false)) { // eslint-disable-line max-len
+            proxyProxy = dd.panelProxy.getProxy();
+
+            // make sure proxy width is fluid in different width columns
+            proxy.getProxy().setWidth('auto');
+
+            if (colEl) {
+                width = colWidth = colEl.getWidth();
+
+                // A floating column was targeted
+                if (over.beforeAfter) {
+
+                    dd.panelProxy.moveProxy(colEl.dom, colEl.dom.firstChild);
+
+                    width = colWidth / 2;
+                    proxyProxy.setWidth(width);
+                }
+                else {
+                    if (aboveItem) {
+                        dd.panelProxy.moveProxy(aboveItem.el.dom.parentNode, aboveItem.el.dom);
+                    }
+                    else {
+                        dd.panelProxy.moveProxy(colEl.dom, null);
+                    }
+
+                    proxyProxy.setWidth('auto');
+
+                }
+
+                proxyProxy.setStyle({
+                    'float': 'none',
+                    'clear': 'none',
+                    'margin-left': (over.beforeAfter > 0)
+                        ? (colWidth - width - colEl.getPadding('lr')) + 'px'
+                        : '',
+                    'margin-top': '7px'
+                });
+            }
+            else {
+                padding = dashboard.body.getPadding('lr');
+
+                proxyProxy.setStyle({
+                    'float': 'left',
+                    'clear': 'left',
+                    'margin': '0 7px 0 7px'
+                });
+
+                proxyProxy.setWidth(dashboard.body.getWidth() - padding);
+
+                // Target the innerCt for the move
+                dd.panelProxy.moveProxy(dashboard.body.dom.firstChild.firstChild, null);
+            }
+
+            this.scrollPos = dashboard.body.getScroll();
+
+            if (hasListeners.dragover) {
+                dashboard.fireEvent('dragover', over);
+            }
+        }
+
+        return over.status;
+    },
+
+    isRowExtensible: function(rowIndex) {
+        var me = this,
+            dashboard = me.dashboard,
+            maxColumns = dashboard.getMaxColumns() || 1,
+            items;
+
+        items = dashboard.query('>dashboard-column[rowIndex=' + rowIndex + ']');
+
+        return Ext.Array.from(items).length < maxColumns;
+    },
+
+    notifyDrop: function(dd, e, data) {
+        this.callParent(arguments);
+
+        // eslint-disable-next-line vars-on-top
+        var dashboard = this.dashboard,
+            over = data.lastOver,
+            panel = over.panel,
+            fromCt = panel.ownerCt,
+            toCt = over.column,
+            side = toCt ? over.beforeAfter : 1,
+            currentIndex = fromCt.items.indexOf(panel),
+            newIndex = toCt
+                ? (over.above ? toCt.items.indexOf(over.above) : toCt.items.getCount())
+                : 0,
+            colIndex, newCol,
+            hasListeners = dashboard.hasListeners;
+
+        // Same column tests
+        if (fromCt === toCt) {
+            if (fromCt.items.getCount() === 1) {
+                return;
+            }
+
+            if (!side) {
+                if (currentIndex < newIndex) {
+                    --newIndex;
+                }
+
+                if (currentIndex === newIndex) {
+                    return;
+                }
+            }
+        }
+
+        if ((hasListeners.validatedrop && dashboard.fireEvent('validatedrop', over) === false) ||
+            (hasListeners.beforedrop && dashboard.fireEvent('beforedrop', over) === false)) {
+            return;
+        }
+
+        Ext.suspendLayouts();
+
+        panel.isMoving = true;
+
+        if (side) {
+            colIndex = dashboard.items.indexOf(toCt);
+
+            // inserting into new Row ?
+            if (colIndex < 0) {
+                colIndex = dashboard.items.getCount();
+            }
+            else if (side > 0) {
+                ++colIndex;
+            }
+
+            newCol = dashboard.createColumn();
+
+            if (toCt) {
+                newCol.columnWidth = toCt.columnWidth = toCt.columnWidth / 2;
+                delete toCt.width;
+            }
+            else {
+                newCol.columnWidth = 1; // full row
+            }
+
+            toCt = dashboard.insert(colIndex, newCol);
+            newIndex = 0;
+        }
+
+        // make sure panel is visible prior to inserting so the layout doesn't ignore it
+        panel.el.dom.style.display = '';
+
+        toCt.insert(newIndex, panel);
+
+        panel.isMoving = false;
+
+        toCt.updateLayout();
+        Ext.resumeLayouts(true);
+
+        if (hasListeners.drop) {
+            dashboard.fireEvent('drop', over);
+        }
+    }
+});

+ 196 - 0
assets/ext-7.4.0.42/classic/classic/src/dashboard/Panel.js

@@ -0,0 +1,196 @@
+/**
+ * This class is used to wrap content items in the `Dashboard`. It uses an
+ * `anchor` layout by default and provides resizing on the bottom edge only.
+ * @protected
+ */
+Ext.define('Ext.dashboard.Panel', {
+    extend: 'Ext.panel.Panel',
+
+    xtype: 'dashboard-panel',
+
+    cls: Ext.baseCSSPrefix + 'dashboard-panel',
+
+    anchor: '100%',
+
+    layout: 'fit',
+
+    frame: true,
+    closable: true,
+    collapsible: true,
+    animCollapse: true,
+    titleCollapse: true,
+
+    stateful: true,
+
+    draggable: {
+        moveOnDrag: false
+    },
+
+    animateClose: true,
+
+    loadMask: true,
+    loadMessage: 'Loading...',
+
+    minHeight: 90,
+
+    resizable: true,
+    resizeHandles: 's',
+
+    // Override Panel's default doClose to provide a custom fade out effect
+    // when a portlet is removed from the portal
+    doClose: function() {
+        var me = this;
+
+        if (me.animateClose) {
+            if (!me.closing) {
+                me.closing = true;
+                me.el.animate({
+                    opacity: 0,
+                    callback: me.finishClose,
+                    scope: me
+                });
+            }
+        }
+        else {
+            me.finishClose();
+        }
+    },
+
+    finishClose: function() {
+        var me = this,
+            closeAction = me.closeAction;
+
+        me.closing = false;
+        me.fireEvent('close', me);
+
+        // The close of the last portlet within a column results in removal of both the column
+        // and its splitter.
+        // So coalesce any layouts resulting from this operation.
+        Ext.suspendLayouts();
+        me[closeAction]();
+        Ext.resumeLayouts(true);
+
+        if (closeAction === 'hide') {
+            // Restore the opacity from doClose
+            me.el.setOpacity(1);
+        }
+    },
+
+    afterRender: function() {
+        this.callParent();
+
+        if (this.loading) {
+            this.onViewBeforeLoad();
+        }
+    },
+
+    doCollapseExpand: function(flags) {
+        // Ensure the layout caused by expand or collapse does not propagate
+        // to the whole dashboard. The dashboard layout is automatically
+        // updated after the operation.
+        this._expandCollapseRoot = this._isLayoutRoot;
+        this._isLayoutRoot = true;
+        this.callParent(arguments);
+    },
+
+    afterExpand: function() {
+        this._isLayoutRoot = this._expandCollapseRoot;
+        this.callParent(arguments);
+    },
+
+    afterCollapse: function() {
+        this._isLayoutRoot = this._expandCollapseRoot;
+        this.callParent(arguments);
+    },
+
+    getLoadMask: function() {
+        var me = this,
+            loadMask = me.rendered && me.loadMask,
+            config;
+
+        if (loadMask && !loadMask.isComponent) {
+            config = {
+                target: me
+            };
+
+            if (loadMask === true) {
+                loadMask = config;
+            }
+            else {
+                Ext.apply(config, loadMask);
+            }
+
+            me.loadMask = loadMask = Ext.ComponentManager.create(config, 'loadmask');
+        }
+
+        return loadMask || null;
+    },
+
+    onAdd: function(view) {
+        this.callParent(arguments);
+
+        view.on({
+            beforeload: 'onViewBeforeLoad',
+            load: 'onViewLoaded',
+            scope: this
+        });
+    },
+
+    onViewBeforeLoad: function() {
+        var loadMask;
+
+        this.loading = true;
+        loadMask = this.getLoadMask();
+
+        if (loadMask) {
+            loadMask.show();
+        }
+    },
+
+    onViewLoaded: function() {
+        var loadMask, view, title;
+
+        this.loading = false;
+        loadMask = this.getLoadMask();
+
+        if (loadMask) {
+            loadMask.hide();
+        }
+
+        view = this.items.getAt(0);
+
+        if (view.getTitle) {
+            title = view.getTitle();
+
+            if (title) {
+                this.setTitle(title);
+            }
+        }
+    },
+
+    /**
+     * @private
+     */
+    setBox: function(box) {
+        // The resizer calls setBox which would set our left/top coordinates but
+        // that is a BAD thing in a column layout which relies on flow!
+        this.setSize(box.width, box.height);
+    },
+
+    /**
+     * @private
+     */
+    getState: function() {
+        var me = this,
+            state = me.callParent() || {};
+
+        if (!state.collapsed) {
+            me.addPropertyToState(
+                state, 'height', me.rendered ? me.getHeight() : me.height || me.minHeight || 100
+            );
+        }
+
+        return state;
+
+    }
+});

+ 201 - 0
assets/ext-7.4.0.42/classic/classic/src/dashboard/Part.js

@@ -0,0 +1,201 @@
+/**
+ * This class encapsulates the creation of items for a `Dashboard`. Generally a `Part` is a
+ * component factory that allows all parts of a common type to be easily coordinated as
+ * needed for that type. For example, an RSS feed might need certain configuration data to
+ * properly initialize. Perahps not all of this data can or should be supplied from the UI
+ * that creates new instances for the `Dashboard`.
+ *
+ * ## Part Configuration
+ *
+ * The primary role of a `Part` is to provide an abstract way to define the configuration
+ * needed to create views. For example, an RSS Part would at least need the URL for the
+ * feed.
+ *
+ * To implement this a derived class provides a `displayForm` method:
+ *
+ *      Ext.define('App.parts.RSS', {
+ *          extend: 'Ext.dashboard.Part',
+ *          alias: 'part.rss',
+ *
+ *          displayForm: function(instance, currentConfig, callback, scope) {
+ *              var me = this,
+ *                  title = instance ? 'Edit RSS Feed' : 'Add RSS Feed';
+ *
+ *              // Display a prompt using current URL as default text.
+ *              //
+ *              Ext.Msg.prompt(title, 'RSS Feed URL', function(btn, text) {
+ *                  if (btn === 'ok') {
+ *                      var config = {
+ *                          feedUrl: text
+ *                      };
+ *
+ *                      callback.call(scope || me, config);
+ *                  }
+ *              }, me, false, currentConfig ? currentConfig.feedUrl : '');
+ *          }
+ *      });
+ *
+ * The returned configuration object is used to create views. It is also passed back to
+ * `displayForm` to allow the user to edit the configuration for an existing view.
+ *
+ * ## Creating Views
+ *
+ * The next step is to define the view (the components) appropriate for the part. To
+ * continue with the above example.
+ *
+ *      Ext.define('App.parts.RSS', {
+ *          extend: 'Ext.dashboard.Part',
+ *          alias: 'part.rss',
+ *
+ *          // The viewTemplate is "component template" that is evaluated against the
+ *          // configuration (as returned by displayForm). The top-most component is
+ *          // a panel specific to the Dashboard so it can be configured but should
+ *          // not be replaced. Instead, fit an appropriate component to the panel.
+ *          //
+ *          viewTemplate: {
+ *              layout: 'fit',
+ *              items: [{
+ *                  xtype: 'feedpanel',
+ *                  feedUrl: '{feedUrl}'  // from the configuration object
+ *              }]
+ *          },
+ *
+ *          displayForm: ...
+ *      });
+ *
+ * You can instead choose to override the `createView` method if `viewTemplate` does not
+ * provide enough flexibility. It is usually a better solution to create a class (like
+ * in the above example) and pass basic configurations to it rather than over-complicate
+ * either the `viewTemplate` or a custom `createView` method.
+ *
+ * @since 5.0.0
+ */
+Ext.define('Ext.dashboard.Part', {
+    mixins: [
+        'Ext.mixin.Factoryable',
+        'Ext.mixin.Identifiable'
+    ],
+
+    requires: [
+        'Ext.util.ObjectTemplate'
+    ],
+
+    alias: 'part.part',
+
+    factoryConfig: {
+        type: 'part'
+    },
+
+    isPart: true,
+
+    /**
+     * The last assigned identifier for instances created by this `Part`.
+     * @private
+     */
+    _lastId: 0,
+
+    config: {
+        id: null,
+
+        /**
+         * The `Dashboard` instance that owns this `part`.
+         * @property {Ext.dashboard.Panel} dashboard
+         * @readonly
+         */
+        dashboard: null,
+
+        /**
+         * @cfg {Object/Ext.util.ObjectTemplate} viewTemplate
+         * The configuration object used for creating instances of this `Part`. This is
+         * used by the `createView` method to create views.
+         */
+        viewTemplate: {
+            collapsed: '{collapsed}',
+            columnIndex: '{columnIndex}',
+            id: '{id}',
+            title: '{title}',
+            height: '{height}'
+        }
+    },
+
+    viewTemplateOptions: {
+        excludeProperties: {
+            bind: 1
+        }
+    },
+
+    valueRe: /^[{][a-z]*[}]$/i,
+
+    constructor: function(config) {
+        this.initConfig(config);
+    },
+
+    applyViewTemplate: function(template) {
+        //<debug>
+        if (!Ext.isObject(template)) {
+            Ext.raise('The viewTemplate for ' + this.$className + ' is not an Object');
+        }
+        //</debug>
+
+        return Ext.util.ObjectTemplate.create(template, this.viewTemplateOptions);
+    },
+
+    /**
+     * This method should display an appropriate edit form (probably a modal `Ext.Window`
+     * or `Ext.Msg.prompt`) to get or edit configuration for an instance of this part.
+     *
+     * See the class documentation for examples on implementing this method.
+     *
+     * @param {Ext.Component} instance The already existing view or `null` if called to
+     * configure a new instance.
+     *
+     * @param {Object} currentConfig The configuration returned from this method for the
+     * existing view (`instance`) or `null` if called to configure a new instance.
+     *
+     * @param {Function} callback The function to call passing
+     * @param {Object} callback.config The configuration that defines the instance to be
+     * created. This value is passed to `createView` and applied to the `viewTemplate`.
+     *
+     * @param {Object} scope The scope with which to call the `callback`.
+     *
+     * @method displayForm
+     * @abstract
+     * @since 5.0.0
+     */
+    displayForm: function(instance, currentConfig, callback, scope) {
+        callback.call(scope || this, {});
+    },
+
+    /**
+     * This method is responsible for converting a configuration object from `displayForm`
+     * into a "view" (an object that can be passed to `Ext.widget`).
+     *
+     * If you override this method it is recommended that you `callParent` to get the view
+     * produced and then edit that result. This is because there are several private
+     * properties placed on the returned configuration object.
+     *
+     *      createView: function(config) {
+     *          var view = this.callParent([config]);
+     *
+     *          // edit view
+     *
+     *          return view;
+     *      }
+     *
+     * @param {Object} config The object returned from `displayForm`.
+     * @return {Object} The view configuration object.
+     * @protected
+     * @since 5.0.0
+     */
+    createView: function(config) {
+        var me = this,
+            template = me.getViewTemplate(),
+            ret = template.apply(config);
+
+        ret.dashboard = me.getDashboard();
+        ret.part = me;
+        ret._partConfig = config;
+
+        return ret;
+    }
+});

+ 334 - 0
assets/ext-7.4.0.42/classic/classic/src/dd/DD.js

@@ -0,0 +1,334 @@
+/*
+ * This is a derivative of the similarly named class in the YUI Library.
+ * The original license:
+ * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ * http://developer.yahoo.net/yui/license.txt
+ */
+
+/**
+ * A DragDrop implementation where the linked element follows the
+ * mouse cursor during a drag.
+ */
+Ext.define('Ext.dd.DD', {
+    extend: 'Ext.dd.DragDrop',
+    requires: ['Ext.dd.DragDropManager'],
+
+    /**
+     * Creates new DD instance.
+     * @param {String} id the id of the linked element
+     * @param {String} sGroup the group of related DragDrop items
+     * @param {Object} config an object containing configurable attributes.
+     * Valid properties for DD: scroll
+     */
+    constructor: function(id, sGroup, config) {
+        if (id) {
+            this.init(id, sGroup, config);
+        }
+    },
+
+    /**
+     * @property {Boolean} scroll
+     * When set to true, the utility automatically tries to scroll the browser
+     * window when a drag and drop element is dragged near the viewport boundary.
+     */
+    scroll: true,
+
+    /**
+     * Sets the pointer offset to the distance between the linked element's top
+     * left corner and the location the element was clicked.
+     * @param {Number} iPageX the X coordinate of the click
+     * @param {Number} iPageY the Y coordinate of the click
+     */
+    autoOffset: function(iPageX, iPageY) {
+        var x = iPageX - this.startPageX,
+            y = iPageY - this.startPageY;
+
+        this.setDelta(x, y);
+    },
+
+    /**
+     * Sets the pointer offset.  You can call this directly to force the
+     * offset to be in a particular location (e.g., pass in 0,0 to set it
+     * to the center of the object)
+     * @param {Number} iDeltaX the distance from the left
+     * @param {Number} iDeltaY the distance from the top
+     */
+    setDelta: function(iDeltaX, iDeltaY) {
+        this.deltaX = iDeltaX;
+        this.deltaY = iDeltaY;
+    },
+
+    /**
+     * Sets the drag element to the location of the mousedown or click event,
+     * maintaining the cursor location relative to the location on the element
+     * that was clicked.  Override this if you want to place the element in a
+     * location other than where the cursor is.
+     * @param {Number} iPageX the X coordinate of the mousedown or drag event
+     * @param {Number} iPageY the Y coordinate of the mousedown or drag event
+     */
+    setDragElPos: function(iPageX, iPageY) {
+        // the first time we do this, we are going to check to make sure
+        // the element has css positioning
+        var el = this.getDragEl();
+
+        this.alignElWithMouse(el, iPageX, iPageY);
+    },
+
+    /**
+     * Sets the element to the location of the mousedown or click event,
+     * maintaining the cursor location relative to the location on the element
+     * that was clicked.  Override this if you want to place the element in a
+     * location other than where the cursor is.
+     * @param {HTMLElement} el the element to move
+     * @param {Number} iPageX the X coordinate of the mousedown or drag event
+     * @param {Number} iPageY the Y coordinate of the mousedown or drag event
+     */
+    alignElWithMouse: function(el, iPageX, iPageY) {
+        var oCoord = this.getTargetCoord(iPageX, iPageY),
+            fly = el.dom ? el : Ext.fly(el, '_dd'),
+            elSize = fly.getSize(),
+            EL = Ext.Element,
+            vpSize, aCoord, newLeft, newTop;
+
+        if (!this.deltaSetXY) {
+            vpSize = this.cachedViewportSize =
+                { width: EL.getDocumentWidth(), height: EL.getDocumentHeight() };
+
+            aCoord = [
+                Math.max(0, Math.min(oCoord.x, vpSize.width - elSize.width)),
+                Math.max(0, Math.min(oCoord.y, vpSize.height - elSize.height))
+            ];
+
+            fly.setXY(aCoord);
+            newLeft = this.getLocalX(fly);
+            newTop = fly.getLocalY();
+
+            this.deltaSetXY = [newLeft - oCoord.x, newTop - oCoord.y];
+        }
+        else {
+            vpSize = this.cachedViewportSize;
+
+            this.setLocalXY(
+                fly,
+                Math.max(0, Math.min(oCoord.x + this.deltaSetXY[0], vpSize.width - elSize.width)),
+                Math.max(0, Math.min(oCoord.y + this.deltaSetXY[1], vpSize.height - elSize.height))
+            );
+        }
+
+        this.cachePosition(oCoord.x, oCoord.y);
+        this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
+
+        return oCoord;
+    },
+
+    /**
+     * Saves the most recent position so that we can reset the constraints and
+     * tick marks on-demand.  We need to know this so that we can calculate the
+     * number of pixels the element is offset from its original position.
+     *
+     * @param {Number} [iPageX] the current x position (this just makes it so we
+     * don't have to look it up again)
+     * @param {Number} [iPageY] the current y position (this just makes it so we
+     * don't have to look it up again)
+     */
+    cachePosition: function(iPageX, iPageY) {
+        var aCoord;
+
+        if (iPageX) {
+            this.lastPageX = iPageX;
+            this.lastPageY = iPageY;
+        }
+        else {
+            aCoord = Ext.fly(this.getEl()).getXY();
+
+            this.lastPageX = aCoord[0];
+            this.lastPageY = aCoord[1];
+        }
+    },
+
+    /**
+     * Auto-scroll the window if the dragged object has been moved beyond the
+     * visible window boundary.
+     * @param {Number} x the drag element's x position
+     * @param {Number} y the drag element's y position
+     * @param {Number} h the height of the drag element
+     * @param {Number} w the width of the drag element
+     * @private
+     */
+    autoScroll: function(x, y, h, w) {
+        var clientH, clientW, st, sl, bot, right, toBot, toRight, thresh, scrAmt;
+
+        if (this.scroll) {
+            // The client height
+            clientH = Ext.Element.getViewportHeight();
+
+            // The client width
+            clientW = Ext.Element.getViewportWidth();
+
+            // The amt scrolled down
+            st = this.DDMInstance.getScrollTop();
+
+            // The amt scrolled right
+            sl = this.DDMInstance.getScrollLeft();
+
+            // Location of the bottom of the element
+            bot = h + y;
+
+            // Location of the right of the element
+            right = w + x;
+
+            // The distance from the cursor to the bottom of the visible area,
+            // adjusted so that we don't scroll if the cursor is beyond the
+            // element drag constraints
+            toBot = (clientH + st - y - this.deltaY);
+
+            // The distance from the cursor to the right of the visible area
+            toRight = (clientW + sl - x - this.deltaX);
+
+            // How close to the edge the cursor must be before we scroll
+            // var thresh = (document.all) ? 100 : 40;
+            thresh = 40;
+
+            // How many pixels to scroll per autoscroll op.  This helps to reduce
+            // clunky scrolling. IE is more sensitive about this ... it needs this
+            // value to be higher.
+            scrAmt = (document.all) ? 80 : 30;
+
+            // Scroll down if we are near the bottom of the visible page and the
+            // obj extends below the crease
+            if (bot > clientH && toBot < thresh) {
+                window.scrollTo(sl, st + scrAmt);
+            }
+
+            // Scroll up if the window is scrolled down and the top of the object
+            // goes above the top border
+            if (y < st && st > 0 && y - st < thresh) {
+                window.scrollTo(sl, st - scrAmt);
+            }
+
+            // Scroll right if the obj is beyond the right border and the cursor is
+            // near the border.
+            if (right > clientW && toRight < thresh) {
+                window.scrollTo(sl + scrAmt, st);
+            }
+
+            // Scroll left if the window has been scrolled to the right and the obj
+            // extends past the left border
+            if (x < sl && sl > 0 && x - sl < thresh) {
+                window.scrollTo(sl - scrAmt, st);
+            }
+        }
+    },
+
+    /**
+     * Finds the location the element should be placed if we want to move
+     * it to where the mouse location less the click offset would place us.
+     * @param {Number} iPageX the X coordinate of the click
+     * @param {Number} iPageY the Y coordinate of the click
+     * @return {Object} An object that contains the coordinates (Object.x and Object.y)
+     * @return {Number} return.x
+     * @return {Number} return.y
+     * @private
+     */
+    getTargetCoord: function(iPageX, iPageY) {
+        var x = iPageX - this.deltaX,
+            y = iPageY - this.deltaY;
+
+        if (this.constrainX) {
+            if (x < this.minX) {
+                x = this.minX;
+            }
+
+            if (x > this.maxX) {
+                x = this.maxX;
+            }
+        }
+
+        if (this.constrainY) {
+            if (y < this.minY) {
+                y = this.minY;
+            }
+
+            if (y > this.maxY) {
+                y = this.maxY;
+            }
+        }
+
+        x = this.getTick(x, this.xTicks);
+        y = this.getTick(y, this.yTicks);
+
+        return { x: x, y: y };
+    },
+
+    /**
+     * Sets up config options specific to this class. Overrides
+     * Ext.dd.DragDrop, but all versions of this method through the
+     * inheritance chain are called
+     */
+    applyConfig: function() {
+        this.callParent();
+
+        this.scroll = (this.config.scroll !== false);
+    },
+
+    /**
+     * Event that fires prior to the onMouseDown event.  Overrides
+     * Ext.dd.DragDrop.
+     */
+    b4MouseDown: function(e) {
+        // this.resetConstraints();
+        var xy = e.getXY();
+
+        this.autoOffset(xy[0], xy[1]);
+    },
+
+    /**
+     * Event that fires prior to the onDrag event.  Overrides
+     * Ext.dd.DragDrop.
+     */
+    b4Drag: function(e) {
+        var xy = e.getXY();
+
+        this.setDragElPos(xy[0], xy[1]);
+    },
+
+    toString: function() {
+        return ("DD " + this.id);
+    },
+
+    getLocalX: function(el) {
+        return el.getLocalX();
+    },
+
+    setLocalXY: function(el, x, y) {
+        el.setLocalXY(x, y);
+    }
+
+    // ////////////////////////////////////////////////////////////////////////
+    // Debugging ygDragDrop events that can be overridden
+    // ////////////////////////////////////////////////////////////////////////
+    /*
+    startDrag: function(x, y) {
+    },
+
+    onDrag: function(e) {
+    },
+
+    onDragEnter: function(e, id) {
+    },
+
+    onDragOver: function(e, id) {
+    },
+
+    onDragOut: function(e, id) {
+    },
+
+    onDragDrop: function(e, id) {
+    },
+
+    endDrag: function(e) {
+    }
+
+    */
+});

+ 212 - 0
assets/ext-7.4.0.42/classic/classic/src/dd/DDProxy.js

@@ -0,0 +1,212 @@
+/*
+ * This is a derivative of the similarly named class in the YUI Library.
+ * The original license:
+ * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ * http://developer.yahoo.net/yui/license.txt
+ */
+
+/**
+ * A DragDrop implementation that inserts an empty, bordered div into
+ * the document that follows the cursor during drag operations.  At the time of
+ * the click, the frame div is resized to the dimensions of the linked html
+ * element, and moved to the exact location of the linked element.
+ *
+ * References to the "frame" element refer to the single proxy element that
+ * was created to be dragged in place of all DDProxy elements on the
+ * page.
+ */
+Ext.define('Ext.dd.DDProxy', {
+    extend: 'Ext.dd.DD',
+
+    statics: {
+        /**
+         * The default drag frame div id
+         * @static
+         */
+        dragElId: "ygddfdiv"
+    },
+
+    /**
+     * Creates new DDProxy.
+     * @param {String} id the id of the linked html element
+     * @param {String} sGroup the group of related DragDrop objects
+     * @param {Object} config an object containing configurable attributes.
+     * Valid properties for DDProxy in addition to those in DragDrop:
+     * 
+     * - resizeFrame
+     * - centerFrame
+     * - dragElId
+     */
+    constructor: function(id, sGroup, config) {
+        if (id) {
+            this.init(id, sGroup, config);
+            this.initFrame();
+        }
+    },
+
+    /**
+     * @property {Boolean} resizeFrame
+     * By default we resize the drag frame to be the same size as the element
+     * we want to drag (this is to get the frame effect).  We can turn it off
+     * if we want a different behavior.
+     */
+    resizeFrame: true,
+
+    /**
+     * @property {Boolean} centerFrame
+     * By default the frame is positioned exactly where the drag element is, so
+     * we use the cursor offset provided by Ext.dd.DD.  Another option that works only if
+     * you do not have constraints on the obj is to have the drag frame centered
+     * around the cursor.  Set centerFrame to true for this effect.
+     */
+    centerFrame: false,
+
+    /**
+     * Creates the proxy element if it does not yet exist
+     */
+    createFrame: function() {
+        var self = this,
+            body = document.body,
+            div,
+            s;
+
+        if (!body || !body.firstChild) {
+            Ext.defer(function() {
+                self.createFrame();
+            }, 50);
+
+            return;
+        }
+
+        div = this.getDragEl();
+
+        if (!div) {
+            div = document.createElement("div");
+            div.id = this.dragElId;
+            div.setAttribute('role', 'presentation');
+            s = div.style;
+
+            s.position = "absolute";
+            s.visibility = "hidden";
+            s.cursor = "move";
+            s.border = "2px solid #aaa";
+            s.zIndex = 999;
+
+            // appendChild can blow up IE if invoked prior to the window load event
+            // while rendering a table.  It is possible there are other scenarios
+            // that would cause this to happen as well.
+            body.insertBefore(div, body.firstChild);
+        }
+    },
+
+    /**
+     * Initialization for the drag frame element.  Must be called in the
+     * constructor of all subclasses
+     */
+    initFrame: function() {
+        this.createFrame();
+    },
+
+    applyConfig: function() {
+        this.callParent();
+
+        this.resizeFrame = (this.config.resizeFrame !== false);
+        this.centerFrame = (this.config.centerFrame);
+        this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
+    },
+
+    /**
+     * Resizes the drag frame to the dimensions of the clicked object, positions
+     * it over the object, and finally displays it
+     * @param {Number} iPageX X click position
+     * @param {Number} iPageY Y click position
+     * @private
+     */
+    showFrame: function(iPageX, iPageY) {
+        var me = this,
+            dragEl = me.getDragEl(),
+            s = dragEl.style;
+
+        me._resizeProxy();
+
+        if (me.centerFrame) {
+            me.setDelta(Math.round(parseInt(s.width, 10) / 2),
+                        Math.round(parseInt(s.height, 10) / 2));
+        }
+
+        me.setDragElPos(iPageX, iPageY);
+
+        Ext.fly(dragEl).show();
+    },
+
+    /**
+     * The proxy is automatically resized to the dimensions of the linked
+     * element when a drag is initiated, unless resizeFrame is set to false
+     * @private
+     */
+    _resizeProxy: function() {
+        var el;
+
+        if (this.resizeFrame) {
+            el = this.getEl();
+
+            Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
+        }
+    },
+
+    // overrides Ext.dd.DragDrop
+    b4MouseDown: function(e) {
+        var xy = e.getXY(),
+            x = xy[0],
+            y = xy[1];
+
+        this.autoOffset(x, y);
+        this.setDragElPos(x, y);
+    },
+
+    // overrides Ext.dd.DragDrop
+    b4StartDrag: function(x, y) {
+        // show the drag frame
+        this.showFrame(x, y);
+    },
+
+    // overrides Ext.dd.DragDrop
+    b4EndDrag: function(e) {
+        Ext.fly(this.getDragEl()).hide();
+    },
+
+    // overrides Ext.dd.DragDrop
+    // By default we try to move the element to the last location of the frame.
+    // This is so that the default behavior mirrors that of Ext.dd.DD.
+    endDrag: function(e) {
+
+        var lel = this.getEl(),
+            del = this.getDragEl();
+
+        // Show the drag frame briefly so we can get its position
+        del.style.visibility = "";
+
+        this.beforeMove();
+        // Hide the linked element before the move to get around a Safari
+        // rendering bug.
+        lel.style.visibility = "hidden";
+        Ext.dd.DDM.moveToEl(lel, del);
+        del.style.visibility = "hidden";
+        lel.style.visibility = "";
+
+        this.afterDrag();
+    },
+
+    beforeMove: function() {
+
+    },
+
+    afterDrag: function() {
+
+    },
+
+    toString: function() {
+        return ("DDProxy " + this.id);
+    }
+});

+ 196 - 0
assets/ext-7.4.0.42/classic/classic/src/dd/DDTarget.js

@@ -0,0 +1,196 @@
+/*
+ * This is a derivative of the similarly named class in the YUI Library.
+ * The original license:
+ * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+ * Code licensed under the BSD License:
+ * http://developer.yahoo.net/yui/license.txt
+ */
+
+/**
+ * A DragDrop implementation that does not move, but can be a drop
+ * target.  You would get the same result by simply omitting implementation
+ * for the event callbacks, but this way we reduce the processing cost of the
+ * event listener and the callbacks.
+ */
+Ext.define('Ext.dd.DDTarget', {
+    extend: 'Ext.dd.DragDrop',
+
+    /**
+     * Creates new DDTarget.
+     * @param {String} id the id of the element that is a drop target
+     * @param {String} sGroup the group of related DragDrop objects
+     * @param {Object} config an object containing configurable attributes.
+     * Valid properties for DDTarget in addition to those in DragDrop: none.
+     */
+    constructor: function(id, sGroup, config) {
+        if (id) {
+            this.initTarget(id, sGroup, config);
+        }
+    },
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    getDragEl: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    isValidHandleChild: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    startDrag: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    endDrag: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onDrag: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onDragDrop: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onDragEnter: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onDragOut: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onDragOver: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onInvalidDrop: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onMouseDown: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    onMouseUp: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    setXConstraint: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    setYConstraint: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    resetConstraints: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    clearConstraints: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    clearTicks: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    setInitPosition: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    setDragElId: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    setHandleElId: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    setOuterHandleElId: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    addInvalidHandleClass: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    addInvalidHandleId: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    addInvalidHandleType: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    removeInvalidHandleClass: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    removeInvalidHandleId: Ext.emptyFn,
+
+    /**
+     * Overridden and disabled. A DDTarget does not support being dragged.
+     * @method
+     */
+    removeInvalidHandleType: Ext.emptyFn,
+
+    toString: function() {
+        return ("DDTarget " + this.id);
+    }
+});

File diff suppressed because it is too large
+ 1166 - 0
assets/ext-7.4.0.42/classic/classic/src/dd/DragDrop.js


File diff suppressed because it is too large
+ 1531 - 0
assets/ext-7.4.0.42/classic/classic/src/dd/DragDropManager.js


+ 484 - 0
assets/ext-7.4.0.42/classic/classic/src/dd/DragSource.js

@@ -0,0 +1,484 @@
+/**
+ * A simple class that provides the basic implementation needed to make any element draggable.
+ */
+Ext.define('Ext.dd.DragSource', {
+    extend: 'Ext.dd.DDProxy',
+    requires: [
+        'Ext.dd.StatusProxy',
+        'Ext.dd.DragDropManager'
+    ],
+
+    /**
+     * @cfg {String} ddGroup
+     * A named drag drop group to which this object belongs.  If a group is specified, then this
+     * object will only interact with other drag drop objects in the same group.
+     */
+
+    /**
+     * @property {Object} dragData
+     * This property contains the data representing the dragged object. This data is set up
+     * by the implementation of the {@link #getDragData} method. It must contain a ddel property,
+     * but can contain any other data according to the application's needs.
+     */
+
+    /**
+     * @cfg {String} dropAllowed
+     * The CSS class returned to the drag source when drop is allowed.
+     */
+    dropAllowed: Ext.baseCSSPrefix + 'dd-drop-ok',
+    /**
+     * @cfg {String} dropNotAllowed
+     * The CSS class returned to the drag source when drop is not allowed.
+     */
+    dropNotAllowed: Ext.baseCSSPrefix + 'dd-drop-nodrop',
+
+    /**
+     * @cfg {Boolean} animRepair
+     * If true, animates the proxy element back to the position of the handle element used to
+     * trigger the drag.
+     */
+    animRepair: true,
+
+    /**
+     * @cfg {String} repairHighlightColor
+     * The color to use when visually highlighting the drag source in the afterRepair
+     * method after a failed drop (defaults to light blue). The color must be a 6 digit hex value,
+     * without a preceding '#'.
+     */
+    repairHighlightColor: 'c3daf9',
+
+    /**
+     * Creates new drag-source.
+     * @param {String/HTMLElement/Ext.dom.Element} el The container element or ID of it.
+     * @param {Object} config (optional) Config object.
+     */
+    constructor: function(el, config) {
+        this.el = Ext.get(el);
+
+        if (!this.dragData) {
+            this.dragData = {};
+        }
+
+        Ext.apply(this, config);
+
+        if (!this.proxy) {
+            this.proxy = new Ext.dd.StatusProxy({
+                id: this.el.id + '-drag-status-proxy',
+                animRepair: this.animRepair
+            });
+        }
+
+        this.callParent(
+            [this.el.dom, this.ddGroup || this.group,
+             { dragElId: this.proxy.id, resizeFrame: false, isTarget: false,
+               scroll: this.scroll === true }]
+        );
+
+        this.dragging = false;
+    },
+
+    /**
+     * Returns the data object associated with this drag source
+     * @return {Object} data An object containing arbitrary data
+     */
+    getDragData: function(e) {
+        return this.dragData;
+    },
+
+    /**
+     * @private
+     */
+    onDragEnter: function(e, id) {
+        var target = Ext.dd.DragDropManager.getDDById(id),
+            status;
+
+        this.cachedTarget = target;
+
+        if (this.beforeDragEnter(target, e, id) !== false) {
+            if (target.isNotifyTarget) {
+                status = target.notifyEnter(this, e, this.dragData);
+                this.proxy.setStatus(status);
+            }
+            else {
+                this.proxy.setStatus(this.dropAllowed);
+            }
+
+            if (this.afterDragEnter) {
+                /**
+                 * An empty function by default, but provided so that you can perform a custom
+                 * action when the dragged item enters the drop target by providing
+                 * an implementation.
+                 * @param {Ext.dd.DragDrop} target The drop target
+                 * @param {Event} e The event object
+                 * @param {String} id The id of the dragged element
+                 * @method afterDragEnter
+                 */
+                this.afterDragEnter(target, e, id);
+            }
+        }
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action
+     * before the dragged item enters the drop target and optionally cancel the onDragEnter.
+     * @param {Ext.dd.DragDrop} target The drop target
+     * @param {Event} e The event object
+     * @param {String} id The id of the dragged element
+     * @return {Boolean} isValid True if the drag event is valid, else false to cancel
+     * @template
+     */
+    beforeDragEnter: function(target, e, id) {
+        return true;
+    },
+
+    /**
+     * @private
+     */
+    onDragOver: function(e, id) {
+        var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id),
+            status;
+
+        if (this.beforeDragOver(target, e, id) !== false) {
+            if (target.isNotifyTarget) {
+                status = target.notifyOver(this, e, this.dragData);
+                this.proxy.setStatus(status);
+            }
+
+            if (this.afterDragOver) {
+                /**
+                 * An empty function by default, but provided so that you can perform a custom
+                 * action while the dragged item is over the drop target by providing
+                 * an implementation.
+                 * @param {Ext.dd.DragDrop} target The drop target
+                 * @param {Event} e The event object
+                 * @param {String} id The id of the dragged element
+                 * @method afterDragOver
+                 */
+                this.afterDragOver(target, e, id);
+            }
+        }
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action
+     * while the dragged item is over the drop target and optionally cancel the onDragOver.
+     * @param {Ext.dd.DragDrop} target The drop target
+     * @param {Event} e The event object
+     * @param {String} id The id of the dragged element
+     * @return {Boolean} isValid True if the drag event is valid, else false to cancel
+     * @template
+     */
+    beforeDragOver: function(target, e, id) {
+        return true;
+    },
+
+    /**
+     * @private
+     */
+    onDragOut: function(e, id) {
+        var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
+
+        if (this.beforeDragOut(target, e, id) !== false) {
+            if (target.isNotifyTarget) {
+                target.notifyOut(this, e, this.dragData);
+            }
+
+            this.proxy.reset();
+
+            if (this.afterDragOut) {
+                /**
+                 * An empty function by default, but provided so that you can perform a custom
+                 * action after the dragged item is dragged out of the target without dropping.
+                 * @param {Ext.dd.DragDrop} target The drop target
+                 * @param {Event} e The event object
+                 * @param {String} id The id of the dragged element
+                 * @method afterDragOut
+                 */
+                this.afterDragOut(target, e, id);
+            }
+        }
+
+        this.cachedTarget = null;
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action before
+     * the dragged item is dragged out of the target without dropping, and optionally cancel
+     * the onDragOut.
+     * @param {Ext.dd.DragDrop} target The drop target
+     * @param {Event} e The event object
+     * @param {String} id The id of the dragged element
+     * @return {Boolean} isValid True if the drag event is valid, else false to cancel
+     * @template
+     */
+    beforeDragOut: function(target, e, id) {
+        return true;
+    },
+
+    /**
+     * @private
+     */
+    onDragDrop: function(e, id) {
+        var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
+
+        if (this.beforeDragDrop(target, e, id) !== false) {
+            if (target.isNotifyTarget) {
+                if (target.notifyDrop(this, e, this.dragData) !== false) { // valid drop?
+                    this.onValidDrop(target, e, id);
+                }
+                else {
+                    this.onInvalidDrop(target, e, id);
+                }
+            }
+            else {
+                this.onValidDrop(target, e, id);
+            }
+
+            if (this.afterDragDrop) {
+                /**
+                 * An empty function by default, but provided so that you can perform a custom
+                 * action after a valid drag drop has occurred by providing an implementation.
+                 * @param {Ext.dd.DragDrop} target The drop target
+                 * @param {Event} e The event object
+                 * @param {String} id The id of the dropped element
+                 * @method afterDragDrop
+                 */
+                this.afterDragDrop(target, e, id);
+            }
+        }
+
+        delete this.cachedTarget;
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action before
+     * the dragged item is dropped onto the target and optionally cancel the onDragDrop.
+     * @param {Ext.dd.DragDrop} target The drop target
+     * @param {Event} e The event object
+     * @param {String} id The id of the dragged element
+     * @return {Boolean} isValid True if the drag drop event is valid, else false to cancel
+     * @template
+     */
+    beforeDragDrop: function(target, e, id) {
+        return true;
+    },
+
+    /**
+     * @private
+     */
+    onValidDrop: function(target, e, id) {
+        this.hideProxy();
+
+        if (this.afterValidDrop) {
+            /**
+             * An empty function by default, but provided so that you can perform a custom action
+             * after a valid drop has occurred by providing an implementation.
+             * @param {Object} target The target DD
+             * @param {Event} e The event object
+             * @param {String} id The id of the dropped element
+             * @method afterValidDrop
+             */
+            this.afterValidDrop(target, e, id);
+        }
+    },
+
+    /**
+     * @private
+     */
+    getRepairXY: function(e, data) {
+        return this.el.getXY();
+    },
+
+    /**
+     * @private
+     */
+    onInvalidDrop: function(target, e, id) {
+        // This method may be called by the DragDropManager.
+        // To preserve backwards compat, it only passes the event object
+        // Here we correct the arguments.
+        var me = this;
+
+        if (!e) {
+            e = target;
+            target = null;
+            id = e.getTarget().id;
+        }
+
+        if (me.beforeInvalidDrop(target, e, id) !== false) {
+            if (me.cachedTarget) {
+                if (me.cachedTarget.isNotifyTarget) {
+                    me.cachedTarget.notifyOut(me, e, me.dragData);
+                }
+
+                me.cacheTarget = null;
+            }
+
+            me.proxy.repair(me.getRepairXY(e, me.dragData), me.afterRepair, me);
+
+            if (me.afterInvalidDrop) {
+                /**
+                * An empty function by default, but provided so that you can perform a custom action
+                * after an invalid drop has occurred by providing an implementation.
+                * @param {Event} e The event object
+                * @param {String} id The id of the dropped element
+                * @method afterInvalidDrop
+                */
+                me.afterInvalidDrop(e, id);
+            }
+        }
+    },
+
+    /**
+     * @private
+     */
+    afterRepair: function() {
+        var me = this;
+
+        if (Ext.enableFx) {
+            me.el.highlight(me.repairHighlightColor);
+        }
+
+        me.dragging = false;
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action after
+     * an invalid drop has occurred.
+     * @param {Ext.dd.DragDrop} target The drop target
+     * @param {Event} e The event object
+     * @param {String} id The id of the dragged element
+     * @return {Boolean} isValid True if the invalid drop should proceed, else false to cancel
+     * @template
+     */
+    beforeInvalidDrop: function(target, e, id) {
+        return true;
+    },
+
+    /**
+     * @private
+     */
+    handleMouseDown: function(e) {
+        var data;
+
+        if (this.dragging) {
+            return;
+        }
+
+        data = this.getDragData(e);
+
+        if (data && this.onBeforeDrag(data, e) !== false) {
+            this.dragData = data;
+            this.proxy.stop();
+            this.callParent(arguments);
+        }
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action before
+     * the initial drag event begins and optionally cancel it.
+     * @param {Object} data An object containing arbitrary data to be shared with drop targets
+     * @param {Event} e The event object
+     * @return {Boolean} isValid True if the drag event is valid, else false to cancel
+     * @template
+     */
+    onBeforeDrag: function(data, e) {
+        return true;
+    },
+
+    /**
+     * An empty function by default, but provided so that you can perform a custom action once
+     * the initial drag event has begun.  The drag cannot be canceled from this function.
+     * @param {Number} x The x position of the click on the dragged object
+     * @param {Number} y The y position of the click on the dragged object
+     * @method
+     * @template
+     */
+    onStartDrag: Ext.emptyFn,
+
+    alignElWithMouse: function() {
+        this.proxy.ensureAttachedToBody(true);
+
+        return this.callParent(arguments);
+    },
+
+    /**
+     * @private
+     */
+    startDrag: function(x, y) {
+        this.proxy.reset();
+        this.proxy.hidden = false;
+        this.dragging = true;
+        this.proxy.update("");
+        this.onInitDrag(x, y);
+        this.proxy.show();
+    },
+
+    /**
+     * @private
+     */
+    onInitDrag: function(x, y) {
+        var clone = this.el.dom.cloneNode(true);
+
+        clone.id = Ext.id(); // prevent duplicate ids
+        this.proxy.update(clone);
+        this.onStartDrag(x, y);
+
+        return true;
+    },
+
+    /**
+     * Returns the drag source's underlying {@link Ext.dd.StatusProxy}
+     * @return {Ext.dd.StatusProxy} proxy The StatusProxy
+     */
+    getProxy: function() {
+        return this.proxy;
+    },
+
+    /**
+     * Hides the drag source's {@link Ext.dd.StatusProxy}
+     */
+    hideProxy: function() {
+        this.proxy.hide();
+        this.proxy.reset(true);
+        this.dragging = false;
+    },
+
+    /**
+     * @private
+     */
+    triggerCacheRefresh: function() {
+        Ext.dd.DDM.refreshCache(this.groups);
+    },
+
+    /**
+     * @private
+     */
+    b4EndDrag: function(e) {
+    },
+
+    /**
+     * @private
+     */
+    endDrag: function(e) {
+        this.onEndDrag(this.dragData, e);
+    },
+
+    /**
+     * @private
+     */
+    onEndDrag: function(data, e) {
+    },
+
+    /**
+     * @private
+     */
+    autoOffset: function(x, y) {
+        this.setDelta(-12, -20);
+    },
+
+    destroy: function() {
+        Ext.destroy(this.proxy);
+
+        this.callParent();
+    }
+});

+ 777 - 0
assets/ext-7.4.0.42/classic/classic/src/dd/DragTracker.js

@@ -0,0 +1,777 @@
+/**
+ * A DragTracker listens for drag events on an Element and fires events at the start and end of the
+ * drag, as well as during the drag. This is useful for components such as {@link Ext.slider.Multi},
+ * where there is an element that can be dragged around to change the Slider's value.
+ *
+ * DragTracker provides a series of template methods that should be overridden to provide
+ * functionality in response to detected drag operations. These are onBeforeStart, onStart, onDrag,
+ * onCancel and onEnd.
+ * See {@link Ext.slider.Multi}'s initEvents function for an example implementation.
+ */
+Ext.define('Ext.dd.DragTracker', {
+    uses: ['Ext.util.Region'],
+
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    /**
+     * @property {Boolean} active
+     * Indicates whether the user is currently dragging this tracker.
+     * @readonly
+     */
+    active: false,
+
+    /**
+     * @property {HTMLElement} dragTarget
+     * The element being dragged.
+     *
+     * Only valid during drag operations.
+     *
+     * If the {@link #delegate} option is used, this will be the delegate element which was
+     * mousedowned.
+     * @readonly
+     */
+
+    /**
+     * @cfg {Boolean} trackOver
+     * Set to true to fire mouseover and mouseout events when the mouse enters or leaves the target
+     * element.
+     *
+     * This is implicitly set when an {@link #overCls} is specified.
+     *
+     * If the {@link #delegate} option is used, these events fire only when a delegate element
+     * is entered of left.
+     */
+    trackOver: false,
+
+    /**
+     * @cfg {String} overCls
+     * A CSS class to add to the DragTracker's target element when the element (or, if the
+     * {@link #delegate} option is used, when a delegate element) is mouseovered.
+     *
+     * If the {@link #delegate} option is used, these events fire only when a delegate element
+     * is entered of left.
+     */
+
+    /**
+     * @cfg {Ext.util.Region/Ext.dom.Element} constrainTo
+     * A {@link Ext.util.Region Region} (Or an element from which a Region measurement will be read)
+     * which is used to constrain the result of the {@link #getOffset} call.
+     *
+     * This may be set any time during the DragTracker's lifecycle to set a dynamic constraining
+     * region.
+     */
+
+    /**
+     * @cfg {Number} tolerance
+     * Number of pixels the drag target must be moved before dragging is
+     * considered to have started.
+     */
+    tolerance: 5,
+
+    /**
+     * @cfg {Boolean/Number} autoStart
+     * Specify `true` to defer trigger start by 1000 ms.
+     * Specify a Number for the number of milliseconds to defer trigger start.
+     */
+    autoStart: false,
+
+    /**
+     * @cfg {Ext.dom.Element/HTMLElement/String} el
+     * The target element or ID of the element on which the DragTracker will be initialized.
+     */
+
+    /**
+     * @cfg {String} delegate
+     * A CSS selector which identifies child elements within the DragTracker's encapsulating
+     * Element which are the tracked elements. This limits tracking to only begin when the matching
+     * elements are mousedowned.
+     *
+     * This may also be a specific child element within the DragTracker's encapsulating element
+     * to use as the tracked element.
+     */
+
+    /**
+     * @cfg {Boolean} [preventDefault=true]
+     * Specify `false` to enable default actions on onMouseDown events.
+     */
+
+    /**
+     * @cfg {Boolean} [stopEvent=false]
+     * Specify `true` to stop the `mousedown` event from bubbling to outer listeners from the target
+     * element (or its delegates).
+     */
+
+    /**
+     * @event mouseover
+     * Fires when the mouse enters the DragTracker's target element (or if {@link #delegate} is
+     * used, when the mouse enters a delegate element).
+     *
+     * **Only available when {@link #trackOver} is `true`**
+     *
+     * @param {Object} this
+     * @param {Object} e event object
+     * @param {HTMLElement} target The element mouseovered.
+     */
+
+    /**
+     * @event mouseout
+     * Fires when the mouse exits the DragTracker's target element (or if {@link #delegate} is
+     * used, when the mouse exits a delegate element).
+     * 
+     * **Only available when {@link #trackOver} is `true`**
+     *
+     * @param {Object} this
+     * @param {Object} e event object
+     */
+
+    /**
+     * @event mousedown
+     * Fires when the mouse button is pressed down, but before a drag operation begins. The
+     * drag operation begins after either the mouse has been moved by {@link #tolerance} pixels,
+     * or after the {@link #autoStart} timer fires.
+     *
+     * Return `false` to veto the drag operation.
+     *
+     * @param {Object} this
+     * @param {Object} e event object
+     */
+
+    /**
+     * @event mouseup
+     * @param {Object} this
+     * @param {Object} e event object
+     */
+
+    /**
+     * @event mousemove
+     * Fired when the mouse is moved. Returning false cancels the drag operation.
+     * @param {Object} this
+     * @param {Object} e event object
+     */
+
+    /**
+     * @event beforedragstart
+     * @param {Object} this
+     * @param {Object} e event object
+     */
+
+    /**
+     * @event dragstart
+     * @param {Object} this
+     * @param {Object} e event object
+     */
+
+    /**
+     * @event dragend
+     * @param {Object} this
+     * @param {Object} e event object
+     */
+
+    /**
+     * @event drag
+     * @param {Object} this
+     * @param {Object} e event object
+     */
+
+    constructor: function(config) {
+        var me = this;
+
+        Ext.apply(me, config);
+
+        me.dragRegion = new Ext.util.Region(0, 0, 0, 0);
+
+        if (me.el) {
+            me.initEl(me.el);
+        }
+
+        // Dont pass the config so that it is not applied to 'this' again
+        me.mixins.observable.constructor.call(me);
+
+        if (me.disabled) {
+            me.disable();
+        }
+
+        if (Ext.supports.Touch) {
+            Ext.getWin().on({
+                touchstart: 'onWindowTouchStart',
+                scope: me,
+                capture: true
+            });
+        }
+    },
+
+    /**
+     * Initializes the DragTracker on a given element.
+     * @param {Ext.dom.Element/HTMLElement/String} el The element or element ID
+     */
+    initEl: function(el) {
+        var me = this,
+            delegate = me.delegate,
+            elCmp, touchScrollable, unselectable;
+
+        me.el = el = Ext.get(el);
+
+        // Disable drag to select. We must take over any drag selecting gestures.
+
+        // The delegate option may also be an element on which to listen
+        if (delegate) {
+            if (delegate.isElement) {
+                me.handle = delegate;
+                unselectable = delegate;
+            }
+        }
+        else {
+            unselectable = el;
+        }
+
+        // Only make the element unselectable if we have a known delegate, or this item
+        // is to be dragged. Otherwise it's too wide of a net to cast, callers will need
+        // to apply unselectable to the appropriate delegated elements to get the same effect.
+        if (unselectable) {
+            unselectable.addCls(Ext.baseCSSPrefix + 'unselectable');
+        }
+
+        // If delegate specified an actual element to listen on, we do not use
+        // the delegate listener option
+        me.delegate = me.handle ? undefined : me.delegate;
+
+        // See if the handle or delegates are inside the scrolling part of the component.
+        // If they are, we will need to use longpress to trigger the dragstart.
+        if (Ext.supports.Touch) {
+            elCmp = Ext.Component.from(el);
+            touchScrollable = elCmp && elCmp.getScrollable();
+
+            if (touchScrollable) {
+                elCmp = touchScrollable.getElement();
+
+                if (me.handle && !elCmp.contains(me.handle)) {
+                    touchScrollable = false;
+                }
+                else if (me.delegate && !elCmp.down(me.delegate)) {
+                    touchScrollable = false;
+                }
+                else {
+                    touchScrollable = touchScrollable.getX() || touchScrollable.getY();
+                }
+            }
+        }
+
+        if (!me.handle) {
+            me.handle = el;
+        }
+
+        // Add a mousedown listener which reacts only on the elements targeted
+        // by the delegate config.
+        // We process mousedown to begin tracking.
+        me.handleListeners = {
+            scope: me,
+            delegate: me.delegate,
+            dragstart: me.onDragStart
+        };
+
+        // If the element is part of a component which is scrollable by touch
+        // then we have to use a longpress to trigger drag.
+        // In this case, we also use untranslated mousedown because of multi input platforms.
+        if (touchScrollable) {
+            me.handleListeners.longpress = me.onMouseDown;
+            me.handleListeners.mousedown = {
+                fn: me.onMouseDown,
+                delegate: me.delegate,
+                translate: false
+            };
+
+            me.handleListeners.contextmenu = function(e) {
+                e.stopEvent();
+            };
+        }
+        else {
+            me.handleListeners.mousedown = me.onMouseDown;
+        }
+
+        // If configured to do so, track mouse entry and exit into the target (or delegate).
+        // The mouseover and mouseout CANNOT be replaced with mouseenter and mouseleave
+        // because delegate cannot work with those pseudoevents. Entry/exit checking is done
+        // in the handler.
+        if (!Ext.supports.TouchEvents && (me.trackOver || me.overCls)) {
+            Ext.apply(me.handleListeners, {
+                mouseover: me.onMouseOver,
+                mouseout: me.onMouseOut
+            });
+        }
+
+        me.mon(me.handle, me.handleListeners);
+
+        // Accessibility
+        me.keyNav = new Ext.util.KeyNav({
+            target: el,
+            up: me.onResizeKeyDown,
+            left: me.onResizeKeyDown,
+            right: me.onResizeKeyDown,
+            down: me.onResizeKeyDown,
+            scope: me
+        });
+    },
+
+    disable: function() {
+        this.disabled = true;
+    },
+
+    enable: function() {
+        this.disabled = false;
+    },
+
+    destroy: function() {
+        // endDrag has a mandatory event parameter
+        this.endDrag({});
+        Ext.destroy(this.keyNav);
+        this.callParent();
+    },
+
+    onWindowTouchStart: function(e) {
+        if (this.mouseIsDown) {
+            // on devices that support multi-touch the second touch terminates drag
+            this.onMouseUp(e);
+        }
+    },
+
+    // When the pointer enters a tracking element, fire a mouseover if the mouse entered
+    // from outside. This is mouseenter functionality, but we cannot use mouseenter because
+    // we are using "delegate" to filter mouse targets
+    onMouseOver: function(e, target) {
+        var me = this,
+            handleCls, el, i, len, cls;
+
+        if (!me.disabled) {
+            // Note that usually `delegate` is the same as `handleCls` just with a preceding '.'
+            // Also, we're now adding the classes directly to the resizer el rather than to
+            // an ancestor since this caused unwanted scrollbar flickering in IE 9 and less
+            // (both quirks and standards) when the panel contained a textarea with auto overflow.
+            // It would cause an unwanted recalc as the ancestor had classes added and removed.
+            // See EXTJS-11673.
+            if (e.within(e.target, true, true) || me.delegate) {
+                handleCls = me.handleCls;
+                me.mouseIsOut = false;
+
+                if (handleCls) {
+                    for (i = 0, len = me.handleEls.length; i < len; i++) {
+                        el = me.handleEls[i];
+                        cls = el.delegateCls;
+
+                        if (!cls) {
+                            cls = el.delegateCls = [handleCls, '-', el.region, '-over'].join('');
+                        }
+
+                        el.addCls([cls, me.overCls]);
+                    }
+                }
+
+                me.fireEvent(
+                    'mouseover', me, e, me.delegate ? e.getTarget(me.delegate, target) : me.handle
+                );
+            }
+        }
+    },
+
+    // When the pointer exits a tracking element, fire a mouseout.
+    // This is mouseleave functionality, but we cannot use mouseleave because we are using
+    // "delegate" to filter mouse targets
+    onMouseOut: function(e) {
+        var me = this,
+            el, i, len;
+
+        if (me.mouseIsDown) {
+            me.mouseIsOut = true;
+        }
+        else {
+            if (me.handleCls) {
+                for (i = 0, len = me.handleEls.length; i < len; i++) {
+                    el = me.handleEls[i];
+                    el.removeCls([el.delegateCls, me.overCls]);
+                }
+            }
+
+            me.fireEvent('mouseout', me, e);
+        }
+    },
+
+    onMouseDown: function(e, target) {
+        var me = this,
+            // If this is a translated event, the event object is chained, so
+            // we need to track on the parentEvent if it exists.
+            trackEvent = e.parentEvent || e;
+
+        // Ignore all mousedown events that were not started by the primary button
+        // If this is disabled, or the mousedown has been processed by an upstream DragTracker,
+        // return
+        if (e.button || me.disabled || trackEvent.dragTracked) {
+            return;
+        }
+
+        // This information should be available in mousedown listener and onBeforeStart
+        // implementations
+        me.dragTarget = me.delegate ? target : me.handle.dom;
+        me.startXY = me.lastXY = e.getXY();
+        me.startRegion = Ext.fly(me.dragTarget).getRegion();
+
+        if (me.fireEvent('mousedown', me, e) === false ||
+            me.fireEvent('beforedragstart', me, e) === false ||
+            me.onBeforeStart(e) === false) {
+            return;
+        }
+
+        // Track when the mouse is down so that mouseouts while the mouse is down are not processed.
+        // The onMouseOut method will only ever be called after mouseup.
+        me.mouseIsDown = true;
+
+        // Flag for downstream DragTracker instances that the mouse is being tracked.
+        trackEvent.dragTracked = true;
+
+        // See Ext.dd.DragDropManager::handleMouseDown
+        //<feature legacyBrowser>
+        me.el.setCapture();
+        //</feature>
+
+        e.stopPropagation();
+
+        if (me.preventDefault !== false || e.pointerType === 'touch') {
+            e.preventDefault();
+        }
+
+        Ext.getDoc().on({
+            scope: me,
+            capture: true,
+            mouseup: me.onMouseUp,
+            mousemove: me.onMouseMove,
+            selectstart: me.stopSelect
+        });
+
+        // Flag for the onMouseMove method.
+        // If endDrag is called while active via some other code such as a timer, or key event
+        // then it sets dragEnded to indicate to any subsequent mousemove event that
+        // it should not proceed.
+        me.dragEnded = false;
+
+        if (!me.tolerance) {
+            me.triggerStart();
+        }
+        else if (me.autoStart) {
+            me.timer =
+                Ext.defer(me.triggerStart, me.autoStart === true ? 1000 : me.autoStart, me, [e]);
+        }
+    },
+
+    onMouseMove: function(e, target) {
+        var me = this,
+            xy = e.getXY(),
+            s = me.startXY;
+
+        e.stopPropagation();
+
+        if (me.preventDefault !== false) {
+            e.preventDefault();
+        }
+
+        // If, during a drag, some other action (eg a keystroke) hides or destroys the target,
+        // endDrag will be called and the mousemove listener removed. But is the mouse is down
+        // events continue to be delivered to the handler. If this happens, active will be false
+        // here.
+        if (me.dragEnded) {
+            return;
+        }
+
+        me.lastXY = xy;
+
+        if (!me.active) {
+            if (Math.max(Math.abs(s[0] - xy[0]), Math.abs(s[1] - xy[1])) > me.tolerance) {
+                me.triggerStart(e);
+            }
+            else {
+                return;
+            }
+        }
+
+        // Returning false from a mousemove listener deactivates
+        if (me.fireEvent('mousemove', me, e) === false) {
+            me.onMouseUp(e);
+        }
+        else {
+            me.onDrag(e);
+            me.fireEvent('drag', me, e);
+        }
+    },
+
+    onMouseUp: function(e) {
+        var me = this;
+
+        // Clear the flag which ensures onMouseOut fires only after the mouse button
+        // is lifted if the mouseout happens *during* a drag.
+        me.mouseIsDown = false;
+
+        // If we mouseouted the el *during* the drag, the onMouseOut method will not have fired.
+        // Ensure that it gets processed.
+        if (me.mouseIsOut) {
+            me.mouseIsOut = false;
+            me.onMouseOut(e);
+        }
+
+        if (me.preventDefault !== false) {
+            e.preventDefault();
+        }
+
+        // See Ext.dd.DragDropManager::handleMouseDown
+        if (Ext.isIE && document.releaseCapture) {
+            document.releaseCapture();
+        }
+
+        me.fireEvent('mouseup', me, e);
+        me.endDrag(e);
+    },
+
+    /**
+     * @private
+     * Stop the drag operation, and remove active mouse listeners.
+     */
+    endDrag: function(e) {
+        var me = this,
+            wasActive = me.active;
+
+        Ext.getDoc().un({
+            mousemove: me.onMouseMove,
+            mouseup: me.onMouseUp,
+            selectstart: me.stopSelect,
+            capture: true,
+            scope: me
+        });
+        me.clearStart();
+        me.active = false;
+        me.dragEnded = true;
+
+        if (wasActive) {
+            me.onEnd(e);
+            me.fireEvent('dragend', me, e);
+        }
+        else {
+            me.onCancel(e);
+        }
+
+        // Private property calculated when first required and only cached during a drag
+        me._constrainRegion = null;
+    },
+
+    triggerStart: function(e) {
+        var me = this;
+
+        me.clearStart();
+        me.active = true;
+        me.onStart(e);
+        me.fireEvent('dragstart', me, e);
+    },
+
+    clearStart: function() {
+        var timer = this.timer;
+
+        if (timer) {
+            Ext.undefer(timer);
+            this.timer = null;
+        }
+    },
+
+    stopSelect: function(e) {
+        e.stopEvent();
+
+        return false;
+    },
+
+    /**
+     * Template method which should be overridden by each DragTracker instance. Called when the user
+     * first clicks and holds the mouse button down. Return false to disallow the drag
+     * @param {Ext.event.Event} e The event object
+     * @template
+     */
+    onBeforeStart: function(e) {
+
+    },
+
+    /**
+     * Template method which should be overridden by each DragTracker instance. Called when a drag
+     * operation starts (e.g. the user has moved the tracked element beyond the specified tolerance)
+     * @param {Ext.event.Event} e The event object
+     * @template
+     */
+    onStart: function(e) {
+
+    },
+
+    /**
+     * Template method which should be overridden by each DragTracker instance. Called whenever
+     * a drag has been detected.
+     * @param {Ext.event.Event} e The event object
+     * @template
+     */
+    onDrag: function(e) {
+
+    },
+
+    /**
+     * Template method which mey be overridden by each DragTracker instance. Called when a mouseup
+     * gesture is detected but the onStart has not yet been reached. To clear things up
+     * that may have been set up on {@link #onBeforeStart}.
+     * @param {Ext.event.Event} e The event object
+     * @template
+     */
+    onCancel: function(e) {
+
+    },
+
+    /**
+     * Template method which should be overridden by each DragTracker instance. Called when a drag
+     * operation has been completed (e.g. the user clicked and held the mouse down, dragged
+     * the element and then released the mouse button)
+     * @param {Ext.event.Event} e The event object
+     * @template
+     */
+    onEnd: function(e) {
+
+    },
+
+    /**
+     * Returns the drag target. This is usually the DragTracker's encapsulating element.
+     *
+     * If the {@link #delegate} option is being used, this may be a child element which matches the
+     * {@link #delegate} selector.
+     *
+     * @return {Ext.dom.Element} The element currently being tracked.
+     */
+    getDragTarget: function() {
+        return this.dragTarget;
+    },
+
+    /**
+     * @private
+     * @return {Ext.dom.Element} The DragTracker's encapsulating element.
+     */
+    getDragCt: function() {
+        return this.el;
+    },
+
+    /**
+     * @private
+     * Return the Region into which the drag operation is constrained.
+     * Either the XY pointer itself can be constrained, or the dragTarget element
+     * The private property _constrainRegion is cached until onMouseUp
+     */
+    getConstrainRegion: function() {
+        var me = this;
+
+        if (me.constrainTo) {
+            if (me.constrainTo instanceof Ext.util.Region) {
+                return me.constrainTo;
+            }
+
+            if (!me._constrainRegion) {
+                me._constrainRegion = Ext.fly(me.constrainTo).getViewRegion();
+            }
+        }
+        else {
+            if (!me._constrainRegion) {
+                me._constrainRegion = me.getDragCt().getViewRegion();
+            }
+        }
+
+        return me._constrainRegion;
+    },
+
+    getXY: function(constrain) {
+        return constrain ? this.constrainModes[constrain](this, this.lastXY) : this.lastXY;
+    },
+
+    /**
+     * Returns the X, Y offset of the current mouse position from the mousedown point.
+     *
+     * This method may optionally constrain the real offset values, and returns a point coerced
+     * in one of two modes:
+     *
+     *  - `point` The current mouse position is coerced into the constrainRegion and the resulting
+     * position is returned.
+     *  - `dragTarget` The new {@link Ext.util.Region Region} of the
+     * {@link #getDragTarget dragTarget} is calculated based upon the current mouse position,
+     * and then coerced into the constrainRegion. The returned mouse position is then adjusted
+     * by the same delta as was used to coerce the region.
+     *
+     * @param {String} constrain (Optional) If omitted the true mouse position is returned.
+     * May be passed as `point` or `dragTarget`. See above.
+     * @return {Number[]} The `X, Y` offset from the mousedown point, optionally constrained.
+     */
+    getOffset: function(constrain) {
+        var xy = this.getXY(constrain),
+            s = this.startXY;
+
+        return [xy[0] - s[0], xy[1] - s[1]];
+    },
+
+    onDragStart: function(e) {
+        e.stopPropagation();
+    },
+
+    constrainModes: {
+        // Constrain the passed point to within the constrain region
+        point: function(me, xy) {
+            var dr = me.dragRegion,
+                constrainTo = me.getConstrainRegion();
+
+            // No constraint
+            if (!constrainTo) {
+                return xy;
+            }
+
+            dr.x = dr.left = dr[0] = dr.right = xy[0];
+            dr.y = dr.top = dr[1] = dr.bottom = xy[1];
+            dr.constrainTo(constrainTo);
+
+            return [dr.left, dr.top];
+        },
+
+        // Constrain the dragTarget to within the constrain region. Return the passed xy
+        // adjusted by the same delta.
+        dragTarget: function(me, xy) {
+            var s = me.startXY,
+                dr = me.startRegion.copy(),
+                constrainTo = me.getConstrainRegion(),
+                adjust;
+
+            // No constraint
+            if (!constrainTo) {
+                return xy;
+            }
+
+            // See where the passed XY would put the dragTarget if translated by the unconstrained
+            // offset. If it overflows, we constrain the passed XY to bring the potential
+            // region back within the boundary.
+            dr.translateBy(xy[0] - s[0], xy[1] - s[1]);
+
+            // Constrain the X coordinate by however much the dragTarget overflows
+            if (dr.right > constrainTo.right) {
+                xy[0] += adjust = (constrainTo.right - dr.right);    // overflowed the right
+                dr.left += adjust;
+            }
+
+            if (dr.left < constrainTo.left) {
+                xy[0] += (constrainTo.left - dr.left);      // overflowed the left
+            }
+
+            // Constrain the Y coordinate by however much the dragTarget overflows
+            if (dr.bottom > constrainTo.bottom) {
+                xy[1] += adjust = (constrainTo.bottom - dr.bottom);  // overflowed the bottom
+                dr.top += adjust;
+            }
+
+            if (dr.top < constrainTo.top) {
+                xy[1] += (constrainTo.top - dr.top);        // overflowed the top
+            }
+
+            return xy;
+        }
+    }
+});

+ 147 - 0
assets/ext-7.4.0.42/classic/classic/src/dd/DragZone.js

@@ -0,0 +1,147 @@
+/**
+ * This class provides a container DD instance that allows dragging of multiple child source nodes.
+ *
+ * This class does not move the drag target nodes, but a proxy element which may contain any DOM
+ * structure you wish. The DOM element to show in the proxy is provided by either a provided
+ * implementation of {@link #getDragData}, or by registered draggables registered with
+ * {@link Ext.dd.Registry}
+ *
+ * If you wish to provide draggability for an arbitrary number of DOM nodes, each of which represent
+ * some application object (For example nodes in a {@link Ext.view.View DataView}) then use of this
+ * class is the most efficient way to "activate" those nodes.
+ *
+ * By default, this class requires that draggable child nodes are registered with
+ * {@link Ext.dd.Registry}. However a simpler way to allow a DragZone to manage any number
+ * of draggable elements is to configure the DragZone with an implementation of the
+ * {@link #getDragData} method which interrogates the passed mouse event to see if it has taken
+ * place within an element, or class of elements. This is easily done by using the event's {@link
+ * Ext.event.Event#getTarget getTarget} method to identify a node based on a CSS selector.
+ * For example, to make the nodes of a DataView draggable, use the following technique.
+ * Knowledge of the use of the DataView is required:
+ *
+ *     myDataView.on('render', function(v) {
+ *         myDataView.dragZone = new Ext.dd.DragZone(v.getEl(), {
+ *
+ *     //      On receipt of a mousedown event, see if it is within a DataView node.
+ *     //      Return a drag data object if so.
+ *             getDragData: function(e) {
+ *
+ *     //          Use the DataView's own itemSelector (a mandatory property) to
+ *     //          test if the mousedown is within one of the DataView's nodes.
+ *                 var sourceEl = e.getTarget(v.itemSelector, 10);
+ *
+ *     //          If the mousedown is within a DataView node, clone the node to produce
+ *     //          a ddel element for use by the drag proxy. Also add application data
+ *     //          to the returned data object.
+ *                 if (sourceEl) {
+ *                     d = sourceEl.cloneNode(true);
+ *                     d.id = Ext.id();
+ *                     return {
+ *                         ddel: d,
+ *                         sourceEl: sourceEl,
+ *                         repairXY: Ext.fly(sourceEl).getXY(),
+ *                         sourceStore: v.store,
+ *                         draggedRecord: v.getRecord(sourceEl)
+ *                     }
+ *                 }
+ *             },
+ *
+ *     //      Provide coordinates for the proxy to slide back to on failed drag.
+ *     //      This is the original XY coordinates of the draggable element captured
+ *     //      in the getDragData method.
+ *             getRepairXY: function() {
+ *                 return this.dragData.repairXY;
+ *             }
+ *         });
+ *     });
+ *
+ * See the {@link Ext.dd.DropZone DropZone} documentation for details about building a DropZone
+ * which cooperates with this DragZone.
+ */
+Ext.define('Ext.dd.DragZone', {
+    extend: 'Ext.dd.DragSource',
+
+    /**
+     * Creates new DragZone.
+     * @param {String/HTMLElement/Ext.dom.Element} el The container element or ID of it.
+     * @param {Object} config
+     */
+    constructor: function(el, config) {
+        var me = this,
+            scroll;
+
+        me.callParent([el, config]);
+
+        scroll = me.containerScroll;
+
+        if (scroll) {
+            el = me.scrollEl || el;
+            el = Ext.get(el);
+
+            if (Ext.isObject(scroll)) {
+                el.ddScrollConfig = scroll;
+            }
+
+            Ext.dd.ScrollManager.register(el);
+        }
+    },
+
+    /**
+     * @cfg {Object/Boolean} containerScroll
+     * True to register this container with the Scrollmanager for auto scrolling during
+     * drag operations.
+     * A {@link Ext.dd.ScrollManager} configuration may also be passed.
+     */
+
+    /**
+     * @cfg {String/HTMLElement/Ext.dom.Element} scrollEl
+     * An element to register with the ScrollManager if {@link #containerScroll}
+     * is set. Defaults to the drag element.
+     */
+
+    /**
+     * Called when a mousedown occurs in this container. Looks in {@link Ext.dd.Registry}
+     * for a valid target to drag based on the mouse down. Override this method to provide your own
+     * lookup logic (e.g. finding a child by class name). Make sure your returned object
+     * has a "ddel" attribute (with an HTML Element) for other functions to work.
+     * @param {Event} e The mouse down event
+     * @return {Object} The dragData
+     */
+    getDragData: function(e) {
+        return Ext.dd.Registry.getHandleFromEvent(e);
+    },
+
+    /**
+     * Called once drag threshold has been reached to initialize the proxy element.
+     * By default, it clones the this.dragData.ddel
+     * @param {Number} x The x position of the click on the dragged object
+     * @param {Number} y The y position of the click on the dragged object
+     * @return {Boolean} true to continue the drag, false to cancel
+     * @template
+     */
+    onInitDrag: function(x, y) {
+        this.proxy.update(this.dragData.ddel.cloneNode(true));
+        this.onStartDrag(x, y);
+
+        return true;
+    },
+
+    /**
+     * Called before a repair of an invalid drop to get the XY to animate to.
+     * By default returns the XY of this.dragData.ddel
+     * @param {Event} e The mouse up event
+     * @return {Number[]} The xy location (e.g. `[100, 200]`)
+     * @template
+     */
+    getRepairXY: function(e) {
+        return Ext.fly(this.dragData.ddel).getXY();
+    },
+
+    destroy: function() {
+        if (this.containerScroll) {
+            Ext.dd.ScrollManager.unregister(this.scrollEl || this.el);
+        }
+
+        this.callParent();
+    }
+});

+ 146 - 0
assets/ext-7.4.0.42/classic/classic/src/dd/DropTarget.js

@@ -0,0 +1,146 @@
+/**
+ * A simple class that provides the basic implementation needed to make any element a drop target
+ * that can have draggable items dropped onto it.  The drop has no effect until an implementation
+ * of notifyDrop is provided.
+ */
+Ext.define('Ext.dd.DropTarget', {
+    extend: 'Ext.dd.DDTarget',
+    requires: ['Ext.dd.ScrollManager'],
+
+    /**
+     * Creates new DropTarget.
+     * @param {String/HTMLElement/Ext.dom.Element} el The container element or ID of it.
+     * @param {Object} config
+     */
+    constructor: function(el, config) {
+        this.el = Ext.get(el);
+
+        Ext.apply(this, config);
+
+        if (this.containerScroll) {
+            Ext.dd.ScrollManager.register(this.el);
+        }
+
+        this.callParent([this.el.dom, this.ddGroup || this.group,
+                         { isTarget: true }]);
+    },
+
+    /**
+     * @cfg {Boolean} containerScroll
+     * True to register this container with the ScrollManager for auto scrolling during
+     * drag operations.
+     */
+    containerScroll: false,
+
+    /**
+     * @cfg {String} ddGroup
+     * A named drag drop group to which this object belongs.  If a group is specified, then
+     * this object will only interact with other drag drop objects in the same group.
+     */
+    /**
+     * @cfg {String} [overClass=""]
+     * The CSS class applied to the drop target element while the drag source is over it.
+     */
+    /**
+     * @cfg {String} dropAllowed
+     * The CSS class returned to the drag source when drop is allowed.
+     */
+    dropAllowed: Ext.baseCSSPrefix + 'dd-drop-ok',
+    /**
+     * @cfg {String} dropNotAllowed
+     * The CSS class returned to the drag source when drop is not allowed.
+     */
+    dropNotAllowed: Ext.baseCSSPrefix + 'dd-drop-nodrop',
+
+    /**
+     * @private
+     */
+    isTarget: true,
+
+    /**
+     * @private
+     */
+    isNotifyTarget: true,
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls once to notify this drop target that the
+     * source is now over the target.  This default implementation adds the CSS class specified
+     * by overClass (if any) to the drop element and returns the dropAllowed config value.
+     * This method should be overridden if drop validation is required.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {String} status The CSS class that communicates the drop status back to the source
+     * so that the underlying {@link Ext.dd.StatusProxy} can be updated
+     * @template
+     */
+    notifyEnter: function(source, e, data) {
+        if (this.overClass) {
+            this.el.addCls(this.overClass);
+        }
+
+        return this.dropAllowed;
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls continuously while it is being dragged over
+     * the target. This method will be called on every mouse movement while the drag source is over
+     * the drop target. This default implementation simply returns the dropAllowed config value.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {String} status The CSS class that communicates the drop status back to the source
+     * so that the underlying {@link Ext.dd.StatusProxy} can be updated
+     * @template
+     */
+    notifyOver: function(source, e, data) {
+        return this.dropAllowed;
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls once to notify this drop target
+     * that the source has been dragged out of the target without dropping.
+     * This default implementation simply removes the CSS class specified by `overClass`
+     * (if any) from the drop element.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @template
+     */
+    notifyOut: function(source, e, data) {
+        if (this.overClass) {
+            this.el.removeCls(this.overClass);
+        }
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls once to notify this drop target that
+     * the dragged item has been dropped on it. This method removes any `overClass` and returns
+     * false, so you must provide an implementation that does something to process the drop event
+     * and returns true so that the drag source's repair action does not run.
+     *
+     * You should `callParent` from an override of this method to ensure proper cleanup is
+     * performed.
+     *
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {Boolean} False if the drop was invalid.
+     * @template
+     */
+    notifyDrop: function(source, e, data) {
+        if (this.overClass) {
+            this.el.removeCls(this.overClass);
+        }
+
+        return false;
+    },
+
+    destroy: function() {
+        if (this.containerScroll) {
+            Ext.dd.ScrollManager.unregister(this.el);
+        }
+
+        this.callParent();
+    }
+});

+ 291 - 0
assets/ext-7.4.0.42/classic/classic/src/dd/DropZone.js

@@ -0,0 +1,291 @@
+/**
+ * This class provides a container DD instance that allows dropping on multiple child target nodes.
+ *
+ * By default, this class requires that child nodes accepting drop are registered with
+ * {@link Ext.dd.Registry}. However a simpler way to allow a DropZone to manage any number of target
+ * elements is to configure the DropZone with an implementation of {@link #getTargetFromEvent}
+ * which interrogates the passed mouse event to see if it has taken place within an element,
+ * or class of elements. This is easily done by using the event's
+ * {@link Ext.event.Event#getTarget getTarget} method to identify a node based on a CSS selector.
+ *
+ * Once the DropZone has detected through calling getTargetFromEvent, that the mouse is over
+ * a drop target, that target is passed as the first parameter to {@link #onNodeEnter},
+ * {@link #onNodeOver}, {@link #onNodeOut}, {@link #onNodeDrop}. You may configure the instance
+ * of DropZone with implementations of these methods to provide application-specific behaviour
+ * for these events to update both application state, and UI state.
+ *
+ * For example to make a GridPanel a cooperating target with the example illustrated in
+ * {@link Ext.dd.DragZone DragZone}, the following technique might be used:
+ *
+ *     myGridPanel.on('render', function() {
+ *         myGridPanel.dropZone = new Ext.dd.DropZone(myGridPanel.getView().scroller, {
+ *
+ *             // If the mouse is over a grid row, return that node. This is
+ *             // provided as the "target" parameter in all "onNodeXXXX"
+ *             // node event handling functions
+ *             getTargetFromEvent: function(e) {
+ *                 return e.getTarget(myGridPanel.getView().rowSelector);
+ *             },
+ *
+ *             // On entry into a target node, highlight that node.
+ *             onNodeEnter: function(target, dd, e, data) {
+ *                 Ext.fly(target).addCls('my-row-highlight-class');
+ *             },
+ *
+ *             // On exit from a target node, unhighlight that node.
+ *             onNodeOut: function(target, dd, e, data) {
+ *                 Ext.fly(target).removeCls('my-row-highlight-class');
+ *             },
+ *
+ *             // While over a target node, return the default drop allowed class which
+ *             // places a "tick" icon into the drag proxy.
+ *             onNodeOver: function(target, dd, e, data) {
+ *                 return Ext.dd.DropZone.prototype.dropAllowed;
+ *             },
+ *
+ *             // On node drop we can interrogate the target to find the underlying
+ *             // application object that is the real target of the dragged data.
+ *             // In this case, it is a Record in the GridPanel's Store.
+ *             // We can use the data set up by the DragZone's getDragData method to read
+ *             // any data we decided to attach in the DragZone's getDragData method.
+ *             onNodeDrop: function(target, dd, e, data) {
+ *                 var rowIndex = myGridPanel.getView().findRowIndex(target);
+ *                 var r = myGridPanel.getStore().getAt(rowIndex);
+ *                 Ext.Msg.alert('Drop gesture', 'Dropped Record id ' + data.draggedRecord.id +
+ *                     ' on Record id ' + r.id);
+ *                 return true;
+ *             }
+ *         });
+ *     }
+ *
+ * See the {@link Ext.dd.DragZone DragZone} documentation for details about building
+ * a DragZone which cooperates with this DropZone.
+ */
+Ext.define('Ext.dd.DropZone', {
+    extend: 'Ext.dd.DropTarget',
+    requires: ['Ext.dd.Registry'],
+
+    /**
+     * Returns a custom data object associated with the DOM node that is the target of the event.
+     * By default this looks up the event target in the {@link Ext.dd.Registry}, although you can
+     * override this method to provide your own custom lookup.
+     * @param {Event} e The event
+     * @return {Object} data The custom data
+     */
+    getTargetFromEvent: function(e) {
+        return Ext.dd.Registry.getTargetFromEvent(e);
+    },
+
+    /**
+     * Called when the DropZone determines that a {@link Ext.dd.DragSource} has entered a drop node
+     * that has either been registered or detected by a configured implementation of
+     * {@link #getTargetFromEvent}. This method has no default implementation and should be
+     * overridden to provide node-specific processing if necessary.
+     * @param {Object} nodeData The custom data associated with the drop node (this is the same
+     * value returned from  {@link #getTargetFromEvent} for this node)
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     */
+    onNodeEnter: function(nodeData, source, e, data) {
+
+    },
+
+    /**
+     * Called while the DropZone determines that a {@link Ext.dd.DragSource} is over a drop node
+     * that has either been registered or detected by a configured implementation of
+     * {@link #getTargetFromEvent}. The default implementation returns this.dropAllowed,
+     * so it should be overridden to provide the proper feedback.
+     * @param {Object} nodeData The custom data associated with the drop node (this is the same
+     * value returned from {@link #getTargetFromEvent} for this node)
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {String} status The CSS class that communicates the drop status back to the source
+     * so that the underlying {@link Ext.dd.StatusProxy} can be updated
+     * @template
+     */
+    onNodeOver: function(nodeData, source, e, data) {
+        return this.dropAllowed;
+    },
+
+    /**
+     * Called when the DropZone determines that a {@link Ext.dd.DragSource} has been dragged out of
+     * the drop node without dropping.  This method has no default implementation and should be
+     * overridden to provide node-specific processing if necessary.
+     * @param {Object} nodeData The custom data associated with the drop node (this is the same
+     * value returned from {@link #getTargetFromEvent} for this node)
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @template
+     */
+    onNodeOut: function(nodeData, source, e, data) {
+
+    },
+
+    /**
+     * Called when the DropZone determines that a {@link Ext.dd.DragSource} has been dropped onto
+     * the drop node.  The default implementation returns false, so it should be overridden
+     * to provide the appropriate processing of the drop event and return true so that the drag
+     * source's repair action does not run.
+     * @param {Object} nodeData The custom data associated with the drop node (this is the same
+     * value returned from
+     * {@link #getTargetFromEvent} for this node)
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {Boolean} True if the drop was valid, else false
+     * @template
+     */
+    onNodeDrop: function(nodeData, source, e, data) {
+        return false;
+    },
+
+    /**
+     * Called while the DropZone determines that a {@link Ext.dd.DragSource} is being dragged
+     * over it, but not over any of its registered drop nodes. The default implementation returns
+     * this.dropNotAllowed, so it should be overridden to provide the proper feedback if necessary.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {String} status The CSS class that communicates the drop status back to the source
+     * so that the underlying {@link Ext.dd.StatusProxy} can be updated
+     * @template
+     */
+    onContainerOver: function(source, e, data) {
+        return this.dropNotAllowed;
+    },
+
+    /**
+     * Called when the DropZone determines that a {@link Ext.dd.DragSource} has been dropped on it,
+     * but not on any of its registered drop nodes.  The default implementation returns false, so it
+     * should be overridden to provide the appropriate processing of the drop event if you need
+     * the drop zone itself to be able to accept drops. It should return true when valid so that
+     * the drag source's repair action does not run.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {Boolean} True if the drop was valid, else false
+     * @template
+     */
+    onContainerDrop: function(source, e, data) {
+        return false;
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls once to notify this drop zone that the source
+     * is now over the zone. The default implementation returns this.dropNotAllowed and expects
+     * that only registered drop nodes can process drag drop operations, so if you need the drop
+     * zone itself to be able to process drops you should override this method and provide a custom
+     * implementation.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {String} status The CSS class that communicates the drop status back to the source
+     * so that the underlying {@link Ext.dd.StatusProxy} can be updated
+     * @template
+     */
+    notifyEnter: function(source, e, data) {
+        this.callParent([source, e, data]);
+
+        return this.dropNotAllowed;
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls continuously while it is being dragged over
+     * the drop zone. This method will be called on every mouse movement while the drag source
+     * is over the drop zone. It will call {@link #onNodeOver} while the drag source is over
+     * a registered node, and will also automatically delegate to the appropriate node-specific
+     * methods as necessary when the drag source enters and exits registered nodes
+     * ({@link #onNodeEnter}, {@link #onNodeOut}). If the drag source is not currently over a
+     * registered node, it will call {@link #onContainerOver}.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {String} status The CSS class that communicates the drop status back to the source
+     * so that the
+     * underlying {@link Ext.dd.StatusProxy} can be updated
+     * @template
+     */
+    notifyOver: function(source, e, data) {
+        var me = this,
+            n = me.getTargetFromEvent(e);
+
+        if (!n) { // not over valid drop target
+            if (me.lastOverNode) {
+                me.onNodeOut(me.lastOverNode, source, e, data);
+                me.lastOverNode = null;
+            }
+
+            return me.onContainerOver(source, e, data);
+        }
+
+        if (me.lastOverNode !== n) {
+            if (me.lastOverNode) {
+                me.onNodeOut(me.lastOverNode, source, e, data);
+            }
+
+            me.onNodeEnter(n, source, e, data);
+            me.lastOverNode = n;
+        }
+
+        return me.onNodeOver(n, source, e, data);
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls once to notify this drop zone that the source
+     * has been dragged out of the zone without dropping.  If the drag source is currently over
+     * a registered node, the notification will be delegated to {@link #onNodeOut} for node-specific
+     * handling, otherwise it will be ignored.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop target
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag zone
+     * @template
+     */
+    notifyOut: function(source, e, data) {
+        this.callParent([source, e, data]);
+
+        if (this.lastOverNode) {
+            this.onNodeOut(this.lastOverNode, source, e, data);
+            this.lastOverNode = null;
+        }
+    },
+
+    /**
+     * The function a {@link Ext.dd.DragSource} calls once to notify this drop zone that the dragged
+     * item has been dropped on it.  The drag zone will look up the target node based on the event
+     * passed in, and if there is a node registered for that event, it will delegate to
+     * {@link #onNodeDrop} for node-specific handling, otherwise it will call
+     * {@link #onContainerDrop}.
+     * @param {Ext.dd.DragSource} source The drag source that was dragged over this drop zone
+     * @param {Event} e The event
+     * @param {Object} data An object containing arbitrary data supplied by the drag source
+     * @return {Boolean} False if the drop was invalid.
+     * @template
+     */
+    notifyDrop: function(source, e, data) {
+        var me = this,
+            n = me.getTargetFromEvent(e),
+            result = n
+                ? me.onNodeDrop(n, source, e, data)
+                : me.onContainerDrop(source, e, data);
+
+        // Exit the overNode upon drop.
+        // Must do this after dropping because exiting a node may perform actions
+        // which invalidate a drop.
+        if (me.lastOverNode) {
+            me.onNodeOut(me.lastOverNode, source, e, data);
+            me.lastOverNode = null;
+        }
+
+        return result;
+    },
+
+    /**
+     * @private
+     */
+    triggerCacheRefresh: function() {
+        Ext.dd.DDM.refreshCache(this.groups);
+    }
+});

+ 139 - 0
assets/ext-7.4.0.42/classic/classic/src/dd/Registry.js

@@ -0,0 +1,139 @@
+/**
+ * Provides easy access to all drag drop components that are registered on a page.
+ * Items can be retrieved either directly by DOM node id, or by passing in the drag drop event
+ * that occurred and looking up the event target.
+ */
+Ext.define('Ext.dd.Registry', {
+    singleton: true,
+    constructor: function() {
+        this.elements = {};
+        this.handles = {};
+        this.autoIdSeed = 0;
+    },
+
+    getId: function(el, autogen) {
+        var id;
+
+        if (typeof el === "string") {
+            return el;
+        }
+
+        id = el.id;
+
+        if (!id && autogen !== false) {
+            id = "extdd-" + (++this.autoIdSeed);
+            el.id = id;
+        }
+
+        return id;
+    },
+
+    /**
+     * Registers a drag drop element.
+     *
+     * @param {String/HTMLElement} el The id or DOM node to register
+     * @param {Object} data An custom data object that will be passed between the elements that are
+     * involved in drag drop operations. You can populate this object with any arbitrary properties
+     * that your own code knows how to interpret, plus there are some specific properties known to
+     * the Registry that should be populated in the data object (if applicable):
+     * @param {HTMLElement[]} data.handles Array of DOM nodes that trigger dragging for the element
+     * being registered.
+     * @param {Boolean} data.isHandle True if the element passed in triggers dragging itself,
+     * else false.
+     */
+    register: function(el, data) {
+        var hs, i, len;
+
+        data = data || {};
+
+        if (typeof el === "string") {
+            el = document.getElementById(el);
+        }
+
+        data.ddel = el;
+        this.elements[this.getId(el)] = data;
+
+        if (data.isHandle !== false) {
+            this.handles[data.ddel.id] = data;
+        }
+
+        if (data.handles) {
+            hs = data.handles;
+
+            for (i = 0, len = hs.length; i < len; i++) {
+                this.handles[this.getId(hs[i])] = data;
+            }
+        }
+    },
+
+    /**
+     * Unregister a drag drop element
+     * @param {String/HTMLElement} el The id or DOM node to unregister
+     */
+    unregister: function(el) {
+        var id = this.getId(el, false),
+            data = this.elements[id],
+            hs, i, len;
+
+        if (data) {
+            delete this.elements[id];
+
+            if (data.handles) {
+                hs = data.handles;
+
+                for (i = 0, len = hs.length; i < len; i++) {
+                    delete this.handles[this.getId(hs[i], false)];
+                }
+            }
+        }
+    },
+
+    /**
+     * Returns the handle registered for a DOM Node by id
+     * @param {String/HTMLElement} id The DOM node or id to look up
+     * @return {Object} handle The custom handle data
+     */
+    getHandle: function(id) {
+        if (typeof id !== "string") { // must be element?
+            id = id.id;
+        }
+
+        return this.handles[id];
+    },
+
+    /**
+     * Returns the handle that is registered for the DOM node that is the target of the event
+     * @param {Event} e The event
+     * @return {Object} handle The custom handle data
+     */
+    getHandleFromEvent: function(e) {
+        var t = e.getTarget();
+
+        return t ? this.handles[t.id] : null;
+    },
+
+    /**
+     * Returns a custom data object that is registered for a DOM node by id
+     * @param {String/HTMLElement} id The DOM node or id to look up
+     * @return {Object} data The custom data
+     */
+    getTarget: function(id) {
+        if (typeof id !== "string") { // must be element?
+            id = id.id;
+        }
+
+        return this.elements[id];
+    },
+
+    /**
+     * Returns a custom data object that is registered for the DOM node that is the target
+     * of the event
+     * @param {Event} e The event
+     * @return {Object} data The custom data
+     */
+    getTargetFromEvent: function(e) {
+        var t = e.getTarget();
+
+        return t ? this.elements[t.id] || this.handles[t.id] : null;
+    }
+});

+ 313 - 0
assets/ext-7.4.0.42/classic/classic/src/dd/ScrollManager.js

@@ -0,0 +1,313 @@
+/**
+ * Provides automatic scrolling of overflow regions in the page during drag operations.
+ *
+ * The ScrollManager configs will be used as the defaults for any scroll container registered
+ * with it, but you can also override most of the configs per scroll container by adding a
+ * ddScrollConfig object to the target element that contains these properties: {@link #hthresh},
+ * {@link #vthresh}, {@link #increment} and {@link #frequency}. Example usage:
+ *
+ *     var el = Ext.get('scroll-ct');
+ *     el.ddScrollConfig = {
+ *         vthresh: 50,
+ *         hthresh: -1,
+ *         frequency: 100,
+ *         increment: 200
+ *     };
+ *     Ext.dd.ScrollManager.register(el);
+ *
+ * Note: This class is designed to be used in "Point Mode
+ */
+Ext.define('Ext.dd.ScrollManager', {
+    singleton: true,
+    requires: [
+        'Ext.dd.DragDropManager'
+    ],
+
+    /**
+     * The number of pixels from the top or bottom edge of a container the pointer needs to be
+     * to trigger scrolling
+     */
+    vthresh: 25 * (window.devicePixelRatio || 1),
+
+    /**
+     * The number of pixels from the right or left edge of a container the pointer needs to be
+     * to trigger scrolling
+     */
+    hthresh: 25 * (window.devicePixelRatio || 1),
+
+    /**
+     * The number of pixels to scroll in each scroll increment
+     */
+    increment: 100,
+
+    /**
+     * The frequency of scrolls in milliseconds
+     */
+    frequency: 500,
+
+    /**
+     * True to animate the scroll
+     */
+    animate: true,
+
+    /**
+     * The animation duration in seconds - MUST BE less than Ext.dd.ScrollManager.frequency!
+     */
+    animDuration: 0.4,
+
+    /**
+     * @property {String} ddGroup
+     * The named drag drop {@link Ext.dd.DragSource#ddGroup group} to which this container belongs.
+     * If a ddGroup is specified, then container scrolling will only occur when a dragged object
+     * is in the same ddGroup.
+     */
+    ddGroup: undefined,
+
+    dirTrans: {
+        up: -1,
+        left: -1,
+        down: 1,
+        right: 1
+    },
+
+    constructor: function() {
+        var ddm = Ext.dd.DragDropManager;
+
+        ddm.fireEvents = Ext.Function.createSequence(ddm.fireEvents, this.onFire, this);
+        ddm.stopDrag = Ext.Function.createSequence(ddm.stopDrag, this.onStop, this);
+        this.doScroll = this.doScroll.bind(this);
+        this.ddmInstance = ddm;
+        this.els = {};
+        this.dragEl = null;
+        this.proc = {};
+    },
+
+    onStop: function(e) {
+        var sm = Ext.dd.ScrollManager;
+
+        sm.dragEl = null;
+        sm.clearProc();
+    },
+
+    triggerRefresh: function() {
+        if (this.ddmInstance.dragCurrent) {
+            this.ddmInstance.refreshCache(this.ddmInstance.dragCurrent.groups);
+        }
+    },
+
+    doScroll: function() {
+        var me = this;
+
+        if (me.ddmInstance.dragCurrent) {
+            // eslint-disable-next-line vars-on-top, one-var
+            var proc = me.proc,
+                procEl = proc.el,
+                scrollComponent = proc.component,
+                ddScrollConfig = proc.el.ddScrollConfig,
+                distance, animate, afterScroll;
+
+            distance = ddScrollConfig && ddScrollConfig.increment
+                ? ddScrollConfig.increment
+                : me.increment;
+
+            animate = ddScrollConfig && 'animate' in ddScrollConfig
+                ? ddScrollConfig.animate
+                : me.animate;
+
+            afterScroll = function() {
+                me.triggerRefresh();
+            };
+
+            if (animate) {
+                if (animate === true) {
+                    animate = {
+                        callback: afterScroll
+                    };
+                }
+                else {
+                    animate.callback = animate.callback
+                        ? Ext.Function.createSequence(animate.callback, afterScroll)
+                        : afterScroll;
+                }
+            }
+
+            // If the element is the overflow element of a Component, and we are scrolling
+            // using CSS transform, then scroll using the correct method!
+            if (scrollComponent) {
+
+                // Left/right means increment has to be negated
+                distance = distance * me.dirTrans[proc.dir];
+
+                // Pass X or Y params depending upon dimension being scrolled
+                if (proc.dir === 'up' || proc.dir === 'down') {
+                    scrollComponent.scrollBy(0, distance, animate);
+                }
+                else {
+                    scrollComponent.scrollBy(distance, 0, animate);
+                }
+            }
+            else {
+                procEl.scroll(proc.dir, distance, animate);
+            }
+
+            if (!animate) {
+                afterScroll();
+            }
+        }
+    },
+
+    clearProc: function() {
+        var proc = this.proc;
+
+        if (proc.id) {
+            Ext.uninterval(proc.id);
+        }
+
+        proc.id = 0;
+        proc.el = null;
+        proc.dir = "";
+    },
+
+    startProc: function(el, dir) {
+        var me = this,
+            proc = me.proc,
+            group, freq;
+
+        me.clearProc();
+        proc.el = el;
+        proc.dir = dir;
+
+        group = el.ddScrollConfig ? el.ddScrollConfig.ddGroup : undefined;
+        freq = (el.ddScrollConfig && el.ddScrollConfig.frequency)
+            ? el.ddScrollConfig.frequency
+            : me.frequency;
+
+        if (group === undefined || me.ddmInstance.dragCurrent.ddGroup === group) {
+            proc.id = Ext.interval(me.doScroll, freq);
+        }
+    },
+
+    onFire: function(e, isDrop) {
+        var me = this,
+            pt, proc, els, id, el, elementRegion, configSource, ownerCt, scrollerOwner;
+
+        if (isDrop || !me.ddmInstance.dragCurrent) {
+            return;
+        }
+
+        if (!me.dragEl || me.dragEl !== me.ddmInstance.dragCurrent) {
+            me.dragEl = me.ddmInstance.dragCurrent;
+            // refresh regions on drag start
+            me.refreshCache();
+        }
+
+        pt = e.getPoint();
+        proc = me.proc;
+        els = me.els;
+
+        for (id in els) {
+            el = els[id];
+            elementRegion = el.getRegion();
+            configSource = el.ddScrollConfig || me;
+
+            if (elementRegion && elementRegion.contains(pt)) {
+                if (!el.isScrollable()) {
+                    ownerCt = el.component && el.component.ownerCt;
+                    scrollerOwner =
+                        ownerCt && ownerCt.getScrollerOwner && ownerCt.getScrollerOwner();
+
+                    if (scrollerOwner) {
+                        el = scrollerOwner.getScrollable().getElement();
+                        elementRegion = el.getRegion();
+                    }
+                    else {
+                        continue;
+                    }
+                }
+
+                if (elementRegion.bottom - pt.y <= configSource.vthresh) {
+                    if (proc.el !== el) {
+                        me.startProc(el, "down");
+                    }
+
+                    return;
+                }
+                else if (elementRegion.right - pt.x <= configSource.hthresh) {
+                    if (proc.el !== el) {
+                        me.startProc(el, "right");
+                    }
+
+                    return;
+                }
+                else if (pt.y - elementRegion.top <= configSource.vthresh) {
+                    if (proc.el !== el) {
+                        me.startProc(el, "up");
+                    }
+
+                    return;
+                }
+                else if (pt.x - elementRegion.left <= configSource.hthresh) {
+                    if (proc.el !== el) {
+                        me.startProc(el, "left");
+                    }
+
+                    return;
+                }
+            }
+        }
+
+        me.clearProc();
+    },
+
+    /**
+     * Registers new overflow element(s) to auto scroll
+     * @param {String/HTMLElement/Ext.dom.Element/String[]/HTMLElement[]/Ext.dom.Element[]} el
+     * The id of or the element to be scrolled or an array of either
+     */
+    register: function(el) {
+        var i, len;
+
+        if (Ext.isArray(el)) {
+            for (i = 0, len = el.length; i < len; i++) {
+                this.register(el[i]);
+            }
+        }
+        else {
+            el = Ext.get(el);
+            this.els[el.id] = el;
+        }
+    },
+
+    /**
+     * Unregisters overflow element(s) so they are no longer scrolled
+     * @param {String/HTMLElement/Ext.dom.Element/String[]/HTMLElement[]/Ext.dom.Element[]} el
+     * The id of or the element to be removed or an array of either
+     */
+    unregister: function(el) {
+        var i, len;
+
+        if (Ext.isArray(el)) {
+            for (i = 0, len = el.length; i < len; i++) {
+                this.unregister(el[i]);
+            }
+        }
+        else {
+            el = Ext.get(el);
+            delete this.els[el.id];
+        }
+    },
+
+    /**
+     * Manually trigger a cache refresh.
+     */
+    refreshCache: function() {
+        var els = this.els,
+            id;
+
+        for (id in els) {
+            if (typeof els[id] === 'object') { // for people extending the object prototype
+                els[id]._region = els[id].getRegion();
+            }
+        }
+    }
+});

+ 206 - 0
assets/ext-7.4.0.42/classic/classic/src/dd/StatusProxy.js

@@ -0,0 +1,206 @@
+/**
+ * A specialized floating Component that supports a drop status icon and auto-repair.
+ * This is the default drag proxy used by all Ext.dd components.
+ */
+Ext.define('Ext.dd.StatusProxy', {
+    extend: 'Ext.Component',
+    animRepair: false,
+
+    childEls: [
+        'ghost'
+    ],
+
+    /* eslint-disable indent, max-len */
+    renderTpl: [
+        '<div class="' + Ext.baseCSSPrefix + 'dd-drop-icon" role="presentation"></div>' +
+        '<div id="{id}-ghost" data-ref="ghost" class="' + Ext.baseCSSPrefix + 'dd-drag-ghost" role="presentation"></div>'
+    ],
+    /* eslint-enable indent, max-len */
+
+    repairCls: Ext.baseCSSPrefix + 'dd-drag-repair',
+
+    ariaRole: 'presentation',
+
+    skipLayout: true,
+    alignOnScroll: false,
+
+    /**
+     * Creates new StatusProxy.
+     * @param {Object} [config] Config object.
+     */
+    constructor: function(config) {
+        var me = this;
+
+        config = config || {};
+
+        Ext.apply(me, {
+            hideMode: 'visibility',
+            hidden: true,
+            floating: true,
+            id: me.id || Ext.id(),
+            cls: Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed,
+            shadow: config.shadow || false,
+            renderTo: Ext.getDetachedBody()
+        });
+
+        me.callParent(arguments);
+
+        this.dropStatus = this.dropNotAllowed;
+    },
+
+    /**
+     * @cfg {String} dropAllowed
+     * The CSS class to apply to the status element when drop is allowed.
+     */
+    dropAllowed: Ext.baseCSSPrefix + 'dd-drop-ok',
+
+    /**
+     * @cfg {String} dropNotAllowed
+     * The CSS class to apply to the status element when drop is not allowed.
+     */
+    dropNotAllowed: Ext.baseCSSPrefix + 'dd-drop-nodrop',
+
+    /**
+     * Updates the proxy's visual element to indicate the status of whether or not drop is allowed
+     * over the current target element.
+     * @param {String} cssClass The css class for the new drop status indicator image
+     */
+    setStatus: function(cssClass) {
+        cssClass = cssClass || this.dropNotAllowed;
+
+        if (this.dropStatus !== cssClass) {
+            this.el.replaceCls(this.dropStatus, cssClass);
+            this.dropStatus = cssClass;
+        }
+    },
+
+    /**
+     * Resets the status indicator to the default dropNotAllowed value
+     * @param {Boolean} clearGhost True to also remove all content from the ghost,
+     * false to preserve it
+     */
+    reset: function(clearGhost) {
+        var me = this,
+            clsPrefix = Ext.baseCSSPrefix + 'dd-drag-proxy ';
+
+        me.el.replaceCls(clsPrefix + me.dropAllowed, clsPrefix + me.dropNotAllowed);
+        me.dropStatus = me.dropNotAllowed;
+
+        if (clearGhost) {
+            me.ghost.setHtml('');
+        }
+    },
+
+    /**
+     * Updates the contents of the ghost element
+     * @param {String/HTMLElement} html The html that will replace the current innerHTML
+     * of the ghost element, or a DOM node to append as the child of the ghost element
+     * (in which case the innerHTML will be cleared first).
+     */
+    update: function(html) {
+        var el;
+
+        if (typeof html === "string") {
+            this.ghost.setHtml(html);
+        }
+        else {
+            this.ghost.setHtml('');
+            html.style.margin = "0";
+            this.ghost.dom.appendChild(html);
+        }
+
+        el = this.ghost.dom.firstChild;
+
+        if (el) {
+            Ext.fly(el).setStyle('float', 'none');
+        }
+    },
+
+    /**
+     * Returns the ghost element
+     * @return {Ext.dom.Element} el
+     */
+    getGhost: function() {
+        return this.ghost;
+    },
+
+    /**
+     * Hides the proxy
+     * @param {Boolean} clear True to reset the status and clear the ghost contents,
+     * false to preserve them
+     */
+    hide: function(clear) {
+        this.callParent();
+
+        if (clear) {
+            this.reset(true);
+        }
+    },
+
+    /**
+     * Stops the repair animation if it's currently running
+     */
+    stop: function() {
+        if (this.anim && this.anim.isAnimated && this.anim.isAnimated()) {
+            this.anim.stop();
+        }
+    },
+
+    /**
+     * Force the Element to sync its shadow and shim positions
+     */
+    sync: function() {
+        this.el.syncUnderlays();
+    },
+
+    /**
+     * Causes the proxy to return to its position of origin via an animation.
+     * Should be called after an invalid drop operation by the item being dragged.
+     * @param {Number[]} xy The XY position of the element ([x, y])
+     * @param {Function} callback The function to call after the repair is complete.
+     * @param {Object} scope The scope (`this` reference) in which the callback function
+     * is executed. Defaults to the browser window.
+     */
+    repair: function(xy, callback, scope) {
+        var me = this;
+
+        me.callback = callback;
+        me.scope = scope;
+
+        if (xy && me.animRepair !== false) {
+            me.el.addCls(me.repairCls);
+            me.el.setUnderlaysVisible(false);
+            me.anim = me.el.animate({
+                duration: me.repairDuration || 500,
+                easing: 'ease-out',
+                to: {
+                    x: xy[0],
+                    y: xy[1]
+                },
+                stopAnimation: true,
+                callback: me.afterRepair,
+                scope: me
+            });
+        }
+        else {
+            me.afterRepair();
+        }
+    },
+
+    /**
+     * @private
+     */
+    afterRepair: function() {
+        var me = this;
+
+        me.hide(true);
+        me.el.removeCls(me.repairCls);
+
+        if (typeof me.callback === "function") {
+            me.callback.call(me.scope || me);
+        }
+
+        delete me.callback;
+        delete me.scope;
+    }
+});

+ 92 - 0
assets/ext-7.4.0.42/classic/classic/src/dom/ButtonElement.js

@@ -0,0 +1,92 @@
+/**
+ * A special Ext.dom.Element used by Buttons.  Since buttons use `display:table` elements
+ * for their layout, some special adjustments are needed when the width switches from
+ * auto to fixed width and back.
+ *
+ * When the button has a width other than `auto`, and a right-aligned arrow, long button
+ * text will cause the arrow to disappear off the right edge of the button if the btnWrap
+ * element has table-layout:auto.  To prevent this, we need to set table-layout:fixed
+ * on the btnWrap when the button has a width, however, when the button is shrinkwrap
+ * width the btnWrap cannot have table-layout:fixed because its width:100% style will
+ * cause the button to expand outward.
+ *
+ * Additionally, in shrinkWrap height mode, the button css sets a height on the btnEl
+ * element, but if the height is being stretched, the btnEl's height will cause the contents
+ * to be incorrectly vertically centered, so we dynamically set the btnEl's height to
+ * "auto" in fixed-height mode.
+ *
+ * @private
+ */
+Ext.define('Ext.dom.ButtonElement', {
+    extend: 'Ext.dom.Element',
+
+    setSize: function(width, height, animate) {
+        var me = this,
+            component = me.component;
+
+        me.callParent([width, height, animate]);
+
+        component.btnWrap.setStyle(
+            'table-layout',
+            (!width || width === 'auto') ? '' : 'fixed'
+        );
+
+        component.btnEl.setStyle(
+            'height',
+            (!height || height === 'auto') ? '' : 'auto'
+        );
+
+        return me;
+    },
+
+    setStyle: function(prop, value) {
+        var me = this,
+            component = me.component,
+            width, height;
+
+        me.callParent([prop, value]);
+
+        if (prop) {
+            if (prop === 'width' || (typeof prop !== 'string' && 'width' in prop)) {
+                width = value || prop.width;
+                component.btnWrap.setStyle(
+                    'table-layout',
+                    (!width || width === 'auto') ? '' : 'fixed'
+                );
+            }
+
+            if (prop === 'height' || (typeof prop !== 'string' && 'height' in prop)) {
+                height = value || prop.height;
+
+                component.btnEl.setStyle(
+                    'height',
+                    (!height || height === 'auto') ? '' : 'auto'
+                );
+            }
+        }
+
+        return me;
+    },
+
+    setHeight: function(height, animate) {
+        this.callParent([height, animate]);
+
+        this.component.btnEl.setStyle(
+            'height',
+            (!height || height === 'auto') ? '' : 'auto'
+        );
+
+        return this;
+    },
+
+    setWidth: function(width, animate) {
+        this.callParent([width, animate]);
+
+        this.component.btnWrap.setStyle(
+            'table-layout',
+            (!width || width === 'auto') ? '' : 'fixed'
+        );
+
+        return this;
+    }
+});

+ 187 - 0
assets/ext-7.4.0.42/classic/classic/src/dom/Layer.js

@@ -0,0 +1,187 @@
+/**
+ * An extended {@link Ext.dom.Element} object that supports a shadow and shim
+ *
+ * @deprecated 5.1.0 Ext.dom.Element now includes support for shadow and shim
+ * see {@link Ext.dom.Element#enableShadow enableShadow} and
+ * {@link Ext.dom.Element#enableShim enableShim}
+ */
+Ext.define('Ext.dom.Layer', {
+    extend: 'Ext.dom.Element',
+    alternateClassName: 'Ext.Layer',
+
+    /**
+     * @cfg {String/Boolean} [shadow=false]
+     * True to automatically create an {@link Ext.Shadow}, or a string indicating the
+     * shadow's display {@link Ext.Shadow#mode}. False to disable the shadow.
+     */
+
+    /**
+     * @cfg {String/Boolean} [shim=false]
+     * True to automatically create a {@link Ext.dom.Shim}.
+     */
+
+    /**
+     * @cfg {Object} [dh={tag: 'div', cls: 'x-layer'}]
+     * DomHelper object config to create element with.
+     */
+
+    /**
+     * @cfg {Boolean} [constrain=true]
+     * False to disable constrain to viewport.
+     */
+
+    /**
+     * @cfg {String} cls
+     * CSS class to add to the element
+     */
+
+    /**
+     * @cfg {Number} [zindex=11000]
+     * Starting z-index.
+     */
+
+    /**
+     * @cfg {Number} [shadowOffset=4]
+     * Number of pixels to offset the shadow
+     */
+
+    /**
+     * @cfg {Boolean} [useDisplay=false]
+     * Defaults to use css offsets to hide the Layer. Specify <tt>true</tt>
+     * to use css style <tt>'display:none;'</tt> to hide the Layer.
+     */
+
+    /**
+     * @cfg {String} visibilityCls
+     * The CSS class name to add in order to hide this Layer if this layer
+     * is configured with <code>{@link #hideMode}: 'asclass'</code>
+     */
+
+    /**
+     * @cfg {String} hideMode
+     * A String which specifies how this Layer will be hidden.
+     * Values may be:
+     *
+     * - `'display'` : The Component will be hidden using the `display: none` style.
+     * - `'visibility'` : The Component will be hidden using the `visibility: hidden` style.
+     * - `'offsets'` : The Component will be hidden by absolutely positioning it out of the
+     * visible area of the document. This is useful when a hidden Component must maintain
+     * measurable dimensions. Hiding using `display` results in a Component having zero dimensions.
+     */
+
+    isLayer: true,
+
+    /**
+     * Creates new Layer.
+     * @param {Object} [config] An object with config options.
+     * @param {String/HTMLElement} [existingEl] Uses an existing DOM element.
+     * If the element is not found it creates it.
+     */
+    constructor: function(config, existingEl) {
+        config = config || {};
+
+        // eslint-disable-next-line vars-on-top
+        var me = this,
+            dh = Ext.DomHelper,
+            cp = config.parentEl,
+            pel = cp ? Ext.getDom(cp) : document.body,
+            hm = config.hideMode,
+            cls = Ext.baseCSSPrefix + (config.fixed ? 'fixed-layer' : 'layer'),
+            dom, id, element, shadowConfig;
+
+        if (existingEl) {
+            dom = Ext.getDom(existingEl);
+
+            if (!dom.parentNode) {
+                pel.appendChild(dom);
+            }
+        }
+
+        if (!dom) {
+            dom = dh.append(pel, config.dh || {
+                tag: 'div',
+                cls: cls // primarily to give el 'position:absolute' or, if fixed, 'position:fixed'
+            });
+        }
+
+        if (config.id) {
+            dom.id = config.id;
+        }
+
+        id = dom.id;
+
+        if (id) {
+            element = Ext.cache[id];
+
+            if (element) {
+                // if we have an existing Ext.Element in the cache for this same dom
+                // element, delete it, so that it can be replaced by this layer instance
+                // when we callParent below.
+                delete Ext.cache[id];
+                element.dom = null;
+            }
+        }
+
+        this.callParent([dom]);
+
+        if (existingEl) {
+            me.addCls(cls);
+        }
+
+        if (config.preventSync) {
+            me.preventSync = true;
+        }
+
+        if (config.cls) {
+            me.addCls(config.cls);
+        }
+
+        me.constrain = config.constrain !== false;
+
+        // Allow Components to pass their hide mode down to the Layer if they are floating.
+        // Otherwise, allow useDisplay to override the default hiding method which is visibility.
+        // TODO: Have ExtJS's Element implement visibilityMode by using classes as in Mobile.
+        if (hm) {
+            me.setVisibilityMode(Ext.Element[hm.toUpperCase()]);
+        }
+        else if (config.useDisplay) {
+            me.setVisibilityMode(Ext.Element.DISPLAY);
+        }
+        else {
+            me.setVisibilityMode(Ext.Element.VISIBILITY);
+        }
+
+        if (config.shadow) {
+            me.shadowOffset = config.shadowOffset || 4;
+            shadowConfig = {
+                offset: me.shadowOffset,
+                fixed: config.fixed
+            };
+
+            if (config.shadow !== true) {
+                shadowConfig.mode = config.shadow;
+            }
+
+            me.enableShadow(shadowConfig);
+        }
+        else {
+            me.shadowOffset = 0;
+        }
+
+        if (config.shim) {
+            me.enableShim({
+                fixed: config.fixed
+            });
+        }
+
+        // Keep the following only for cases where Ext.Layer would be instantiated
+        // directly.  We don't ever pass hidden in the config in the framework
+        // since this is handled by the Component lifecycle.
+        if (config.hidden === true) {
+            me.hide();
+        }
+        else if (config.hidden === false) {
+            me.show();
+        }
+    }
+});

+ 24 - 0
assets/ext-7.4.0.42/classic/classic/src/enums.js

@@ -0,0 +1,24 @@
+//
+// Definitions of enums referenced in documentation.
+//
+
+/**
+ * @enum [Ext.enums.Layout=layout.*]
+ * Enumeration of all layout types.
+ */
+
+/**
+ * @enum [Ext.enums.Widget=widget.*]
+ * Enumeration of all xtypes.
+ */
+
+/**
+ * @enum [Ext.enums.Plugin=plugin.*]
+ * Enumeration of all ptypes.
+ */
+
+/**
+ * @enum [Ext.enums.Feature=feature.*]
+ * Enumeration of all ftypes.
+ */
+

+ 66 - 0
assets/ext-7.4.0.42/classic/classic/src/event/publisher/MouseEnterLeave.js

@@ -0,0 +1,66 @@
+/**
+ * A publisher that adds support for mousenter and mouseleave events on browsers that do
+ * not support those events natively
+ * @private
+ */
+Ext.define('Ext.event.publisher.MouseEnterLeave', {
+    extend: 'Ext.event.publisher.Dom',
+    type: 'mouseEnterLeave'
+}, function(MouseEnterLeave) {
+    var eventMap = {
+        mouseover: 'mouseenter',
+        mouseout: 'mouseleave'
+    };
+
+    if (!Ext.supports.MouseEnterLeave) {
+        MouseEnterLeave.override({
+            handledDomEvents: ['mouseover', 'mouseout'],
+            handledEvents: ['mouseenter', 'mouseleave'],
+
+            publishDelegatedDomEvent: function(e) {
+                var target, relatedTarget, id, el, type, event;
+
+                // call parent to dispatch the native browser event first (mouseover, mouseout)
+                this.callParent([e]);
+
+                target = e.getTarget();
+                relatedTarget = e.getRelatedTarget();
+
+                if (relatedTarget && Ext.fly(target).contains(relatedTarget)) {
+                    return;
+                }
+
+                id = target.id;
+
+                if (id) {
+                    el = Ext.cache[id];
+
+                    if (el) {
+                        type = eventMap[e.type];
+                        e = e.chain({
+                            type: type
+                        });
+
+                        if (el.hasListeners[type]) {
+                            event = el.events[type];
+
+                            if (event) {
+                                // mouseenter/leave are always tracked by the "directs"
+                                // Ext.util.Event because they are listed in the directEvents
+                                // map of Dom publisher
+                                event = event.directs;
+
+                                if (event) {
+                                    e.setCurrentTarget(el.dom);
+                                    event.fire(e, e.target);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+    MouseEnterLeave.instance = new MouseEnterLeave();
+});

+ 252 - 0
assets/ext-7.4.0.42/classic/classic/src/flash/Component.js

@@ -0,0 +1,252 @@
+/**
+ * A simple Component for displaying an Adobe Flash SWF movie. The movie will be sized and can
+ * participate in layout like any other Component.
+ *
+ * This component requires the third-party SWFObject library version 2.2 or above. It is not
+ * included within the ExtJS distribution, so you will have to include it into your page manually
+ * in order to use this component.
+ * The SWFObject library can be downloaded from the [SWFObject project page](http://code.google.com/p/swfobject)
+ * and then simply import it into the head of your HTML document:
+ *
+ *     <script type="text/javascript" src="path/to/local/swfobject.js"></script>
+ *
+ * ## Configuration
+ *
+ * This component allows several options for configuring how the target Flash movie is embedded.
+ * The most important is the required {@link #url} which points to the location of the Flash movie
+ * to load. Other configurations include:
+ *
+ * - {@link #backgroundColor}
+ * - {@link #wmode}
+ * - {@link #flashVars}
+ * - {@link #flashParams}
+ * - {@link #flashAttributes}
+ *
+ * ## Example usage:
+ *
+ *     var win = Ext.widget('window', {
+ *         title: "It's a tiger!",
+ *         layout: 'fit',
+ *         width: 300,
+ *         height: 300,
+ *         x: 20,
+ *         y: 20,
+ *         resizable: true,
+ *         items: {
+ *             xtype: 'flash',
+ *             url: 'tiger.swf'
+ *         }
+ *     });
+ *     win.show();
+ *
+ * ## Express Install
+ *
+ * Adobe provides a tool called [Express Install](http://www.adobe.com/devnet/flashplayer/articles/express_install.html)
+ * that offers users an easy way to upgrade their Flash player. If you wish to make use of this,
+ * you should set the static EXPRESS_INSTALL_URL property to the location of your Express Install
+ * SWF file:
+ *
+ *     Ext.flash.Component.EXPRESS_INSTALL_URL = 'path/to/local/expressInstall.swf';
+ */
+Ext.define('Ext.flash.Component', {
+    extend: 'Ext.Component',
+    alternateClassName: 'Ext.FlashComponent',
+    alias: 'widget.flash',
+
+    /**
+     * @cfg {String} [flashVersion="9.0.115"]
+     * Indicates the version the flash content was published for.
+     */
+    flashVersion: '9.0.115',
+
+    /**
+     * @cfg {String} [backgroundColor="#ffffff"]
+     * The background color of the SWF movie.
+     */
+    backgroundColor: '#ffffff',
+
+    /**
+     * @cfg {String} [wmode="opaque"]
+     * The wmode of the flash object. This can be used to control layering.
+     * Set to 'transparent' to ignore the {@link #backgroundColor} and make the background
+     * of the Flash movie transparent.
+     */
+    wmode: 'opaque',
+
+    /**
+     * @cfg {Object} flashVars
+     * A set of key value pairs to be passed to the flash object as flash variables.
+     */
+
+    /**
+     * @cfg {Object} flashParams
+     * A set of key value pairs to be passed to the flash object as parameters. Possible parameters
+     * can be found here: http://kb2.adobe.com/cps/127/tn_12701.html
+     */
+
+    /**
+     * @cfg {Object} flashAttributes
+     * A set of key value pairs to be passed to the flash object as attributes.
+     */
+
+    /**
+     * @cfg {String} url (required)
+     * The URL of the SWF file to include.
+     */
+
+    /**
+     * @cfg {String/Number} [swfWidth="100%"]
+     * The width of the embedded SWF movie inside the component.
+     *
+     * Defaults to "100%" so that the movie matches the width of the component.
+     */
+    swfWidth: '100%',
+
+    /**
+     * @cfg {String/Number} [swfHeight="100%"]
+     * The height of the embedded SWF movie inside the component.
+     *
+     * Defaults to "100%" so that the movie matches the height of the component.
+     */
+    swfHeight: '100%',
+
+    /**
+     * @cfg {Boolean} [expressInstall=false]
+     * True to prompt the user to install flash if not installed. Note that this uses
+     * Ext.FlashComponent.EXPRESS_INSTALL_URL, which should be set to the local resource.
+     */
+    expressInstall: false,
+
+    /**
+     * @property {Ext.dom.Element} swf
+     * A reference to the object or embed element into which the SWF file is loaded. Only
+     * populated after the component is rendered and the SWF has been successfully embedded.
+     */
+
+    // Have to create a placeholder div with the swfId, which SWFObject will replace with the
+    // object/embed element.
+    renderTpl: ['<div id="{swfId}" role="application"></div>'],
+
+    /**
+     * @event success
+     * Fired when the Flash movie has been successfully embedded
+     * @param {Ext.flash.Component} this
+     */
+
+    /**
+     * @event failure
+     * Fired when the Flash movie embedding fails
+     * @param {Ext.flash.Component} this
+     */
+
+    initComponent: function() {
+        /* global swfobject */
+        //<debug>
+        if (!('swfobject' in window)) {
+            Ext.raise('The SWFObject library is not loaded. Ext.flash.Component requires ' +
+                      'SWFObject version 2.2 or later: http://code.google.com/p/swfobject/');
+        }
+
+        if (!this.url) {
+            Ext.raise('The "url" config is required for Ext.flash.Component');
+        }
+        //</debug>
+
+        this.callParent();
+    },
+
+    beforeRender: function() {
+        this.callParent();
+
+        Ext.applyIf(this.renderData, {
+            swfId: this.getSwfId()
+        });
+    },
+
+    afterRender: function() {
+        var me = this,
+            flashParams = Ext.apply({}, me.flashParams),
+            flashVars = Ext.apply({}, me.flashVars);
+
+        me.callParent();
+
+        flashParams = Ext.apply({
+            allowScriptAccess: 'always',
+            bgcolor: me.backgroundColor,
+            wmode: me.wmode
+        }, flashParams);
+
+        flashVars = Ext.apply({
+            allowedDomain: document.location.hostname
+        }, flashVars);
+
+        new swfobject.embedSWF(
+            me.url,
+            me.getSwfId(),
+            me.swfWidth,
+            me.swfHeight,
+            me.flashVersion,
+            me.expressInstall ? me.statics.EXPRESS_INSTALL_URL : undefined,
+            flashVars,
+            flashParams,
+            me.flashAttributes,
+            me.swfCallback.bind(me)
+        );
+    },
+
+    /**
+     * @private
+     * The callback method for handling an embedding success or failure by SWFObject
+     * @param {Object} e The event object passed by SWFObject - see http://code.google.com/p/swfobject/wiki/api
+     */
+    swfCallback: function(e) {
+        var me = this;
+
+        if (e.success) {
+            me.swf = Ext.get(e.ref);
+            me.onSuccess();
+            me.fireEvent('success', me);
+        }
+        else {
+            me.onFailure();
+            me.fireEvent('failure', me);
+        }
+    },
+
+    /**
+     * Retrieves the id of the SWF object/embed element.
+     */
+    getSwfId: function() {
+        return this.swfId || (this.swfId = "extswf" + this.getAutoId());
+    },
+
+    onSuccess: function() {
+        // swfobject forces visiblity:visible on the swf element, which prevents it 
+        // from getting hidden when an ancestor is given visibility:hidden.
+        this.swf.setStyle('visibility', 'inherit');
+    },
+
+    onFailure: Ext.emptyFn,
+
+    doDestroy: function() {
+        var me = this,
+            swf = me.swf;
+
+        if (swf) {
+            swfobject.removeSWF(me.getSwfId());
+            me.swf = Ext.destroy(swf);
+        }
+
+        me.callParent();
+    },
+
+    statics: {
+        /**
+         * @property {String}
+         * The url for installing flash if it doesn't exist. This should be set to a local resource.
+         * See [http://get.adobe.com/flashplayer/](http://get.adobe.com/flashplayer/) for details.
+         * @static
+         */
+        EXPRESS_INSTALL_URL: 'http://swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf'
+    }
+});

File diff suppressed because it is too large
+ 1307 - 0
assets/ext-7.4.0.42/classic/classic/src/form/Basic.js


+ 564 - 0
assets/ext-7.4.0.42/classic/classic/src/form/CheckboxGroup.js

@@ -0,0 +1,564 @@
+/**
+ * A {@link Ext.form.FieldContainer field container} which has a specialized layout for arranging
+ * {@link Ext.form.field.Checkbox} controls into columns, and provides convenience
+ * {@link Ext.form.field.Field} methods for {@link #getValue getting}, {@link #setValue setting},
+ * and {@link #validate validating} the group of checkboxes as a whole.
+ *
+ * # Validation
+ *
+ * Individual checkbox fields themselves have no default validation behavior, but
+ * sometimes you want to require a user to select at least one of a group of checkboxes.
+ * CheckboxGroup allows this by setting the config `{@link #allowBlank}:false`; when the user
+ * does not check at least one of the checkboxes, the entire group will be highlighted as invalid
+ * and the {@link #blankText error message} will be displayed according to the {@link #msgTarget}
+ * config.
+ *
+ * # Layout
+ *
+ * The default layout for CheckboxGroup makes it easy to arrange the checkboxes into
+ * columns; see the {@link #columns} and {@link #vertical} config documentation for details.
+ * You may also use a completely different layout by setting the {@link #cfg-layout} to one of the 
+ * other supported layout types; for instance you may wish to use a custom arrangement 
+ * of hbox and vbox containers. In that case the checkbox components at any depth will 
+ * still be managed by the CheckboxGroup's validation.
+ *
+ *     @example
+ *     Ext.create('Ext.form.Panel', {
+ *         title: 'Checkbox Group',
+ *         width: 300,
+ *         height: 125,
+ *         bodyPadding: 10,
+ *         renderTo: Ext.getBody(),
+ *         items:[{
+ *             xtype: 'checkboxgroup',
+ *             fieldLabel: 'Two Columns',
+ *             // Arrange checkboxes into two columns, distributed vertically
+ *             columns: 2,
+ *             vertical: true,
+ *             items: [
+ *                 { boxLabel: 'Item 1', name: 'rb', inputValue: '1' },
+ *                 { boxLabel: 'Item 2', name: 'rb', inputValue: '2', checked: true },
+ *                 { boxLabel: 'Item 3', name: 'rb', inputValue: '3' },
+ *                 { boxLabel: 'Item 4', name: 'rb', inputValue: '4' },
+ *                 { boxLabel: 'Item 5', name: 'rb', inputValue: '5' },
+ *                 { boxLabel: 'Item 6', name: 'rb', inputValue: '6' }
+ *             ]
+ *         }]
+ *     });
+ */
+Ext.define('Ext.form.CheckboxGroup', {
+    extend: 'Ext.form.FieldContainer',
+    xtype: 'checkboxgroup',
+
+    /**
+     * @property {Boolean} isCheckboxGroup
+     * The value `true` to identify an object as an instance of this or derived class.
+     * @readonly
+     * @since 6.2.0
+     */
+    isCheckboxGroup: true,
+
+    mixins: {
+        field: 'Ext.form.field.Field'
+    },
+
+    requires: [
+        'Ext.layout.container.CheckboxGroup',
+        'Ext.form.field.Checkbox',
+        'Ext.form.field.Base'
+    ],
+
+    /**
+     * @cfg {String} name The value of the `name` attribute of the input elements
+     * belonging to this Group. If not set, Group's `id` will be used.
+     */
+
+    /**
+     * @cfg {Ext.form.field.Checkbox[]/Object[]} items
+     * An Array of {@link Ext.form.field.Checkbox Checkbox}es or Checkbox config objects to arrange
+     * in the group.
+     */
+
+    /**
+     * @cfg {String/Number/Number[]} columns
+     * Specifies the number of columns to use when displaying grouped checkbox/radio controls using
+     * automatic layout. This config can take several types of values:
+     *
+     * - 'auto' - The controls will be rendered one per column on one row and the width of each
+     *   column will be evenly distributed based on the width of the overall field container.
+     *   This is the default.
+     * - Number - If you specific a number (e.g., 3) that number of columns will be created
+     *   and the contained controls will be automatically distributed based on the value
+     *   of {@link #vertical}.
+     * - Array - You can also specify an array of column widths, mixing integer (fixed width)
+     *   and float (percentage width) values as needed (e.g., [100, .25, .75]). Any integer values
+     *   will be rendered first, then any float values will be calculated as a percentage
+     *   of the remaining space. Float values do not have to add up to 1 (100%)
+     *   although if you want the controls to take up the entire field container you should do so.
+     */
+    columns: 'auto',
+
+    /**
+     * @cfg {Boolean} vertical
+     * True to distribute contained controls across columns, completely filling each column top
+     * to bottom before starting on the next column. The number of controls in each column will be
+     * automatically calculated to keep columns as even as possible. The default value is false,
+     * so that controls will be added to columns one at a time, completely filling each row
+     * left to right before starting on the next row.
+     */
+    vertical: false,
+
+    /**
+     * @cfg {Boolean} allowBlank
+     * False to validate that at least one item in the group is checked. If no items are selected at
+     * validation time, {@link #blankText} will be used as the error text.
+     */
+    allowBlank: true,
+
+    /**
+     * @cfg {String} blankText
+     * Error text to display if the {@link #allowBlank} validation fails
+     * @locale
+     */
+    blankText: "You must select at least one item in this group",
+
+    defaultType: 'checkboxfield',
+
+    defaultBindProperty: 'value',
+
+    /**
+     * @private
+     */
+    groupCls: Ext.baseCSSPrefix + 'form-check-group',
+
+    /**
+     * @private
+     */
+    extraFieldBodyCls: Ext.baseCSSPrefix + 'form-checkboxgroup-body',
+
+    layout: 'checkboxgroup',
+
+    componentCls: Ext.baseCSSPrefix + 'form-checkboxgroup',
+
+    ariaRole: 'group',
+    ariaEl: 'containerEl',
+
+    // containerEl is a div, it cannot be referenced by a <label for="...">
+    // We set aria-labelledby on the containerEl instead
+    skipLabelForAttribute: true,
+
+    // Checkbox and radio groups start as valid
+    ariaRenderAttributes: {
+        'aria-invalid': false
+    },
+
+    initComponent: function() {
+        var me = this;
+
+        me.name = me.name || me.id;
+
+        me.callParent();
+        me.initField();
+    },
+
+    initRenderData: function() {
+        var me = this,
+            data, ariaAttr;
+
+        data = me.callParent();
+
+        // ariaEl is yet a string
+        data.inputId = me.id + '-' + me.ariaEl;
+
+        ariaAttr = data.ariaAttributes;
+
+        if (ariaAttr) {
+            if (!ariaAttr['aria-labelledby']) {
+                ariaAttr['aria-labelledby'] = me.id + '-labelTextEl';
+            }
+        }
+
+        return data;
+    },
+
+    /**
+     * Initializes the field's value based on the initial config. If the {@link #value} config
+     * is specified then we use that to set the value; otherwise we initialize the originalValue
+     * by querying the values of all sub-checkboxes after they have been initialized.
+     * @protected
+     */
+    initValue: function() {
+        var me = this,
+            valueCfg = me.value;
+
+        me.originalValue = me.lastValue = valueCfg || me.getValue();
+
+        if (valueCfg) {
+            me.setValue(valueCfg);
+        }
+    },
+
+    /**
+     * When a checkbox is added to the group, monitor it for changes
+     * @param {Object} field The field being added
+     * @protected
+     */
+    onAdd: function(field) {
+        var me = this,
+            items,
+            len, i;
+
+        if (field.isCheckbox) {
+            // Checkboxes and especially Radio buttons MUST have similar name
+            // if they belong to a group but also must allow explicit override.
+            if (field.name == null) {
+                field.name = me.name;
+            }
+
+            me.mon(field, 'change', me.checkChange, me);
+        }
+        else if (field.isContainer) {
+            items = field.items.items;
+
+            for (i = 0, len = items.length; i < len; i++) {
+                me.onAdd(items[i]);
+            }
+        }
+
+        me.callParent(arguments);
+    },
+
+    onRemove: function(item) {
+        var me = this,
+            items,
+            len, i;
+
+        if (item.isCheckbox) {
+            me.mun(item, 'change', me.checkChange, me);
+        }
+        else if (item.isContainer) {
+            items = item.items.items;
+
+            for (i = 0, len = items.length; i < len; i++) {
+                me.onRemove(items[i]);
+            }
+        }
+
+        me.callParent(arguments);
+    },
+
+    /**
+      * @private
+      * The group value is a complex object, compare using object serialization
+      */
+    isEqual: function(value1, value2) {
+        var toQueryString = Ext.Object.toQueryString;
+
+        return toQueryString(value1) === toQueryString(value2);
+    },
+
+    /**
+     * Runs CheckboxGroup's validations and returns an array of any errors. The only error
+     * by default is if allowBlank is set to false and no items are checked.
+     * @return {String[]} Array of all validation errors
+     */
+    getErrors: function() {
+        var errors = [];
+
+        if (!this.allowBlank && Ext.isEmpty(this.getChecked())) {
+            errors.push(this.blankText);
+        }
+
+        return errors;
+    },
+
+    /**
+     * @private
+     * Returns all checkbox components within the container
+     * @param {String} [query] An additional query to add to the selector.
+     */
+    getBoxes: function(query) {
+        return this.query('[isCheckbox]' + (query || ''));
+    },
+
+    /**
+     * @private
+     * Convenience function which calls the given function for every checkbox in the group
+     * @param {Function} fn The function to call
+     * @param {Object} [scope] scope object
+     */
+    eachBox: function(fn, scope) {
+        Ext.Array.forEach(this.getBoxes(), fn, scope || this);
+    },
+
+    /**
+     * Returns an Array of all checkboxes in the container which are currently checked
+     * @return {Ext.form.field.Checkbox[]} Array of Ext.form.field.Checkbox components
+     */
+    getChecked: function() {
+        return this.getBoxes('[checked]');
+    },
+
+    /**
+     * @private
+     */
+    isDirty: function() {
+        var boxes = this.getBoxes(),
+            b,
+            bLen = boxes.length;
+
+        for (b = 0; b < bLen; b++) {
+            if (boxes[b].isDirty()) {
+                return true;
+            }
+        }
+    },
+
+    /**
+     * @private
+     */
+    setReadOnly: function(readOnly) {
+        var boxes = this.getBoxes(),
+            b,
+            bLen = boxes.length;
+
+        for (b = 0; b < bLen; b++) {
+            boxes[b].setReadOnly(readOnly);
+        }
+
+        this.readOnly = readOnly;
+    },
+
+    /**
+     * Resets the checked state of all {@link Ext.form.field.Checkbox checkboxes} in the group
+     * to their originally loaded values and clears any validation messages.
+     * See {@link Ext.form.Basic}.{@link Ext.form.Basic#trackResetOnLoad trackResetOnLoad}
+     */
+    reset: function() {
+        var me = this,
+            hadError = me.hasActiveError(),
+            preventMark = me.preventMark;
+
+        me.preventMark = true;
+        me.batchChanges(function() {
+            var boxes = me.getBoxes(),
+                b,
+                bLen = boxes.length;
+
+            for (b = 0; b < bLen; b++) {
+                boxes[b].reset();
+            }
+        });
+        me.preventMark = preventMark;
+        me.unsetActiveError();
+
+        if (hadError) {
+            me.updateLayout();
+        }
+    },
+
+    resetOriginalValue: function() {
+        var me = this,
+            boxes = me.getBoxes(),
+            b,
+            bLen = boxes.length;
+
+        for (b = 0; b < bLen; b++) {
+            boxes[b].resetOriginalValue();
+        }
+
+        me.originalValue = me.getValue();
+        me.checkDirty();
+    },
+
+    /**
+     * Sets the value(s) of all checkboxes in the group. The expected format is an Object
+     * of name-value pairs corresponding to the names of the checkboxes in the group. Each pair
+     * can have either a single or multiple values:
+     *
+     *   - A single Boolean or String value will be passed to the `setValue` method of the checkbox
+     *     with that name. See the rules in {@link Ext.form.field.Checkbox#setValue}
+     *     for accepted values.
+     *   - An Array of String values will be matched against the
+     *     {@link Ext.form.field.Checkbox#inputValue inputValue} of checkboxes in the group
+     *     with that name; those checkboxes whose inputValue exists in the array will be
+     *     checked and others will be unchecked.
+     *
+     * If a checkbox's name is not in the mapping at all, it will be unchecked.
+     *
+     * An example:
+     *
+     *     var myCheckboxGroup = new Ext.form.CheckboxGroup({
+     *         columns: 3,
+     *         items: [{
+     *             name: 'cb1',
+     *             boxLabel: 'Single 1'
+     *         }, {
+     *             name: 'cb2',
+     *             boxLabel: 'Single 2'
+     *         }, {
+     *             name: 'cb3',
+     *             boxLabel: 'Single 3'
+     *         }, {
+     *             name: 'cbGroup',
+     *             boxLabel: 'Grouped 1'
+     *             inputValue: 'value1'
+     *         }, {
+     *             name: 'cbGroup',
+     *             boxLabel: 'Grouped 2'
+     *             inputValue: 'value2'
+     *         }, {
+     *             name: 'cbGroup',
+     *             boxLabel: 'Grouped 3'
+     *             inputValue: 'value3'
+     *         }]
+     *     });
+     *
+     *     myCheckboxGroup.setValue({
+     *         cb1: true,
+     *         cb3: false,
+     *         cbGroup: ['value1', 'value3']
+     *     });
+     *
+     * The above code will cause the checkbox named 'cb1' to be checked, as well as the first
+     * and third checkboxes named 'cbGroup'. The other three checkboxes will be unchecked.
+     *
+     * @param {Object} value The mapping of checkbox names to values.
+     * @return {Ext.form.CheckboxGroup} this
+     */
+    setValue: function(value) {
+        var me = this,
+            boxes = me.getBoxes(),
+            b,
+            bLen = boxes.length,
+            box, name,
+            cbValue;
+
+        me.batchChanges(function() {
+            Ext.suspendLayouts();
+
+            for (b = 0; b < bLen; b++) {
+                box = boxes[b];
+                name = box.getName();
+                cbValue = false;
+
+                if (value) {
+                    if (Ext.isArray(value[name])) {
+                        cbValue = Ext.Array.contains(value[name], box.inputValue);
+                    }
+                    else {
+                        // single value, let the checkbox's own setValue handle conversion
+                        cbValue = value[name];
+                    }
+                }
+
+                box.setValue(cbValue);
+            }
+
+            Ext.resumeLayouts(true);
+        });
+
+        return me;
+    },
+
+    /**
+     * Returns an object containing the values of all checked checkboxes within the group.
+     * Each key-value pair in the object corresponds to a checkbox
+     * {@link Ext.form.field.Checkbox#name name}. If there is only one checked checkbox
+     * with a particular name, the value of that pair will be the String
+     * {@link Ext.form.field.Checkbox#inputValue inputValue} of that checkbox. If there are
+     * multiple checked checkboxes with that name, the value of that pair will be an Array
+     * of the selected inputValues.
+     *
+     * The object format returned from this method can also be passed directly to the
+     * {@link #setValue} method.
+     *
+     * NOTE: In Ext 3, this method returned an array of Checkbox components; this was changed
+     * to make it more consistent with other field components and with the {@link #setValue}
+     * argument signature. If you need the old behavior in Ext 4+, use the {@link #getChecked}
+     * method instead.
+     */
+    getValue: function() {
+        var values = {},
+            boxes = this.getBoxes(),
+            b,
+            bLen = boxes.length,
+            box, name, inputValue, bucket;
+
+        for (b = 0; b < bLen; b++) {
+            box = boxes[b];
+            name = box.getName();
+            inputValue = box.inputValue;
+
+            if (box.getValue()) {
+                if (values.hasOwnProperty(name)) {
+                    bucket = values[name];
+
+                    if (!Ext.isArray(bucket)) {
+                        bucket = values[name] = [bucket];
+                    }
+
+                    bucket.push(inputValue);
+                }
+                else {
+                    values[name] = inputValue;
+                }
+            }
+        }
+
+        return values;
+    },
+
+    /*
+     * Don't return any data for submit; the form will get the info from the individual checkboxes
+     * themselves.
+     */
+    getSubmitData: function() {
+        return null;
+    },
+
+    /*
+     * Don't return any data for the model; the form will get the info from the individual
+     * checkboxes themselves.
+     */
+    getModelData: function() {
+        return null;
+    },
+
+    validate: function() {
+        var me = this,
+            errors,
+            isValid,
+            wasValid;
+
+        if (me.disabled) {
+            isValid = true;
+        }
+        else {
+            errors = me.getErrors();
+            isValid = Ext.isEmpty(errors);
+            wasValid = me.wasValid;
+
+            if (isValid) {
+                me.unsetActiveError();
+            }
+            else {
+                me.setActiveError(errors);
+            }
+        }
+
+        if (isValid !== wasValid) {
+            me.wasValid = isValid;
+            me.fireEvent('validitychange', me, isValid);
+
+            if (wasValid != null || !isValid) {
+                me.updateLayout();
+            }
+        }
+
+        return isValid;
+    }
+}, function() {
+    this.borrow(Ext.form.field.Base, ['markInvalid', 'clearInvalid', 'setError']);
+});
+

+ 14 - 0
assets/ext-7.4.0.42/classic/classic/src/form/CheckboxManager.js

@@ -0,0 +1,14 @@
+/**
+ * @private
+ * Private utility class for managing all {@link Ext.form.field.Checkbox} fields grouped by name.
+ */
+Ext.define('Ext.form.CheckboxManager', {
+    extend: 'Ext.util.MixedCollection',
+    singleton: true,
+
+    getByName: function(name, formId) {
+        return this.filterBy(function(item) {
+            return item.name === name && item.getFormId() === formId;
+        });
+    }
+});

+ 206 - 0
assets/ext-7.4.0.42/classic/classic/src/form/FieldAncestor.js

@@ -0,0 +1,206 @@
+/**
+ * A mixin for {@link Ext.container.Container} components that are likely to have form fields
+ * in their items subtree. Adds the following capabilities:
+ *
+ * - Methods for handling the addition and removal of {@link Ext.form.Labelable} and
+ *   {@link Ext.form.field.Field} instances at any depth within the container.
+ * - Events ({@link #fieldvaliditychange} and {@link #fielderrorchange}) for handling changes
+ *   to the state of individual fields at the container level.
+ * - Automatic application of {@link #fieldDefaults} config properties to each field added
+ *   within the container, to facilitate uniform configuration of all fields.
+ *
+ * This mixin is primarily for internal use by {@link Ext.form.Panel} and
+ * {@link Ext.form.FieldContainer}, and should not normally need to be used directly.
+ */
+Ext.define('Ext.form.FieldAncestor', {
+    extend: 'Ext.Mixin',
+
+    requires: [
+        'Ext.container.Monitor'
+    ],
+
+    mixinConfig: {
+        id: 'fieldAncestor',
+
+        after: {
+            initInheritedState: 'initFieldInheritedState'
+        },
+
+        before: {
+            doDestroy: 'onBeforeDestroy'
+        }
+    },
+
+    /**
+     * @cfg {Object} fieldDefaults
+     * If specified, the properties in this object are used as default config values for each
+     * {@link Ext.form.Labelable} instance (e.g. {@link Ext.form.field.Base} or
+     * {@link Ext.form.FieldContainer}) that is added as a descendant of this container.
+     * Corresponding values specified in an individual field's own configuration, or from the
+     * {@link Ext.container.Container#defaults defaults config} of its parent container,
+     * will take precedence. See the documentation for {@link Ext.form.Labelable} to see
+     * what config options may be specified in the fieldDefaults.
+     *
+     * Example:
+     *
+     *     new Ext.form.Panel({
+     *         fieldDefaults: {
+     *             labelAlign: 'left',
+     *             labelWidth: 100
+     *         },
+     *         items: [{
+     *             xtype: 'fieldset',
+     *             defaults: {
+     *                 labelAlign: 'top'
+     *             },
+     *             items: [{
+     *                 name: 'field1'
+     *             }, {
+     *                 name: 'field2'
+     *             }]
+     *         }, {
+     *             xtype: 'fieldset',
+     *             items: [{
+     *                 name: 'field3',
+     *                 labelWidth: 150
+     *             }, {
+     *                 name: 'field4'
+     *             }]
+     *         }]
+     *     });
+     *
+     * In this example, field1 and field2 will get labelAlign: 'top' (from the fieldset's defaults)
+     * and labelWidth: 100 (from fieldDefaults), field3 and field4 will both get labelAlign: 'left'
+     * (from fieldDefaults and field3 will use the labelWidth: 150 from its own config.
+     */
+
+    /**
+     * @event fieldvaliditychange
+     * Fires when the validity state of any one of the {@link Ext.form.field.Field} instances
+     * within this container changes.
+     * @param {Ext.form.FieldAncestor} this
+     * @param {Ext.form.Labelable} field The Field instance whose validity changed
+     * @param {String} isValid The field's new validity state
+     */
+
+    /**
+     * @event fielderrorchange
+     * Fires when the active error message is changed for any one of the {@link Ext.form.Labelable}
+     * instances within this container.
+     * @param {Ext.form.FieldAncestor} this
+     * @param {Ext.form.Labelable} field The Labelable instance whose active error was changed
+     * @param {String} error The active error message
+     */
+
+    /**
+     * Initializes the FieldAncestor's state; this must be called from the initComponent method
+     * of any components importing this mixin.
+     * @protected
+     */
+    initFieldAncestor: function() {
+        var me = this;
+
+        // We use the monitor here as opposed to event bubbling. The problem with bubbling
+        // is it doesn't let us react to items being added/remove at different places
+        // in the hierarchy which may have an impact on the error/valid state.
+        me.monitor = new Ext.container.Monitor({
+            scope: me,
+            selector: '[isFormField]:not([excludeForm])',
+            addHandler: me.onChildFieldAdd,
+            removeHandler: me.onChildFieldRemove
+        });
+
+        me.initFieldDefaults();
+    },
+
+    initMonitor: function() {
+        this.monitor.bind(this);
+    },
+
+    initFieldInheritedState: function(inheritedState) {
+        var inheritedFieldDefaults = inheritedState.fieldDefaults,
+            fieldDefaults = this.fieldDefaults;
+
+        if (fieldDefaults) {
+            if (inheritedFieldDefaults) {
+                inheritedState.fieldDefaults =
+                        Ext.apply(Ext.Object.chain(inheritedFieldDefaults), fieldDefaults);
+            }
+            else {
+                inheritedState.fieldDefaults = fieldDefaults;
+            }
+        }
+    },
+
+    onChildFieldAdd: function(field) {
+        var me = this;
+
+        me.mon(field, 'errorchange', me.handleFieldErrorChange, me);
+        me.mon(field, 'validitychange', me.handleFieldValidityChange, me);
+    },
+
+    onChildFieldRemove: function(field) {
+        var me = this;
+
+        me.mun(field, 'errorchange', me.handleFieldErrorChange, me);
+        me.mun(field, 'validitychange', me.handleFieldValidityChange, me);
+    },
+
+    /**
+     * @private
+     * Initialize the {@link #fieldDefaults} object
+     */
+    initFieldDefaults: function() {
+        if (!this.fieldDefaults) {
+            this.fieldDefaults = {};
+        }
+    },
+
+    /**
+     * @private
+     * Handle bubbled validitychange events from descendants; invoke the aggregated event and method
+     */
+    handleFieldValidityChange: function(field, isValid) {
+        var me = this;
+
+        if (field !== me) {
+            me.fireEvent('fieldvaliditychange', me, field, isValid);
+            me.onFieldValidityChange(field, isValid);
+        }
+    },
+
+    /**
+     * @private
+     * Handle bubbled errorchange events from descendants; invoke the aggregated event and method
+     */
+    handleFieldErrorChange: function(labelable, activeError) {
+        var me = this;
+
+        if (labelable !== me) {
+            me.fireEvent('fielderrorchange', me, labelable, activeError);
+            me.onFieldErrorChange(labelable, activeError);
+        }
+    },
+
+    /**
+     * @method
+     * Fired when the validity of any field within the container changes.
+     * @param {Ext.form.field.Field} field The sub-field whose validity changed
+     * @param {Boolean} valid The new validity state
+     * @protected
+     */
+    onFieldValidityChange: Ext.emptyFn,
+
+    /**
+     * @method
+     * Fired when the error message of any field within the container changes.
+     * @param {Ext.form.Labelable} field The sub-field whose active error changed
+     * @param {String} error The new active error message
+     * @protected
+     */
+    onFieldErrorChange: Ext.emptyFn,
+
+    onBeforeDestroy: function() {
+        this.monitor = Ext.destroy(this.monitor);
+    }
+});

+ 362 - 0
assets/ext-7.4.0.42/classic/classic/src/form/FieldContainer.js

@@ -0,0 +1,362 @@
+/**
+ * FieldContainer is a derivation of {@link Ext.container.Container Container} that implements the
+ * {@link Ext.form.Labelable Labelable} mixin. This allows it to be configured so that it is
+ * rendered with a {@link #fieldLabel field label} and optional {@link #msgTarget error message}
+ * around its sub-items. This is useful for arranging a group of fields within a single item
+ * in a form, so that it lines up nicely with other fields. A common use is for grouping a set
+ * of related fields under a single label in a form.
+ * 
+ * The container's configured {@link #cfg-items} will be layed out within the field body area
+ * according to the configured {@link #layout} type. The default layout is `'autocontainer'`.
+ * 
+ * Like regular fields, FieldContainer can inherit its decoration configuration from the
+ * {@link Ext.form.Panel#fieldDefaults fieldDefaults} of an enclosing FormPanel. In addition,
+ * FieldContainer itself can pass {@link #fieldDefaults} to any {@link Ext.form.Labelable fields}
+ * it may itself contain.
+ * 
+ * If you are grouping a set of {@link Ext.form.field.Checkbox Checkbox} or
+ * {@link Ext.form.field.Radio Radio} fields in a single labeled container, consider using
+ * a {@link Ext.form.CheckboxGroup} or {@link Ext.form.RadioGroup} instead as they are specialized
+ * for handling those types.
+ *
+ * # Example
+ * 
+ *     @example
+ *     Ext.create('Ext.form.Panel', {
+ *         title: 'FieldContainer Example',
+ *         width: 550,
+ *         bodyPadding: 10,
+ * 
+ *         items: [{
+ *             xtype: 'fieldcontainer',
+ *             fieldLabel: 'Last Three Jobs',
+ *             labelWidth: 100,
+ * 
+ *             // The body area will contain three text fields, arranged
+ *             // horizontally, separated by draggable splitters.
+ *             layout: 'hbox',
+ *             items: [{
+ *                 xtype: 'textfield',
+ *                 flex: 1
+ *             }, {
+ *                 xtype: 'splitter'
+ *             }, {
+ *                 xtype: 'textfield',
+ *                 flex: 1
+ *             }, {
+ *                 xtype: 'splitter'
+ *             }, {
+ *                 xtype: 'textfield',
+ *                 flex: 1
+ *             }]
+ *         }],
+ *         renderTo: Ext.getBody()
+ *     });
+ * 
+ * # Usage of fieldDefaults
+ *
+ *     @example
+ *     Ext.create('Ext.form.Panel', {
+ *         title: 'FieldContainer Example',
+ *         width: 350,
+ *         bodyPadding: 10,
+ * 
+ *         items: [{
+ *             xtype: 'fieldcontainer',
+ *             fieldLabel: 'Your Name',
+ *             labelWidth: 75,
+ *             defaultType: 'textfield',
+ * 
+ *             // Arrange fields vertically, stretched to full width
+ *             layout: 'anchor',
+ *             defaults: {
+ *                 layout: '100%'
+ *             },
+ * 
+ *             // These config values will be applied to both sub-fields, except
+ *             // for Last Name which will use its own msgTarget.
+ *             fieldDefaults: {
+ *                 msgTarget: 'under',
+ *                 labelAlign: 'top'
+ *             },
+ * 
+ *             items: [{
+ *                 fieldLabel: 'First Name',
+ *                 name: 'firstName'
+ *             }, {
+ *                 fieldLabel: 'Last Name',
+ *                 name: 'lastName',
+ *                 msgTarget: 'under'
+ *             }]
+ *         }],
+ *         renderTo: Ext.getBody()
+ *     });
+ */
+Ext.define('Ext.form.FieldContainer', {
+    extend: 'Ext.container.Container',
+    alias: 'widget.fieldcontainer',
+
+    requires: [
+        'Ext.layout.component.field.FieldContainer'
+    ],
+
+    mixins: {
+        labelable: 'Ext.form.Labelable',
+        fieldAncestor: 'Ext.form.FieldAncestor'
+    },
+
+    componentLayout: 'fieldcontainer',
+    componentCls: Ext.baseCSSPrefix + 'form-fieldcontainer',
+    shrinkWrap: true,
+
+    autoEl: {
+        tag: 'div',
+        role: 'presentation'
+    },
+
+    childEls: [
+        'containerEl'
+    ],
+
+    /**
+     * @cfg {Boolean} combineLabels
+     * If set to true, and there is no defined {@link #fieldLabel}, the field container will
+     * automatically generate its label by combining the labels of all the fields it contains.
+     * Defaults to false.
+     */
+    combineLabels: false,
+
+    /**
+     * @cfg {String} labelConnector
+     * The string to use when joining the labels of individual sub-fields, when
+     * {@link #combineLabels} is set to true. Defaults to ', '.
+     * @locale
+     */
+    labelConnector: ', ',
+
+    /**
+     * @cfg {Boolean} combineErrors
+     * If set to true, the field container will automatically combine and display the validation
+     * errors from all the fields it contains as a single error on the container, according to the
+     * configured {@link #msgTarget}. Defaults to false.
+     */
+    combineErrors: false,
+
+    maskOnDisable: false,
+
+    // If we allow this to mark with the invalidCls it will cascade to all
+    // child fields, let them handle themselves
+    invalidCls: '',
+
+    /* eslint-disable indent */
+    fieldSubTpl: [
+        '<div id="{id}-containerEl" data-ref="containerEl" class="{containerElCls}"',
+            '<tpl if="ariaAttributes">',
+                '<tpl foreach="ariaAttributes"> {$}="{.}"</tpl>',
+            '<tpl else>',
+                ' role="presentation"',
+            '</tpl>',
+        '>',
+            '{%this.renderContainer(out,values)%}',
+        '</div>'
+    ],
+    /* eslint-enable indent */
+
+    initComponent: function() {
+        var me = this;
+
+        // Init mixins
+        me.initLabelable();
+        me.initFieldAncestor();
+
+        me.callParent();
+        me.initMonitor();
+    },
+
+    onAdd: function(labelItem) {
+        var me = this;
+
+        // Fix for https://sencha.jira.com/browse/EXTJSIV-6424 Which was *sneakily* fixed
+        // in version 37
+        // In FF < 37, positioning absolutely within a TD positions relative to the TR!
+        // So we must add the width of a visible, left-aligned label cell to the x coordinate.
+        if (labelItem.isLabelable && Ext.isGecko && Ext.firefoxVersion < 37 &&
+            me.layout.type === 'absolute' && !me.hideLabel && me.labelAlign !== 'top') {
+            labelItem.x += (me.labelWidth + me.labelPad);
+        }
+
+        me.callParent(arguments);
+
+        if (labelItem.isLabelable && me.combineLabels) {
+            labelItem.oldHideLabel = labelItem.hideLabel;
+            labelItem.hideLabel = true;
+        }
+
+        me.updateLabel();
+    },
+
+    onRemove: function(labelItem, isDestroying) {
+        var me = this;
+
+        me.callParent(arguments);
+
+        if (!isDestroying) {
+            if (labelItem.isLabelable && me.combineLabels) {
+                labelItem.hideLabel = labelItem.oldHideLabel;
+            }
+
+            me.updateLabel();
+        }
+    },
+
+    initRenderData: function() {
+        var me = this,
+            data = me.callParent();
+
+        data.containerElCls = me.containerElCls;
+        data = Ext.applyIf(data, me.getLabelableRenderData());
+
+        if (me.labelAlign === 'top' || me.msgTarget === 'under') {
+            data.extraFieldBodyCls += ' ' + Ext.baseCSSPrefix + 'field-container-body-vertical';
+        }
+
+        data.tipAnchorTarget = me.id + '-containerEl';
+
+        return data;
+    },
+
+    /**
+     * Returns the combined field label if {@link #combineLabels} is set to true and if there is no
+     * set {@link #fieldLabel}. Otherwise returns the fieldLabel like normal. You can also override
+     * this method to provide a custom generated label.
+     * @template
+     * @return {String} The label, or empty string if none.
+     */
+    getFieldLabel: function() {
+        var label = this.fieldLabel || '';
+
+        if (!label && this.combineLabels) {
+            label = Ext.Array.map(this.query('[isFieldLabelable]'), function(field) {
+                return field.getFieldLabel();
+            }).join(this.labelConnector);
+        }
+
+        return label;
+    },
+
+    getSubTplData: function() {
+        var ret = this.initRenderData();
+
+        Ext.apply(ret, this.subTplData);
+
+        return ret;
+    },
+
+    getSubTplMarkup: function(fieldData) {
+        var me = this,
+            tpl = me.lookupTpl('fieldSubTpl'),
+            html;
+
+        if (!tpl.renderContent) {
+            me.setupRenderTpl(tpl);
+        }
+
+        html = tpl.apply(me.getSubTplData(fieldData));
+
+        return html;
+    },
+
+    /**
+     * @private
+     * Updates the content of the labelEl if it is rendered
+     */
+    updateLabel: function() {
+        var me = this,
+            label = me.labelEl;
+
+        if (label) {
+            me.setFieldLabel(me.getFieldLabel());
+        }
+    },
+
+    /**
+     * @private
+     * Fired when the error message of any field within the container changes, and updates the
+     * combined error message to match.
+     */
+    onFieldErrorChange: function() {
+        if (this.combineErrors) {
+            // eslint-disable-next-line vars-on-top
+            var me = this,
+                oldError = me.getActiveError(),
+                invalidFields = Ext.Array.filter(me.query('[isFormField]'), function(field) {
+                    return field.hasActiveError();
+                }),
+                newErrors = me.getCombinedErrors(invalidFields);
+
+            if (newErrors) {
+                me.setActiveErrors(newErrors);
+            }
+            else {
+                me.unsetActiveError();
+            }
+
+            if (oldError !== me.getActiveError()) {
+                me.updateLayout();
+            }
+        }
+    },
+
+    /**
+     * Takes an Array of invalid {@link Ext.form.field.Field} objects and builds a combined list
+     * of error messages from them. Defaults to prepending each message by the field name
+     * and a colon. This can be overridden to provide custom combined error message handling,
+     * for instance changing the format of each message or sorting the array (it is sorted
+     * in order of appearance by default).
+     * @param {Ext.form.field.Field[]} invalidFields An Array of the sub-fields which are currently
+     * invalid.
+     * @return {String[]} The combined list of error messages
+     */
+    getCombinedErrors: function(invalidFields) {
+        var errors = [],
+            fLen = invalidFields.length,
+            f, field, activeErrors, a, aLen, error, label;
+
+        for (f = 0; f < fLen; f++) {
+            field = invalidFields[f];
+            activeErrors = field.getActiveErrors();
+            aLen = activeErrors.length;
+
+            for (a = 0; a < aLen; a++) {
+                error = activeErrors[a];
+                label = field.getFieldLabel();
+
+                errors.push((label ? label + ': ' : '') + error);
+            }
+        }
+
+        return errors;
+    },
+
+    privates: {
+        applyTargetCls: function(targetCls) {
+            var containerElCls = this.containerElCls;
+
+            this.containerElCls = containerElCls ? containerElCls + ' ' + targetCls : targetCls;
+        },
+
+        getTargetEl: function() {
+            return this.containerEl;
+        },
+
+        initRenderTpl: function() {
+            var me = this;
+
+            if (!me.hasOwnProperty('renderTpl')) {
+                me.renderTpl = me.lookupTpl('labelableRenderTpl');
+            }
+
+            return me.callParent();
+        }
+    }
+});

+ 759 - 0
assets/ext-7.4.0.42/classic/classic/src/form/FieldSet.js

@@ -0,0 +1,759 @@
+/**
+ * A container for grouping sets of fields, rendered as a HTML `fieldset` element.
+ * The {@link #title} config will be rendered as the fieldset's `legend`.
+ *
+ * While FieldSets commonly contain simple groups of fields, they are general
+ * {@link Ext.container.Container Containers} and may therefore contain any type of components
+ * in their {@link #cfg-items}, including other nested containers. The default {@link #layout}
+ * for the FieldSet's items is `'anchor'`, but it can be configured to use any other layout type.
+ *
+ * FieldSets may also be collapsed if configured to do so; this can be done in two ways:
+ *
+ * 1. Set the {@link #collapsible} config to true; this will result in a collapse button being
+ *    rendered next to the {@link #title legend title}, or:
+ * 2. Set the {@link #checkboxToggle} config to true; this is similar to using {@link #collapsible}
+ *    but renders a {@link Ext.form.field.Checkbox checkbox} in place of the toggle button.
+ *    The fieldset will be expanded when the checkbox is checked and collapsed when it is unchecked.
+ *    The checkbox will also be included in the {@link Ext.form.Basic#submit form submit parameters}
+ *    using {@link #checkbox}.
+ *
+ * # Example usage
+ *
+ *     @example
+ *     Ext.create('Ext.form.Panel', {
+ *         title: 'Simple Form with FieldSets',
+ *         labelWidth: 75, // label settings here cascade unless overridden
+ *         url: 'save-form.php',
+ *         frame: true,
+ *         bodyStyle: 'padding:5px 5px 0',
+ *         width: 550,
+ *         renderTo: Ext.getBody(),
+ *         layout: 'column', // arrange fieldsets side by side
+ *         items: [{
+ *             // Fieldset in Column 1 - collapsible via toggle button
+ *             xtype:'fieldset',
+ *             columnWidth: 0.5,
+ *             title: 'Fieldset 1',
+ *             collapsible: true,
+ *             defaultType: 'textfield',
+ *             defaults: {anchor: '100%'},
+ *             layout: 'anchor',
+ *             items :[{
+ *                 fieldLabel: 'Field 1',
+ *                 name: 'field1'
+ *             }, {
+ *                 fieldLabel: 'Field 2',
+ *                 name: 'field2'
+ *             }]
+ *         }, {
+ *             // Fieldset in Column 2 - collapsible via checkbox, collapsed by default,
+ *             // contains a panel
+ *             xtype:'fieldset',
+ *             title: 'Show Panel', // title or checkboxToggle creates fieldset header
+ *             columnWidth: 0.5,
+ *             checkboxToggle: true,
+ *             collapsed: true, // fieldset initially collapsed
+ *             layout:'anchor',
+ *             items :[{
+ *                 xtype: 'panel',
+ *                 anchor: '100%',
+ *                 title: 'Panel inside a fieldset',
+ *                 frame: true,
+ *                 height: 52
+ *             }]
+ *         }]
+ *     });
+ */
+Ext.define('Ext.form.FieldSet', {
+    extend: 'Ext.container.Container',
+    alias: 'widget.fieldset',
+
+    mixins: {
+        fieldAncestor: 'Ext.form.FieldAncestor'
+    },
+
+    uses: [
+        'Ext.form.field.Checkbox',
+        'Ext.panel.Tool',
+        'Ext.layout.container.Anchor',
+        'Ext.layout.component.FieldSet'
+    ],
+
+    /**
+     * @cfg {String} title
+     * A title to be displayed in the fieldset's legend. May contain HTML markup.
+     */
+
+    /**
+     * @cfg {Boolean} [checkboxToggle=false]
+     * Set to true to render a checkbox into the fieldset frame just in front of the legend
+     * to expand/collapse the fieldset when the checkbox is toggled. This checkbox will be included
+     * in form submits using the {@link #checkbox} configuration.
+     */
+
+    /**
+     * @cfg {String} checkboxName
+     * @deprecated 6.2.0 Use the name property in {@link #checkbox} instead.
+     * The name to assign to the fieldset's checkbox if {@link #checkboxToggle} = true
+     * (defaults to '[fieldset id]-checkbox').
+     */
+
+    /**
+     * @cfg {String} checkboxUI
+     * The ui to use for the fieldset's checkbox.
+     */
+    checkboxUI: 'default',
+
+    /**
+     * @cfg {Boolean} [collapsible=false]
+     * Set to true to make the fieldset collapsible and have the expand/collapse toggle button
+     * automatically rendered into the legend element, false to keep the fieldset statically sized
+     * with no collapse button. Another option is to configure {@link #checkboxToggle}.
+     * Use the {@link #collapsed} config to collapse the fieldset by default.
+     */
+
+    /**
+     * @cfg {Boolean} collapsed
+     * Set to true to render the fieldset as collapsed by default. If {@link #checkboxToggle}
+     * is specified, the checkbox will also be unchecked by default.
+     */
+    collapsed: false,
+
+    /**
+     * @cfg {Boolean} toggleOnTitleClick
+     * Set to true will add a listener to the titleCmp property for the click event which
+     * will execute the {@link #toggle} method. This option is only used when the
+     * {@link #collapsible} property is set to true.
+     */
+    toggleOnTitleClick: true,
+
+    /**
+     * @property {Ext.Component} legend
+     * The component for the fieldset's legend. Will only be defined if the configuration requires
+     * a legend to be created, by setting the {@link #title} or {@link #checkboxToggle} options.
+     */
+
+    /**
+     * @cfg {String} baseCls
+     * The base CSS class applied to the fieldset.
+     */
+    baseCls: Ext.baseCSSPrefix + 'fieldset',
+
+    /**
+     * @cfg {Ext.enums.Layout/Object} layout
+     * The {@link Ext.container.Container#layout} for the fieldset's immediate child items.
+     */
+    layout: 'anchor',
+
+    /**
+     * @cfg {String} descriptionText
+     * Fieldset description to be announced by screen readers.
+     * @locale
+     */
+    descriptionText: '{0} field set',
+
+    /**
+     * @cfg {String} expandText
+     * Text to be announced by screen readers when toggle tool
+     * or checkbox is focused.
+     * @locale
+     */
+    expandText: 'Expand field set',
+
+    componentLayout: 'fieldset',
+
+    /**
+     * @property ariaRole
+     * @inheritdoc
+     */
+    ariaRole: 'group',
+
+    /**
+     * @property focusable
+     * @inheritdoc
+     */
+    focusable: false,
+
+    /**
+     * @cfg autoEl
+     * @inheritdoc
+     */
+    autoEl: 'fieldset',
+
+    /**
+     * @cfg {Object} checkbox
+     * A configuration for the generated checkbox that is adjacent to the {@link #title}
+     * in the header. This config is only effective when {@link #checkboxToggle} is true
+     *
+     * @since 6.2.0
+     */
+    checkbox: null,
+
+    /**
+     * @cfg childEls
+     * @inheritdoc
+     */
+    childEls: [
+        'body'
+    ],
+
+    /* eslint-disable indent, max-len */
+    /**
+     * @cfg renderTpl
+     * @inheritdoc
+     */
+    renderTpl: [
+        '{%this.renderLegend(out,values);%}',
+        '<div id="{id}-body" data-ref="body" class="{baseCls}-body {baseCls}-body-{ui} {bodyTargetCls}" ',
+                'role="presentation"<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>>',
+            '{%this.renderContainer(out,values);%}',
+        '</div>'
+    ],
+    /* eslint-enable indent, max-len */
+
+    /**
+     * @cfg stateEvents
+     * @inheritdoc Ext.state.Stateful#cfg-stateEvents
+     * @localdoc By default the following stateEvents are added:
+     * 
+     *  - {@link #event-resize} - _(added by Ext.Component)_
+     *  - {@link #event-collapse}
+     *  - {@link #event-expand}
+     */
+    stateEvents: [ 'collapse', 'expand' ],
+
+    /**
+     * @property maskOnDisable
+     * @inheritdoc
+     */
+    maskOnDisable: false,
+
+    /**
+     * @event beforeexpand
+     * Fires before this FieldSet is expanded. Return false to prevent the expand.
+     * @param {Ext.form.FieldSet} fieldset The FieldSet being expanded.
+     */
+
+    /**
+     * @event beforecollapse
+     * Fires before this FieldSet is collapsed. Return false to prevent the collapse.
+     * @param {Ext.form.FieldSet} fieldset The FieldSet being collapsed.
+     */
+
+    /**
+     * @event expand
+     * Fires after this FieldSet has expanded.
+     * @param {Ext.form.FieldSet} fieldset The FieldSet that has been expanded.
+     */
+
+    /**
+     * @event collapse
+     * Fires after this FieldSet has collapsed.
+     * @param {Ext.form.FieldSet} fieldset The FieldSet that has been collapsed.
+     */
+
+    initComponent: function() {
+        var me = this,
+            baseCls = me.baseCls;
+
+        // We need to render the aria-label attribute instead of relying on
+        // aria-labelledby because the contents of these differ.
+        if (me.ariaRole && !me.ariaLabel) {
+            me.ariaLabel = Ext.String.formatEncode(me.descriptionText, me.title || '');
+        }
+
+        me.ariaRenderAttributes = me.ariaRenderAttributes || {};
+        me.ariaRenderAttributes['aria-expanded'] = !me.collapsed;
+
+        me.initFieldAncestor();
+
+        me.callParent();
+
+        // Fieldsets cannot support managePadding because the managePadding config causes
+        // the paddding to be added to the innerCt instead of the fieldset element.  The
+        // padding must be on the fieldset element because the horizontal position of the
+        // legend is determined by the fieldset element's padding
+        // 
+        // As a consequence of the inability to support managePadding, manageOverflow
+        // cannot be supported either because the correct overflow cannot be calculated
+        // without managePadding to adjust for cross-browser differences in the way
+        // padding is handled on overflowing elements.
+        // See Ext.layout.container.Auto for more info.
+        me.layout.managePadding = me.layout.manageOverflow = false;
+
+        if (me.collapsed) {
+            me.addCls(baseCls + '-collapsed');
+            me.collapse();
+        }
+
+        if (me.title || me.checkboxToggle || me.collapsible) {
+            me.addTitleClasses();
+            me.legend = me.createLegendCt();
+        }
+
+        me.initMonitor();
+    },
+
+    /**
+     * Initialized the renderData to be used when rendering the renderTpl.
+     * @return {Object} Object with keys and values that are going to be applied to the renderTpl
+     * @private
+     */
+    initRenderData: function() {
+        var me = this,
+            data = me.callParent();
+
+        data.bodyTargetCls = me.bodyTargetCls;
+        me.protoBody.writeTo(data);
+        delete me.protoBody;
+
+        return data;
+    },
+
+    doDestroy: function() {
+        var me = this,
+            legend = me.legend;
+
+        if (legend) {
+            // get rid of the ownerCt since it's not a proper item
+            delete legend.ownerCt;
+            legend.destroy();
+            me.legend = null;
+        }
+
+        me.callParent();
+    },
+
+    getState: function() {
+        var state = this.callParent();
+
+        state = this.addPropertyToState(state, 'collapsed');
+
+        return state;
+    },
+
+    afterCollapse: Ext.emptyFn,
+    afterExpand: Ext.emptyFn,
+
+    collapsedHorizontal: function() {
+        return true;
+    },
+
+    collapsedVertical: function() {
+        return true;
+    },
+
+    createLegendCt: function() {
+        var me = this,
+            items = [],
+            legendCfg = {
+                baseCls: me.baseCls + '-header',
+                // use container layout so we don't get the auto layout innerCt/outerCt
+                layout: 'container',
+                ui: me.ui,
+                id: me.id + '-legend',
+                autoEl: 'legend',
+                ariaRole: null,
+                items: items,
+                ownerCt: me,
+                shrinkWrap: true,
+                ownerLayout: me.componentLayout
+            },
+            legend;
+
+        // Checkbox
+        if (me.checkboxToggle) {
+            items.push(me.createCheckboxCmp());
+        }
+        else if (me.collapsible) {
+            // Toggle button
+            items.push(me.createToggleCmp());
+        }
+
+        // Title
+        items.push(me.createTitleCmp());
+
+        legend = new Ext.container.Container(legendCfg);
+
+        return legend;
+    },
+
+    /**
+     * Creates the legend title component. This is only called internally, but could be overridden
+     * in subclasses to customize the title component. If {@link #toggleOnTitleClick} is set
+     * to true, a listener for the click event will toggle the collapsed state of the FieldSet.
+     * @return {Ext.Component}
+     * @protected
+     */
+    createTitleCmp: function() {
+        var me = this,
+            cfg = {
+                html: me.title,
+                ui: me.ui,
+                cls: me.baseCls + '-header-text',
+                id: me.id + '-legendTitle',
+                ariaRole: 'presentation'
+            };
+
+        if (me.collapsible && me.toggleOnTitleClick) {
+            cfg.listeners = {
+                click: {
+                    element: 'el',
+                    scope: me,
+                    fn: me.toggle
+                }
+            };
+
+            cfg.cls += ' ' + me.baseCls + '-header-text-collapsible';
+        }
+
+        me.titleCmp = new Ext.Component(cfg);
+
+        return me.titleCmp;
+    },
+
+    /**
+     * @property {Ext.form.field.Checkbox} checkboxCmp
+     * Refers to the {@link Ext.form.field.Checkbox} component that is added next to the title
+     * in the legend. Only populated if the fieldset is configured with
+     * {@link #checkboxToggle}: true.
+     */
+
+    /**
+     * Creates the checkbox component. This is only called internally, but could be overridden
+     * in subclasses to customize the checkbox's configuration or even return an entirely different
+     * component type.
+     * @return {Ext.Component}
+     * @protected
+     */
+    createCheckboxCmp: function() {
+        var me = this,
+            suffix = '-checkbox',
+            cls = me.baseCls + '-header' + suffix,
+            checkboxCmp;
+
+        cls += ' ' + cls + '-' + me.ui;
+
+        me.checkboxCmp = checkboxCmp = new Ext.form.field.Checkbox(Ext.apply({
+            hideEmptyLabel: true,
+            name: me.checkboxName || me.id + suffix,
+            cls: cls,
+            id: me.id + '-legendChk',
+            ui: me.checkboxUI,
+            checked: !me.collapsed,
+            msgTarget: 'none',
+            listeners: {
+                change: me.onCheckChange,
+                scope: me
+            },
+            ariaLabel: me.expandText
+        }, me.checkbox));
+
+        return checkboxCmp;
+    },
+
+    /**
+     * @property {Ext.panel.Tool} toggleCmp
+     * Refers to the {@link Ext.panel.Tool} component that is added as the collapse/expand button
+     * next to the title in the legend. Only populated if the fieldset is configured with
+     * {@link #collapsible}: true.
+     */
+
+    /**
+     * Creates the toggle button component. This is only called internally, but could be overridden
+     * in subclasses to customize the toggle component.
+     * @return {Ext.Component}
+     * @protected
+     */
+    createToggleCmp: function() {
+        var me = this,
+            toggleCmp;
+
+        me.toggleCmp = toggleCmp = new Ext.panel.Tool({
+            // fieldset tools may be styled differently from regular tools and so we need
+            // to tell the layout system not to cache the height if this tool happens
+            // to be the first one through the layout system
+            cacheHeight: false,
+            cls: me.baseCls + '-header-tool-' + me.ui,
+            type: 'toggle',
+            handler: me.toggle,
+            id: me.id + '-legendToggle',
+            scope: me,
+
+            // This tool is akin to a checkbox; its is considered "checked"
+            // when fieldset is expanded, and vice versa.
+            ariaRole: 'checkbox',
+            ariaLabel: me.expandText,
+            ariaRenderAttributes: {
+                'aria-checked': !me.collapsed
+            }
+        });
+
+        return toggleCmp;
+    },
+
+    doRenderLegend: function(out, renderData) {
+        // Careful! This method is bolted on to the renderTpl so all we get for context is
+        // the renderData! The "this" pointer is the renderTpl instance!
+
+        var me = renderData.$comp,
+            legend = me.legend,
+            tree;
+
+        // Create the Legend component if needed
+        if (legend) {
+            legend.ownerLayout.configureItem(legend);
+            me.setLegendCollapseImmunity(legend);
+            tree = legend.getRenderTree();
+            Ext.DomHelper.generateMarkup(tree, out);
+        }
+    },
+
+    getCollapsed: function() {
+        return this.collapsed ? 'top' : false;
+    },
+
+    getCollapsedDockedItems: function() {
+        var legend = this.legend;
+
+        return legend ? [ legend ] : [];
+    },
+
+    /**
+     * Sets the title of this fieldset.
+     * @param {String} title The new title.
+     * @return {Ext.form.FieldSet} this
+     */
+    setTitle: function(title) {
+        var me = this,
+            legend = me.legend;
+
+        me.title = title;
+        me.ariaLabel = Ext.String.formatEncode(me.descriptionText, title || '');
+
+        if (me.rendered) {
+            if (!legend) {
+                me.legend = legend = me.createLegendCt();
+                me.addTitleClasses();
+                legend.ownerLayout.configureItem(legend);
+                me.setLegendCollapseImmunity(legend);
+                legend.render(me.el, 0);
+            }
+
+            me.titleCmp.update(title);
+
+            // ariaLabel property was htmlEncoded in initComponent
+            me.ariaEl.dom.setAttribute('aria-label', me.ariaLabel);
+        }
+        else if (legend) {
+            me.titleCmp.update(title);
+        }
+        else {
+            me.addTitleClasses();
+            me.legend = me.createLegendCt();
+        }
+
+        return me;
+    },
+
+    addTitleClasses: function() {
+        var me = this,
+            title = me.title,
+            baseCls = me.baseCls;
+
+        if (title) {
+            me.addCls(baseCls + '-with-title');
+        }
+
+        if (title || me.checkboxToggle || me.collapsible) {
+            me.addCls(baseCls + '-with-legend');
+        }
+    },
+
+    /**
+     * Expands the fieldset.
+     * @return {Ext.form.FieldSet} this
+     */
+    expand: function() {
+        return this.setExpanded(true);
+    },
+
+    /**
+     * Collapses the fieldset.
+     * @return {Ext.form.FieldSet} this
+     */
+    collapse: function() {
+        return this.setExpanded(false);
+    },
+
+    /**
+     * Set the collapsed state of the fieldset.
+     * @param {Boolean} collapsed The collapsed state.
+     *
+     * @since 6.2.0
+     */
+    setCollapsed: function(collapsed) {
+        this.setExpanded(!collapsed);
+    },
+
+    /**
+     * @private
+     * Collapse or expand the fieldset.
+     */
+    setExpanded: function(expanded) {
+        var me = this,
+            checkboxCmp = me.checkboxCmp,
+            toggleCmp = me.toggleCmp,
+            operation = expanded ? 'expand' : 'collapse';
+
+        if (!me.rendered || me.fireEvent('before' + operation, me) !== false) {
+            expanded = !!expanded;
+
+            if (checkboxCmp) {
+                checkboxCmp.setValue(expanded);
+            }
+            else if (toggleCmp && toggleCmp.ariaEl.dom) {
+                toggleCmp.ariaEl.dom.setAttribute('aria-checked', expanded);
+            }
+
+            if (expanded) {
+                me.removeCls(me.baseCls + '-collapsed');
+            }
+            else {
+                me.addCls(me.baseCls + '-collapsed');
+            }
+
+            if (me.ariaEl.dom) {
+                me.ariaEl.dom.setAttribute('aria-expanded', !!expanded);
+            }
+
+            me.collapsed = !expanded;
+
+            if (expanded) {
+                delete me.getInherited().collapsed;
+            }
+            else {
+                me.getInherited().collapsed = true;
+            }
+
+            if (me.rendered) {
+                // say explicitly we are not root because when we have a fixed/configured height
+                // our ownerLayout would say we are root and so would not have it's height
+                // updated since it's not included in the layout cycle
+                me.updateLayout({ isRoot: false });
+                me.fireEvent(operation, me);
+            }
+        }
+
+        return me;
+    },
+
+    getRefItems: function(deep) {
+        var refItems = this.callParent(arguments),
+            legend = this.legend;
+
+        // Prepend legend items to ensure correct order
+        if (legend) {
+            refItems.unshift(legend);
+
+            if (deep) {
+                refItems.unshift.apply(refItems, legend.getRefItems(true));
+            }
+        }
+
+        return refItems;
+    },
+
+    /**
+     * Toggle the fieldset's collapsed state to the opposite of what it is currently.
+     */
+    toggle: function() {
+        this.setExpanded(!!this.collapsed);
+    },
+
+    privates: {
+        applyTargetCls: function(targetCls) {
+            this.bodyTargetCls = targetCls;
+        },
+
+        finishRender: function() {
+            var legend = this.legend;
+
+            this.callParent();
+
+            if (legend) {
+                legend.finishRender();
+            }
+        },
+
+        getProtoBody: function() {
+            var me = this,
+                body = me.protoBody;
+
+            if (!body) {
+                me.protoBody = body = new Ext.util.ProtoElement({
+                    styleProp: 'bodyStyle',
+                    styleIsText: true
+                });
+            }
+
+            return body;
+        },
+
+        getDefaultContentTarget: function() {
+            return this.body;
+        },
+
+        getTargetEl: function() {
+            return this.body || this.frameBody || this.el;
+        },
+
+        initPadding: function(targetEl) {
+            var me = this,
+                body = me.getProtoBody(),
+                padding = me.padding,
+                bodyPadding;
+
+            if (padding !== undefined) {
+                if (Ext.isIE8) {
+                    // IE8 and below display fieldset top padding outside the border
+                    // so we transfer the top padding to the body element.
+                    padding = me.parseBox(padding);
+                    bodyPadding = Ext.Element.parseBox(0);
+                    bodyPadding.top = padding.top;
+                    padding.top = 0;
+                    body.setStyle('padding', me.unitizeBox(bodyPadding));
+                }
+
+                targetEl.setStyle('padding', me.unitizeBox(padding));
+            }
+        },
+
+        /**
+         * @private
+         * Handle changes in the checkbox checked state.
+         */
+        onCheckChange: function(cmp, checked) {
+            this.setExpanded(checked);
+        },
+
+        setLegendCollapseImmunity: function(legend) {
+            // Mark the legend as immune to collapse so that when the fieldset
+            // *is* collapsed and the toggle tool or checkbox is focused,
+            // calling isVisible(true) on it will return true instead of false.
+            // See also below in createCheckboxCmp and createToggleCmp.
+            // 
+            // It is important to defer this until the inherited hierarchy is setup
+            // completely, otherwise we could cause our inheritedState to get 
+            // initialized incorrectly.
+            legend.collapseImmune = true;
+            legend.getInherited().collapseImmune = true;
+        },
+
+        setupRenderTpl: function(renderTpl) {
+            this.callParent(arguments);
+
+            renderTpl.renderLegend = this.doRenderLegend;
+        }
+    }
+});

+ 118 - 0
assets/ext-7.4.0.42/classic/classic/src/form/Label.js

@@ -0,0 +1,118 @@
+/**
+ * Produces a standalone `<label />` element which can be inserted into a form and be associated
+ * with a field in that form using the {@link #forId} property.
+ * 
+ * **NOTE:** in most cases it will be more appropriate to use the
+ * {@link Ext.form.Labelable#fieldLabel fieldLabel} and associated config properties
+ * ({@link Ext.form.Labelable#labelAlign}, {@link Ext.form.Labelable#labelWidth}, etc.)
+ * in field components themselves, as that allows labels to be uniformly sized throughout the form.
+ * Ext.form.Label should only be used when your layout can not be achieved with the standard
+ * {@link Ext.form.Labelable field layout}.
+ * 
+ * You will likely be associating the label with a field component that extends
+ * {@link Ext.form.field.Base}, so you should make sure the {@link #forId} is set to the same value
+ * as the {@link Ext.form.field.Base#inputId inputId} of that field.
+ * 
+ * The label's text can be set using either the {@link #text} or {@link #html} configuration
+ * properties; the difference between the two is that the former will automatically escape HTML
+ * characters when rendering, while the latter will not.
+ *
+ * # Example
+ * 
+ * This example creates a Label after its associated Text field, an arrangement that cannot
+ * currently be achieved using the standard Field layout's labelAlign.
+ * 
+ *     @example
+ *     Ext.create('Ext.form.Panel', {
+ *         title: 'Field with Label',
+ *         width: 400,
+ *         bodyPadding: 10,
+ *         renderTo: Ext.getBody(),
+ *         layout: {
+ *             type: 'hbox',
+ *             align: 'middle'
+ *         },
+ *         items: [{
+ *             xtype: 'textfield',
+ *             hideLabel: true,
+ *             flex: 1
+ *         }, {
+ *             xtype: 'label',
+ *             forId: 'myFieldId',
+ *             text: 'My Awesome Field',
+ *             margin: '0 0 0 10'
+ *         }]
+ *     });
+ */
+Ext.define('Ext.form.Label', {
+    extend: 'Ext.Component',
+    alias: 'widget.label',
+
+    requires: ['Ext.util.Format'],
+
+    autoEl: 'label',
+
+    /**
+     * @cfg {String} [text='']
+     * The plain text to display within the label. If you need to include HTML
+     * tags within the label's innerHTML, use the {@link #html} config instead.
+     */
+
+    /**
+     * @cfg {String} forId
+     * The id of the input element to which this label will be bound via the standard HTML 'for'
+     * attribute. If not specified, the attribute will not be added to the label. In most cases
+     * you will be associating the label with a {@link Ext.form.field.Base} component,
+     * so you should make sure this matches the {@link Ext.form.field.Base#inputId inputId}
+     * of that field.
+     */
+
+    /**
+     * @cfg {String} [html='']
+     * An HTML fragment that will be used as the label's innerHTML.
+     * Note that if {@link #text} is specified it will take precedence and this value
+     * will be ignored.
+     */
+
+    maskOnDisable: false,
+
+    getElConfig: function() {
+        var me = this;
+
+        me.html = me.text ? Ext.util.Format.htmlEncode(me.text) : (me.html || '');
+
+        return Ext.apply(me.callParent(), {
+            htmlFor: me.forId || ''
+        });
+    },
+
+    /**
+     * Updates the label's innerHTML with the specified string.
+     * @param {String} text The new label text
+     * @param {Boolean} [encode=true] False to skip HTML-encoding the text when rendering it
+     * to the label. This might be useful if you want to include tags in the label's innerHTML
+     * rather than rendering them as string literals per the default logic.
+     * @return {Ext.form.Label} this
+     */
+    setText: function(text, encode) {
+        var me = this;
+
+        encode = encode !== false;
+
+        if (encode) {
+            me.text = text;
+            delete me.html;
+        }
+        else {
+            me.html = text;
+            delete me.text;
+        }
+
+        if (me.rendered) {
+            me.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(text) : text;
+            me.updateLayout();
+        }
+
+        return me;
+    }
+});

File diff suppressed because it is too large
+ 1142 - 0
assets/ext-7.4.0.42/classic/classic/src/form/Labelable.js


+ 483 - 0
assets/ext-7.4.0.42/classic/classic/src/form/Panel.js

@@ -0,0 +1,483 @@
+/**
+ * FormPanel provides a standard container for forms. It is essentially a standard
+ * {@link Ext.panel.Panel} which automatically creates a {@link Ext.form.Basic BasicForm}
+ * for managing any {@link Ext.form.field.Field} objects that are added as descendants of the panel.
+ * It also includes conveniences for configuring and working with the BasicForm and the collection
+ * of Fields.
+ * 
+ * # Layout
+ * 
+ * By default, FormPanel is configured with `{@link Ext.layout.container.Anchor layout:'anchor'}`
+ * for the layout of its immediate child items. This can be changed to any of the supported
+ * container layouts. The layout of sub-containers is configured in
+ * {@link Ext.container.Container#layout the standard way}.
+ * 
+ * # BasicForm
+ * 
+ * FormPanel class accepts all
+ * of the config options supported by the {@link Ext.form.Basic} class, and will pass them along to
+ * the internal BasicForm when it is created.
+ * 
+ * The following events fired by the BasicForm will be re-fired by the FormPanel and can therefore
+ * be listened for on the FormPanel itself:
+ * 
+ * - {@link Ext.form.Basic#beforeaction beforeaction}
+ * - {@link Ext.form.Basic#actionfailed actionfailed}
+ * - {@link Ext.form.Basic#actioncomplete actioncomplete}
+ * - {@link Ext.form.Basic#validitychange validitychange}
+ * - {@link Ext.form.Basic#dirtychange dirtychange}
+ * 
+ * # Field Defaults
+ * 
+ * The {@link #fieldDefaults} config option conveniently allows centralized configuration of default
+ * values for all fields added as descendants of the FormPanel. Any config option recognized
+ * by implementations of {@link Ext.form.Labelable} may be included in this object. See the
+ * {@link #fieldDefaults} documentation for details of how the defaults are applied.
+ * 
+ * # Form Validation
+ * 
+ * With the default configuration, form fields are validated on-the-fly while the user edits
+ * their values. This can be controlled on a per-field basis (or via the {@link #fieldDefaults}
+ * config) with the field config properties {@link Ext.form.field.Field#validateOnChange} and
+ * {@link Ext.form.field.Base#checkChangeEvents}, and the FormPanel's config properties
+ * {@link #pollForChanges} and {@link #pollInterval}.
+ * 
+ * Any component within the FormPanel can be configured with `formBind: true`. This will cause that
+ * component to be automatically disabled when the form is invalid, and enabled when it is valid.
+ * This is most commonly used for Button components to prevent submitting the form in an invalid
+ * state, but can be used on any component type.
+ * 
+ * For more information on form validation see the following:
+ * 
+ * - {@link Ext.form.field.Field#validateOnChange}
+ * - {@link #pollForChanges} and {@link #pollInterval}
+ * - {@link Ext.form.field.VTypes}
+ * - {@link Ext.form.Basic#doAction BasicForm.doAction clientValidation notes}
+ * 
+ * # Form Submission
+ * 
+ * By default, Ext Forms are submitted through Ajax, using {@link Ext.form.action.Action}.
+ * See the documentation for {@link Ext.form.Basic} for details.
+ *
+ * # Example usage
+ * 
+ *     @example
+ *     Ext.create('Ext.form.Panel', {
+ *         title: 'Simple Form',
+ *         bodyPadding: 5,
+ *         width: 350,
+ * 
+ *         // The form will submit an AJAX request to this URL when submitted
+ *         url: 'save-form.php',
+ * 
+ *         // Fields will be arranged vertically, stretched to full width
+ *         layout: 'anchor',
+ *         defaults: {
+ *             anchor: '100%'
+ *         },
+ * 
+ *         // The fields
+ *         defaultType: 'textfield',
+ *         items: [{
+ *             fieldLabel: 'First Name',
+ *             name: 'first',
+ *             allowBlank: false
+ *         },{
+ *             fieldLabel: 'Last Name',
+ *             name: 'last',
+ *             allowBlank: false
+ *         }],
+ * 
+ *         // Reset and Submit buttons
+ *         buttons: [{
+ *             text: 'Reset',
+ *             handler: function() {
+ *                 this.up('form').getForm().reset();
+ *             }
+ *         }, {
+ *             text: 'Submit',
+ *             formBind: true, //only enabled once the form is valid
+ *             disabled: true,
+ *             handler: function() {
+ *                 var form = this.up('form').getForm();
+ *                 if (form.isValid()) {
+ *                     form.submit({
+ *                         success: function(form, action) {
+ *                            Ext.Msg.alert('Success', action.result.msg);
+ *                         },
+ *                         failure: function(form, action) {
+ *                             Ext.Msg.alert('Failed', action.result.msg);
+ *                         }
+ *                     });
+ *                 }
+ *             }
+ *         }],
+ *         renderTo: Ext.getBody()
+ *     });
+ *
+ */
+Ext.define('Ext.form.Panel', {
+    extend: 'Ext.panel.Panel',
+    alias: 'widget.form',
+    alternateClassName: ['Ext.FormPanel', 'Ext.form.FormPanel'],
+
+    requires: [
+        'Ext.form.Basic',
+        'Ext.util.TaskRunner'
+    ],
+
+    mixins: {
+        fieldAncestor: 'Ext.form.FieldAncestor'
+    },
+
+    /**
+     * @cfg {Boolean} pollForChanges
+     * If set to `true`, sets up an interval task (using the {@link #pollInterval}) in which the
+     * panel's fields are repeatedly checked for changes in their values. This is in addition
+     * to the normal detection each field does on its own input element, and is not needed
+     * in most cases. It does, however, provide a means to absolutely guarantee detection
+     * of all changes including some edge cases in some browsers which do not fire native events.
+     * Defaults to `false`.
+     */
+
+    /**
+     * @cfg {Number} pollInterval
+     * Interval in milliseconds at which the form's fields are checked for value changes. Only used
+     * if the {@link #pollForChanges} option is set to `true`. Defaults to 500 milliseconds.
+     */
+
+    /**
+     * @cfg {Ext.enums.Layout/Object} layout
+     * The {@link Ext.container.Container#layout} for the form panel's immediate child items.
+     */
+    layout: 'anchor',
+
+    bodyAriaRole: 'form',
+
+    basicFormConfigs: [
+        /**
+         * @cfg api
+         * @inheritdoc Ext.form.Basic#cfg!api
+         */
+        'api',
+
+        /**
+         * @cfg baseParams
+         * @inheritdoc Ext.form.Basic#cfg!baseParams
+         */
+        'baseParams',
+
+        /**
+         * @cfg errorReader
+         * @inheritdoc Ext.form.Basic#cfg!errorReader
+         */
+        'errorReader',
+
+        /**
+         * @cfg jsonSubmit
+         * @inheritdoc Ext.form.Basic#cfg!jsonSubmit
+         */
+        'jsonSubmit',
+
+        /**
+         * @cfg method
+         * @inheritdoc Ext.form.Basic#cfg!method
+         */
+        'method',
+
+        /**
+         * @cfg paramOrder
+         * @inheritdoc Ext.form.Basic#cfg!paramOrder
+         */
+        'paramOrder',
+
+        /**
+         * @cfg paramsAsHash
+         * @inheritdoc Ext.form.Basic#cfg!paramsAsHash
+         */
+        'paramsAsHash',
+
+        /**
+         * @cfg reader
+         * @inheritdoc Ext.form.Basic#cfg!reader
+         */
+        'reader',
+
+        /**
+         * @cfg standardSubmit
+         * @inheritdoc Ext.form.Basic#cfg!standardSubmit
+         */
+        'standardSubmit',
+
+        /**
+         * @cfg timeout
+         * @inheritdoc Ext.form.Basic#cfg!timeout
+         */
+        'timeout',
+
+        /**
+         * @cfg trackResetOnLoad
+         * @inheritdoc Ext.form.Basic#cfg!trackResetOnLoad
+         */
+        'trackResetOnLoad',
+
+        /**
+         * @cfg url
+         * @inheritdoc Ext.form.Basic#cfg!url
+         */
+        'url',
+
+        /**
+         * @cfg waitMsgTarget
+         * @inheritdoc Ext.form.Basic#cfg!waitMsgTarget
+         */
+        'waitMsgTarget',
+
+        /**
+         * @cfg waitTitle
+         * @inheritdoc Ext.form.Basic#cfg!waitTitle
+         */
+        'waitTitle'
+    ],
+
+    initComponent: function() {
+        var me = this;
+
+        if (me.frame) {
+            me.border = false;
+        }
+
+        me.initFieldAncestor();
+        me.callParent();
+
+        me.relayEvents(me.form, [
+            /**
+             * @event beforeaction
+             * @inheritdoc Ext.form.Basic#beforeaction
+             */
+            'beforeaction',
+
+            /**
+             * @event actionfailed
+             * @inheritdoc Ext.form.Basic#actionfailed
+             */
+            'actionfailed',
+
+            /**
+             * @event actioncomplete
+             * @inheritdoc Ext.form.Basic#actioncomplete
+             */
+            'actioncomplete',
+
+            /**
+             * @event validitychange
+             * @inheritdoc Ext.form.Basic#validitychange
+             */
+            'validitychange',
+
+            /**
+             * @event dirtychange
+             * @inheritdoc Ext.form.Basic#dirtychange
+             */
+            'dirtychange'
+        ]);
+
+        // Start polling if configured
+        if (me.pollForChanges) {
+            me.startPolling(me.pollInterval || 500);
+        }
+    },
+
+    initItems: function() {
+        // Create the BasicForm
+        this.callParent();
+        this.initMonitor();
+        this.form = this.createForm();
+    },
+
+    // Initialize the BasicForm after all layouts have been completed.
+    afterFirstLayout: function() {
+        this.callParent(arguments);
+        this.form.initialize();
+    },
+
+    /**
+     * @private
+     */
+    createForm: function() {
+        var cfg = {},
+            props = this.basicFormConfigs,
+            len = props.length,
+            i = 0,
+            prop;
+
+        for (; i < len; ++i) {
+            prop = props[i];
+            cfg[prop] = this[prop];
+        }
+
+        return new Ext.form.Basic(this, cfg);
+    },
+
+    /**
+     * Provides access to the {@link Ext.form.Basic Form} which this Panel contains.
+     * @return {Ext.form.Basic} The {@link Ext.form.Basic Form} which this Panel contains.
+     */
+    getForm: function() {
+        return this.form;
+    },
+
+    /**
+     * Loads an {@link Ext.data.Model} into this form (internally just calls
+     * {@link Ext.form.Basic#loadRecord}).
+     * See also {@link Ext.form.Basic#trackResetOnLoad trackResetOnLoad}. The fields in the model
+     * are mapped to  fields in the form by matching either the {@link Ext.form.field.Base#name}
+     * or {@link Ext.Component#itemId}.  
+     * @param {Ext.data.Model} record The record to load
+     * @return {Ext.form.Basic} The Ext.form.Basic attached to this FormPanel
+     */
+    loadRecord: function(record) {
+        return this.getForm().loadRecord(record);
+    },
+
+    /**
+     * Returns the currently loaded Ext.data.Model instance if one was loaded via
+     * {@link #loadRecord}.
+     * @return {Ext.data.Model} The loaded instance
+     */
+    getRecord: function() {
+        return this.getForm().getRecord();
+    },
+
+    /**
+     * Persists the values in this form into the passed {@link Ext.data.Model} object
+     * in a beginEdit/endEdit block. If the record is not specified, it will attempt to update
+     * (if it exists) the record provided to {@link #loadRecord}.
+     * @param {Ext.data.Model} [record] The record to edit
+     * @return {Ext.form.Basic} The Ext.form.Basic attached to this FormPanel
+     */
+    updateRecord: function(record) {
+        return this.getForm().updateRecord(record);
+    },
+
+    /**
+     * @method getValues
+     * Convenience function for fetching the current value of each field in the form.
+     * This is the same as calling {@link Ext.form.Basic#getValues this.getForm().getValues()}.
+     *
+     * @inheritdoc Ext.form.Basic#getValues
+     */
+    getValues: function(asString, dirtyOnly, includeEmptyText, useDataValues) {
+        return this.getForm().getValues(asString, dirtyOnly, includeEmptyText, useDataValues);
+    },
+
+    /**
+     * @method isDirty
+     * Convenience function to check if the form has any dirty fields. This is the same as calling
+     * {@link Ext.form.Basic#isDirty this.getForm().isDirty()}.
+     *
+     * @inheritdoc Ext.form.Basic#isDirty
+     */
+    isDirty: function() {
+        return this.form.isDirty();
+    },
+
+    /**
+     * @method isValid
+     * Convenience function to check if the form has all valid fields. This is the same as calling
+     * {@link Ext.form.Basic#isValid this.getForm().isValid()}.
+     *
+     * @inheritdoc Ext.form.Basic#isValid
+     */
+    isValid: function() {
+        return this.form.isValid();
+    },
+
+    /**
+     * @method reset
+     * Convenience function reset the form. This is the same as calling
+     * {@link Ext.form.Basic#reset this.getForm().reset()}.
+     *
+     * @inheritdoc Ext.form.Basic#reset
+     */
+    reset: function(resetRecord) {
+        return this.form.reset(resetRecord);
+    },
+
+    /**
+     * @method hasInvalidField
+     * Convenience function to check if the form has any invalid fields. This is the same as calling
+     * {@link Ext.form.Basic#hasInvalidField this.getForm().hasInvalidField()}.
+     *
+     * @inheritdoc Ext.form.Basic#hasInvalidField
+     */
+    hasInvalidField: function() {
+        return this.form.hasInvalidField();
+    },
+
+    doDestroy: function() {
+        this.stopPolling();
+        this.form.destroy();
+
+        this.callParent();
+    },
+
+    /**
+     * This is a proxy for the underlying BasicForm's {@link Ext.form.Basic#load} call.
+     * @param {Object} options The options to pass to the action (see {@link Ext.form.Basic#load}
+     * and {@link Ext.form.Basic#doAction} for details)
+     */
+    load: function(options) {
+        this.form.load(options);
+    },
+
+    /**
+     * This is a proxy for the underlying BasicForm's {@link Ext.form.Basic#submit} call.
+     * @param {Object} options The options to pass to the action (see {@link Ext.form.Basic#submit}
+     * and {@link Ext.form.Basic#doAction} for details)
+     */
+    submit: function(options) {
+        this.form.submit(options);
+    },
+
+    /**
+     * Start an interval task to continuously poll all the fields in the form for changes in their
+     * values. This is normally started automatically by setting the {@link #pollForChanges} config.
+     * @param {Number} interval The interval in milliseconds at which the check should run.
+     */
+    startPolling: function(interval) {
+        this.stopPolling();
+
+        this.pollTask = Ext.util.TaskManager.start({
+            interval: interval,
+            run: this.checkChange,
+            scope: this
+        });
+    },
+
+    /**
+     * Stop a running interval task that was started by {@link #startPolling}.
+     */
+    stopPolling: function() {
+        var task = this.pollTask;
+
+        if (task) {
+            Ext.util.TaskManager.stop(task, true);
+            this.pollTask = null;
+        }
+    },
+
+    /**
+     * Forces each field within the form panel to
+     * {@link Ext.form.field.Field#checkChange check if its value has changed}.
+     */
+    checkChange: function() {
+        var fields = this.form.getFields().items,
+            f,
+            fLen = fields.length;
+
+        for (f = 0; f < fLen; f++) {
+            fields[f].checkChange();
+        }
+    }
+});

+ 416 - 0
assets/ext-7.4.0.42/classic/classic/src/form/RadioGroup.js

@@ -0,0 +1,416 @@
+/**
+ * A {@link Ext.form.FieldContainer field container} which has a specialized layout for arranging
+ * {@link Ext.form.field.Radio} controls into columns, and provides convenience
+ * {@link Ext.form.field.Field} methods for {@link #getValue getting}, {@link #setValue setting},
+ * and {@link #validate validating} the group of radio buttons as a whole.
+ *
+ * ## Validation
+ *
+ * Individual radio buttons themselves have no default validation behavior, but
+ * sometimes you want to require a user to select one of a group of radios. RadioGroup
+ * allows this by setting the config `{@link #allowBlank}:false`; when the user does not check at
+ * one of the radio buttons, the entire group will be highlighted as invalid and the
+ * {@link #blankText error message} will be displayed according to the {@link #msgTarget} config.
+ *
+ * ## Layout
+ *
+ * The default layout for RadioGroup makes it easy to arrange the radio buttons into
+ * columns; see the {@link #columns} and {@link #vertical} config documentation for details.
+ * You may also use a completely different layout by setting the {@link #cfg-layout} to one of the 
+ * other supported layout types; for instance you may wish to use a custom arrangement 
+ * of hbox and vbox containers. In that case the Radio components at any depth will 
+ * still be managed by the RadioGroup's validation.
+ *
+ * ## Example usage
+ *
+ *     @example
+ *     Ext.create('Ext.form.Panel', {
+ *         title: 'RadioGroup Example',
+ *         width: 300,
+ *         bodyPadding: 10,
+ *         renderTo: Ext.getBody(),
+ *         items:[{
+ *             xtype: 'radiogroup',
+ *             fieldLabel: 'Two Columns',
+ *             // Arrange radio buttons into two columns, distributed vertically
+ *             columns: 2,
+ *             vertical: true,
+ *             items: [
+ *                 { boxLabel: 'Item 1', name: 'rb', inputValue: '1' },
+ *                 { boxLabel: 'Item 2', name: 'rb', inputValue: '2', checked: true},
+ *                 { boxLabel: 'Item 3', name: 'rb', inputValue: '3' },
+ *                 { boxLabel: 'Item 4', name: 'rb', inputValue: '4' },
+ *                 { boxLabel: 'Item 5', name: 'rb', inputValue: '5' },
+ *                 { boxLabel: 'Item 6', name: 'rb', inputValue: '6' }
+ *             ]
+ *         }]
+ *     });
+ *
+ * ## Example with value binding to the RadioGroup.  In the below example, "Item 2" will
+ * initially be checked using `myValue: '2'` from the ViewModel.
+ *
+ *     @example
+ *     Ext.define('MyApp.main.view.Main', {
+ *         extend: 'Ext.app.ViewModel',
+ *         alias: 'viewmodel.main',
+ *         data: {
+ *             myValue: '2'
+ *         }
+ *     });
+ *
+ *     Ext.create('Ext.form.Panel', {
+ *         title: 'RadioGroup Example',
+ *         viewModel: {
+ *             type: 'main'
+ *         },
+ *         width: 300,
+ *         bodyPadding: 10,
+ *         renderTo: Ext.getBody(),
+ *         items:[{
+ *             xtype: 'radiogroup',
+ *             fieldLabel: 'Two Columns',
+ *             // Arrange radio buttons into two columns, distributed vertically
+ *             columns: 2,
+ *             vertical: true,
+ *             simpleValue: true,  // set simpleValue to true to enable value binding
+ *             bind: '{myValue}',
+ *             items: [
+ *                 { boxLabel: 'Item 1', name: 'rb', inputValue: '1' },
+ *                 { boxLabel: 'Item 2', name: 'rb', inputValue: '2' },
+ *                 { boxLabel: 'Item 3', name: 'rb', inputValue: '3' },
+ *                 { boxLabel: 'Item 4', name: 'rb', inputValue: '4' },
+ *                 { boxLabel: 'Item 5', name: 'rb', inputValue: '5' },
+ *                 { boxLabel: 'Item 6', name: 'rb', inputValue: '6' }
+ *             ]
+ *         }]
+ *     });
+ *
+ */
+Ext.define('Ext.form.RadioGroup', {
+    extend: 'Ext.form.CheckboxGroup',
+    xtype: 'radiogroup',
+
+    /**
+     * @property {Boolean} isRadioGroup
+     * The value `true` to identify an object as an instance of this or derived class.
+     * @readonly
+     * @since 6.2.0
+     */
+    isRadioGroup: true,
+
+    requires: [
+        'Ext.form.field.Radio'
+    ],
+
+    /**
+     * @cfg {Ext.form.field.Radio[]/Object[]} items
+     * An Array of {@link Ext.form.field.Radio Radio}s or Radio config objects to arrange
+     * in the group.
+     */
+
+    /**
+     * @cfg {Boolean} allowBlank
+     * True to allow every item in the group to be blank.
+     * If allowBlank = false and no items are selected at validation time,
+     * {@link #blankText} will be used as the error text.
+     */
+    allowBlank: true,
+
+    /**
+     * @cfg {String} blankText
+     * Error text to display if the {@link #allowBlank} validation fails
+     * @locale
+     */
+    blankText: 'You must select one item in this group',
+
+    defaultType: 'radiofield',
+
+    /**
+     * @cfg {Boolean} [local=false]
+     * By default, child {@link Ext.form.field.Radio radio} `name`s are scoped to the
+     * encapsulating {@link Ext.form.Panel form panel} if any, of the document.
+     *
+     * If you are using multiple `RadioGroup`s each of which uses the same `name`
+     * configuration in child {@link Ext.form.field.Radio radio}s, configure this as
+     * `true` to scope the names to within this `RadioGroup`
+     */
+    local: false,
+
+    /**
+     * @cfg {Boolean} simpleValue
+     * When set to `true` the `value` of this group of `radiofield` components will be
+     * mapped to the `inputValue` of the checked item. This is, the `getValue` method
+     * will return the `inputValue` of the checked item while `setValue` will check the
+     * `radiofield` whose `inputValue` matches the given value.
+     *
+     * This field allows the `radiogroup` to participate in binding an entire group of
+     * radio buttons to a single value.
+     *
+     * In the below example, "Item 2" will initially be checked using `myValue: '2'` from
+     * the ViewModel.
+     *
+     *     @example
+     *     Ext.define('MyApp.main.view.Main', {
+     *         extend: 'Ext.app.ViewModel',
+     *         alias: 'viewmodel.main',
+     *         data: {
+     *             myValue: '2'
+     *         }
+     *     });
+     *
+     *     Ext.create('Ext.form.Panel', {
+     *         title: 'RadioGroup Example',
+     *         viewModel: {
+     *             type: 'main'
+     *         },
+     *         width: 300,
+     *         bodyPadding: 10,
+     *         renderTo: Ext.getBody(),
+     *         items:[{
+     *             xtype: 'radiogroup',
+     *             fieldLabel: 'Two Columns',
+     *             // Arrange radio buttons into two columns, distributed vertically
+     *             columns: 2,
+     *             vertical: true,
+     *             simpleValue: true,  // set simpleValue to true to enable value binding
+     *             bind: '{myValue}',
+     *             items: [
+     *                 { boxLabel: 'Item 1', name: 'rb', inputValue: '1' },
+     *                 { boxLabel: 'Item 2', name: 'rb', inputValue: '2' },
+     *                 { boxLabel: 'Item 3', name: 'rb', inputValue: '3' },
+     *                 { boxLabel: 'Item 4', name: 'rb', inputValue: '4' },
+     *                 { boxLabel: 'Item 5', name: 'rb', inputValue: '5' },
+     *                 { boxLabel: 'Item 6', name: 'rb', inputValue: '6' }
+     *             ]
+     *         }]
+     *     });
+     *
+     * @since 6.2.0
+     */
+    simpleValue: false,
+
+    defaultBindProperty: 'value',
+
+    /**
+     * @private
+     */
+    groupCls: Ext.baseCSSPrefix + 'form-radio-group',
+
+    ariaRole: 'radiogroup',
+
+    initRenderData: function() {
+        var me = this,
+            data, ariaAttr;
+
+        data = me.callParent();
+        ariaAttr = data.ariaAttributes;
+
+        if (ariaAttr) {
+            ariaAttr['aria-required'] = !me.allowBlank;
+            ariaAttr['aria-invalid'] = false;
+        }
+
+        return data;
+    },
+
+    lookupComponent: function(config) {
+        var result = this.callParent([config]);
+
+        // Local means that the exclusivity of checking by name is scoped to this RadioGroup.
+        // So multiple RadioGroups can be used which use the same Radio names.
+        // This enables their use as a grid widget.
+        if (this.local) {
+            result.formId = this.getId();
+        }
+
+        return result;
+    },
+
+    getBoxes: function(query, root) {
+        return (root || this).query('[isRadio]' + (query || ''));
+    },
+
+    checkChange: function() {
+        var me = this,
+            value, key;
+
+        value = me.getValue();
+
+        // Safari might throw an exception on trying to get the keys of a Number
+        key = typeof value === 'object' && Ext.Object.getKeys(value)[0];
+
+        // If the value is an array we skip out here because it's during a change
+        // between multiple items, so we never want to fire a change.
+        // Check if we have a radio group not using simpleValue that has been
+        // reset for which we want to fire a change event
+        if (me.simpleValue || ((key && !Ext.isArray(value[key])) ||
+            (Ext.isObject(value) && Ext.Object.isEmpty(value)))) {
+            me.callParent();
+        }
+    },
+
+    isEqual: function(value1, value2) {
+        if (this.simpleValue) {
+            return value1 === value2;
+        }
+
+        return this.callParent([ value1, value2 ]);
+    },
+
+    getValue: function() {
+        var me = this,
+            items = me.items.items,
+            i, item, ret;
+
+        if (me.simpleValue) {
+            for (i = items.length; i-- > 0;) {
+                item = items[i];
+
+                if (item.checked) {
+                    ret = item.inputValue;
+                    break;
+                }
+            }
+        }
+        else {
+            ret = me.callParent();
+        }
+
+        return ret;
+    },
+
+    /**
+     * Sets the value of the radio group. The radio with corresponding name and value will be set.
+     * This method is simpler than {@link Ext.form.CheckboxGroup#setValue} because only 1 value
+     * is allowed for each name. You can use the setValue method as:
+     *
+     *     var form = Ext.create('Ext.form.Panel', {
+     *         title       : 'RadioGroup Example',
+     *         width       : 300,
+     *         bodyPadding : 10,
+     *         renderTo    : Ext.getBody(),
+     *         items       : [
+     *             {
+     *                 xtype      : 'radiogroup',
+     *                 fieldLabel : 'Group',
+     *                 items      : [
+     *                     { boxLabel : 'Item 1', name : 'rb', inputValue : 1 },
+     *                     { boxLabel : 'Item 2', name : 'rb', inputValue : 2 }
+     *                 ]
+     *             }
+     *         ],
+     *         tbar        : [
+     *             {
+     *                 text    : 'setValue on RadioGroup',
+     *                 handler : function() {
+     *                     form.child('radiogroup').setValue({
+     *                         rb : 2
+     *                     });
+     *                 }
+     *             }
+     *         ]
+     *     });
+     *
+     * @param {Mixed} value An Object to map names to values to be set. If not an Object,
+     * this `radiofield` with a matching `inputValue` will be checked.
+     * @return {Ext.form.RadioGroup} this
+     */
+    setValue: function(value) {
+        var items = this.items,
+            cbValue, cmp, formId, radios, i, len, name;
+
+        Ext.suspendLayouts();
+
+        if (this.simpleValue) {
+            for (i = 0, len = items.length; i < len; ++i) {
+                cmp = items.items[i];
+
+                cmp.$groupChange = true;
+                cmp.setValue(cmp.inputValue === value);
+                delete cmp.$groupChange;
+            }
+        }
+        else if (Ext.isObject(value)) {
+            cmp = items.first();
+            formId = cmp ? cmp.getFormId() : null;
+
+            for (name in value) {
+                cbValue = value[name];
+                radios = Ext.form.RadioManager.getWithValue(name, cbValue, formId).items;
+                len = radios.length;
+
+                for (i = 0; i < len; ++i) {
+                    radios[i].setValue(true);
+                }
+            }
+        }
+
+        Ext.resumeLayouts(true);
+
+        return this;
+    },
+
+    markInvalid: function(errors) {
+        var ariaDom = this.ariaEl.dom;
+
+        this.callParent([errors]);
+
+        if (ariaDom) {
+            ariaDom.setAttribute('aria-invalid', true);
+        }
+    },
+
+    clearInvalid: function() {
+        var ariaDom = this.ariaEl.dom;
+
+        this.callParent();
+
+        if (ariaDom) {
+            ariaDom.setAttribute('aria-invalid', false);
+        }
+    }
+}, function() {
+    // Firefox has a nasty bug, or a misfeature, with tabbing over radio buttons
+    // when there is no checked button in a group. In such case the first button
+    // in the group should be focused upon tabbing into the group, and subsequent
+    // tab key press should leave the group; however Firefox will tab over every
+    // radio button individually as if they were checkboxes.
+    // Fortunately for us this bugfeature only applies to tabbing; arrow key
+    // navigation is not affected. So the issue can be easily worked around
+    // by removing all group buttons from tab order upon focusing the first button
+    // in the group, and restoring their tabbable state upon focusleave.
+    // This works exactly the same way regardless of having or not a checked button
+    // in the group, so we keep the code simple.
+
+    // This condition should get more version specific when this bug is fixed:
+    // https://bugzilla.mozilla.org/show_bug.cgi?id=1267488
+    if (Ext.isGecko) {
+        this.override({
+            onFocusEnter: function(e) {
+                var target = e.toComponent,
+                    radios, i, len;
+
+                if (target.isRadio) {
+                    radios = target.getManager().getByName(target.name, target.getFormId()).items;
+
+                    for (i = 0, len = radios.length; i < len; i++) {
+                        radios[i].disableTabbing();
+                    }
+                }
+            },
+
+            onFocusLeave: function(e) {
+                var target = e.fromComponent,
+                    radios, i, len;
+
+                if (target.isRadio) {
+                    radios = target.getManager().getByName(target.name, target.getFormId()).items;
+
+                    for (i = 0, len = radios.length; i < len; i++) {
+                        radios[i].enableTabbing();
+                    }
+                }
+            }
+        });
+    }
+});

+ 28 - 0
assets/ext-7.4.0.42/classic/classic/src/form/RadioManager.js

@@ -0,0 +1,28 @@
+/**
+ * @private
+ * Private utility class for managing all {@link Ext.form.field.Radio} fields grouped by name.
+ */
+Ext.define('Ext.form.RadioManager', {
+    extend: 'Ext.util.MixedCollection',
+    singleton: true,
+
+    getByName: function(name, formId) {
+        return this.filterBy(function(item) {
+            return item.name === name && item.getFormId() === formId;
+        });
+    },
+
+    getWithValue: function(name, value, formId) {
+        return this.filterBy(function(item) {
+            return item.name === name &&
+                   item.inputValue == value && // eslint-disable-line eqeqeq
+                   item.getFormId() === formId;
+        });
+    },
+
+    getChecked: function(name, formId) {
+        return this.findBy(function(item) {
+            return item.name === name && item.checked && item.getFormId() === formId;
+        });
+    }
+});

+ 332 - 0
assets/ext-7.4.0.42/classic/classic/src/form/action/Action.js

@@ -0,0 +1,332 @@
+/**
+ * The subclasses of this class provide actions to perform upon {@link Ext.form.Basic Form}s.
+ *
+ * Instances of this class are only created by a {@link Ext.form.Basic Form} when the Form needs
+ * to perform an action such as submit or load. The Configuration options listed for this class
+ * are set through the Form's action methods: {@link Ext.form.Basic#submit submit},
+ * {@link Ext.form.Basic#load load} and {@link Ext.form.Basic#doAction doAction}
+ *
+ * The instance of Action which performed the action is passed to the success and failure callbacks
+ * of the Form's action methods ({@link Ext.form.Basic#submit submit},
+ * {@link Ext.form.Basic#load load} and {@link Ext.form.Basic#doAction doAction}), and to the
+ * {@link Ext.form.Basic#actioncomplete actioncomplete} and
+ * {@link Ext.form.Basic#actionfailed actionfailed} event handlers.
+ */
+Ext.define('Ext.form.action.Action', {
+    alternateClassName: 'Ext.form.Action',
+
+    /**
+     * @cfg {Ext.form.Basic} form
+     * The {@link Ext.form.Basic BasicForm} instance that is invoking this Action. Required.
+     */
+
+    /**
+     * @cfg {String} url
+     * The URL that the Action is to invoke. Will default to the {@link Ext.form.Basic#url url}
+     * configured on the {@link #form}.
+     */
+
+    /**
+     * @cfg {Boolean} reset
+     * When set to **true**, causes the Form to be {@link Ext.form.Basic#reset reset} on Action
+     * success. If specified, this happens before the {@link #success} callback is called and before
+     * the Form's {@link Ext.form.Basic#actioncomplete actioncomplete} event fires.
+     */
+
+    /**
+     * @cfg {String} method
+     * The HTTP method to use to access the requested URL.
+     * Defaults to the {@link Ext.form.Basic#method BasicForm's method}, or 'POST' if not specified.
+     */
+
+    /**
+     * @cfg {Object/String} params
+     * Extra parameter values to pass. These are added to the Form's
+     * {@link Ext.form.Basic#baseParams} and passed to the specified URL along with the Form's
+     * input fields.
+     *
+     * Parameters are encoded as standard HTTP parameters using
+     * {@link Ext#urlEncode Ext.Object.toQueryString}.
+     */
+
+    /**
+     * @cfg {Object} headers
+     * Extra headers to be sent in the AJAX request for submit and load actions.
+     * See {@link Ext.data.proxy.Ajax#headers}.
+     * 
+     * **Note:** Headers are not sent during file upload.
+     */
+
+    /**
+     * @cfg {Number} timeout
+     * The number of seconds to wait for a server response before failing with the
+     * {@link #failureType} as {@link Ext.form.action.Action#CONNECT_FAILURE}. If not specified,
+     * defaults to the configured {@link Ext.form.Basic#timeout timeout} of the {@link #form}.
+     */
+
+    /**
+     * @cfg {Function/String} success
+     * The function to call when a valid success return packet is received.
+     * @cfg {Ext.form.Basic} success.form The form that requested the action
+     * @cfg {Ext.form.action.Action} success.action The Action class. The {@link #result} property
+     * of this object may be examined to perform custom post-processing.
+     * 
+     * @controllable
+     */
+
+    /**
+     * @cfg {Function/String} failure
+     * The function to call when a failure packet was received, or when an error 
+     * occurred in the Ajax communication.
+     * @cfg {Ext.form.Basic} failure.form The form that requested the action
+     * @cfg {Ext.form.action.Action} failure.action The Action class. If an Ajax error 
+     * occurred, the failure type will be in {@link #failureType}. The {@link #result} 
+     * property of this object may be examined to perform custom post-processing.
+     * 
+     * @controllable
+     */
+
+    /**
+     * @cfg {Object} scope
+     * The scope in which to call the configured #success and #failure callback functions
+     * (the `this` reference for the callback functions).
+     */
+
+    /**
+     * @cfg {String} waitMsg
+     * The message to be displayed by a call to {@link Ext.window.MessageBox#wait} during the time
+     * the action is being processed.
+     */
+
+    /**
+     * @cfg {String} waitTitle
+     * The title to be displayed by a call to {@link Ext.window.MessageBox#wait} during the time
+     * the action is being processed.
+     */
+
+    /**
+     * @cfg {Boolean} submitEmptyText
+     * If set to true, the emptyText value will be sent with the form when it is submitted.
+     */
+    submitEmptyText: true,
+
+    /**
+     * @property {String} type
+     * The type of action this Action instance performs. Currently only "submit" and "load"
+     * are supported.
+     */
+
+    /* eslint-disable max-len */
+    /**
+     * @property {String} failureType
+     * The type of failure detected will be one of these:
+     * {@link #CLIENT_INVALID}, {@link #SERVER_INVALID}, {@link #CONNECT_FAILURE}, or {@link #LOAD_FAILURE}.
+     *
+     * Usage:
+     *
+     *     var fp = new Ext.form.Panel({
+     *     ...
+     *     buttons: [{
+     *         text: 'Save',
+     *         formBind: true,
+     *         handler: function(){
+     *             if(fp.getForm().isValid()){
+     *                 fp.getForm().submit({
+     *                     url: 'form-submit.php',
+     *                     waitMsg: 'Submitting your data...',
+     *                     success: function(form, action){
+     *                         // server responded with success = true
+     *                         var result = action.result;
+     *                     },
+     *                     failure: function(form, action){
+     *                         if (action.{@link #failureType} === Ext.form.action.Action.CONNECT_FAILURE) {
+     *                             Ext.Msg.alert('Error',
+     *                                 'Status:'+action.response.status+': '+
+     *                                 action.response.statusText);
+     *                         }
+     *                         if (action.failureType === Ext.form.action.Action.SERVER_INVALID){
+     *                             // server responded with success = false
+     *                             Ext.Msg.alert('Invalid', action.result.errormsg);
+     *                         }
+     *                     }
+     *                 });
+     *             }
+     *         }
+     *     },{
+     *         text: 'Reset',
+     *         handler: function(){
+     *             fp.getForm().reset();
+     *         }
+     *     }]
+     */
+    /* eslint-enable max-len */
+
+    /**
+     * @property {Object} response
+     * The raw XMLHttpRequest object used to perform the action.
+     */
+
+    /**
+     * @property {Object} result
+     * The decoded response object containing a boolean `success` property and other,
+     * action-specific properties.
+     */
+
+    /**
+     * Creates new Action.
+     * @param {Object} [config] Config object.
+     */
+    constructor: function(config) {
+        var params;
+
+        if (config) {
+            Ext.apply(this, config);
+        }
+
+        // Normalize the params option to an Object
+        params = config.params;
+
+        if (Ext.isString(params)) {
+            this.params = Ext.Object.fromQueryString(params);
+        }
+    },
+
+    /**
+     * @method
+     * Invokes this action using the current configuration.
+     */
+    run: Ext.emptyFn,
+
+    /**
+     * @private
+     * @method onSuccess
+     * Callback method that gets invoked when the action completes successfully. Must be implemented
+     * by subclasses.
+     * @param {Object} response
+     */
+
+    /**
+     * @private
+     * @method handleResponse
+     * Handles the raw response and builds a result object from it. Must be implemented
+     * by subclasses.
+     * @param {Object} response
+     */
+
+    /**
+     * @private
+     * Handles a failure response.
+     * @param {Object} response
+     */
+    onFailure: function(response) {
+        var form = this.form,
+            formActive = form && !form.destroying && !form.destroyed;
+
+        this.response = response;
+        this.failureType = Ext.form.action.Action.CONNECT_FAILURE;
+
+        if (formActive) {
+            form.afterAction(this, false);
+        }
+    },
+
+    /**
+     * @private
+     * Validates that a response contains either responseText or responseXML and invokes
+     * {@link #handleResponse} to build the result object.
+     * @param {Object} response The raw response object.
+     * @return {Object/Boolean} The result object as built by handleResponse, or `true` if
+     * the response had empty responseText and responseXML.
+     */
+    processResponse: function(response) {
+        this.response = response;
+
+        if (!response.responseText && !response.responseXML) {
+            return true;
+        }
+
+        return (this.result = this.handleResponse(response));
+    },
+
+    /**
+     * @private
+     * Build the URL for the AJAX request. Used by the standard AJAX submit and load actions.
+     * @return {String} The URL.
+     */
+    getUrl: function() {
+        return this.url || this.form.url;
+    },
+
+    /**
+     * @private
+     * Determine the HTTP method to be used for the request.
+     * @return {String} The HTTP method
+     */
+    getMethod: function() {
+        return (this.method || this.form.method || 'POST').toUpperCase();
+    },
+
+    /**
+     * @private
+     * Get the set of parameters specified in the BasicForm's baseParams and/or the params option.
+     * Items in params override items of the same name in baseParams.
+     * @return {Object} the full set of parameters
+     */
+    getParams: function() {
+        return Ext.apply({}, this.params, this.form.baseParams);
+    },
+
+    /**
+     * @private
+     * Creates a callback object.
+     */
+    createCallback: function() {
+        var me = this;
+
+        return {
+            success: me.onSuccess,
+            failure: me.onFailure,
+            scope: me,
+            timeout: (me.timeout || me.form.timeout) * 1000
+        };
+    },
+
+    statics: {
+        /**
+         * @property
+         * Failure type returned when client side validation of the Form fails thus aborting
+         * a submit action. Client side validation is performed unless
+         * {@link Ext.form.action.Submit#clientValidation} is explicitly set to false.
+         * @static
+         */
+        CLIENT_INVALID: 'client',
+
+        /**
+         * @property
+         * Failure type returned when server side processing fails and the {@link #result}'s
+         * `success` property is set to false.
+         *
+         * In the case of a form submission, field-specific error messages may be returned
+         * in the {@link #result}'s errors property.
+         * @static
+         */
+        SERVER_INVALID: 'server',
+
+        /**
+         * @property
+         * Failure type returned when a communication error happens when attempting to send
+         * a request to the remote server. The {@link #response} may be examined to provide
+         * further information.
+         * @static
+         */
+        CONNECT_FAILURE: 'connect',
+
+        /**
+         * @property
+         * Failure type returned when the response's `success` property is set to false,
+         * or no field values are returned in the response's data property.
+         * @static
+         */
+        LOAD_FAILURE: 'load'
+    }
+});

+ 36 - 0
assets/ext-7.4.0.42/classic/classic/src/form/action/DirectAction.js

@@ -0,0 +1,36 @@
+/**
+ * @class Ext.form.action.DirectAction
+ * A mixin that contains methods specific to Ext Direct actions shared
+ * by DirectLoad and DirectSubmit.
+ * @private
+ */
+Ext.define('Ext.form.action.DirectAction', {
+    extend: 'Ext.Mixin',
+
+    mixinConfig: {
+        id: 'directaction'
+    },
+
+    resolveMethod: function(type) {
+        var me = this,
+            form = me.form,
+            api, fn;
+
+        api = Ext.direct.Manager.resolveApi(form.api, me);
+
+        //<debug>
+        if (!api) {
+            Ext.raise("Cannot resolve Ext Direct API method for " + type +
+                            " action; form " + form.id + " has no api object defined");
+        }
+        //</debug>
+
+        fn = api[type];
+
+        if (!fn) {
+            Ext.raise("Cannot resolve Ext Direct API method for " + type + " action");
+        }
+
+        return fn;
+    }
+});

+ 104 - 0
assets/ext-7.4.0.42/classic/classic/src/form/action/DirectLoad.js

@@ -0,0 +1,104 @@
+/**
+ * Provides Ext Direct support for loading form data.
+ *
+ * This example illustrates usage of Ext Direct to load a form.
+ *
+ *     var myFormPanel = new Ext.form.Panel({
+ *         // configs for FormPanel
+ *         title: 'Basic Information',
+ *         renderTo: document.body,
+ *         width: 300, height: 160,
+ *         padding: 10,
+ *
+ *         // configs apply to child items
+ *         defaults: {anchor: '100%'},
+ *         defaultType: 'textfield',
+ *         items: [{
+ *             fieldLabel: 'Name',
+ *             name: 'name'
+ *         },{
+ *             fieldLabel: 'Email',
+ *             name: 'email'
+ *         },{
+ *             fieldLabel: 'Company',
+ *             name: 'company'
+ *         }],
+ *
+ *         // configs for BasicForm
+ *         api: {
+ *             // The server-side method to call for load() requests
+ *             load: 'Profile.getBasicInfo',
+ *             // The server-side must mark the submit handler as a 'formHandler'
+ *             submit: 'Profile.updateBasicInfo'
+ *         },
+ *         // specify the order for the passed params
+ *         paramOrder: ['uid', 'foo']
+ *     });
+ *
+ *     // load the form
+ *     myFormPanel.getForm().load({
+ *         // pass 2 arguments to server side getBasicInfo method (len=2)
+ *         params: {
+ *             foo: 'bar',
+ *             uid: 34
+ *         }
+ *     });
+ *
+ * Before using DirectLoad action, make sure you set up Ext Direct remoting provider.
+ * See {@link Ext.direct.Manager} for more information.
+ *
+ * For corresponding submit action, see {@link Ext.form.action.DirectSubmit}.
+ */
+Ext.define('Ext.form.action.DirectLoad', {
+    extend: 'Ext.form.action.Load',
+    alternateClassName: 'Ext.form.Action.DirectLoad',
+    alias: 'formaction.directload',
+
+    requires: [
+        'Ext.direct.Manager'
+    ],
+
+    mixins: [
+        'Ext.form.action.DirectAction'
+    ],
+
+    type: 'directload',
+
+    run: function() {
+        var me = this,
+            form = me.form,
+            metadata = me.metadata || form.metadata,
+            timeout = me.timeout || form.timeout,
+            args, fn;
+
+        fn = me.resolveMethod('load');
+
+        args = fn.directCfg.method.getArgs({
+            params: me.getParams(),
+            paramOrder: form.paramOrder,
+            paramsAsHash: form.paramsAsHash,
+            options: timeout != null ? { timeout: timeout * 1000 } : null,
+            metadata: metadata,
+            callback: me.onComplete,
+            scope: me
+        });
+
+        fn.apply(window, args);
+    },
+
+    // Direct actions have already been processed and therefore
+    // we can directly set the result; Direct Actions do not have
+    // a this.response property.
+    processResponse: function(result) {
+        return (this.result = result);
+    },
+
+    onComplete: function(data) {
+        if (data) {
+            this.onSuccess(data);
+        }
+        else {
+            this.onFailure(null);
+        }
+    }
+});

+ 107 - 0
assets/ext-7.4.0.42/classic/classic/src/form/action/DirectSubmit.js

@@ -0,0 +1,107 @@
+/**
+ * Provides Ext Direct support for submitting form data.
+ *
+ * This example illustrates usage of Ext Direct to submit a form.
+ *
+ *     var myFormPanel = new Ext.form.Panel({
+ *         // configs for FormPanel
+ *         title: 'Basic Information',
+ *         renderTo: document.body,
+ *         width: 300, height: 160,
+ *         padding: 10,
+ *         buttons:[{
+ *             text: 'Submit',
+ *             handler: function(){
+ *                 myFormPanel.getForm().submit({
+ *                     params: {
+ *                         foo: 'bar',
+ *                         uid: 34
+ *                     }
+ *                 });
+ *             }
+ *         }],
+ *
+ *         // configs apply to child items
+ *         defaults: {anchor: '100%'},
+ *         defaultType: 'textfield',
+ *         items: [{
+ *             fieldLabel: 'Name',
+ *             name: 'name'
+ *         },{
+ *             fieldLabel: 'Email',
+ *             name: 'email'
+ *         },{
+ *             fieldLabel: 'Company',
+ *             name: 'company'
+ *         }],
+ *
+ *         // configs for BasicForm
+ *         api: {
+ *             // The server-side method to call for load() requests
+ *             load: 'Profile.getBasicInfo',
+ *             // The server-side must mark the submit handler as a 'formHandler'
+ *             submit: 'Profile.updateBasicInfo'
+ *         },
+ *         // specify the order for the passed params
+ *         paramOrder: ['uid', 'foo']
+ *     });
+ *
+ * Before using DirectLoad action, make sure you set up Ext Direct remoting provider.
+ * See {@link Ext.direct.Manager} for more information.
+ *
+ * For corresponding load action, see {@link Ext.form.action.DirectLoad}.
+ */
+Ext.define('Ext.form.action.DirectSubmit', {
+    extend: 'Ext.form.action.Submit',
+    alternateClassName: 'Ext.form.Action.DirectSubmit',
+    alias: 'formaction.directsubmit',
+
+    requires: [
+        'Ext.direct.Manager'
+    ],
+
+    mixins: [
+        'Ext.form.action.DirectAction'
+    ],
+
+    type: 'directsubmit',
+
+    doSubmit: function() {
+        var me = this,
+            form = me.form,
+            metadata = me.metadata || form.metadata,
+            timeout = me.timeout || form.timeout,
+            fn, formInfo, args;
+
+        fn = me.resolveMethod('submit');
+        formInfo = me.buildForm();
+
+        args = fn.directCfg.method.getArgs({
+            params: formInfo.formEl,
+            options: timeout != null ? { timeout: timeout * 1000 } : null,
+            metadata: metadata,
+            callback: me.onComplete,
+            scope: me
+        });
+
+        fn.apply(window, args);
+
+        me.cleanup(formInfo);
+    },
+
+    // Direct actions have already been processed and therefore
+    // we can directly set the result; Direct Actions do not have
+    // a this.response property.
+    processResponse: function(result) {
+        return (this.result = result);
+    },
+
+    onComplete: function(data) {
+        if (data) {
+            this.onSuccess(data);
+        }
+        else {
+            this.onFailure(null);
+        }
+    }
+});

+ 138 - 0
assets/ext-7.4.0.42/classic/classic/src/form/action/Load.js

@@ -0,0 +1,138 @@
+/**
+ * A class which handles loading of data from a server into the Fields of an {@link Ext.form.Basic}.
+ *
+ * Instances of this class are only created by a {@link Ext.form.Basic Form} when
+ * {@link Ext.form.Basic#load load}ing.
+ *
+ * ## Response Packet Criteria
+ *
+ * A response packet **must** contain:
+ *
+ *   - **`success`** property : Boolean
+ *   - **`data`** property : Object
+ *
+ * The `data` property contains the values of Fields to load. The individual value object
+ * for each Field is passed to the Field's {@link Ext.form.field.Field#setValue setValue} method.
+ *
+ * ## JSON Packets
+ *
+ * By default, response packets are assumed to be JSON, so for the following form load call:
+ *
+ *     var myFormPanel = new Ext.form.Panel({
+ *         title: 'Client and routing info',
+ *         renderTo: Ext.getBody(),
+ *         defaults: {
+ *             xtype: 'textfield'
+ *         },
+ *         items: [{
+ *             fieldLabel: 'Client',
+ *             name: 'clientName'
+ *         }, {
+ *             fieldLabel: 'Port of loading',
+ *             name: 'portOfLoading'
+ *         }, {
+ *             fieldLabel: 'Port of discharge',
+ *             name: 'portOfDischarge'
+ *         }]
+ *     });
+ *     myFormPanel.getForm().load({
+ *         url: '/getRoutingInfo.php',
+ *         params: {
+ *             consignmentRef: myConsignmentRef
+ *         },
+ *         failure: function(form, action) {
+ *             Ext.Msg.alert("Load failed", action.result.errorMessage);
+ *         }
+ *     });
+ *
+ * a **success response** packet may look like this:
+ *
+ *     {
+ *         success: true,
+ *         data: {
+ *             clientName: "Fred. Olsen Lines",
+ *             portOfLoading: "FXT",
+ *             portOfDischarge: "OSL"
+ *         }
+ *     }
+ *
+ * while a **failure response** packet may look like this:
+ *
+ *     {
+ *         success: false,
+ *         errorMessage: "Consignment reference not found"
+ *     }
+ *
+ * Other data may be placed into the response for processing the {@link Ext.form.Basic Form}'s
+ * callback or event handler methods. The object decoded from this JSON is available in the
+ * {@link Ext.form.action.Action#result result} property.
+ */
+Ext.define('Ext.form.action.Load', {
+    extend: 'Ext.form.action.Action',
+    requires: ['Ext.data.Connection'],
+    alternateClassName: 'Ext.form.Action.Load',
+    alias: 'formaction.load',
+
+    type: 'load',
+
+    /**
+     * @private
+     */
+    run: function() {
+        Ext.Ajax.request(Ext.apply(
+            this.createCallback(),
+            {
+                method: this.getMethod(),
+                url: this.getUrl(),
+                headers: this.headers,
+                params: this.getParams()
+            }
+        ));
+    },
+
+    /**
+     * @private
+     */
+    onSuccess: function(response) {
+        var result = this.processResponse(response),
+            form = this.form,
+            formActive = form && !form.destroying && !form.destroyed;
+
+        if (result === true || !result.success || !result.data) {
+            this.failureType = Ext.form.action.Action.LOAD_FAILURE;
+
+            if (formActive) {
+                form.afterAction(this, false);
+            }
+
+            return;
+        }
+
+        if (formActive) {
+            form.clearInvalid();
+            form.setValues(result.data);
+            form.afterAction(this, true);
+        }
+    },
+
+    /**
+     * @private
+     */
+    handleResponse: function(response) {
+        var reader = this.form.reader,
+            rs, data;
+
+        if (reader) {
+            rs = reader.read(response);
+            data = rs.records && rs.records[0] ? rs.records[0].data : null;
+
+            return {
+                success: rs.success,
+                data: data
+            };
+        }
+
+        return Ext.decode(response.responseText);
+    }
+});
+

+ 36 - 0
assets/ext-7.4.0.42/classic/classic/src/form/action/StandardSubmit.js

@@ -0,0 +1,36 @@
+/**
+ * A class which handles submission of data from {@link Ext.form.Basic Form}s using a standard
+ * `<form>` element submit. It does not handle the response from the submit.
+ *
+ * If validation of the form fields fails, the Form's afterAction method will be called.
+ * Otherwise, afterAction will not be called.
+ *
+ * Instances of this class are only created by a {@link Ext.form.Basic Form} when
+ * {@link Ext.form.Basic#submit submit}ting, when the form's {@link Ext.form.Basic#standardSubmit}
+ * config option is true.
+ */
+Ext.define('Ext.form.action.StandardSubmit', {
+    extend: 'Ext.form.action.Submit',
+    alias: 'formaction.standardsubmit',
+
+    /**
+     * @cfg {String} target
+     * Optional target attribute to be used for the form when submitting.
+     * 
+     * Defaults to the current window/frame.
+     */
+
+    /**
+     * @private
+     * Perform the form submit. Creates and submits a temporary form element containing
+     * an input element for each field value returned by {@link Ext.form.Basic#getValues},
+     * plus any configured {@link #params params} or {@link Ext.form.Basic#baseParams baseParams}.
+     */
+    doSubmit: function() {
+        var formInfo = this.buildForm();
+
+        formInfo.formEl.submit();
+
+        this.cleanup(formInfo);
+    }
+});

+ 345 - 0
assets/ext-7.4.0.42/classic/classic/src/form/action/Submit.js

@@ -0,0 +1,345 @@
+/**
+ * A class which handles submission of data from {@link Ext.form.Basic Form}s and processes
+ * the returned response.
+ *
+ * Instances of this class are only created by a {@link Ext.form.Basic Form} when
+ * {@link Ext.form.Basic#submit submit}ting.
+ *
+ * # Response Packet Criteria
+ *
+ * A response packet may contain:
+ *
+ *   - **`success`** property : Boolean - required.
+ *
+ *   - **`errors`** property : Object - optional, contains error messages for invalid fields.
+ *
+ * # JSON Packets
+ *
+ * By default, response packets are assumed to be JSON, so a typical response packet may look
+ * like this:
+ *
+ *     {
+ *         success: false,
+ *         errors: {
+ *             clientCode: "Client not found",
+ *             portOfLoading: "This field must not be null"
+ *         }
+ *     }
+ *
+ * Other data may be placed into the response for processing by the {@link Ext.form.Basic}'s
+ * callback or event handler methods. The object decoded from this JSON is available in the
+ * {@link Ext.form.action.Action#result result} property.
+ *
+ * Alternatively, if an {@link Ext.form.Basic#errorReader errorReader} is specified as an
+ * {@link Ext.data.reader.Xml XmlReader}:
+ *
+ *     errorReader: new Ext.data.reader.Xml({
+ *             record : 'field',
+ *             success: '@success'
+ *         }, [
+ *             'id', 'msg'
+ *         ]
+ *     )
+ *
+ * then the results may be sent back in XML format:
+ *
+ *     <?xml version="1.0" encoding="UTF-8"?>
+ *     <message success="false">
+ *     <errors>
+ *         <field>
+ *             <id>clientCode</id>
+ *             <msg>
+ *                 <![CDATA[
+ *                     Code not found. <br />
+ *                     <i>This is a test validation message from the server </i>
+ *                 ]]>
+ *             </msg>
+ *         </field>
+ *         <field>
+ *             <id>portOfLoading</id>
+ *             <msg>
+ *                 <![CDATA[
+ *                     Port not found. <br />
+ *                     <i>This is a test validation message from the server </i>
+ *                 ]]>
+ *             </msg>
+ *         </field>
+ *     </errors>
+ *     </message>
+ *
+ * Other elements may be placed into the response XML for processing by the {@link Ext.form.Basic}'s
+ * callback or event handler methods. The XML document is available in the
+ * {@link Ext.form.Basic#errorReader errorReader}'s {@link Ext.data.reader.Xml#xmlData xmlData}
+ * property.
+ */
+Ext.define('Ext.form.action.Submit', {
+    extend: 'Ext.form.action.Action',
+    alternateClassName: 'Ext.form.Action.Submit',
+    alias: 'formaction.submit',
+
+    type: 'submit',
+
+    /**
+     * @cfg {Boolean} [clientValidation=true]
+     * Determines whether a Form's fields are validated in a final call
+     * to {@link Ext.form.Basic#isValid isValid} prior to submission. Pass false in the Form's
+     * submit options to prevent this.
+     */
+
+    run: function() {
+        var me = this,
+            form = me.form;
+
+        if (me.clientValidation === false || form.isValid()) {
+            me.doSubmit();
+        }
+        else {
+            // client validation failed
+            me.failureType = Ext.form.action.Action.CLIENT_INVALID;
+            form.afterAction(me, false);
+        }
+    },
+
+    /**
+     * @private
+     * Performs the submit of the form data.
+     */
+    doSubmit: function() {
+        var me = this,
+            ajaxOptions = Ext.apply(me.createCallback(), {
+                url: me.getUrl(),
+                method: me.getMethod(),
+                headers: me.headers
+            }),
+            form = me.form,
+            jsonSubmit = me.jsonSubmit || form.jsonSubmit,
+            paramsProp = jsonSubmit ? 'jsonData' : 'params',
+            formInfo;
+
+        // For uploads we need to create an actual form that contains the file upload fields,
+        // and pass that to the ajax call so it can do its iframe-based submit method.
+        if (form.hasUpload()) {
+            formInfo = me.buildForm();
+            ajaxOptions.form = formInfo.formEl;
+            ajaxOptions.isUpload = true;
+        }
+        else {
+            ajaxOptions[paramsProp] = me.getParams(jsonSubmit);
+        }
+
+        Ext.Ajax.request(ajaxOptions);
+
+        if (formInfo) {
+            me.cleanup(formInfo);
+        }
+    },
+
+    cleanup: function(formInfo) {
+        var formEl = formInfo.formEl,
+            uploadEls = formInfo.uploadEls,
+            uploadFields = formInfo.uploadFields,
+            len = uploadFields.length,
+            i, field;
+
+        for (i = 0; i < len; ++i) {
+            field = uploadFields[i];
+
+            if (!field.clearOnSubmit) {
+                field.restoreInput(uploadEls[i]);
+            }
+        }
+
+        if (formEl) {
+            Ext.removeNode(formEl);
+        }
+    },
+
+    /**
+     * @private
+     * Builds the full set of parameters from the field values plus any additional
+     * configured params.
+     */
+    getParams: function(useModelValues) {
+        var falseVal = false,
+            configParams = this.callParent(),
+            fieldParams;
+
+        fieldParams = this.form.getValues(
+            falseVal, falseVal, this.submitEmptyText !== falseVal, useModelValues,
+            /* isSubmitting */ true
+        );
+
+        return Ext.apply({}, fieldParams, configParams);
+    },
+
+    /**
+     * @private
+     * Builds a form element containing fields corresponding to all the parameters to be
+     * submitted (everything returned by {@link #getParams}.
+     *
+     * NOTE: the form element is automatically added to the DOM, so any code that uses
+     * it must remove it from the DOM after finishing with it.
+     *
+     * @return {HTMLElement}
+     */
+    buildForm: function() {
+        var me = this,
+            fieldsSpec = [],
+            formSpec,
+            formEl,
+            basicForm = me.form,
+            params = me.getParams(),
+            uploadFields = [],
+            uploadEls = [],
+            fields = basicForm.getFields().items,
+            i,
+            len = fields.length,
+            field, key, value, v, vLen,
+            el;
+
+        for (i = 0; i < len; ++i) {
+            field = fields[i];
+
+            if (field.isFileUpload()) {
+                uploadFields.push(field);
+            }
+        }
+
+        for (key in params) {
+            if (params.hasOwnProperty(key)) {
+                value = params[key];
+
+                if (Ext.isArray(value)) {
+                    vLen = value.length;
+
+                    for (v = 0; v < vLen; v++) {
+                        fieldsSpec.push(me.getFieldConfig(key, value[v]));
+                    }
+                }
+                else {
+                    fieldsSpec.push(me.getFieldConfig(key, value));
+                }
+            }
+        }
+
+        formSpec = {
+            tag: 'form',
+            role: 'presentation',
+            action: me.getUrl(),
+            method: me.getMethod(),
+            target: me.target
+                ? (Ext.isString(me.target) ? me.target : Ext.fly(me.target).dom.name)
+                : '_self',
+            style: 'display:none',
+            cn: fieldsSpec
+        };
+
+        //<debug>
+        if (!formSpec.target) {
+            Ext.raise('Invalid form target.');
+        }
+        //</debug>
+
+        // Set the proper encoding for file uploads
+        if (uploadFields.length) {
+            formSpec.encoding = formSpec.enctype = 'multipart/form-data';
+        }
+
+        // Create the form
+        formEl = Ext.DomHelper.append(Ext.getBody(), formSpec);
+
+        // Special handling for file upload fields: since browser security measures prevent setting
+        // their values programatically, and prevent carrying their selected values over
+        // when cloning, we have to move the actual field instances out of their components
+        // and into the form.
+        len = uploadFields.length;
+
+        for (i = 0; i < len; ++i) {
+            el = uploadFields[i].extractFileInput();
+            formEl.appendChild(el);
+            uploadEls.push(el);
+        }
+
+        return {
+            formEl: formEl,
+            uploadFields: uploadFields,
+            uploadEls: uploadEls
+        };
+    },
+
+    getFieldConfig: function(name, value) {
+        return {
+            tag: 'input',
+            type: 'hidden',
+            name: name,
+            value: Ext.String.htmlEncode(value)
+        };
+    },
+
+    /**
+     * @private
+     */
+    onSuccess: function(response) {
+        var form = this.form,
+            formActive = form && !form.destroying && !form.destroyed,
+            success = true,
+            result = this.processResponse(response);
+
+        if (result !== true && !result.success) {
+            if (result.errors && formActive) {
+                form.markInvalid(result.errors);
+            }
+
+            this.failureType = Ext.form.action.Action.SERVER_INVALID;
+            success = false;
+        }
+
+        if (formActive) {
+            form.afterAction(this, success);
+        }
+    },
+
+    /**
+     * @private
+     */
+    handleResponse: function(response) {
+        var form = this.form,
+            errorReader = form.errorReader,
+            rs, errors, i, len, records, result;
+
+        if (errorReader) {
+            rs = errorReader.read(response);
+            records = rs.records;
+            errors = [];
+
+            if (records) {
+                for (i = 0, len = records.length; i < len; i++) {
+                    errors[i] = records[i].data;
+                }
+            }
+
+            if (errors.length < 1) {
+                errors = null;
+            }
+
+            result = {
+                success: rs.success,
+                errors: errors
+            };
+        }
+        else {
+            try {
+                result = Ext.decode(response.responseText);
+            }
+            catch (e) {
+                result = {
+                    success: false,
+                    errors: []
+                };
+            }
+
+        }
+
+        return result;
+    }
+});

File diff suppressed because it is too large
+ 1259 - 0
assets/ext-7.4.0.42/classic/classic/src/form/field/Base.js


+ 781 - 0
assets/ext-7.4.0.42/classic/classic/src/form/field/Checkbox.js

@@ -0,0 +1,781 @@
+/**
+ * Single checkbox field. Can be used as a direct replacement for traditional checkbox fields.
+ * Also serves as a parent class for {@link Ext.form.field.Radio radio buttons}.
+ *
+ * ## Labeling
+ *
+ * In addition to the {@link Ext.form.Labelable standard field labeling options}, checkboxes
+ * may be given an optional {@link #boxLabel} which will be displayed immediately after checkbox.
+ * Also see {@link Ext.form.CheckboxGroup} for a convenient method of grouping related checkboxes.
+ *
+ * # Values
+ *
+ * The main value of a checkbox is a boolean, indicating whether or not the checkbox is checked.
+ * The following values will check the checkbox:
+ *
+ * - `true`
+ * - `'true'`
+ * - `'1'`
+ * - `'on'`
+ *
+ * Any other value will un-check the checkbox.
+ *
+ * In addition to the main boolean value, you may also specify a separate {@link #inputValue}.
+ * This will be sent as the parameter value when the form is
+ * {@link Ext.form.Basic#submit submitted}. You will want to set this value if you have multiple
+ * checkboxes with the same {@link #name}. If not specified, the value `on` will be used.
+ *
+ * ## Example usage
+ *
+ *     @example
+ *     Ext.create('Ext.form.Panel', {
+ *         bodyPadding: 10,
+ *         width: 300,
+ *         title: 'Pizza Order',
+ *         items: [
+ *             {
+ *                 xtype: 'fieldcontainer',
+ *                 fieldLabel: 'Toppings',
+ *                 defaultType: 'checkboxfield',
+ *                 items: [
+ *                     {
+ *                         boxLabel  : 'Anchovies',
+ *                         name      : 'topping',
+ *                         inputValue: '1',
+ *                         id        : 'checkbox1'
+ *                     }, {
+ *                         boxLabel  : 'Artichoke Hearts',
+ *                         name      : 'topping',
+ *                         inputValue: '2',
+ *                         checked   : true,
+ *                         id        : 'checkbox2'
+ *                     }, {
+ *                         boxLabel  : 'Bacon',
+ *                         name      : 'topping',
+ *                         inputValue: '3',
+ *                         id        : 'checkbox3'
+ *                     }
+ *                 ]
+ *             }
+ *         ],
+ *         bbar: [
+ *             {
+ *                 text: 'Select Bacon',
+ *                 handler: function() {
+ *                     Ext.getCmp('checkbox3').setValue(true);
+ *                 }
+ *             },
+ *             '-',
+ *             {
+ *                 text: 'Select All',
+ *                 handler: function() {
+ *                     Ext.getCmp('checkbox1').setValue(true);
+ *                     Ext.getCmp('checkbox2').setValue(true);
+ *                     Ext.getCmp('checkbox3').setValue(true);
+ *                 }
+ *             },
+ *             {
+ *                 text: 'Deselect All',
+ *                 handler: function() {
+ *                     Ext.getCmp('checkbox1').setValue(false);
+ *                     Ext.getCmp('checkbox2').setValue(false);
+ *                     Ext.getCmp('checkbox3').setValue(false);
+ *                 }
+ *             }
+ *         ],
+ *         renderTo: Ext.getBody()
+ *     });
+ */
+Ext.define('Ext.form.field.Checkbox', {
+    extend: 'Ext.form.field.Base',
+    alias: ['widget.checkboxfield', 'widget.checkbox'],
+    alternateClassName: 'Ext.form.Checkbox',
+    requires: ['Ext.XTemplate', 'Ext.form.CheckboxManager' ],
+
+    /**
+     * @cfg {Boolean/String/Number} modelValue
+     * The value to use for {@link #getModelData} when checked.
+     *
+     * @since 6.2.1
+     */
+    modelValue: true,
+
+    /**
+     * @cfg {Boolean/String/Number} modelValueUnchecked
+     * The value to use for {@link #getModelData} when unchecked.
+     *
+     * @since 6.2.1
+     */
+    modelValueUnchecked: false,
+
+    // inputEl should always retain the same size, never stretch
+    stretchInputElFixed: false,
+
+    /**
+     * @property {Ext.dom.Element} boxLabelEl
+     * A reference to the label element created for the {@link #boxLabel}. Only present
+     * if the component has been rendered and has a boxLabel configured.
+     */
+
+    /**
+     * @cfg childEls
+     * @inheritdoc
+     */
+    childEls: [
+        'boxLabelEl',
+        'innerWrapEl',
+        'displayEl'
+    ],
+
+    /* eslint-disable indent, max-len */
+    // note: {id} here is really {inputId}, but {cmpId} is available
+    /**
+     * @cfg fieldSubTpl
+     * @inheritdoc
+     */
+    fieldSubTpl: [
+        '<div id="{cmpId}-innerWrapEl" data-ref="innerWrapEl" role="presentation"',
+            ' class="{wrapInnerCls}">',
+            '<tpl if="labelAlignedBefore">',
+                '{beforeBoxLabelTpl}',
+                '<label id="{cmpId}-boxLabelEl" data-ref="boxLabelEl" {boxLabelAttrTpl} class="{boxLabelCls} ',
+                        '{boxLabelCls}-{ui} {boxLabelCls}-{boxLabelAlign} {noBoxLabelCls} {childElCls}" for="{id}">',
+                    '{beforeBoxLabelTextTpl}',
+                    '{boxLabel}',
+                    '{afterBoxLabelTextTpl}',
+                '</label>',
+                '{afterBoxLabelTpl}',
+            '</tpl>',
+            '<span id="{cmpId}-displayEl" data-ref="displayEl" role="presentation" class="{fieldCls} {typeCls} ',
+                '{typeCls}-{ui} {inputCls} {inputCls}-{ui} {fixCls} {childElCls} {afterLabelCls}">',
+                '<input type="{inputType}" id="{id}" name="{inputName}" data-ref="inputEl" {inputAttrTpl}',
+                    '<tpl if="tabIdx != null"> tabindex="{tabIdx}"</tpl>',
+                    '<tpl if="disabled"> disabled="disabled"</tpl>',
+                    '<tpl if="checked"> checked="checked"</tpl>',
+                    '<tpl if="fieldStyle"> style="{fieldStyle}"</tpl>',
+                    ' class="{checkboxCls}" autocomplete="off" hidefocus="true" ',
+                    '<tpl foreach="ariaElAttributes"> {$}="{.}"</tpl>',
+                    '<tpl foreach="inputElAriaAttributes"> {$}="{.}"</tpl>',
+                    '/>',
+            '</span>',
+            '<tpl if="!labelAlignedBefore">',
+                '{beforeBoxLabelTpl}',
+                '<label id="{cmpId}-boxLabelEl" data-ref="boxLabelEl" {boxLabelAttrTpl} class="{boxLabelCls} ',
+                        '{boxLabelCls}-{ui} {boxLabelCls}-{boxLabelAlign} {noBoxLabelCls} {childElCls}" for="{id}">',
+                    '{beforeBoxLabelTextTpl}',
+                    '{boxLabel}',
+                    '{afterBoxLabelTextTpl}',
+                '</label>',
+                '{afterBoxLabelTpl}',
+            '</tpl>',
+        '</div>',
+        {
+            disableFormats: true,
+            compiled: true
+        }
+    ],
+    /* eslint-enable indent, max-len */
+
+    /**
+     * @cfg publishes
+     * @inheritdoc
+     */
+    publishes: {
+        checked: 1
+    },
+
+    subTplInsertions: [
+        /**
+         * @cfg {String/Array/Ext.XTemplate} beforeBoxLabelTpl
+         * An optional string or `XTemplate` configuration to insert in the field markup
+         * before the box label element. If an `XTemplate` is used, the component's
+         * {@link Ext.form.field.Base#getSubTplData subTpl data} serves as the context.
+         */
+        'beforeBoxLabelTpl',
+
+        /**
+         * @cfg {String/Array/Ext.XTemplate} afterBoxLabelTpl
+         * An optional string or `XTemplate` configuration to insert in the field markup
+         * after the box label element. If an `XTemplate` is used, the component's
+         * {@link Ext.form.field.Base#getSubTplData subTpl data} serves as the context.
+         */
+        'afterBoxLabelTpl',
+
+        /**
+         * @cfg {String/Array/Ext.XTemplate} beforeBoxLabelTextTpl
+         * An optional string or `XTemplate` configuration to insert in the field markup
+         * before the box label text. If an `XTemplate` is used, the component's
+         * {@link Ext.form.field.Base#getSubTplData subTpl data} serves as the context.
+         */
+        'beforeBoxLabelTextTpl',
+
+        /**
+         * @cfg {String/Array/Ext.XTemplate} afterBoxLabelTextTpl
+         * An optional string or `XTemplate` configuration to insert in the field markup
+         * after the box label text. If an `XTemplate` is used, the component's
+         * {@link Ext.form.field.Base#getSubTplData subTpl data} serves as the context.
+         */
+        'afterBoxLabelTextTpl',
+
+        /**
+         * @cfg {String/Array/Ext.XTemplate} boxLabelAttrTpl
+         * An optional string or `XTemplate` configuration to insert in the field markup
+         * inside the box label element (as attributes). If an `XTemplate` is used, the component's
+         * {@link Ext.form.field.Base#getSubTplData subTpl data} serves as the context.
+         */
+        'boxLabelAttrTpl',
+
+        'inputAttrTpl'
+    ],
+
+    /**
+     * @property {Boolean} isCheckbox
+     * `true` in this class to identify an object as an instantiated Checkbox, or subclass thereof.
+     */
+    isCheckbox: true,
+
+    /**
+     * @cfg {String} focusCls
+     * The CSS class to use when the checkbox receives focus
+     */
+    focusCls: 'form-checkbox-focus',
+
+    /**
+     * @cfg {String} [fieldCls='x-form-field']
+     * The default CSS class for the checkbox
+     */
+
+    /**
+     * @private
+     */
+    fieldBodyCls: Ext.baseCSSPrefix + 'form-cb-wrap',
+
+    /**
+     * @cfg {Boolean} checked
+     * true if the checkbox should render initially checked
+     */
+    checked: false,
+
+    /**
+     * @cfg {String} checkedCls
+     * The CSS class(es) added to the component's main element when it is in the checked state.
+     * You can add your own class (checkedCls='myClass x-form-cb-checked') or replace the default 
+     * class altogether (checkedCls='myClass').
+     */
+    checkedCls: Ext.baseCSSPrefix + 'form-cb-checked',
+
+    /**
+     * @cfg {String} boxLabel
+     * An optional text label that will appear next to the checkbox. Whether it appears before
+     * or after the checkbox is determined by the {@link #boxLabelAlign} config.
+     */
+
+    /**
+     * @cfg {String} boxLabelCls
+     * The CSS class to be applied to the {@link #boxLabel} element
+     */
+    boxLabelCls: Ext.baseCSSPrefix + 'form-cb-label',
+
+    /**
+     * @cfg {String} boxLabelAlign
+     * The position relative to the checkbox where the {@link #boxLabel} should appear.
+     * Recognized values are 'before' and 'after'.
+     */
+    boxLabelAlign: 'after',
+
+    afterLabelCls: Ext.baseCSSPrefix + 'form-cb-after',
+
+    wrapInnerCls: Ext.baseCSSPrefix + 'form-cb-wrap-inner',
+
+    noBoxLabelCls: Ext.baseCSSPrefix + 'form-cb-no-box-label',
+
+    /**
+     * @cfg {String/Boolean} inputValue
+     * The value that should go into the generated input element's value attribute and
+     * should be used as the parameter value when submitting as part of a form.
+     */
+    inputValue: 'on',
+
+    /**
+     * @cfg {String} uncheckedValue
+     * If configured, this will be submitted as the checkbox's value during form submit
+     * if the checkbox is unchecked. By default this is undefined, which results in
+     * nothing being submitted for the checkbox field when the form is submitted
+     * (the default behavior of HTML checkboxes).
+     */
+
+    /**
+     * @cfg {Function/String} [handler=undefined]
+     * A function called when the {@link #checked} value changes (can be used instead of handling
+     * the {@link #change change event}).
+     * @cfg {Ext.form.field.Checkbox} handler.checkbox The Checkbox being toggled.
+     * @cfg {Boolean} handler.checked The new checked state of the checkbox.
+     * @controllable
+     */
+
+    /**
+     * @cfg {Object} scope
+     * An object to use as the scope ('this' reference) of the {@link #handler} function.
+     *
+     * Defaults to this Checkbox.
+     */
+
+    /**
+     * @private
+     */
+    checkChangeEvents: [],
+
+    // See IE8 override
+    changeEventName: 'change',
+
+    /**
+     * @cfg inputType
+     * @inheritdoc
+     */
+    inputType: 'checkbox',
+
+    /**
+     * @cfg isTextInput
+     * @inheritdoc
+     */
+    isTextInput: false,
+
+    /**
+     * @property ariaRole
+     * @inheritdoc
+     */
+    ariaRole: 'native',
+
+    /**
+     * @private
+     */
+    onRe: /^on$/i,
+
+    // the form-cb css class is for styling shared between checkbox and subclasses (radio)
+    inputCls: Ext.baseCSSPrefix + 'form-cb',
+    _checkboxCls: Ext.baseCSSPrefix + 'form-cb-input',
+
+    initComponent: function() {
+        var me = this,
+            value = me.value;
+
+        if (value !== undefined) {
+            me.checked = me.isChecked(value, me.inputValue);
+        }
+
+        me.callParent();
+
+        me.getManager().add(me);
+    },
+
+    // Checkboxes and Radio buttons may have their names managed by their respective group.
+    // This happens in CheckboxGroup.onAdd() so we skip default name assignment here.
+    initDefaultName: Ext.emptyFn,
+
+    initValue: function() {
+        var me = this,
+            checked = !!me.checked;
+
+        /**
+         * @property {Object} originalValue
+         * The original value of the field as configured in the {@link #checked} configuration,
+         * or as loaded by the last form load operation if the form's
+         * {@link Ext.form.Basic#trackResetOnLoad trackResetOnLoad} setting is `true`.
+         */
+        me.originalValue = me.initialValue = me.lastValue = checked;
+
+        // Set the initial checked state
+        me.setValue(checked);
+    },
+
+    getElConfig: function() {
+        var me = this;
+
+        // Add the checked class if this begins checked
+        if (me.isChecked(me.rawValue, me.inputValue)) {
+            me.addCls(me.checkedCls);
+        }
+
+        if (!me.fieldLabel) {
+            me.skipLabelForAttribute = true;
+        }
+
+        return me.callParent();
+    },
+
+    getModelData: function() {
+        var me = this,
+            o = me.callParent(arguments);
+
+        if (o) {
+            o[me.getName()] = me.checked ? me.modelValue : me.modelValueUnchecked;
+        }
+
+        return o;
+    },
+
+    getSubTplData: function(fieldData) {
+        var me = this,
+            boxLabel = me.boxLabel,
+            boxLabelAlign = me.boxLabelAlign,
+            labelAlignedBefore = boxLabelAlign === 'before',
+            data, inputElAttr;
+
+        data = Ext.apply(me.callParent([fieldData]), {
+            inputType: me.inputType,
+            checkboxCls: me._checkboxCls,
+            disabled: me.readOnly || me.disabled,
+            checked: !!me.checked,
+            wrapInnerCls: me.wrapInnerCls,
+            boxLabel: boxLabel,
+            boxLabelCls: me.boxLabelCls,
+            boxLabelAlign: boxLabelAlign,
+            labelAlignedBefore: labelAlignedBefore,
+            afterLabelCls: labelAlignedBefore ? me.afterLabelCls : '',
+            noBoxLabelCls: !boxLabel ? me.noBoxLabelCls : '',
+
+            // We need to have name attribute on the <input> element
+            // even if it wasn't specified in component config;
+            // some browsers (Chrome, Safari) will treat missing name
+            // as empty, grouping all radio buttons with empty name
+            // together. This causes funky but unwanted effects
+            // with regards to keyboard navigation.
+            inputName: me.name || me.id
+        });
+
+        inputElAttr = data.inputElAriaAttributes;
+
+        if (inputElAttr) {
+            // aria-readonly is not valid for Checkboxes and Radio buttons
+            delete inputElAttr['aria-readonly'];
+        }
+
+        return data;
+    },
+
+    initEvents: function() {
+        var me = this;
+
+        me.callParent();
+
+        me.inputEl.on(me.changeEventName, me.onChangeEvent, me, { delegated: false });
+
+        // In all IE versions it is possible to focus ANY element by clicking
+        // regardless of tabIndex attribute. In this case, clicking on boxLabelEl
+        // will end up focusing its parent bodyEl before focusing and activating
+        // the associated input element. Dark wizardry in Focus publisher fails
+        // to propagate the second focusin event so we have to accommodate here
+        // by not allowing bodyEl to focus.
+        if (Ext.isIE) {
+            me.bodyEl.on('mousedown', me.onBodyElMousedown, me);
+        }
+
+        // Conversely in Safari and Firefox on Mac clicking either box label or input
+        // itself will result in input activation, value change, and immediate blur
+        // to the document body. We place more faith in consistency over platform
+        // specific quirks so have to force inputEl focus here and prevent blurring.
+        // Oh Sanity Where Art Thou. :/
+        else if (Ext.isMac && (Ext.isGecko || Ext.isSafari)) {
+            me.boxLabelEl.on('mousedown', me.onBoxLabelOrInputMousedown, me);
+            me.inputEl.on('mousedown', me.onBoxLabelOrInputMousedown, me);
+        }
+    },
+
+    /**
+     * Sets the {@link #boxLabel} for this checkbox.
+     * @param {String} boxLabel The new label
+     */
+    setBoxLabel: function(boxLabel) {
+        var me = this;
+
+        me.boxLabel = boxLabel;
+
+        if (me.rendered) {
+            me.boxLabelEl.setHtml(boxLabel);
+            me.boxLabelEl[boxLabel ? 'removeCls' : 'addCls'](me.noBoxLabelCls);
+            me.updateLayout();
+        }
+    },
+
+    /**
+     * @private
+     * Handle mousedown events on bodyEl. See explanations in initEvents().
+     */
+    onBodyElMousedown: function(e) {
+        if (e.target !== this.inputEl.dom) {
+            e.preventDefault();
+        }
+    },
+
+    /**
+     * @private
+     * Handle mousedown events on boxLabelEl and inputEl.
+     * See explanations in initEvents().
+     */
+    onBoxLabelOrInputMousedown: function(e) {
+        this.inputEl.focus();
+        e.preventDefault();
+    },
+
+    /**
+     * @private
+     * Handle the change event from the DOM.
+     */
+    onChangeEvent: function(e) {
+        this.updateValueFromDom();
+    },
+
+    /**
+     * @private
+     */
+    updateValueFromDom: function() {
+        var me = this,
+            inputEl = me.inputEl && me.inputEl.dom;
+
+        if (inputEl) {
+            me.checked = me.rawValue = me.value = inputEl.checked;
+
+            me.checkChange();
+        }
+    },
+
+    /**
+     * @private
+     */
+    updateCheckedCls: function(checked) {
+        var me = this;
+
+        checked = checked != null ? checked : me.getValue();
+
+        me[checked ? 'addCls' : 'removeCls'](me.checkedCls);
+    },
+
+    /**
+     * Returns the checked state of the checkbox.
+     * @return {Boolean} True if checked, else false
+     */
+    getRawValue: function() {
+        var inputEl = this.inputEl && this.inputEl.dom;
+
+        return inputEl ? inputEl.checked : this.checked;
+    },
+
+    /**
+     * Returns the checked state of the checkbox.
+     * @return {Boolean} True if checked, else false
+     */
+    getValue: function() {
+        var inputEl = this.inputEl && this.inputEl.dom;
+
+        return inputEl ? inputEl.checked : this.checked;
+    },
+
+    /**
+     * Returns the submit value for the checkbox which can be used when submitting forms.
+     * @return {String} If checked the {@link #inputValue} is returned; otherwise the
+     * {@link #uncheckedValue} (or null if the latter is not configured).
+     */
+    getSubmitValue: function() {
+        var unchecked = this.uncheckedValue,
+            uncheckedVal = Ext.isDefined(unchecked) ? unchecked : null;
+
+        return this.getValue() ? this.inputValue : uncheckedVal;
+    },
+
+    isChecked: function(rawValue, inputValue) {
+        var ret = false;
+
+        if (rawValue === true || rawValue === 'true') {
+            ret = true;
+        }
+        else {
+            if (inputValue !== 'on' && (inputValue || inputValue === 0) &&
+                (Ext.isString(rawValue) || Ext.isNumber(rawValue))) {
+                ret = rawValue == inputValue; // eslint-disable-line eqeqeq
+            }
+            else {
+                ret = rawValue === '1' || rawValue === 1 || this.onRe.test(rawValue);
+            }
+        }
+
+        return ret;
+    },
+
+    /**
+     * Sets the checked state of the checkbox.
+     *
+     * @param {Boolean/String/Number} value The following values will check the checkbox:
+     * - `true, 'true'.
+     * - '1', 1, or 'on'`, when there is no {@link #inputValue}.
+     * - Value that matches the {@link #inputValue}.
+     * Any other value will un-check the checkbox.
+     * @return {Boolean} the new checked state of the checkbox
+     */
+    setRawValue: function(value) {
+        var me = this,
+            inputEl = me.inputEl && me.inputEl.dom,
+            checked = me.isChecked(value, me.inputValue);
+
+        if (inputEl) {
+            // Setting checked property will fire unwanted propertychange event in IE8.
+            me.duringSetRawValue = true;
+            inputEl.checked = checked;
+            me.duringSetRawValue = false;
+
+            me.updateCheckedCls(checked);
+        }
+
+        me.checked = me.rawValue = checked;
+
+        if (!me.duringSetValue) {
+            me.lastValue = checked;
+        }
+
+        return checked;
+    },
+
+    /**
+     * Sets the checked state of the checkbox, and invokes change detection.
+     * @param {Array/Boolean/String} checked The following values will check the checkbox:
+     * `true, 'true', '1', or 'on'`, as well as a String that matches the {@link #inputValue}.
+     * Any other value will  un-check the checkbox.
+     *
+     * You may also pass an array of string values. If an array of strings is passed, all checkboxes
+     * in the group with a matched name will be checked.  The checkbox will be unchecked
+     * if a corresponding value is not found in the array.
+     * @return {Ext.form.field.Checkbox} this
+     */
+    setValue: function(checked) {
+        var me = this,
+            boxes, i, len, box;
+
+        // If an array of strings is passed, find all checkboxes in the group with the same name
+        // as this one and check all those whose inputValue is in the array, un-checking all the 
+        // others. This is to facilitate setting values from Ext.form.Basic#setValues, 
+        // but is not publicly documented as we don't want users depending on this 
+        // behavior.
+        if (Ext.isArray(checked)) {
+            boxes = me.getManager().getByName(me.name, me.getFormId()).items;
+            len = boxes.length;
+
+            for (i = 0; i < len; ++i) {
+                box = boxes[i];
+                box.setValue(Ext.Array.contains(checked, box.inputValue));
+            }
+        }
+        else {
+            // The callParent() call ends up trigger setRawValue, we only want to modify
+            // the lastValue when setRawValue being called independently.
+            me.duringSetValue = true;
+            me.callParent(arguments);
+            delete me.duringSetValue;
+        }
+
+        return me;
+    },
+
+    /**
+     * @method valueToRaw
+     * @private
+     */
+    valueToRaw: Ext.identityFn,
+
+    /**
+     * @private
+     * Called when the checkbox's checked state changes. Invokes the {@link #handler} callback
+     * function if specified.
+     */
+    onChange: function(newVal, oldVal) {
+        var me = this,
+            handler = me.handler;
+
+        me.updateCheckedCls(newVal);
+
+        if (handler) {
+            Ext.callback(handler, me.scope, [me, newVal], 0, me);
+        }
+
+        me.callParent(arguments);
+
+        if (me.reference && me.publishState) {
+            me.publishState('checked', newVal);
+        }
+    },
+
+    /**
+     * @private
+     */
+    resetOriginalValue: function(fromBoxInGroup) {
+        var me = this,
+            boxes, box, len, i;
+
+        // If we're resetting the value of a field in a group, also reset the others.
+        if (!fromBoxInGroup) {
+            boxes = me.getManager().getByName(me.name, me.getFormId()).items;
+            len = boxes.length;
+
+            for (i = 0; i < len; ++i) {
+                box = boxes[i];
+
+                if (box !== me) {
+                    boxes[i].resetOriginalValue(true);
+                }
+            }
+        }
+
+        me.callParent();
+    },
+
+    doDestroy: function() {
+        this.getManager().removeAtKey(this.id);
+
+        this.callParent();
+    },
+
+    getManager: function() {
+        return Ext.form.CheckboxManager;
+    },
+
+    onEnable: function() {
+        var me = this,
+            inputEl = me.inputEl && me.inputEl.dom;
+
+        me.callParent();
+
+        if (inputEl) {
+            // Can still be disabled if the field is readOnly
+            inputEl.disabled = me.readOnly;
+        }
+    },
+
+    setReadOnly: function(readOnly) {
+        var me = this,
+            inputEl = me.inputEl && me.inputEl.dom;
+
+        if (inputEl) {
+            // Set the button to disabled when readonly
+            inputEl.disabled = !!readOnly || me.disabled;
+        }
+
+        me.callParent(arguments);
+    },
+
+    getFormId: function() {
+        var me = this,
+            form;
+
+        if (!me.formId) {
+            form = me.up('form');
+
+            if (form) {
+                me.formId = form.id;
+            }
+        }
+
+        return me.formId;
+    },
+
+    getFocusClsEl: function() {
+        return this.displayEl;
+    }
+});

File diff suppressed because it is too large
+ 2761 - 0
assets/ext-7.4.0.42/classic/classic/src/form/field/ComboBox.js


+ 864 - 0
assets/ext-7.4.0.42/classic/classic/src/form/field/Date.js

@@ -0,0 +1,864 @@
+/**
+ * Provides a date input field with a {@link Ext.picker.Date date picker} dropdown and automatic
+ * date validation.
+ *
+ * This field recognizes and uses the JavaScript Date object as its main {@link #value} type.
+ * In addition, it recognizes string values which are parsed according to the {@link #format}
+ * and/or {@link #altFormats} configs. These may be reconfigured to use date formats appropriate
+ * for the user's locale.
+ *
+ * The field may be limited to a certain range of dates by using the {@link #minValue},
+ * {@link #maxValue}, {@link #disabledDays}, and {@link #disabledDates} config parameters.
+ * These configurations will be used both in the field's validation, and in the date picker
+ * dropdown by preventing invalid dates from being selected.
+ *
+ * # Example usage
+ *
+ *     @example
+ *     Ext.create('Ext.form.Panel', {
+ *         renderTo: Ext.getBody(),
+ *         width: 300,
+ *         bodyPadding: 10,
+ *         title: 'Dates',
+ *         items: [{
+ *             xtype: 'datefield',
+ *             anchor: '100%',
+ *             fieldLabel: 'From',
+ *             name: 'from_date',
+ *             maxValue: new Date()  // limited to the current date or prior
+ *         }, {
+ *             xtype: 'datefield',
+ *             anchor: '100%',
+ *             fieldLabel: 'To',
+ *             name: 'to_date',
+ *             value: new Date()  // defaults to today
+ *         }]
+ *     });
+ *
+ * # Date Formats Examples
+ *
+ * This example shows a couple of different date format parsing scenarios. Both use custom date
+ * format configurations; the first one matches the configured `format` while the second matches
+ * the `altFormats`.
+ *
+ *     @example
+ *     Ext.create('Ext.form.Panel', {
+ *         renderTo: Ext.getBody(),
+ *         width: 300,
+ *         bodyPadding: 10,
+ *         title: 'Dates',
+ *         items: [{
+ *             xtype: 'datefield',
+ *             anchor: '100%',
+ *             fieldLabel: 'Date',
+ *             name: 'date',
+ *             // The value matches the format; will be parsed and displayed using that format.
+ *             format: 'm d Y',
+ *             value: '02 04 1978'
+ *         }, {
+ *             xtype: 'datefield',
+ *             anchor: '100%',
+ *             fieldLabel: 'Date',
+ *             name: 'date',
+ *             // The value does not match the format, but does match an altFormat; will be parsed
+ *             // using the altFormat and displayed using the format.
+ *             format: 'm d Y',
+ *             altFormats: 'm,d,Y|m.d.Y',
+ *             value: '02.04.1978'
+ *         }]
+ *     });
+ */
+Ext.define('Ext.form.field.Date', {
+    extend: 'Ext.form.field.Picker',
+    alias: 'widget.datefield',
+    requires: ['Ext.picker.Date'],
+    alternateClassName: ['Ext.form.DateField', 'Ext.form.Date'],
+
+    /**
+     * @cfg {String} format
+     * The default date format string which can be overriden for localization support.
+     * The format must be valid according to {@link Ext.Date#parse}.
+     * @locale
+     */
+    format: "m/d/Y",
+
+    /**
+     * @cfg {String} ariaFormat
+     * This date format will be used to format ARIA attributes in the field and its Picker,
+     * to provide Assistive Technologies such as screen readers with user friendly text.
+     * The format must be valid {@link Ext.Date#format}.
+     * @locale
+     */
+    ariaFormat: 'M j Y',
+
+    /**
+     * @cfg {String} altFormats
+     * Multiple date formats separated by "|" to try when parsing a user input value and it
+     * does not match the defined format.
+     * @locale
+     */
+    // eslint-disable-next-line max-len
+    altFormats: "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|n-j|n/j",
+
+    /**
+     * @cfg {String} disabledDaysText
+     * The tooltip to display when the date falls on a disabled day of week.
+     * @locale
+     */
+    disabledDaysText: "Disabled",
+
+    /**
+     * @cfg {String} ariaDisabledDaysText
+     * The text that Assistive Technologies such as screen readers will announce when the
+     * date falls on a disabled day of week.
+     * @locale
+     */
+    ariaDisabledDaysText: "This day of week is disabled",
+
+    /**
+     * @cfg {String} disabledDatesText
+     * The tooltip text to display when the date falls on a disabled date.
+     * @locale
+     */
+    disabledDatesText: "Disabled",
+
+    /**
+     * @cfg {String} ariaDisabledDatesText
+     * The text that Assistive Technologies such as screen readers will announce when the
+     * date falls on a disabled date.
+     * @locale
+     */
+    ariaDisabledDatesText: "This date cannot be selected",
+
+    /**
+     * @cfg {String} minText
+     * The error text to display when the date in the cell is before {@link #minValue}.
+     * @locale
+     */
+    minText: "The date in this field must be equal to or after {0}",
+
+    /**
+     * @cfg {String} ariaMinText
+     * The text that Assistive Technologies such as screen readers will announce when the
+     * date in the cell is before {@link #minValue}. The date substituted for {0} will be
+     * formatted as per {@link #ariaFormat}.
+     * @locale
+     */
+    ariaMinText: "The date must be equal to or after {0}",
+
+    /**
+     * @cfg {String} maxText
+     * The error text to display when the date in the cell is after {@link #maxValue}.
+     * @locale
+     */
+    maxText: "The date in this field must be equal to or before {0}",
+
+    /**
+     * @cfg {String} ariaMaxText
+     * The text that Assistive Technologies such as screen readers will announce when the
+     * date in the cell is after {@link #maxValue}. The date substituted for {0} will be
+     * formatted as per {@link #ariaFormat}.
+     * @locale
+     */
+    ariaMaxText: "The date must be equal to or before {0}",
+
+    /**
+     * @cfg {String} invalidText
+     * The error text to display when the date in the field is invalid.
+     * @locale
+     */
+    invalidText: "{0} is not a valid date - it must be in the format {1}",
+
+    /**
+     * @cfg {String} formatText
+     * The format text to be announced by screen readers when the field is focused.
+     * @locale
+     */
+    formatText: 'Expected date format {0}.',
+
+    /**
+     * @cfg {String} triggerCls
+     * An additional CSS class used to style the trigger button. The trigger will always get
+     * the class 'x-form-trigger' and triggerCls will be **appended** if specified
+     * (default class displays a calendar icon).
+     */
+    triggerCls: Ext.baseCSSPrefix + 'form-date-trigger',
+
+    /**
+     * @cfg {Boolean} showToday
+     * false to hide the footer area of the Date picker containing the Today button and disable
+     * the keyboard handler for spacebar that selects the current date.
+     */
+    showToday: true,
+
+    /**
+     * @cfg {Date/String} minValue
+     * The minimum allowed date. Can be either a Javascript date object or a string date
+     * in a valid format.
+     */
+
+    /**
+     * @cfg {Date/String} maxValue
+     * The maximum allowed date. Can be either a Javascript date object or a string date
+     * in a valid format.
+     */
+
+    /**
+     * @cfg {Number[]} disabledDays
+     * An array of days to disable, 0 based. Some examples:
+     *
+     *     // disable Sunday and Saturday:
+     *     disabledDays:  [0, 6]
+     *     // disable weekdays:
+     *     disabledDays: [1,2,3,4,5]
+     */
+
+    /**
+     * @cfg {String[]} disabledDates
+     * An array of "dates" to disable, as strings. These strings will be used to build
+     * a dynamic regular expression so they are very powerful. Some examples:
+     *
+     *     // disable these exact dates:
+     *     disabledDates: ["03/08/2003", "09/16/2003"]
+     *     // disable these days for every year:
+     *     disabledDates: ["03/08", "09/16"]
+     *     // only match the beginning (useful if you are using short years):
+     *     disabledDates: ["^03/08"]
+     *     // disable every day in March 2006:
+     *     disabledDates: ["03/../2006"]
+     *     // disable every day in every March:
+     *     disabledDates: ["^03"]
+     *
+     * Note that the format of the dates included in the array should exactly match
+     * the {@link #format} config. In order to support regular expressions, if you are using
+     * a {@link #format date format} that has "." in it, you will have to escape the dot
+     * when restricting dates. For example: `["03\\.08\\.03"]`.
+     */
+
+    /**
+     * @cfg {String} submitFormat
+     * The date format string which will be submitted to the server. The format must be valid
+     * according to {@link Ext.Date#parse}.
+     *
+     * Defaults to {@link #format}.
+     */
+
+    /**
+     * @cfg {Boolean} useStrict
+     * True to enforce strict date parsing to prevent the default Javascript "date rollover".
+     * Defaults to the useStrict parameter set on Ext.Date
+     * See {@link Ext.Date#parse}.
+     */
+    useStrict: undefined,
+
+    // in the absence of a time value, a default value of 12 noon will be used
+    // (note: 12 noon was chosen because it steers well clear of all DST timezone changes)
+    initTime: '12', // 24 hour format
+
+    initTimeFormat: 'H',
+
+    /**
+     * @cfg matchFieldWidth
+     * @inheritdoc
+     */
+    matchFieldWidth: false,
+
+    /**
+     * @cfg {Number} startDay
+     * Day index at which the week should begin, 0-based.
+     *
+     * Defaults to `0` (Sunday).
+     * @locale
+     */
+    startDay: 0,
+
+    /**
+     * @cfg valuePublishEvent
+     * @inheritdoc
+     */
+    valuePublishEvent: ['select', 'blur'],
+
+    /**
+     * @cfg componentCls
+     * @inheritdoc
+     */
+    componentCls: Ext.baseCSSPrefix + 'form-field-date',
+
+    /**
+     * @property ariaRole
+     * @inheritdoc
+     */
+    ariaRole: 'combobox',
+
+    /**
+     * @private
+     */
+    rawDate: null,
+
+    /**
+     * @private
+     */
+    rawDateText: '',
+
+    // Date field should validate on focusleave not blur
+    validateOnFocusLeave: true,
+
+    /**
+     * @event select
+     * Fires when a value is selected via the picker or when value is getting set
+     * explicitly by setter.
+     * @param {Ext.form.field.Date} field This field instance
+     * @param {Object} value The value that was selected. 
+     */
+
+    initComponent: function() {
+        var me = this,
+            isString = Ext.isString,
+            min, max;
+
+        min = me.minValue;
+        max = me.maxValue;
+
+        if (isString(min)) {
+            me.minValue = me.parseDate(min);
+        }
+
+        if (isString(max)) {
+            me.maxValue = me.parseDate(max);
+        }
+
+        me.disabledDatesRE = null;
+        me.initDisabledDays();
+
+        me.callParent();
+    },
+
+    getSubTplData: function(fieldData) {
+        var me = this,
+            data, ariaAttr;
+
+        data = me.callParent([fieldData]);
+
+        if (!me.ariaStaticRoles[me.ariaRole]) {
+            ariaAttr = data.ariaElAttributes;
+
+            if (ariaAttr) {
+                ariaAttr['aria-owns'] = me.id + '-inputEl ' + me.id + '-picker-eventEl';
+                ariaAttr['aria-autocomplete'] = 'none';
+            }
+        }
+
+        return data;
+    },
+
+    initValue: function() {
+        var me = this,
+            value = me.value;
+
+        // If a String value was supplied, try to convert it to a proper Date
+        if (Ext.isString(value)) {
+            me.value = me.rawToValue(value);
+            me.rawDate = me.value;
+            me.rawDateText = me.parseDate(me.value);
+        }
+        else {
+            me.value = value || null;
+            me.rawDate = me.value;
+            me.rawDateText = me.value ? me.parseDate(me.value) : '';
+        }
+
+        me.callParent();
+    },
+
+    /**
+     * @private
+     */
+    initDisabledDays: function() {
+        if (this.disabledDates) {
+            // eslint-disable-next-line vars-on-top
+            var dd = this.disabledDates,
+                len = dd.length - 1,
+                re = "(?:",
+                d,
+                dLen = dd.length,
+                date;
+
+            for (d = 0; d < dLen; d++) {
+                date = dd[d];
+
+                re += Ext.isDate(date)
+                    ? '^' + Ext.String.escapeRegex(date.dateFormat(this.format)) + '$'
+                    : date;
+
+                if (d !== len) {
+                    re += '|';
+                }
+            }
+
+            this.disabledDatesRE = new RegExp(re + ')');
+        }
+    },
+
+    /**
+     * Replaces any existing disabled dates with new values and refreshes the Date picker.
+     * @param {String[]} disabledDates An array of date strings (see the {@link #disabledDates}
+     * config for details on supported values) used to disable a pattern of dates.
+     */
+    setDisabledDates: function(disabledDates) {
+        var me = this,
+            picker = me.picker;
+
+        me.disabledDates = disabledDates;
+        me.initDisabledDays();
+
+        if (picker) {
+            picker.setDisabledDates(me.disabledDatesRE);
+        }
+    },
+
+    /**
+     * Replaces any existing disabled days (by index, 0-6) with new values and refreshes
+     * the Date picker.
+     * @param {Number[]} disabledDays An array of disabled day indexes.
+     * See the {@link #disabledDays} config for details on supported values.
+     */
+    setDisabledDays: function(disabledDays) {
+        var picker = this.picker;
+
+        this.disabledDays = disabledDays;
+
+        if (picker) {
+            picker.setDisabledDays(disabledDays);
+        }
+    },
+
+    /**
+     * Replaces any existing {@link #minValue} with the new value and refreshes the Date picker.
+     * @param {Date} value The minimum date that can be selected
+     */
+    setMinValue: function(value) {
+        var me = this,
+            picker = me.picker,
+            minValue = (Ext.isString(value) ? me.parseDate(value) : value);
+
+        me.minValue = minValue;
+
+        if (picker) {
+            picker.minText = Ext.String.format(me.minText, me.formatDate(me.minValue));
+            picker.setMinDate(minValue);
+        }
+    },
+
+    /**
+     * Replaces any existing {@link #maxValue} with the new value and refreshes the Date picker.
+     * @param {Date} value The maximum date that can be selected
+     */
+    setMaxValue: function(value) {
+        var me = this,
+            picker = me.picker,
+            maxValue = (Ext.isString(value) ? me.parseDate(value) : value);
+
+        me.maxValue = maxValue;
+
+        if (picker) {
+            picker.maxText = Ext.String.format(me.maxText, me.formatDate(me.maxValue));
+            picker.setMaxDate(maxValue);
+        }
+    },
+
+    /**
+     * Runs all of Date's validations and returns an array of any errors. Note that this first
+     * runs Text's validations, so the returned array is an amalgamation of all field errors.
+     * The additional validation checks are testing that the date format is valid, that the chosen
+     * date is within the min and max date constraints set, that the date chosen is not in the
+     * disabledDates regex and that the day chosed is not one of the disabledDays.
+     * @param {Object} [value] The value to get errors for (defaults to the current field value)
+     * @return {String[]} All validation errors for this field
+     */
+    getErrors: function(value) {
+        value = arguments.length > 0
+            ? value
+            : this.formatDate(this.processRawValue(this.getRawValue()));
+
+        // eslint-disable-next-line vars-on-top
+        var me = this,
+            format = Ext.String.format,
+            clearTime = Ext.Date.clearTime,
+            errors = me.callParent([value]),
+            disabledDays = me.disabledDays,
+            disabledDatesRE = me.disabledDatesRE,
+            minValue = me.minValue,
+            maxValue = me.maxValue,
+            len = disabledDays ? disabledDays.length : 0,
+            i = 0,
+            svalue, fvalue, day, time;
+
+        // if it's blank and textfield didn't flag it then it's valid
+        if (value === null || value.length < 1) {
+            return errors;
+        }
+
+        svalue = value;
+        value = me.parseDate(value);
+
+        if (!value) {
+            errors.push(format(me.invalidText, svalue, Ext.Date.unescapeFormat(me.format)));
+
+            return errors;
+        }
+
+        time = value.getTime();
+
+        if (minValue && time < clearTime(minValue).getTime()) {
+            errors.push(format(me.minText, me.formatDate(minValue)));
+        }
+
+        if (maxValue && time > clearTime(maxValue).getTime()) {
+            errors.push(format(me.maxText, me.formatDate(maxValue)));
+        }
+
+        if (disabledDays) {
+            day = value.getDay();
+
+            for (; i < len; i++) {
+                if (day === disabledDays[i]) {
+                    errors.push(me.disabledDaysText);
+                    break;
+                }
+            }
+        }
+
+        fvalue = me.formatDate(value);
+
+        if (disabledDatesRE && disabledDatesRE.test(fvalue)) {
+            errors.push(format(me.disabledDatesText, fvalue));
+        }
+
+        return errors;
+    },
+
+    rawToValue: function(rawValue) {
+        var me = this;
+
+        if (rawValue === me.rawDateText) {
+            return me.rawDate;
+        }
+
+        return me.parseDate(rawValue) || rawValue || null;
+    },
+
+    valueToRaw: function(value) {
+        return this.formatDate(this.parseDate(value));
+    },
+
+    /**
+     * @method setValue
+     * Sets the value of the date field. You can pass a date object or any string that can be parsed
+     * into a valid date, using {@link #format} as the date format, according to the same rules
+     * as {@link Ext.Date#parse} (the default format used is "m/d/Y").
+     *
+     * Usage:
+     *
+     *     // All of these calls set the same date value (May 4, 2006)
+     *
+     *     // Pass a date object:
+     *     var dt = new Date('5/4/2006');
+     *     dateField.me = this,
+     *     setValue(dt);
+     *
+     *     // Pass a date string (default format):
+     *     dateField.setValue('05/04/2006');
+     *
+     *     // Pass a date string (custom format):
+     *     dateField.format = 'Y-m-d';
+     *     dateField.setValue('2006-05-04');
+     *
+     * @param {String/Date} v The date or valid date string
+     * @return {Ext.form.field.Date} this
+     */
+    setValue: function(v) {
+        var me = this,
+            utilDate = Ext.Date,
+            rawDate,
+            oldVal = me.lastValue;
+
+        me.lastValue = me.rawDateText;
+        me.lastDate = me.rawDate;
+
+        if (Ext.isDate(v)) {
+            rawDate = me.rawDate = v;
+            me.rawDateText = me.formatDate(v);
+        }
+        else {
+            rawDate = me.rawDate = me.rawToValue(v);
+            me.rawDateText = me.formatDate(v);
+
+            if (rawDate === v) {
+                rawDate = me.rawDate = null;
+                me.rawDateText = '';
+            }
+        }
+
+        if (rawDate && !utilDate.formatContainsHourInfo(me.format)) {
+            me.rawDate = utilDate.clearTime(rawDate, true);
+        }
+
+        me.callParent(arguments);
+
+        // Checking if there is a value change
+        // If yes, trigger select event
+        if (!me.destroyed && me.didValueChange(me.rawDate, oldVal)) {
+            me.fireEvent('select', me, v);
+        }
+    },
+
+    /**
+     * Checks whether the value of the field has changed since the last time it was checked.
+     * If the value has changed, it:
+     *
+     * 1. Fires the {@link #change change event},
+     * 2. Performs validation if the {@link #validateOnChange} config is enabled, firing the
+     *    {@link #validitychange validitychange event} if the validity has changed, and
+     * 3. Checks the {@link #isDirty dirty state} of the field and fires the
+     *    {@link #dirtychange dirtychange event} if it has changed.
+     */
+    checkChange: function() {
+        var me = this,
+            newVal, oldVal, lastDate;
+
+        if (!me.suspendCheckChange) {
+            newVal = me.getRawValue();
+            oldVal = me.lastValue;
+            lastDate = me.lastDate;
+
+            if (!me.destroyed && me.didValueChange(newVal, oldVal)) {
+                me.rawDate = me.rawToValue(newVal);
+                me.rawDateText = me.formatDate(newVal);
+                me.lastValue = newVal;
+                me.lastDate = me.rawDate;
+                me.fireEvent('change', me, me.getValue(), lastDate);
+                me.onChange(newVal, oldVal);
+            }
+        }
+    },
+
+    /**
+     * Attempts to parse a given string value using a given {@link Ext.Date#parse date format}.
+     * @param {String} value The value to attempt to parse
+     * @param {String} format A valid date format (see {@link Ext.Date#parse})
+     * @return {Date} The parsed Date object, or null if the value could not be successfully parsed.
+     */
+    safeParse: function(value, format) {
+        var me = this,
+            utilDate = Ext.Date,
+            result = null,
+            strict = me.useStrict,
+            parsedDate;
+
+        if (utilDate.formatContainsHourInfo(format)) {
+            // if parse format contains hour information, no DST adjustment is necessary
+            result = utilDate.parse(value, format, strict);
+        }
+        else {
+            // set time to 12 noon, then clear the time
+            parsedDate = utilDate.parse(
+                value + ' ' + me.initTime, format + ' ' + me.initTimeFormat, strict
+            );
+
+            if (parsedDate) {
+                result = utilDate.clearTime(parsedDate);
+            }
+        }
+
+        return result;
+    },
+
+    /**
+     * @private
+     */
+    getSubmitValue: function() {
+        var format = this.submitFormat || this.format,
+            value = this.rawDate;
+
+        return value ? Ext.Date.format(value, format) : '';
+    },
+
+    /**
+     * Returns the current data value of the field. The type of value returned is particular
+     * to the type of the particular field (e.g. a Date object for {@link Ext.form.field.Date}),
+     * as the result of calling {@link #rawToValue} on the field's
+     * {@link #processRawValue processed} String value. To return the raw String value,
+     * see {@link #getRawValue}.
+     * @return {Object} value The field value
+     */
+    getValue: function() {
+        return this.rawDate || null;
+    },
+
+    setRawValue: function(value) {
+        var me = this;
+
+        me.callParent([value]);
+
+        me.rawDate = Ext.isDate(value) ? value : me.rawToValue(value);
+        me.rawDateText = this.formatDate(value);
+    },
+
+    /**
+     * @private
+     */
+    parseDate: function(value) {
+        if (!value || Ext.isDate(value)) {
+            return value;
+        }
+
+        // eslint-disable-next-line vars-on-top
+        var me = this,
+            val = me.safeParse(value, me.format),
+            altFormats = me.altFormats,
+            altFormatsArray = me.altFormatsArray,
+            i = 0,
+            len;
+
+        if (!val && altFormats) {
+            altFormatsArray = altFormatsArray || altFormats.split('|');
+            len = altFormatsArray.length;
+
+            for (; i < len && !val; ++i) {
+                val = me.safeParse(value, altFormatsArray[i]);
+            }
+        }
+
+        return val;
+    },
+
+    /**
+     * @private
+     */
+    formatDate: function(date, format) {
+        return Ext.isDate(date) ? Ext.Date.dateFormat(date, format || this.format) : date;
+    },
+
+    createPicker: function() {
+        var me = this,
+            format = Ext.String.format;
+
+        // Create floating Picker BoundList. It will acquire a floatParent by looking up
+        // its ancestor hierarchy (Pickers use their pickerField property as an upward link)
+        // for a floating component.
+        return new Ext.picker.Date({
+            id: me.id + '-picker',
+            pickerField: me,
+            floating: true,
+            preventRefocus: true,
+            hidden: true,
+            minDate: me.minValue,
+            maxDate: me.maxValue,
+            disabledDatesRE: me.disabledDatesRE,
+            disabledDatesText: me.disabledDatesText,
+            ariaDisabledDatesText: me.ariaDisabledDatesText,
+            disabledDays: me.disabledDays,
+            disabledDaysText: me.disabledDaysText,
+            ariaDisabledDaysText: me.ariaDisabledDaysText,
+            format: me.format,
+            showToday: me.showToday,
+            startDay: me.startDay,
+            minText: format(me.minText, me.formatDate(me.minValue)),
+            ariaMinText: format(me.ariaMinText, me.formatDate(me.minValue, me.ariaFormat)),
+            maxText: format(me.maxText, me.formatDate(me.maxValue)),
+            ariaMaxText: format(me.ariaMaxText, me.formatDate(me.maxValue, me.ariaFormat)),
+            listeners: {
+                scope: me,
+                select: me.onSelect,
+                tabout: me.onTabOut
+            },
+            keyNavConfig: {
+                esc: function() {
+                    me.inputEl.focus();
+                    me.collapse();
+                }
+            }
+        });
+    },
+
+    createInitialDate: function(value) {
+        var minValue = this.minValue,
+            maxValue = this.maxValue;
+
+        value = value || new Date();
+
+        if (minValue && minValue > value) {
+            value = minValue;
+        }
+        else if (maxValue && maxValue < value) {
+            value = maxValue;
+        }
+
+        return value;
+    },
+
+    onSelect: function(m, d) {
+        var me = this;
+
+        me.setValue(d);
+        me.rawDate = d;
+        // Select event has already been triggered in setValue()
+
+        // Focus the inputEl first and then collapse. We configure
+        // the picker not to revert focus which is a normal thing to do
+        // for floaters; in our case when the picker is focusable it will
+        // lead to unexpected results on Tab key presses.
+        // Note that this focusing might happen synchronously during Tab
+        // key handling in the picker, which is the way we want it.
+        me.onTabOut(m);
+    },
+
+    onTabOut: function(picker) {
+        this.inputEl.focus();
+        this.collapse();
+    },
+
+    /**
+     * @private
+     * Sets the Date picker's value to match the current field value when expanding.
+     */
+    onExpand: function() {
+        var value = this.rawDate;
+
+        this.picker.setValue(Ext.isDate(value) ? value : this.createInitialDate());
+    },
+
+    /**
+     * @private
+     */
+    onBlur: function(e) {
+        var me = this,
+            v = me.rawToValue(me.getRawValue());
+
+        if (v === '' || Ext.isDate(v)) {
+            me.setValue(v);
+        }
+
+        me.callParent([e]);
+    }
+
+    /**
+     * @cfg {Boolean} grow
+     * @private
+     */
+
+    /**
+     * @cfg {Number} growMin
+     * @private
+     */
+
+    /**
+     * @cfg {Number} growMax
+     * @private
+     */
+
+    /**
+     * @method autoSize
+     * @private
+     */
+});

+ 248 - 0
assets/ext-7.4.0.42/classic/classic/src/form/field/Display.js

@@ -0,0 +1,248 @@
+/**
+ * A display-only text field which is not validated and not submitted. This is useful for when
+ * you want to display a value from a form's {@link Ext.form.Basic#load loaded data} but do not want
+ * to allow the user to edit or submit that value. The value can be optionally
+ * {@link #htmlEncode HTML encoded} if it contains HTML markup that you do not want to be rendered.
+ *
+ * If you have more complex content, or need to include components within the displayed content,
+ * also consider using a {@link Ext.form.FieldContainer} instead.
+ *
+ * Example:
+ *
+ *     @example
+ *     Ext.create('Ext.form.Panel', {
+ *         renderTo: Ext.getBody(),
+ *         width: 175,
+ *         height: 150,
+ *         bodyPadding: 10,
+ *         title: 'Final Score',
+ *         items: [{
+ *             xtype: 'displayfield',
+ *             fieldLabel: 'Home',
+ *             name: 'home_score',
+ *             value: '10'
+ *         }, {
+ *             xtype: 'displayfield',
+ *             fieldLabel: 'Visitor',
+ *             name: 'visitor_score',
+ *             value: '11'
+ *         }],
+ *         buttons: [{
+ *             text: 'Update'
+ *         }]
+ *     });
+ */
+Ext.define('Ext.form.field.Display', {
+    extend: 'Ext.form.field.Base',
+    alias: 'widget.displayfield',
+    alternateClassName: ['Ext.form.DisplayField', 'Ext.form.Display'],
+
+    requires: [
+        'Ext.util.Format',
+        'Ext.XTemplate'
+    ],
+
+    /* eslint-disable indent, max-len */
+    /**
+     * @cfg fieldSubTpl
+     * @inheritdoc
+     */
+    fieldSubTpl: [
+        '<div id="{id}" data-ref="inputEl" role="textbox" aria-readonly="true"',
+        ' aria-labelledby="{cmpId}-labelEl" {inputAttrTpl}',
+        ' tabindex="<tpl if="tabIdx != null">{tabIdx}<tpl else>-1</tpl>"',
+        '<tpl if="fieldStyle"> style="{fieldStyle}"</tpl>',
+        ' class="{fieldCls} {fieldCls}-{ui}">{value}</div>',
+        {
+            compiled: true,
+            disableFormats: true
+        }
+    ],
+    /* eslint-enable indent, max-len */
+
+    // We have the ARIA markup pre-rendered so we don't want it to be applied
+    /**
+     * @property ariaRole
+     * @inheritdoc
+     */
+    ariaRole: undefined,
+
+    /**
+     * @property focusable
+     * @inheritdoc
+     */
+    focusable: false,
+
+    // Display fields are divs not real input fields, so rendering
+    // "for" attribute in the label does not do any good.
+    skipLabelForAttribute: true,
+
+    /**
+     * @cfg readOnly
+     * @inheritdoc
+     * @private
+     */
+    readOnly: true,
+
+    /**
+     * @cfg fieldCls
+     * @inheritdoc
+     */
+    fieldCls: Ext.baseCSSPrefix + 'form-display-field',
+
+    /**
+     * @cfg fieldBodyCls
+     * @inheritdoc
+     */
+    fieldBodyCls: Ext.baseCSSPrefix + 'form-display-field-body',
+
+    /**
+     * @cfg {Boolean} htmlEncode
+     * True to escape HTML in text when rendering it.
+     */
+    htmlEncode: false,
+
+    /**
+     * @cfg {Function/String} renderer
+     * A function to transform the raw value for display in the field.
+     * 
+     *     Ext.create('Ext.form.Panel', {
+     *         renderTo: document.body,
+     *         width: 175,
+     *         bodyPadding: 10,
+     *         title: 'Final Score',
+     *         items: [{
+     *             xtype: 'displayfield',
+     *             fieldLabel: 'Grade',
+     *             name: 'final_grade',
+     *             value: 68,
+     *             renderer: function (value, field) {
+     *                 var color = (value < 70) ? 'red' : 'black';
+     *                 return '<span style="color:' + color + ';">' + value + '</span>';
+     *             }
+     *         }]
+     *     });
+     * 
+     * @param {Object} value The raw field {@link #value}
+     * @param {Ext.form.field.Display} field The display field
+     * @return {String} displayValue The HTML string to be rendered
+     * @controllable
+     */
+
+    /**
+     * @cfg {Object} scope
+     * The scope to execute the {@link #renderer} function. Defaults to this.
+     */
+
+    /**
+     * @property noWrap
+     * @inheritdoc
+     */
+    noWrap: false,
+
+    /**
+     * @cfg validateOnChange
+     * @inheritdoc
+     * @private
+     */
+    validateOnChange: false,
+
+    /**
+     * @method initEvents
+     * @inheritdoc
+     */
+    initEvents: Ext.emptyFn,
+
+    /**
+     * @cfg submitValue
+     * @inheritdoc
+     */
+    submitValue: false,
+
+    getValue: function() {
+        return this.value;
+    },
+
+    valueToRaw: function(value) {
+        if (value || value === 0 || value === false) {
+            return value;
+        }
+        else {
+            return '';
+        }
+    },
+
+    isDirty: function() {
+        return false;
+    },
+
+    isValid: Ext.returnTrue,
+
+    validate: Ext.returnTrue,
+
+    getRawValue: function() {
+        return this.rawValue;
+    },
+
+    setRawValue: function(value) {
+        var me = this;
+
+        value = Ext.valueFrom(value, '');
+        me.rawValue = value;
+
+        if (me.rendered) {
+            me.inputEl.dom.innerHTML = me.getDisplayValue();
+            me.updateLayout();
+        }
+
+        return value;
+    },
+
+    /**
+     * @private
+     * Format the value to display.
+     */
+    getDisplayValue: function() {
+        var me = this,
+            value = this.getRawValue(),
+            renderer = me.renderer,
+            display;
+
+        if (renderer) {
+            display = Ext.callback(renderer, me.scope, [value, me], 0, me);
+        }
+        else {
+            display = me.htmlEncode ? Ext.util.Format.htmlEncode(value) : value;
+        }
+
+        return display;
+    },
+
+    getSubTplData: function(fieldData) {
+        var ret = this.callParent(arguments);
+
+        ret.value = this.getDisplayValue();
+
+        return ret;
+    }
+
+    /**
+     * @cfg {String} inputType
+     * @private
+     */
+
+    /**
+     * @cfg {Boolean} disabled
+     * @private
+     */
+
+    /**
+     * @cfg {Number} checkChangeEvents
+     * @private
+     */
+
+    /**
+     * @cfg {Number} checkChangeBuffer
+     * @private
+     */
+});

+ 0 - 0
assets/ext-7.4.0.42/classic/classic/src/form/field/Field.js


Some files were not shown because too many files changed in this diff