eventsource.js 4.1 KB

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