You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

eventsource.js 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /**
  2. * @copyright 2012 Robin Appelman icewind1991@gmail.com
  3. *
  4. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  5. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  6. * @author John Molakvoæ <skjnldsv@protonmail.com>
  7. * @author Lukas Reschke <lukas@statuscode.ch>
  8. * @author Robin Appelman <robin@icewind.nl>
  9. * @author Thomas Müller <thomas.mueller@tmit.eu>
  10. * @author Vincent Petry <vincent@nextcloud.com>
  11. *
  12. * @license GNU AGPL version 3 or any later version
  13. *
  14. * This program is free software: you can redistribute it and/or modify
  15. * it under the terms of the GNU Affero General Public License as
  16. * published by the Free Software Foundation, either version 3 of the
  17. * License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU Affero General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU Affero General Public License
  25. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  26. *
  27. */
  28. /* eslint-disable */
  29. import $ from 'jquery'
  30. import { getToken } from './requesttoken'
  31. /**
  32. * Create a new event source
  33. * @param {string} src
  34. * @param {object} [data] to be send as GET
  35. *
  36. * @constructs OCEventSource
  37. */
  38. const OCEventSource = function(src, data) {
  39. var dataStr = ''
  40. var name
  41. var joinChar
  42. this.typelessListeners = []
  43. this.closed = false
  44. this.listeners = {}
  45. if (data) {
  46. for (name in data) {
  47. dataStr += name + '=' + encodeURIComponent(data[name]) + '&'
  48. }
  49. }
  50. dataStr += 'requesttoken=' + encodeURIComponent(getToken())
  51. if (!this.useFallBack && typeof EventSource !== 'undefined') {
  52. joinChar = '&'
  53. if (src.indexOf('?') === -1) {
  54. joinChar = '?'
  55. }
  56. this.source = new EventSource(src + joinChar + dataStr)
  57. this.source.onmessage = function(e) {
  58. for (var i = 0; i < this.typelessListeners.length; i++) {
  59. this.typelessListeners[i](JSON.parse(e.data))
  60. }
  61. }.bind(this)
  62. } else {
  63. var iframeId = 'oc_eventsource_iframe_' + OCEventSource.iframeCount
  64. OCEventSource.fallBackSources[OCEventSource.iframeCount] = this
  65. this.iframe = $('<iframe/>')
  66. this.iframe.attr('id', iframeId)
  67. this.iframe.hide()
  68. joinChar = '&'
  69. if (src.indexOf('?') === -1) {
  70. joinChar = '?'
  71. }
  72. this.iframe.attr('src', src + joinChar + 'fallback=true&fallback_id=' + OCEventSource.iframeCount + '&' + dataStr)
  73. $('body').append(this.iframe)
  74. this.useFallBack = true
  75. OCEventSource.iframeCount++
  76. }
  77. // add close listener
  78. this.listen('__internal__', function(data) {
  79. if (data === 'close') {
  80. this.close()
  81. }
  82. }.bind(this))
  83. }
  84. OCEventSource.fallBackSources = []
  85. OCEventSource.iframeCount = 0// number of fallback iframes
  86. OCEventSource.fallBackCallBack = function(id, type, data) {
  87. OCEventSource.fallBackSources[id].fallBackCallBack(type, data)
  88. }
  89. OCEventSource.prototype = {
  90. typelessListeners: [],
  91. iframe: null,
  92. listeners: {}, // only for fallback
  93. useFallBack: false,
  94. /**
  95. * Fallback callback for browsers that don't have the
  96. * native EventSource object.
  97. *
  98. * Calls the registered listeners.
  99. *
  100. * @private
  101. * @param {String} type event type
  102. * @param {Object} data received data
  103. */
  104. fallBackCallBack: function(type, data) {
  105. var i
  106. // ignore messages that might appear after closing
  107. if (this.closed) {
  108. return
  109. }
  110. if (type) {
  111. if (typeof this.listeners.done !== 'undefined') {
  112. for (i = 0; i < this.listeners[type].length; i++) {
  113. this.listeners[type][i](data)
  114. }
  115. }
  116. } else {
  117. for (i = 0; i < this.typelessListeners.length; i++) {
  118. this.typelessListeners[i](data)
  119. }
  120. }
  121. },
  122. lastLength: 0, // for fallback
  123. /**
  124. * Listen to a given type of events.
  125. *
  126. * @param {String} type event type
  127. * @param {Function} callback event callback
  128. */
  129. listen: function(type, callback) {
  130. if (callback && callback.call) {
  131. if (type) {
  132. if (this.useFallBack) {
  133. if (!this.listeners[type]) {
  134. this.listeners[type] = []
  135. }
  136. this.listeners[type].push(callback)
  137. } else {
  138. this.source.addEventListener(type, function(e) {
  139. if (typeof e.data !== 'undefined') {
  140. callback(JSON.parse(e.data))
  141. } else {
  142. callback('')
  143. }
  144. }, false)
  145. }
  146. } else {
  147. this.typelessListeners.push(callback)
  148. }
  149. }
  150. },
  151. /**
  152. * Closes this event source.
  153. */
  154. close: function() {
  155. this.closed = true
  156. if (typeof this.source !== 'undefined') {
  157. this.source.close()
  158. }
  159. }
  160. }
  161. export default OCEventSource