IFrame.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /**
  2. * --------------------------------------------
  3. * AdminLTE IFrame.js
  4. * License MIT
  5. * --------------------------------------------
  6. */
  7. import $ from 'jquery'
  8. /**
  9. * Constants
  10. * ====================================================
  11. */
  12. const NAME = 'IFrame'
  13. const DATA_KEY = 'lte.iframe'
  14. const JQUERY_NO_CONFLICT = $.fn[NAME]
  15. const SELECTOR_DATA_TOGGLE = '[data-widget="iframe"]'
  16. const SELECTOR_DATA_TOGGLE_CLOSE = '[data-widget="iframe-close"]'
  17. const SELECTOR_CONTENT_WRAPPER = '.content-wrapper'
  18. const SELECTOR_CONTENT_IFRAME = `${SELECTOR_CONTENT_WRAPPER} iframe`
  19. const SELECTOR_TAB_NAV = `${SELECTOR_DATA_TOGGLE}.iframe-mode .nav`
  20. const SELECTOR_TAB_NAVBAR_NAV = `${SELECTOR_DATA_TOGGLE}.iframe-mode .navbar-nav`
  21. const SELECTOR_TAB_NAVBAR_NAV_ITEM = `${SELECTOR_TAB_NAVBAR_NAV} .nav-item`
  22. const SELECTOR_TAB_CONTENT = `${SELECTOR_DATA_TOGGLE}.iframe-mode .tab-content`
  23. const SELECTOR_TAB_EMPTY = `${SELECTOR_TAB_CONTENT} .tab-empty`
  24. const SELECTOR_TAB_LOADING = `${SELECTOR_TAB_CONTENT} .tab-loading`
  25. const SELECTOR_SIDEBAR_MENU_ITEM = '.main-sidebar .nav-item > a.nav-link'
  26. const SELECTOR_HEADER_MENU_ITEM = '.main-header .nav-item a.nav-link'
  27. const SELECTOR_HEADER_DROPDOWN_ITEM = '.main-header a.dropdown-item'
  28. const CLASS_NAME_IFRAME_MODE = 'iframe-mode'
  29. const Default = {
  30. onTabClick(item) {
  31. return item
  32. },
  33. onTabChanged(item) {
  34. return item
  35. },
  36. onTabCreated(item) {
  37. return item
  38. },
  39. autoIframeMode: true,
  40. autoItemActive: true,
  41. autoShowNewTab: true,
  42. loadingScreen: true,
  43. useNavbarItems: true
  44. }
  45. /**
  46. * Class Definition
  47. * ====================================================
  48. */
  49. class IFrame {
  50. constructor(element, config) {
  51. this._config = config
  52. this._element = element
  53. this._init()
  54. }
  55. // Public
  56. onTabClick(item) {
  57. this._config.onTabClick(item)
  58. }
  59. onTabChanged(item) {
  60. this._config.onTabChanged(item)
  61. }
  62. onTabCreated(item) {
  63. this._config.onTabCreated(item)
  64. }
  65. createTab(title, link, uniqueName, autoOpen) {
  66. const tabId = `panel-${uniqueName}-${Math.floor(Math.random() * 1000)}`
  67. const navId = `tab-${uniqueName}-${Math.floor(Math.random() * 1000)}`
  68. const newNavItem = `<li class="nav-item" role="presentation"><a class="nav-link" data-toggle="row" id="${navId}" href="#${tabId}" role="tab" aria-controls="${tabId}" aria-selected="false">${title}</a></li>`
  69. $(SELECTOR_TAB_NAVBAR_NAV).append(newNavItem)
  70. const newTabItem = `<div class="tab-pane fade" id="${tabId}" role="tabpanel" aria-labelledby="${navId}"><iframe src="${link}"></iframe></div>`
  71. $(SELECTOR_TAB_CONTENT).append(newTabItem)
  72. if (autoOpen) {
  73. if (this._config.loadingScreen) {
  74. const $loadingScreen = $(SELECTOR_TAB_LOADING)
  75. $loadingScreen.fadeIn()
  76. $(`${tabId} iframe`).ready(() => {
  77. if (typeof this._config.loadingScreen === 'number') {
  78. this.switchTab(`#${navId}`, this._config.loadingScreen)
  79. setTimeout(() => {
  80. $loadingScreen.fadeOut()
  81. }, this._config.loadingScreen)
  82. } else {
  83. this.switchTab(`#${navId}`, this._config.loadingScreen)
  84. $loadingScreen.fadeOut()
  85. }
  86. })
  87. } else {
  88. this.switchTab(`#${navId}`)
  89. }
  90. }
  91. this.onTabCreated($(`#${navId}`))
  92. }
  93. openTabSidebar(item, autoOpen = this._config.autoShowNewTab) {
  94. let $item = $(item).clone()
  95. if ($item.attr('href') === undefined) {
  96. $item = $(item).parent('a').clone()
  97. }
  98. $item.find('.right').remove()
  99. let title = $item.find('p').text()
  100. if (title === '') {
  101. title = $item.text()
  102. }
  103. const link = $item.attr('href')
  104. if (link === '#' || link === '' || link === undefined) {
  105. return
  106. }
  107. this.createTab(title, link, link.replace('.html', '').replace('./', '').replaceAll('/', '-'), autoOpen)
  108. }
  109. switchTab(item) {
  110. const $item = $(item)
  111. const tabId = $item.attr('href')
  112. $(SELECTOR_TAB_EMPTY).hide()
  113. $(`${SELECTOR_TAB_NAVBAR_NAV} .active`).tab('dispose').removeClass('active')
  114. this._fixHeight()
  115. $item.tab('show')
  116. $item.parents('li').addClass('active')
  117. this.onTabChanged($item)
  118. if (this._config.autoItemActive) {
  119. this._setItemActive($(`${tabId} iframe`).attr('src'))
  120. }
  121. }
  122. removeActiveTab() {
  123. $(`${SELECTOR_TAB_NAVBAR_NAV_ITEM}.active`).parent().remove()
  124. $('.tab-pane.active').remove()
  125. if ($(SELECTOR_TAB_CONTENT).children().length == $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).length) {
  126. $(SELECTOR_TAB_EMPTY).show()
  127. }
  128. }
  129. // Private
  130. _init() {
  131. if (window.frameElement && this._config.autoIframeMode) {
  132. $('body').addClass(CLASS_NAME_IFRAME_MODE)
  133. } else if ($(SELECTOR_CONTENT_WRAPPER).hasClass(CLASS_NAME_IFRAME_MODE)) {
  134. this._setupListeners()
  135. this._fixHeight(true)
  136. }
  137. }
  138. _setupListeners() {
  139. $(window).on('resize', () => {
  140. setTimeout(() => {
  141. this._fixHeight()
  142. }, 1)
  143. })
  144. $(document).on('click', SELECTOR_SIDEBAR_MENU_ITEM, e => {
  145. e.preventDefault()
  146. this.openTabSidebar(e.target)
  147. })
  148. if (this._config.useNavbarItems) {
  149. $(document).on('click', `${SELECTOR_HEADER_MENU_ITEM}, ${SELECTOR_HEADER_DROPDOWN_ITEM}`, e => {
  150. e.preventDefault()
  151. this.openTabSidebar(e.target)
  152. })
  153. }
  154. $(document).on('click', SELECTOR_TAB_NAVBAR_NAV_ITEM, e => {
  155. e.preventDefault()
  156. this.onTabClick(e.target)
  157. this.switchTab(e.target)
  158. })
  159. $(document).on('click', SELECTOR_DATA_TOGGLE_CLOSE, e => {
  160. e.preventDefault()
  161. this.removeActiveTab()
  162. })
  163. }
  164. _setItemActive(href) {
  165. $(`${SELECTOR_SIDEBAR_MENU_ITEM}, ${SELECTOR_HEADER_DROPDOWN_ITEM}`).removeClass('active')
  166. $(SELECTOR_HEADER_MENU_ITEM).parent().removeClass('active')
  167. const $headerMenuItem = $(`${SELECTOR_HEADER_MENU_ITEM}[href$="${href}"]`)
  168. const $headerDropdownItem = $(`${SELECTOR_HEADER_DROPDOWN_ITEM}[href$="${href}"]`)
  169. const $sidebarMenuItem = $(`${SELECTOR_SIDEBAR_MENU_ITEM}[href$="${href}"]`)
  170. $headerMenuItem.each((i, e) => {
  171. $(e).parent().addClass('active')
  172. })
  173. $headerDropdownItem.each((i, e) => {
  174. $(e).addClass('active')
  175. })
  176. $sidebarMenuItem.each((i, e) => {
  177. $(e).addClass('active')
  178. $(e).parents('.nav-treeview').prevAll('.nav-link').addClass('active')
  179. })
  180. }
  181. _fixHeight(tabEmpty = false) {
  182. const contentWrapperHeight = parseFloat($(SELECTOR_CONTENT_WRAPPER).css('min-height'))
  183. const navbarHeight = $(SELECTOR_TAB_NAV).outerHeight()
  184. if (tabEmpty == true) {
  185. setTimeout(() => {
  186. $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).height(contentWrapperHeight - navbarHeight)
  187. }, 50)
  188. } else {
  189. $(SELECTOR_CONTENT_IFRAME).height(contentWrapperHeight - navbarHeight)
  190. }
  191. }
  192. // Static
  193. static _jQueryInterface(operation, ...args) {
  194. let data = $(this).data(DATA_KEY)
  195. const _options = $.extend({}, Default, $(this).data())
  196. if (!data) {
  197. data = new IFrame(this, _options)
  198. $(this).data(DATA_KEY, data)
  199. }
  200. if (typeof operation === 'string' && operation.match(/createTab|openTabSidebar|switchTab|removeActiveTab/)) {
  201. data[operation](...args)
  202. }
  203. }
  204. }
  205. /**
  206. * Data API
  207. * ====================================================
  208. */
  209. $(window).on('load', () => {
  210. IFrame._jQueryInterface.call($(SELECTOR_DATA_TOGGLE))
  211. })
  212. /**
  213. * jQuery API
  214. * ====================================================
  215. */
  216. $.fn[NAME] = IFrame._jQueryInterface
  217. $.fn[NAME].Constructor = IFrame
  218. $.fn[NAME].noConflict = function () {
  219. $.fn[NAME] = JQUERY_NO_CONFLICT
  220. return IFrame._jQueryInterface
  221. }
  222. export default IFrame