Dashboard sipadu mbip
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. /**
  2. * --------------------------------------------------------------------------
  3. * Bootstrap (v4.3.1): modal.js
  4. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  5. * --------------------------------------------------------------------------
  6. */
  7. import $ from 'jquery'
  8. import Util from './util'
  9. /**
  10. * ------------------------------------------------------------------------
  11. * Constants
  12. * ------------------------------------------------------------------------
  13. */
  14. const NAME = 'modal'
  15. const VERSION = '4.3.1'
  16. const DATA_KEY = 'bs.modal'
  17. const EVENT_KEY = `.${DATA_KEY}`
  18. const DATA_API_KEY = '.data-api'
  19. const JQUERY_NO_CONFLICT = $.fn[NAME]
  20. const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key
  21. const Default = {
  22. backdrop : true,
  23. keyboard : true,
  24. focus : true,
  25. show : true
  26. }
  27. const DefaultType = {
  28. backdrop : '(boolean|string)',
  29. keyboard : 'boolean',
  30. focus : 'boolean',
  31. show : 'boolean'
  32. }
  33. const Event = {
  34. HIDE : `hide${EVENT_KEY}`,
  35. HIDDEN : `hidden${EVENT_KEY}`,
  36. SHOW : `show${EVENT_KEY}`,
  37. SHOWN : `shown${EVENT_KEY}`,
  38. FOCUSIN : `focusin${EVENT_KEY}`,
  39. RESIZE : `resize${EVENT_KEY}`,
  40. CLICK_DISMISS : `click.dismiss${EVENT_KEY}`,
  41. KEYDOWN_DISMISS : `keydown.dismiss${EVENT_KEY}`,
  42. MOUSEUP_DISMISS : `mouseup.dismiss${EVENT_KEY}`,
  43. MOUSEDOWN_DISMISS : `mousedown.dismiss${EVENT_KEY}`,
  44. CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`
  45. }
  46. const ClassName = {
  47. SCROLLABLE : 'modal-dialog-scrollable',
  48. SCROLLBAR_MEASURER : 'modal-scrollbar-measure',
  49. BACKDROP : 'modal-backdrop',
  50. OPEN : 'modal-open',
  51. FADE : 'fade',
  52. SHOW : 'show'
  53. }
  54. const Selector = {
  55. DIALOG : '.modal-dialog',
  56. MODAL_BODY : '.modal-body',
  57. DATA_TOGGLE : '[data-toggle="modal"]',
  58. DATA_DISMISS : '[data-dismiss="modal"]',
  59. FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',
  60. STICKY_CONTENT : '.sticky-top'
  61. }
  62. /**
  63. * ------------------------------------------------------------------------
  64. * Class Definition
  65. * ------------------------------------------------------------------------
  66. */
  67. class Modal {
  68. constructor(element, config) {
  69. this._config = this._getConfig(config)
  70. this._element = element
  71. this._dialog = element.querySelector(Selector.DIALOG)
  72. this._backdrop = null
  73. this._isShown = false
  74. this._isBodyOverflowing = false
  75. this._ignoreBackdropClick = false
  76. this._isTransitioning = false
  77. this._scrollbarWidth = 0
  78. }
  79. // Getters
  80. static get VERSION() {
  81. return VERSION
  82. }
  83. static get Default() {
  84. return Default
  85. }
  86. // Public
  87. toggle(relatedTarget) {
  88. return this._isShown ? this.hide() : this.show(relatedTarget)
  89. }
  90. show(relatedTarget) {
  91. if (this._isShown || this._isTransitioning) {
  92. return
  93. }
  94. if ($(this._element).hasClass(ClassName.FADE)) {
  95. this._isTransitioning = true
  96. }
  97. const showEvent = $.Event(Event.SHOW, {
  98. relatedTarget
  99. })
  100. $(this._element).trigger(showEvent)
  101. if (this._isShown || showEvent.isDefaultPrevented()) {
  102. return
  103. }
  104. this._isShown = true
  105. this._checkScrollbar()
  106. this._setScrollbar()
  107. this._adjustDialog()
  108. this._setEscapeEvent()
  109. this._setResizeEvent()
  110. $(this._element).on(
  111. Event.CLICK_DISMISS,
  112. Selector.DATA_DISMISS,
  113. (event) => this.hide(event)
  114. )
  115. $(this._dialog).on(Event.MOUSEDOWN_DISMISS, () => {
  116. $(this._element).one(Event.MOUSEUP_DISMISS, (event) => {
  117. if ($(event.target).is(this._element)) {
  118. this._ignoreBackdropClick = true
  119. }
  120. })
  121. })
  122. this._showBackdrop(() => this._showElement(relatedTarget))
  123. }
  124. hide(event) {
  125. if (event) {
  126. event.preventDefault()
  127. }
  128. if (!this._isShown || this._isTransitioning) {
  129. return
  130. }
  131. const hideEvent = $.Event(Event.HIDE)
  132. $(this._element).trigger(hideEvent)
  133. if (!this._isShown || hideEvent.isDefaultPrevented()) {
  134. return
  135. }
  136. this._isShown = false
  137. const transition = $(this._element).hasClass(ClassName.FADE)
  138. if (transition) {
  139. this._isTransitioning = true
  140. }
  141. this._setEscapeEvent()
  142. this._setResizeEvent()
  143. $(document).off(Event.FOCUSIN)
  144. $(this._element).removeClass(ClassName.SHOW)
  145. $(this._element).off(Event.CLICK_DISMISS)
  146. $(this._dialog).off(Event.MOUSEDOWN_DISMISS)
  147. if (transition) {
  148. const transitionDuration = Util.getTransitionDurationFromElement(this._element)
  149. $(this._element)
  150. .one(Util.TRANSITION_END, (event) => this._hideModal(event))
  151. .emulateTransitionEnd(transitionDuration)
  152. } else {
  153. this._hideModal()
  154. }
  155. }
  156. dispose() {
  157. [window, this._element, this._dialog]
  158. .forEach((htmlElement) => $(htmlElement).off(EVENT_KEY))
  159. /**
  160. * `document` has 2 events `Event.FOCUSIN` and `Event.CLICK_DATA_API`
  161. * Do not move `document` in `htmlElements` array
  162. * It will remove `Event.CLICK_DATA_API` event that should remain
  163. */
  164. $(document).off(Event.FOCUSIN)
  165. $.removeData(this._element, DATA_KEY)
  166. this._config = null
  167. this._element = null
  168. this._dialog = null
  169. this._backdrop = null
  170. this._isShown = null
  171. this._isBodyOverflowing = null
  172. this._ignoreBackdropClick = null
  173. this._isTransitioning = null
  174. this._scrollbarWidth = null
  175. }
  176. handleUpdate() {
  177. this._adjustDialog()
  178. }
  179. // Private
  180. _getConfig(config) {
  181. config = {
  182. ...Default,
  183. ...config
  184. }
  185. Util.typeCheckConfig(NAME, config, DefaultType)
  186. return config
  187. }
  188. _showElement(relatedTarget) {
  189. const transition = $(this._element).hasClass(ClassName.FADE)
  190. if (!this._element.parentNode ||
  191. this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
  192. // Don't move modal's DOM position
  193. document.body.appendChild(this._element)
  194. }
  195. this._element.style.display = 'block'
  196. this._element.removeAttribute('aria-hidden')
  197. this._element.setAttribute('aria-modal', true)
  198. if ($(this._dialog).hasClass(ClassName.SCROLLABLE)) {
  199. this._dialog.querySelector(Selector.MODAL_BODY).scrollTop = 0
  200. } else {
  201. this._element.scrollTop = 0
  202. }
  203. if (transition) {
  204. Util.reflow(this._element)
  205. }
  206. $(this._element).addClass(ClassName.SHOW)
  207. if (this._config.focus) {
  208. this._enforceFocus()
  209. }
  210. const shownEvent = $.Event(Event.SHOWN, {
  211. relatedTarget
  212. })
  213. const transitionComplete = () => {
  214. if (this._config.focus) {
  215. this._element.focus()
  216. }
  217. this._isTransitioning = false
  218. $(this._element).trigger(shownEvent)
  219. }
  220. if (transition) {
  221. const transitionDuration = Util.getTransitionDurationFromElement(this._dialog)
  222. $(this._dialog)
  223. .one(Util.TRANSITION_END, transitionComplete)
  224. .emulateTransitionEnd(transitionDuration)
  225. } else {
  226. transitionComplete()
  227. }
  228. }
  229. _enforceFocus() {
  230. $(document)
  231. .off(Event.FOCUSIN) // Guard against infinite focus loop
  232. .on(Event.FOCUSIN, (event) => {
  233. if (document !== event.target &&
  234. this._element !== event.target &&
  235. $(this._element).has(event.target).length === 0) {
  236. this._element.focus()
  237. }
  238. })
  239. }
  240. _setEscapeEvent() {
  241. if (this._isShown && this._config.keyboard) {
  242. $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {
  243. if (event.which === ESCAPE_KEYCODE) {
  244. event.preventDefault()
  245. this.hide()
  246. }
  247. })
  248. } else if (!this._isShown) {
  249. $(this._element).off(Event.KEYDOWN_DISMISS)
  250. }
  251. }
  252. _setResizeEvent() {
  253. if (this._isShown) {
  254. $(window).on(Event.RESIZE, (event) => this.handleUpdate(event))
  255. } else {
  256. $(window).off(Event.RESIZE)
  257. }
  258. }
  259. _hideModal() {
  260. this._element.style.display = 'none'
  261. this._element.setAttribute('aria-hidden', true)
  262. this._element.removeAttribute('aria-modal')
  263. this._isTransitioning = false
  264. this._showBackdrop(() => {
  265. $(document.body).removeClass(ClassName.OPEN)
  266. this._resetAdjustments()
  267. this._resetScrollbar()
  268. $(this._element).trigger(Event.HIDDEN)
  269. })
  270. }
  271. _removeBackdrop() {
  272. if (this._backdrop) {
  273. $(this._backdrop).remove()
  274. this._backdrop = null
  275. }
  276. }
  277. _showBackdrop(callback) {
  278. const animate = $(this._element).hasClass(ClassName.FADE)
  279. ? ClassName.FADE : ''
  280. if (this._isShown && this._config.backdrop) {
  281. this._backdrop = document.createElement('div')
  282. this._backdrop.className = ClassName.BACKDROP
  283. if (animate) {
  284. this._backdrop.classList.add(animate)
  285. }
  286. $(this._backdrop).appendTo(document.body)
  287. $(this._element).on(Event.CLICK_DISMISS, (event) => {
  288. if (this._ignoreBackdropClick) {
  289. this._ignoreBackdropClick = false
  290. return
  291. }
  292. if (event.target !== event.currentTarget) {
  293. return
  294. }
  295. if (this._config.backdrop === 'static') {
  296. this._element.focus()
  297. } else {
  298. this.hide()
  299. }
  300. })
  301. if (animate) {
  302. Util.reflow(this._backdrop)
  303. }
  304. $(this._backdrop).addClass(ClassName.SHOW)
  305. if (!callback) {
  306. return
  307. }
  308. if (!animate) {
  309. callback()
  310. return
  311. }
  312. const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)
  313. $(this._backdrop)
  314. .one(Util.TRANSITION_END, callback)
  315. .emulateTransitionEnd(backdropTransitionDuration)
  316. } else if (!this._isShown && this._backdrop) {
  317. $(this._backdrop).removeClass(ClassName.SHOW)
  318. const callbackRemove = () => {
  319. this._removeBackdrop()
  320. if (callback) {
  321. callback()
  322. }
  323. }
  324. if ($(this._element).hasClass(ClassName.FADE)) {
  325. const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)
  326. $(this._backdrop)
  327. .one(Util.TRANSITION_END, callbackRemove)
  328. .emulateTransitionEnd(backdropTransitionDuration)
  329. } else {
  330. callbackRemove()
  331. }
  332. } else if (callback) {
  333. callback()
  334. }
  335. }
  336. // ----------------------------------------------------------------------
  337. // the following methods are used to handle overflowing modals
  338. // todo (fat): these should probably be refactored out of modal.js
  339. // ----------------------------------------------------------------------
  340. _adjustDialog() {
  341. const isModalOverflowing =
  342. this._element.scrollHeight > document.documentElement.clientHeight
  343. if (!this._isBodyOverflowing && isModalOverflowing) {
  344. this._element.style.paddingLeft = `${this._scrollbarWidth}px`
  345. }
  346. if (this._isBodyOverflowing && !isModalOverflowing) {
  347. this._element.style.paddingRight = `${this._scrollbarWidth}px`
  348. }
  349. }
  350. _resetAdjustments() {
  351. this._element.style.paddingLeft = ''
  352. this._element.style.paddingRight = ''
  353. }
  354. _checkScrollbar() {
  355. const rect = document.body.getBoundingClientRect()
  356. this._isBodyOverflowing = rect.left + rect.right < window.innerWidth
  357. this._scrollbarWidth = this._getScrollbarWidth()
  358. }
  359. _setScrollbar() {
  360. if (this._isBodyOverflowing) {
  361. // Note: DOMNode.style.paddingRight returns the actual value or '' if not set
  362. // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set
  363. const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))
  364. const stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT))
  365. // Adjust fixed content padding
  366. $(fixedContent).each((index, element) => {
  367. const actualPadding = element.style.paddingRight
  368. const calculatedPadding = $(element).css('padding-right')
  369. $(element)
  370. .data('padding-right', actualPadding)
  371. .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)
  372. })
  373. // Adjust sticky content margin
  374. $(stickyContent).each((index, element) => {
  375. const actualMargin = element.style.marginRight
  376. const calculatedMargin = $(element).css('margin-right')
  377. $(element)
  378. .data('margin-right', actualMargin)
  379. .css('margin-right', `${parseFloat(calculatedMargin) - this._scrollbarWidth}px`)
  380. })
  381. // Adjust body padding
  382. const actualPadding = document.body.style.paddingRight
  383. const calculatedPadding = $(document.body).css('padding-right')
  384. $(document.body)
  385. .data('padding-right', actualPadding)
  386. .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)
  387. }
  388. $(document.body).addClass(ClassName.OPEN)
  389. }
  390. _resetScrollbar() {
  391. // Restore fixed content padding
  392. const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))
  393. $(fixedContent).each((index, element) => {
  394. const padding = $(element).data('padding-right')
  395. $(element).removeData('padding-right')
  396. element.style.paddingRight = padding ? padding : ''
  397. })
  398. // Restore sticky content
  399. const elements = [].slice.call(document.querySelectorAll(`${Selector.STICKY_CONTENT}`))
  400. $(elements).each((index, element) => {
  401. const margin = $(element).data('margin-right')
  402. if (typeof margin !== 'undefined') {
  403. $(element).css('margin-right', margin).removeData('margin-right')
  404. }
  405. })
  406. // Restore body padding
  407. const padding = $(document.body).data('padding-right')
  408. $(document.body).removeData('padding-right')
  409. document.body.style.paddingRight = padding ? padding : ''
  410. }
  411. _getScrollbarWidth() { // thx d.walsh
  412. const scrollDiv = document.createElement('div')
  413. scrollDiv.className = ClassName.SCROLLBAR_MEASURER
  414. document.body.appendChild(scrollDiv)
  415. const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth
  416. document.body.removeChild(scrollDiv)
  417. return scrollbarWidth
  418. }
  419. // Static
  420. static _jQueryInterface(config, relatedTarget) {
  421. return this.each(function () {
  422. let data = $(this).data(DATA_KEY)
  423. const _config = {
  424. ...Default,
  425. ...$(this).data(),
  426. ...typeof config === 'object' && config ? config : {}
  427. }
  428. if (!data) {
  429. data = new Modal(this, _config)
  430. $(this).data(DATA_KEY, data)
  431. }
  432. if (typeof config === 'string') {
  433. if (typeof data[config] === 'undefined') {
  434. throw new TypeError(`No method named "${config}"`)
  435. }
  436. data[config](relatedTarget)
  437. } else if (_config.show) {
  438. data.show(relatedTarget)
  439. }
  440. })
  441. }
  442. }
  443. /**
  444. * ------------------------------------------------------------------------
  445. * Data Api implementation
  446. * ------------------------------------------------------------------------
  447. */
  448. $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
  449. let target
  450. const selector = Util.getSelectorFromElement(this)
  451. if (selector) {
  452. target = document.querySelector(selector)
  453. }
  454. const config = $(target).data(DATA_KEY)
  455. ? 'toggle' : {
  456. ...$(target).data(),
  457. ...$(this).data()
  458. }
  459. if (this.tagName === 'A' || this.tagName === 'AREA') {
  460. event.preventDefault()
  461. }
  462. const $target = $(target).one(Event.SHOW, (showEvent) => {
  463. if (showEvent.isDefaultPrevented()) {
  464. // Only register focus restorer if modal will actually get shown
  465. return
  466. }
  467. $target.one(Event.HIDDEN, () => {
  468. if ($(this).is(':visible')) {
  469. this.focus()
  470. }
  471. })
  472. })
  473. Modal._jQueryInterface.call($(target), config, this)
  474. })
  475. /**
  476. * ------------------------------------------------------------------------
  477. * jQuery
  478. * ------------------------------------------------------------------------
  479. */
  480. $.fn[NAME] = Modal._jQueryInterface
  481. $.fn[NAME].Constructor = Modal
  482. $.fn[NAME].noConflict = () => {
  483. $.fn[NAME] = JQUERY_NO_CONFLICT
  484. return Modal._jQueryInterface
  485. }
  486. export default Modal