bootstrap-table-cookie.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. /**
  2. * @author: Dennis Hernández
  3. * @webSite: http://djhvscf.github.io/Blog
  4. * @update zhixin wen <wenzhixin2010@gmail.com>
  5. */
  6. const Utils = $.fn.bootstrapTable.utils
  7. const UtilsCookie = {
  8. cookieIds: {
  9. sortOrder: 'bs.table.sortOrder',
  10. sortName: 'bs.table.sortName',
  11. sortPriority: 'bs.table.sortPriority',
  12. pageNumber: 'bs.table.pageNumber',
  13. pageList: 'bs.table.pageList',
  14. columns: 'bs.table.columns',
  15. searchText: 'bs.table.searchText',
  16. reorderColumns: 'bs.table.reorderColumns',
  17. filterControl: 'bs.table.filterControl',
  18. filterBy: 'bs.table.filterBy'
  19. },
  20. getCurrentHeader (that) {
  21. let header = that.$header
  22. if (that.options.height) {
  23. header = that.$tableHeader
  24. }
  25. return header
  26. },
  27. getCurrentSearchControls (that) {
  28. let searchControls = 'select, input'
  29. if (that.options.height) {
  30. searchControls = 'table select, table input'
  31. }
  32. return searchControls
  33. },
  34. cookieEnabled () {
  35. return !!(navigator.cookieEnabled)
  36. },
  37. inArrayCookiesEnabled (cookieName, cookiesEnabled) {
  38. let index = -1
  39. for (let i = 0; i < cookiesEnabled.length; i++) {
  40. if (cookieName.toLowerCase() === cookiesEnabled[i].toLowerCase()) {
  41. index = i
  42. break
  43. }
  44. }
  45. return index
  46. },
  47. setCookie (that, cookieName, cookieValue) {
  48. if ((!that.options.cookie) || (!UtilsCookie.cookieEnabled()) || (that.options.cookieIdTable === '')) {
  49. return
  50. }
  51. if (UtilsCookie.inArrayCookiesEnabled(cookieName, that.options.cookiesEnabled) === -1) {
  52. return
  53. }
  54. cookieName = `${that.options.cookieIdTable}.${cookieName}`
  55. switch (that.options.cookieStorage) {
  56. case 'cookieStorage':
  57. document.cookie = [
  58. cookieName, '=', encodeURIComponent(cookieValue),
  59. `; expires=${UtilsCookie.calculateExpiration(that.options.cookieExpire)}`,
  60. that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
  61. that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '',
  62. that.options.cookieSecure ? '; secure' : '',
  63. `;SameSite=${ that.options.cookieSameSite}`
  64. ].join('')
  65. break
  66. case 'localStorage':
  67. localStorage.setItem(cookieName, cookieValue)
  68. break
  69. case 'sessionStorage':
  70. sessionStorage.setItem(cookieName, cookieValue)
  71. break
  72. case 'customStorage':
  73. if (
  74. !that.options.cookieCustomStorageSet ||
  75. !that.options.cookieCustomStorageGet ||
  76. !that.options.cookieCustomStorageDelete
  77. ) {
  78. throw new Error('The following options must be set while using the customStorage: cookieCustomStorageSet, cookieCustomStorageGet and cookieCustomStorageDelete')
  79. }
  80. Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageSet, [cookieName, cookieValue], '')
  81. break
  82. default:
  83. return false
  84. }
  85. return true
  86. },
  87. getCookie (that, tableName, cookieName) {
  88. if (!cookieName) {
  89. return null
  90. }
  91. if (UtilsCookie.inArrayCookiesEnabled(cookieName, that.options.cookiesEnabled) === -1) {
  92. return null
  93. }
  94. cookieName = `${tableName}.${cookieName}`
  95. switch (that.options.cookieStorage) {
  96. case 'cookieStorage':
  97. const value = `; ${document.cookie}`
  98. const parts = value.split(`; ${cookieName}=`)
  99. return parts.length === 2 ? decodeURIComponent(parts.pop().split(';').shift()) : null
  100. case 'localStorage':
  101. return localStorage.getItem(cookieName)
  102. case 'sessionStorage':
  103. return sessionStorage.getItem(cookieName)
  104. case 'customStorage':
  105. if (
  106. !that.options.cookieCustomStorageSet ||
  107. !that.options.cookieCustomStorageGet ||
  108. !that.options.cookieCustomStorageDelete
  109. ) {
  110. throw new Error('The following options must be set while using the customStorage: cookieCustomStorageSet, cookieCustomStorageGet and cookieCustomStorageDelete')
  111. }
  112. return Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageGet, [cookieName], '')
  113. default:
  114. return null
  115. }
  116. },
  117. deleteCookie (that, tableName, cookieName) {
  118. cookieName = `${tableName}.${cookieName}`
  119. switch (that.options.cookieStorage) {
  120. case 'cookieStorage':
  121. document.cookie = [
  122. encodeURIComponent(cookieName), '=',
  123. '; expires=Thu, 01 Jan 1970 00:00:00 GMT',
  124. that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
  125. that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '',
  126. `;SameSite=${ that.options.cookieSameSite}`
  127. ].join('')
  128. break
  129. case 'localStorage':
  130. localStorage.removeItem(cookieName)
  131. break
  132. case 'sessionStorage':
  133. sessionStorage.removeItem(cookieName)
  134. break
  135. case 'customStorage':
  136. if (
  137. !that.options.cookieCustomStorageSet ||
  138. !that.options.cookieCustomStorageGet ||
  139. !that.options.cookieCustomStorageDelete
  140. ) {
  141. throw new Error('The following options must be set while using the customStorage: cookieCustomStorageSet, cookieCustomStorageGet and cookieCustomStorageDelete')
  142. }
  143. Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageDelete, [cookieName], '')
  144. break
  145. default:
  146. return false
  147. }
  148. return true
  149. },
  150. calculateExpiration (cookieExpire) {
  151. const time = cookieExpire.replace(/[0-9]*/, '') // s,mi,h,d,m,y
  152. cookieExpire = cookieExpire.replace(/[A-Za-z]{1,2}/, '') // number
  153. switch (time.toLowerCase()) {
  154. case 's':
  155. cookieExpire = +cookieExpire
  156. break
  157. case 'mi':
  158. cookieExpire *= 60
  159. break
  160. case 'h':
  161. cookieExpire = cookieExpire * 60 * 60
  162. break
  163. case 'd':
  164. cookieExpire = cookieExpire * 24 * 60 * 60
  165. break
  166. case 'm':
  167. cookieExpire = cookieExpire * 30 * 24 * 60 * 60
  168. break
  169. case 'y':
  170. cookieExpire = cookieExpire * 365 * 24 * 60 * 60
  171. break
  172. default:
  173. cookieExpire = undefined
  174. break
  175. }
  176. if (!cookieExpire) {
  177. return ''
  178. }
  179. const d = new Date()
  180. d.setTime(d.getTime() + cookieExpire * 1000)
  181. return d.toGMTString()
  182. },
  183. initCookieFilters (bootstrapTable) {
  184. setTimeout(() => {
  185. const parsedCookieFilters = JSON.parse(UtilsCookie.getCookie(bootstrapTable, bootstrapTable.options.cookieIdTable, UtilsCookie.cookieIds.filterControl))
  186. if (!bootstrapTable.options.filterControlValuesLoaded && parsedCookieFilters) {
  187. const cachedFilters = {}
  188. const header = UtilsCookie.getCurrentHeader(bootstrapTable)
  189. const searchControls = UtilsCookie.getCurrentSearchControls(bootstrapTable)
  190. const applyCookieFilters = (element, filteredCookies) => {
  191. filteredCookies.forEach(cookie => {
  192. if (cookie.text === '' || (element.type === 'radio' && element.value.toString() !== cookie.text.toString())) {
  193. return
  194. }
  195. if (element.tagName === 'INPUT' && element.type === 'radio' && element.value.toString() === cookie.text.toString()) {
  196. element.checked = true
  197. cachedFilters[cookie.field] = cookie.text
  198. } else if (element.tagName === 'INPUT') {
  199. element.value = cookie.text
  200. cachedFilters[cookie.field] = cookie.text
  201. } else if (element.tagName === 'SELECT' && bootstrapTable.options.filterControlContainer) {
  202. element.value = cookie.text
  203. cachedFilters[cookie.field] = cookie.text
  204. } else if (cookie.text !== '' && element.tagName === 'SELECT') {
  205. for (let i = 0; i < element.length; i++) {
  206. const currentElement = element[i]
  207. if (currentElement.value === cookie.text) {
  208. currentElement.selected = true
  209. return
  210. }
  211. }
  212. const option = document.createElement('option')
  213. option.value = cookie.text
  214. option.text = cookie.text
  215. element.add(option, element[1])
  216. element.selectedIndex = 1
  217. cachedFilters[cookie.field] = cookie.text
  218. }
  219. })
  220. }
  221. let filterContainer = header
  222. if (bootstrapTable.options.filterControlContainer) {
  223. filterContainer = $(`${bootstrapTable.options.filterControlContainer}`)
  224. }
  225. filterContainer.find(searchControls).each(function () {
  226. const field = $(this).closest('[data-field]').data('field')
  227. const filteredCookies = parsedCookieFilters.filter(cookie => cookie.field === field)
  228. applyCookieFilters(this, filteredCookies)
  229. })
  230. bootstrapTable.initColumnSearch(cachedFilters)
  231. bootstrapTable.options.filterControlValuesLoaded = true
  232. bootstrapTable.initServer()
  233. }
  234. }, 250)
  235. }
  236. }
  237. $.extend($.fn.bootstrapTable.defaults, {
  238. cookie: false,
  239. cookieExpire: '2h',
  240. cookiePath: null,
  241. cookieDomain: null,
  242. cookieSecure: null,
  243. cookieSameSite: 'Lax',
  244. cookieIdTable: '',
  245. cookiesEnabled: [
  246. 'bs.table.sortOrder', 'bs.table.sortName', 'bs.table.sortPriority',
  247. 'bs.table.pageNumber', 'bs.table.pageList',
  248. 'bs.table.columns', 'bs.table.searchText',
  249. 'bs.table.filterControl', 'bs.table.filterBy',
  250. 'bs.table.reorderColumns'
  251. ],
  252. cookieStorage: 'cookieStorage', // localStorage, sessionStorage, customStorage
  253. cookieCustomStorageGet: null,
  254. cookieCustomStorageSet: null,
  255. cookieCustomStorageDelete: null,
  256. // internal variable
  257. filterControls: [],
  258. filterControlValuesLoaded: false
  259. })
  260. $.fn.bootstrapTable.methods.push('getCookies')
  261. $.fn.bootstrapTable.methods.push('deleteCookie')
  262. $.extend($.fn.bootstrapTable.utils, {
  263. setCookie: UtilsCookie.setCookie,
  264. getCookie: UtilsCookie.getCookie
  265. })
  266. $.BootstrapTable = class extends $.BootstrapTable {
  267. init () {
  268. if (this.options.cookie) {
  269. // FilterBy logic
  270. const filterByCookieValue = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.filterBy)
  271. if (typeof filterByCookieValue === 'boolean' && !filterByCookieValue) {
  272. throw new Error('The cookie value of filterBy must be a json!')
  273. }
  274. let filterByCookie = {}
  275. try {
  276. filterByCookie = JSON.parse(filterByCookieValue)
  277. } catch (e) {
  278. throw new Error('Could not parse the json of the filterBy cookie!')
  279. }
  280. this.filterColumns = filterByCookie ? filterByCookie : {}
  281. // FilterControl logic
  282. this.options.filterControls = []
  283. this.options.filterControlValuesLoaded = false
  284. this.options.cookiesEnabled = typeof this.options.cookiesEnabled === 'string' ?
  285. this.options.cookiesEnabled.replace('[', '').replace(']', '')
  286. .replace(/'/g, '').replace(/ /g, '').toLowerCase().split(',') :
  287. this.options.cookiesEnabled
  288. if (this.options.filterControl) {
  289. const that = this
  290. this.$el.on('column-search.bs.table', (e, field, text) => {
  291. let isNewField = true
  292. for (let i = 0; i < that.options.filterControls.length; i++) {
  293. if (that.options.filterControls[i].field === field) {
  294. that.options.filterControls[i].text = text
  295. isNewField = false
  296. break
  297. }
  298. }
  299. if (isNewField) {
  300. that.options.filterControls.push({
  301. field,
  302. text
  303. })
  304. }
  305. UtilsCookie.setCookie(that, UtilsCookie.cookieIds.filterControl, JSON.stringify(that.options.filterControls))
  306. }).on('created-controls.bs.table', UtilsCookie.initCookieFilters(that))
  307. }
  308. }
  309. super.init()
  310. }
  311. initServer (...args) {
  312. if (
  313. this.options.cookie &&
  314. this.options.filterControl &&
  315. !this.options.filterControlValuesLoaded
  316. ) {
  317. const cookie = JSON.parse(UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.filterControl))
  318. if (cookie) {
  319. return
  320. }
  321. }
  322. super.initServer(...args)
  323. }
  324. initTable (...args) {
  325. super.initTable(...args)
  326. this.initCookie()
  327. }
  328. onSort (...args) {
  329. super.onSort(...args)
  330. if (this.options.sortName === undefined || this.options.sortOrder === undefined) {
  331. UtilsCookie.deleteCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.sortName)
  332. UtilsCookie.deleteCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.sortOrder)
  333. return
  334. } else {
  335. this.options.sortPriority = undefined
  336. UtilsCookie.deleteCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.sortPriority)
  337. }
  338. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortOrder, this.options.sortOrder)
  339. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortName, this.options.sortName)
  340. }
  341. onMultipleSort (...args) {
  342. super.onMultipleSort(...args)
  343. if (this.options.sortPriority === undefined) {
  344. UtilsCookie.deleteCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.sortPriority)
  345. return
  346. } else {
  347. this.options.sortName = undefined
  348. this.options.sortOrder = undefined
  349. UtilsCookie.deleteCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.sortName)
  350. UtilsCookie.deleteCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.sortOrder)
  351. }
  352. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortPriority, JSON.stringify(this.options.sortPriority))
  353. }
  354. onPageNumber (...args) {
  355. super.onPageNumber(...args)
  356. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
  357. }
  358. onPageListChange (...args) {
  359. super.onPageListChange(...args)
  360. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageList, this.options.pageSize)
  361. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
  362. }
  363. onPagePre (...args) {
  364. super.onPagePre(...args)
  365. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
  366. }
  367. onPageNext (...args) {
  368. super.onPageNext(...args)
  369. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
  370. }
  371. _toggleColumn (...args) {
  372. super._toggleColumn(...args)
  373. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.columns, JSON.stringify(this.getVisibleColumns().map(column => column.field)))
  374. }
  375. _toggleAllColumns (...args) {
  376. super._toggleAllColumns(...args)
  377. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.columns, JSON.stringify(this.getVisibleColumns().map(column => column.field)))
  378. }
  379. selectPage (page) {
  380. super.selectPage(page)
  381. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, page)
  382. }
  383. onSearch (event) {
  384. super.onSearch(event)
  385. if (this.options.search) {
  386. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.searchText, this.searchText)
  387. }
  388. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
  389. }
  390. initHeader (...args) {
  391. if (this.options.reorderableColumns) {
  392. this.columnsSortOrder = JSON.parse(UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.reorderColumns))
  393. }
  394. super.initHeader(...args)
  395. }
  396. persistReorderColumnsState (that) {
  397. UtilsCookie.setCookie(that, UtilsCookie.cookieIds.reorderColumns, JSON.stringify(that.columnsSortOrder))
  398. }
  399. filterBy (...args) {
  400. super.filterBy(...args)
  401. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.filterBy, JSON.stringify(this.filterColumns))
  402. }
  403. initCookie () {
  404. if (!this.options.cookie) {
  405. return
  406. }
  407. if ((this.options.cookieIdTable === '') || (this.options.cookieExpire === '') || (!UtilsCookie.cookieEnabled())) {
  408. console.error('Configuration error. Please review the cookieIdTable and the cookieExpire property. If the properties are correct, then this browser does not support cookies.')
  409. this.options.cookie = false // Make sure that the cookie extension is disabled
  410. return
  411. }
  412. const sortOrderCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.sortOrder)
  413. const sortOrderNameCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.sortName)
  414. const sortPriorityCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.sortPriority)
  415. const pageNumberCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.pageNumber)
  416. const pageListCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.pageList)
  417. const searchTextCookie = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.searchText)
  418. const columnsCookieValue = UtilsCookie.getCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds.columns)
  419. if (typeof columnsCookieValue === 'boolean' && !columnsCookieValue) {
  420. throw new Error('The cookie value of filterBy must be a json!')
  421. }
  422. let columnsCookie = {}
  423. try {
  424. columnsCookie = JSON.parse(columnsCookieValue)
  425. } catch (e) {
  426. throw new Error('Could not parse the json of the columns cookie!', columnsCookieValue)
  427. }
  428. // sortOrder
  429. this.options.sortOrder = sortOrderCookie ? sortOrderCookie : this.options.sortOrder
  430. // sortName
  431. this.options.sortName = sortOrderNameCookie ? sortOrderNameCookie : this.options.sortName
  432. // sortPriority
  433. this.options.sortPriority = sortPriorityCookie ? sortPriorityCookie : this.options.sortPriority
  434. // pageNumber
  435. this.options.pageNumber = pageNumberCookie ? +pageNumberCookie : this.options.pageNumber
  436. // pageSize
  437. this.options.pageSize = pageListCookie ? pageListCookie === this.options.formatAllRows() ? pageListCookie : +pageListCookie : this.options.pageSize
  438. // searchText
  439. this.options.searchText = searchTextCookie ? searchTextCookie : ''
  440. if (columnsCookie) {
  441. for (const column of this.columns) {
  442. column.visible = columnsCookie.filter(columnField => {
  443. if (this.isSelectionColumn(column)) {
  444. return true
  445. }
  446. /**
  447. * This is needed for the old saved cookies or the table will show no columns!
  448. * It can be removed in 2-3 Versions Later!!
  449. * TODO: Remove this part some versions later e.g. 1.17.3
  450. */
  451. if (columnField instanceof Object) {
  452. return columnField.field === column.field
  453. }
  454. return columnField === column.field
  455. }).length > 0 || !column.switchable
  456. }
  457. }
  458. }
  459. getCookies () {
  460. const bootstrapTable = this
  461. const cookies = {}
  462. $.each(UtilsCookie.cookieIds, (key, value) => {
  463. cookies[key] = UtilsCookie.getCookie(bootstrapTable, bootstrapTable.options.cookieIdTable, value)
  464. if (key === 'columns') {
  465. cookies[key] = JSON.parse(cookies[key])
  466. }
  467. })
  468. return cookies
  469. }
  470. deleteCookie (cookieName) {
  471. if ((cookieName === '') || (!UtilsCookie.cookieEnabled())) {
  472. return
  473. }
  474. UtilsCookie.deleteCookie(this, this.options.cookieIdTable, UtilsCookie.cookieIds[cookieName])
  475. }
  476. }