# Sử dụng nodejs và js cấu trúc thư mục tốt P.2 (ok)

Source code

{% file src="/files/aHJ3oCW8jFtkx786I4hH" %}

C:\Users\Administrator\Desktop\Practice Coreui\coreui-main\js\index.umd.js

```
/**
 * --------------------------------------------------------------------------
 * CoreUI (v4.1.3): index.esm.js
 * Licensed under MIT (https://coreui.io/license)
 * --------------------------------------------------------------------------
 */

import Alert from './src/alert'
import Button from './src/button'
import Carousel from './src/carousel'
import Collapse from './src/collapse'
import Dropdown from './src/dropdown'
import Modal from './src/modal'
import Navigation from './src/navigation'
import OffCanvas from './src/offcanvas'
import Popover from './src/popover'
import ScrollSpy from './src/scrollspy'
import Sidebar from './src/sidebar'
import Tab from './src/tab'
import Toast from './src/toast'
import Tooltip from './src/tooltip'

export default {
  Alert,
  Button,
  Carousel,
  Collapse,
  Dropdown,
  Modal,
  Navigation,
  OffCanvas,
  Popover,
  ScrollSpy,
  Sidebar,
  Tab,
  Toast,
  Tooltip
}

```

C:\Users\Administrator\Desktop\Practice Coreui\coreui-main\js\index.esm.js

```
/**
 * --------------------------------------------------------------------------
 * CoreUI (v4.1.3): index.esm.js
 * Licensed under MIT (https://coreui.io/license)
 * --------------------------------------------------------------------------
 */

export { default as Alert } from './src/alert'
export { default as Button } from './src/button'
export { default as Carousel } from './src/carousel'
export { default as Collapse } from './src/collapse'
export { default as Dropdown } from './src/dropdown'
export { default as Modal } from './src/modal'
export { default as Navigation } from './src/navigation'
export { default as Offcanvas } from './src/offcanvas'
export { default as Popover } from './src/popover'
export { default as ScrollSpy } from './src/scrollspy'
export { default as Sidebar } from './src/sidebar'
export { default as Tab } from './src/tab'
export { default as Toast } from './src/toast'
export { default as Tooltip } from './src/tooltip'

```

C:\Users\Administrator\Desktop\Practice Coreui\coreui-main\js\src\button.js

```
/**
 * --------------------------------------------------------------------------
 * CoreUI (v4.1.3): alert.js
 * Licensed under MIT (https://coreui.io/license)
 *
 * This component is a modified version of the Bootstrap's button.js
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 * --------------------------------------------------------------------------
 */

import { defineJQueryPlugin } from './util/index'
import EventHandler from './dom/event-handler'
import BaseComponent from './base-component'

/**
 * ------------------------------------------------------------------------
 * Constants
 * ------------------------------------------------------------------------
 */

const NAME = 'button'
const DATA_KEY = 'coreui.button'
const EVENT_KEY = `.${DATA_KEY}`
const DATA_API_KEY = '.data-api'

const CLASS_NAME_ACTIVE = 'active'

const SELECTOR_DATA_TOGGLE = '[data-coreui-toggle="button"]'

const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`

/**
 * ------------------------------------------------------------------------
 * Class Definition
 * ------------------------------------------------------------------------
 */

class Button extends BaseComponent {
  // Getters

  static get NAME() {
    return NAME
  }

  // Public

  toggle() {
    // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
    this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE))
  }

  // Static

  static jQueryInterface(config) {
    return this.each(function () {
      const data = Button.getOrCreateInstance(this)

      if (config === 'toggle') {
        data[config]()
      }
    })
  }
}

/**
 * ------------------------------------------------------------------------
 * Data Api implementation
 * ------------------------------------------------------------------------
 */

EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, event => {
  event.preventDefault()

  const button = event.target.closest(SELECTOR_DATA_TOGGLE)
  const data = Button.getOrCreateInstance(button)

  data.toggle()
})

/**
 * ------------------------------------------------------------------------
 * jQuery
 * ------------------------------------------------------------------------
 * add .Button to jQuery only if jQuery is present
 */

defineJQueryPlugin(Button)

export default Button

```

C:\Users\Administrator\Desktop\Practice Coreui\coreui-main\js\src\util\index.js

```
/**
 * --------------------------------------------------------------------------
 * CoreUI (v4.1.3): alert.js
 * Licensed under MIT (https://coreui.io/license)
 *
 * This component is a modified version of the Bootstrap's  util/index.js
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 * --------------------------------------------------------------------------
 */

const MAX_UID = 1_000_000
const MILLISECONDS_MULTIPLIER = 1000
const TRANSITION_END = 'transitionend'

// Shoutout AngusCroll (https://goo.gl/pxwQGp)
const toType = object => {
  if (object === null || object === undefined) {
    return `${object}`
  }

  return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase()
}

/**
 * --------------------------------------------------------------------------
 * Public Util Api
 * --------------------------------------------------------------------------
 */

const getUID = prefix => {
  do {
    prefix += Math.floor(Math.random() * MAX_UID)
  } while (document.getElementById(prefix))

  return prefix
}

const getSelector = element => {
  let selector = element.getAttribute('data-coreui-target')

  if (!selector || selector === '#') {
    let hrefAttr = element.getAttribute('href')

    // The only valid content that could double as a selector are IDs or classes,
    // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
    // `document.querySelector` will rightfully complain it is invalid.
    // See https://github.com/twbs/bootstrap/issues/32273
    if (!hrefAttr || (!hrefAttr.includes('#') && !hrefAttr.startsWith('.'))) {
      return null
    }

    // Just in case some CMS puts out a full URL with the anchor appended
    if (hrefAttr.includes('#') && !hrefAttr.startsWith('#')) {
      hrefAttr = `#${hrefAttr.split('#')[1]}`
    }

    selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : null
  }

  return selector
}

const getSelectorFromElement = element => {
  const selector = getSelector(element)

  if (selector) {
    return document.querySelector(selector) ? selector : null
  }

  return null
}

const getElementFromSelector = element => {
  const selector = getSelector(element)

  return selector ? document.querySelector(selector) : null
}

const getTransitionDurationFromElement = element => {
  if (!element) {
    return 0
  }

  // Get transition-duration of the element
  let { transitionDuration, transitionDelay } = window.getComputedStyle(element)

  const floatTransitionDuration = Number.parseFloat(transitionDuration)
  const floatTransitionDelay = Number.parseFloat(transitionDelay)

  // Return 0 if element or transition duration is not found
  if (!floatTransitionDuration && !floatTransitionDelay) {
    return 0
  }

  // If multiple durations are defined, take the first
  transitionDuration = transitionDuration.split(',')[0]
  transitionDelay = transitionDelay.split(',')[0]

  return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER
}

const triggerTransitionEnd = element => {
  element.dispatchEvent(new Event(TRANSITION_END))
}

const isElement = obj => {
  if (!obj || typeof obj !== 'object') {
    return false
  }

  if (typeof obj.jquery !== 'undefined') {
    obj = obj[0]
  }

  return typeof obj.nodeType !== 'undefined'
}

const getElement = obj => {
  if (isElement(obj)) { // it's a jQuery object or a node element
    return obj.jquery ? obj[0] : obj
  }

  if (typeof obj === 'string' && obj.length > 0) {
    return document.querySelector(obj)
  }

  return null
}

const typeCheckConfig = (componentName, config, configTypes) => {
  Object.keys(configTypes).forEach(property => {
    const expectedTypes = configTypes[property]
    const value = config[property]
    const valueType = value && isElement(value) ? 'element' : toType(value)

    if (!new RegExp(expectedTypes).test(valueType)) {
      throw new TypeError(
        `${componentName.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`
      )
    }
  })
}

const isVisible = element => {
  if (!isElement(element) || element.getClientRects().length === 0) {
    return false
  }

  const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible'
  // Handle `details` element as its content may falsie appear visible when it is closed
  const closedDetails = element.closest('details:not([open])')

  if (!closedDetails) {
    return elementIsVisible
  }

  if (closedDetails !== element) {
    const summary = element.closest('summary')
    if (summary && summary.parentNode !== closedDetails) {
      return false
    }

    if (summary === null) {
      return false
    }
  }

  return elementIsVisible
}

const isDisabled = element => {
  if (!element || element.nodeType !== Node.ELEMENT_NODE) {
    return true
  }

  if (element.classList.contains('disabled')) {
    return true
  }

  if (typeof element.disabled !== 'undefined') {
    return element.disabled
  }

  return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'
}

const findShadowRoot = element => {
  if (!document.documentElement.attachShadow) {
    return null
  }

  // Can find the shadow root otherwise it'll return the document
  if (typeof element.getRootNode === 'function') {
    const root = element.getRootNode()
    return root instanceof ShadowRoot ? root : null
  }

  if (element instanceof ShadowRoot) {
    return element
  }

  // when we don't find a shadow root
  if (!element.parentNode) {
    return null
  }

  return findShadowRoot(element.parentNode)
}

const noop = () => {}

/**
 * Trick to restart an element's animation
 *
 * @param {HTMLElement} element
 * @return void
 *
 * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
 */
const reflow = element => {
  // eslint-disable-next-line no-unused-expressions
  element.offsetHeight
}

const getjQuery = () => {
  const { jQuery } = window

  if (jQuery && !document.body.hasAttribute('data-coreui-no-jquery')) {
    return jQuery
  }

  return null
}

const DOMContentLoadedCallbacks = []

const onDOMContentLoaded = callback => {
  if (document.readyState === 'loading') {
    // add listener on the first call when the document is in loading state
    if (!DOMContentLoadedCallbacks.length) {
      document.addEventListener('DOMContentLoaded', () => {
        DOMContentLoadedCallbacks.forEach(callback => callback())
      })
    }

    DOMContentLoadedCallbacks.push(callback)
  } else {
    callback()
  }
}

const isRTL = () => document.documentElement.dir === 'rtl'

const defineJQueryPlugin = plugin => {
  onDOMContentLoaded(() => {
    const $ = getjQuery()
    /* istanbul ignore if */
    if ($) {
      const name = plugin.NAME
      const JQUERY_NO_CONFLICT = $.fn[name]
      $.fn[name] = plugin.jQueryInterface
      $.fn[name].Constructor = plugin
      $.fn[name].noConflict = () => {
        $.fn[name] = JQUERY_NO_CONFLICT
        return plugin.jQueryInterface
      }
    }
  })
}

const execute = callback => {
  if (typeof callback === 'function') {
    callback()
  }
}

const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
  if (!waitForTransition) {
    execute(callback)
    return
  }

  const durationPadding = 5
  const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding

  let called = false

  const handler = ({ target }) => {
    if (target !== transitionElement) {
      return
    }

    called = true
    transitionElement.removeEventListener(TRANSITION_END, handler)
    execute(callback)
  }

  transitionElement.addEventListener(TRANSITION_END, handler)
  setTimeout(() => {
    if (!called) {
      triggerTransitionEnd(transitionElement)
    }
  }, emulatedDuration)
}

/**
 * Return the previous/next element of a list.
 *
 * @param {array} list    The list of elements
 * @param activeElement   The active element
 * @param shouldGetNext   Choose to get next or previous element
 * @param isCycleAllowed
 * @return {Element|elem} The proper element
 */
const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
  let index = list.indexOf(activeElement)

  // if the element does not exist in the list return an element depending on the direction and if cycle is allowed
  if (index === -1) {
    return list[!shouldGetNext && isCycleAllowed ? list.length - 1 : 0]
  }

  const listLength = list.length

  index += shouldGetNext ? 1 : -1

  if (isCycleAllowed) {
    index = (index + listLength) % listLength
  }

  return list[Math.max(0, Math.min(index, listLength - 1))]
}

export {
  getElement,
  getUID,
  getSelectorFromElement,
  getElementFromSelector,
  getTransitionDurationFromElement,
  triggerTransitionEnd,
  isElement,
  typeCheckConfig,
  isVisible,
  isDisabled,
  findShadowRoot,
  noop,
  getNextActiveElement,
  reflow,
  getjQuery,
  onDOMContentLoaded,
  isRTL,
  defineJQueryPlugin,
  execute,
  executeAfterTransition
}

```

C:\Users\Administrator\Desktop\Practice Coreui\coreui-main\js\src\dom\data.js

```
/**
 * --------------------------------------------------------------------------
 * CoreUI (v4.1.3): dom/data.js
 * Licensed under MIT (https://coreui.io/license)
 *
 * This component is a modified version of the Bootstrap's dom/data.js
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 * --------------------------------------------------------------------------
 */

/**
 * ------------------------------------------------------------------------
 * Constants
 * ------------------------------------------------------------------------
 */

const elementMap = new Map()

export default {
  set(element, key, instance) {
    if (!elementMap.has(element)) {
      elementMap.set(element, new Map())
    }

    const instanceMap = elementMap.get(element)

    // make it clear we only want one instance per element
    // can be removed later when multiple key/instances are fine to be used
    if (!instanceMap.has(key) && instanceMap.size !== 0) {
      // eslint-disable-next-line no-console
      console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`)
      return
    }

    instanceMap.set(key, instance)
  },

  get(element, key) {
    if (elementMap.has(element)) {
      return elementMap.get(element).get(key) || null
    }

    return null
  },

  remove(element, key) {
    if (!elementMap.has(element)) {
      return
    }

    const instanceMap = elementMap.get(element)

    instanceMap.delete(key)

    // free up element references if there are no instances left for an element
    if (instanceMap.size === 0) {
      elementMap.delete(element)
    }
  }
}

```

C:\Users\Administrator\Desktop\Practice Coreui\coreui-main\package.json

```
{
  "name": "@coreui/coreui",
  "description": "The most popular front-end framework for developing responsive, mobile-first projects on the web rewritten and maintain by the CoreUI Team",
  "version": "4.1.3",
  "config": {
    "version_short": "4.1"
  },
  "keywords": [
    "css",
    "sass",
    "mobile-first",
    "responsive",
    "front-end",
    "framework",
    "web"
  ],
  "homepage": "https://coreui.io",
  "author": "The CoreUI Team (https://github.com/orgs/coreui/people)",
  "scripts": {
    "start": "npm-run-all --parallel watch",
    "js": "npm-run-all js-compile js-minify",
    "js-compile": "npm-run-all --aggregate-output --parallel js-compile-*",
    "js-compile-standalone": "rollup --environment BUNDLE:false --config build/rollup.config.js --sourcemap",
    "js-compile-standalone-esm": "rollup --environment ESM:true,BUNDLE:false --config build/rollup.config.js --sourcemap",
    "js-compile-bundle": "rollup --environment BUNDLE:true --config build/rollup.config.js --sourcemap",
    "js-compile-plugins": "node build/build-plugins.js",
    "watch": "npm-run-all --parallel watch-*",
    "watch-js-main": "nodemon --watch js/src/ --ext js --exec \"npm-run-all js-compile\""
  },
  "style": "dist/css/coreui.css",
  "sass": "scss/coreui.scss",
  "main": "dist/js/coreui.js",
  "module": "dist/js/coreui.esm.js",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/coreui/coreui.git"
  },
  "bugs": {
    "url": "https://github.com/coreui/coreui/issues"
  },
  "license": "MIT",
  "peerDependencies": {
    "@popperjs/core": "^2.11.2"
  },
  "devDependencies": {
    "@babel/cli": "^7.17.6",
    "@babel/core": "^7.17.5",
    "@babel/preset-env": "^7.16.11",
    "@popperjs/core": "^2.11.2",
    "@rollup/plugin-babel": "^5.3.1",
    "@rollup/plugin-commonjs": "^21.0.2",
    "@rollup/plugin-node-resolve": "^13.1.3",
    "@rollup/plugin-replace": "^4.0.0",
    "auto-changelog": "^2.4.0",
    "autoprefixer": "^10.4.2",
    "bundlewatch": "^0.3.3",
    "clean-css-cli": "^5.5.2",
    "cross-env": "^7.0.3",
    "eslint": "^8.10.0",
    "eslint-config-xo": "^0.40.0",
    "eslint-plugin-import": "^2.25.4",
    "eslint-plugin-unicorn": "^41.0.0",
    "find-unused-sass-variables": "^4.0.3",
    "glob": "^7.2.0",
    "globby": "^11.0.4",
    "hammer-simulator": "0.0.1",
    "hugo-bin": "^0.81.1",
    "ip": "^1.1.5",
    "jquery": "^3.6.0",
    "linkinator": "^3.0.3",
    "lockfile-lint": "^4.6.2",
    "nodemon": "^2.0.15",
    "npm-run-all": "^4.1.5",
    "postcss": "^8.4.7",
    "postcss-cli": "^9.1.0",
    "postcss-combine-duplicated-selectors": "^10.0.3",
    "rollup": "^2.69.0",
    "rollup-plugin-istanbul": "^3.0.0",
    "rtlcss": "^3.5.0",
    "sass": "^1.49.9",
    "shelljs": "^0.8.5",
    "stylelint": "^14.5.3",
    "stylelint-config-twbs-bootstrap": "^3.0.1",
    "terser": "^5.12.0",
    "vnu-jar": "21.10.12"
  },
  "files": [
    "dist/{css,js}/*.{css,js,map}",
    "js/{src,dist}/**/*.{js,map}",
    "scss/**/*.scss"
  ],
  "hugo-bin": {
    "buildTags": "extended"
  },
  "jspm": {
    "registry": "npm",
    "main": "js/coreui",
    "directories": {
      "lib": "dist"
    },
    "shim": {
      "js/coreui": {
        "deps": [
          "@popperjs/core"
        ]
      }
    },
    "dependencies": {},
    "peerDependencies": {
      "@popperjs/core": "^2.11.2"
    }
  },
  "dependencies": {
    "@coreui/coreui": "^4.1.3"
  }
}

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://learncss.gitbook.io/cssadvand/su-dung-nodejs-va-js-cau-truc-thu-muc-tot-p.2-ok.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
