Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 6 commits
  • 17 files changed
  • 0 comments
  • 1 contributor
Feb 15, 2013
Steren Image gallery was only working with images URL ending with images pre…
…fix.

This fix makes it works with any image URL.
55ad60f
Feb 21, 2013
Steren removed the mock tab, added a temporary Joshfire logo and changed the…
… tab icons
92d4106
Steren removed an useless line ? 9fa5f87
Steren Datasrouces can define Server Side Events to listen to.
Data is added to the collection of this datasource
Views are re-renderend because of collection change.

new version of W3C bootstrap, that defines the Server Side Event stream for the first datasource
145e52e
Steren Polyfill for Server Side Events (EventSource.js) 0516dee
Steren optimize 23528fc
2  app/app.desktop.ios.optimized.js
1 addition, 1 deletion not shown
2  app/app.phone.android.optimized.js
1 addition, 1 deletion not shown
2  app/app.phone.ios.optimized.js
1 addition, 1 deletion not shown
2  app/app.tablet.android.optimized.js
1 addition, 1 deletion not shown
2  app/app.tablet.ios.optimized.js
1 addition, 1 deletion not shown
2  app/app.tv.samsung.samsungtv.optimized.js
1 addition, 1 deletion not shown
2  app/app.tv.tv.optimized.js
1 addition, 1 deletion not shown
44  app/bootstrap-w3c.js
@@ -21,7 +21,16 @@
21 21
                     "name": "5dd2b8835bece0a1d574d4611cb45c88.png",
22 22
                     "url": "/transloadit/6c42ff5139b18c289463e79bcfafe4b1"
23 23
                 },
24  
-                "logo": null,
  24
+                "logo": {
  25
+                    "height": 264,
  26
+                    "width": 771,
  27
+                    "encodingFormat": "png",
  28
+                    "contentSize": 7424,
  29
+                    "contentURL": "http://static.platform.joshfire.com.s3.amazonaws.com/b4/c397dfbce15cb0879d6040fee29c70/joshfire-logo-white-on-transparent.png",
  30
+                    "itemType": "ImageObject",
  31
+                    "name": "joshfire-logo-white-on-transparent.png",
  32
+                    "url": "/transloadit/b4c397dfbce15cb0879d6040fee29c70"
  33
+                },
25 34
                 "name": "W3C Gallery",
26 35
                 "version": "1.0"
27 36
             },
@@ -30,7 +39,8 @@
30 39
                 "version": "1.2.16",
31 40
                 "options": {
32 41
                     "color": "gray",
33  
-                    "tabs": ["Feed", "Mock", "Flickr"]
  42
+                    "tabicons":["video","photo"],
  43
+                    "tabs": ["Feed", "Flickr"]
34 44
                 },
35 45
                 "hooks": ["loaded"]
36 46
             }
@@ -77,32 +87,8 @@
77 87
                 }
78 88
             },
79 89
             "outputType": "ImageObject",
80  
-            "runtime": "browser"
81  
-        }, {
82  
-            "name": "Mock",
83  
-            "db": "operator",
84  
-            "col": "updatelinks",
85  
-            "query": {
86  
-                "filter": {
87  
-                    "datasources": {
88  
-                        "main": {
89  
-                            "name": "Mock",
90  
-                            "db": "custom",
91  
-                            "col": "i0",
92  
-                            "query": {
93  
-                                "filter": {},
94  
-                                "options": {}
95  
-                            },
96  
-                            "runatclient": true,
97  
-                            "missingKeys": [],
98  
-                            "runtime": "browser"
99  
-                        }
100  
-                    },
101  
-                    "action": "addtarget"
102  
-                }
103  
-            },
104  
-            "outputType": "ImageObject",
105  
-            "runtime": "browser"
  90
+            "runtime": "browser",
  91
+            "sse" : {"url": "/stream"}
106 92
         }, {
107 93
             "name": "Flickr",
108 94
             "db": "operator",
@@ -116,7 +102,7 @@
116 102
                             "col": "photos",
117 103
                             "query": {
118 104
                                 "filter": {
119  
-                                    "search": "W3C"
  105
+                                    "search": "Mobile World Congress 2013"
120 106
                                 }
121 107
                             },
122 108
                             "runatclient": true,
3  app/index.samsung.html
@@ -82,7 +82,7 @@
82 82
     </script>
83 83
 
84 84
     <script type="text/template" id="template-toolbar">
85  
-      <div id="logo"></div>
  85
+      <div id="logo"><img src="http://static.platform.joshfire.com.s3.amazonaws.com/b4/c397dfbce15cb0879d6040fee29c70/joshfire-logo-white-on-transparent.png" /></div>
86 86
       <ul>
87 87
         <%= children %>
88 88
       </ul>
@@ -421,6 +421,7 @@
421 421
     <script type="text/javascript" src="vendor/moment.js"></script>
422 422
     <script type="text/javascript" src="vendor/sidjs-0.1.js"></script>
423 423
     <script type="text/javascript" src="prettystatus.js"></script>
  424
+    <script type="text/javascript" src="vendor/EventSource.js"></script>
424 425
     <script data-main="app.tv.samsung" src="joshfire-framework/lib/adapters/samsungtv/bootstrap.js"></script>
425 426
   </body>
426 427
 </html>
3  app/index.samsung.optimized.html
@@ -120,7 +120,7 @@
120 120
         <br/>Consider adding a data source.
121 121
       </div></script>
122 122
 
123  
-    <script type="text/template" id="template-toolbar"><div id="logo"></div>
  123
+    <script type="text/template" id="template-toolbar"><div id="logo"><img src="http://static.platform.joshfire.com.s3.amazonaws.com/b4/c397dfbce15cb0879d6040fee29c70/joshfire-logo-white-on-transparent.png" /></div>
124 124
       <ul>
125 125
         <%= children %>
126 126
       </ul>
@@ -414,6 +414,7 @@
414 414
     <script type="text/javascript" src="vendor/moment.js"></script>
415 415
     <script type="text/javascript" src="vendor/sidjs-0.1.js"></script>
416 416
     <script type="text/javascript" src="prettystatus.js"></script>
  417
+    <script type="text/javascript" src="vendor/EventSource.js"></script>
417 418
     <script src="app.tv.samsung.samsungtv.optimized.js"></script>
418 419
   </body>
419 420
 </html>
2  app/index.tv.html
@@ -68,7 +68,7 @@
68 68
     </script>
69 69
 
70 70
     <script type="text/template" id="template-toolbar">
71  
-      <div id="logo"></div>
  71
+      <div id="logo"><img src="http://static.platform.joshfire.com.s3.amazonaws.com/b4/c397dfbce15cb0879d6040fee29c70/joshfire-logo-white-on-transparent.png" /></div>
72 72
       <ul>
73 73
         <%= children %>
74 74
       </ul>
2  app/index.tv.optimized.html
@@ -68,7 +68,7 @@
68 68
     </script>
69 69
 
70 70
     <script type="text/template" id="template-toolbar">
71  
-      <div id="logo"></div>
  71
+      <div id="logo"><img src="http://static.platform.joshfire.com.s3.amazonaws.com/b4/c397dfbce15cb0879d6040fee29c70/joshfire-logo-white-on-transparent.png" /></div>
72 72
       <ul>
73 73
         <%= children %>
74 74
       </ul>
39  app/sleek.js
@@ -185,6 +185,11 @@ function (Collection, DynamicContainer, Item, List, CardPanel, FadeInPanel, Fact
185 185
               collection: collection,
186 186
               index: index
187 187
             };
  188
+
  189
+            // if this datasource is registered to server side event,
  190
+            if(datasource.config.sse) {
  191
+              self.listenToSSE(sections[index], datasource.config.sse.url);
  192
+            }
188 193
           }, self));
189 194
 
190 195
           // Create the views once all sections have been initialized
@@ -470,7 +475,7 @@ function (Collection, DynamicContainer, Item, List, CardPanel, FadeInPanel, Fact
470 475
     },
471 476
 
472 477
     /**
473  
-     * Refreshes a section list.
  478
+     * Refreshes a section list by forcing a fetch from server
474 479
      *
475 480
      * @function
476 481
      * @param {Object} the list section
@@ -488,7 +493,7 @@ function (Collection, DynamicContainer, Item, List, CardPanel, FadeInPanel, Fact
488 493
     },
489 494
 
490 495
     /**
491  
-     * Updates a section list.
  496
+     * Updates a section list (uses cache if present)
492 497
      *
493 498
      * @function
494 499
      * @param {Object} the list section
@@ -503,6 +508,36 @@ function (Collection, DynamicContainer, Item, List, CardPanel, FadeInPanel, Fact
503 508
     },
504 509
 
505 510
     /**
  511
+     * Make this section listen to Server Side Event (SSE)
  512
+     *
  513
+     * @function
  514
+     * @param section: the section that should listen to SSE
  515
+     * @param streamURL: utl of the SSE stream
  516
+     */
  517
+     listenToSSE: function(section, streamURL) {
  518
+      var source = new EventSource(streamURL);
  519
+
  520
+      var self = this;
  521
+      source.addEventListener('message', function(e) {
  522
+        console.log(e.data);
  523
+        var data = JSON.parse(e.data);
  524
+
  525
+        section.collection.add(data);
  526
+      }, false);
  527
+
  528
+      source.addEventListener('open', function(e) {
  529
+        console.log("SSE opened");
  530
+      }, false);
  531
+
  532
+      source.addEventListener('error', function(e) {
  533
+        if (e.readyState == EventSource.CLOSED) {
  534
+          console.log("SSE lost");
  535
+        }
  536
+      }, false);
  537
+
  538
+     },
  539
+
  540
+    /**
506 541
      * Displays a section list
507 542
      * (assuming the section is already active).
508 543
      *
2  app/sleek.tv.js
@@ -448,7 +448,7 @@ function(Sleek, UIElement, UIList, Toolbar, CardPanel, SlidePanel, VerticalList,
448 448
 
449 449
           var container = self.activeSection.view;
450 450
           if (section.collection.length) {
451  
-            self.moveToList(container);
  451
+            //self.moveToList(container); // don't know why this is usefull
452 452
             views.showChild(section.slug);
453 453
           } else {
454 454
             views.showChild(section.slug);
2  app/ui/imagegallery.js
@@ -22,7 +22,7 @@ define([
22 22
 
23 23
       if(options.photoswipe) _.extend(this.photoswipe, options.photoswipe);
24 24
 
25  
-      this.linkSelector = options.linkSelector || 'a[href$=".jpg"],a[href$=".jpeg"],a[href$=".png"],a[href$=".gif"]'
  25
+      this.linkSelector = options.linkSelector || 'a.img'
26 26
 
27 27
       UIList.prototype.initialize.call(this, options);
28 28
     },
174  app/vendor/EventSource.js
... ...
@@ -0,0 +1,174 @@
  1
+;(function (global) {
  2
+
  3
+if ("EventSource" in global) return;
  4
+
  5
+var reTrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
  6
+
  7
+var EventSource = function (url) {
  8
+  var eventsource = this,  
  9
+      interval = 500, // polling interval  
  10
+      lastEventId = null,
  11
+      cache = '';
  12
+
  13
+  if (!url || typeof url != 'string') {
  14
+    throw new SyntaxError('Not enough arguments');
  15
+  }
  16
+
  17
+  this.URL = url;
  18
+  this.readyState = this.CONNECTING;
  19
+  this._pollTimer = null;
  20
+  this._xhr = null;
  21
+  
  22
+  function pollAgain() {
  23
+    eventsource._pollTimer = setTimeout(function () {
  24
+      poll.call(eventsource);
  25
+    }, interval);
  26
+  }
  27
+  
  28
+  function poll() {
  29
+    try { // force hiding of the error message... insane?
  30
+      if (eventsource.readyState == eventsource.CLOSED) return;
  31
+
  32
+      // NOTE: IE7 and upwards support
  33
+      var xhr = new XMLHttpRequest();
  34
+      xhr.open('GET', eventsource.URL, true);
  35
+      xhr.setRequestHeader('Accept', 'text/event-stream');
  36
+      xhr.setRequestHeader('Cache-Control', 'no-cache');
  37
+      // we must make use of this on the server side if we're working with Android - because they don't trigger 
  38
+      // readychange until the server connection is closed
  39
+      xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
  40
+
  41
+      if (lastEventId != null) xhr.setRequestHeader('Last-Event-ID', lastEventId);
  42
+      cache = '';
  43
+    
  44
+      xhr.timeout = 50000;
  45
+      xhr.onreadystatechange = function () {
  46
+        if (this.readyState == 3 || (this.readyState == 4 && this.status == 200)){
  47
+          // on success
  48
+          if (eventsource.readyState == eventsource.CONNECTING) {
  49
+            eventsource.readyState = eventsource.OPEN;
  50
+            eventsource.dispatchEvent('open', { type: 'open' });
  51
+          }
  52
+
  53
+          var responseText = '';
  54
+          try {
  55
+            responseText = this.responseText || '';
  56
+          } catch (e) {}
  57
+        
  58
+          // process this.responseText
  59
+          var parts = responseText.substr(cache.length).split("\n"),
  60
+              eventType = 'message',
  61
+              data = [],
  62
+              i = 0,
  63
+              line = '';
  64
+            
  65
+          cache = responseText;
  66
+        
  67
+          // TODO handle 'event' (for buffer name), retry
  68
+          for (; i < parts.length; i++) {
  69
+            line = parts[i].replace(reTrim, '');
  70
+            if (line.indexOf('event') == 0) {
  71
+              eventType = line.replace(/event:?\s*/, '');
  72
+            } else if (line.indexOf('data') == 0) {
  73
+              data.push(line.replace(/data:?\s*/, ''));
  74
+            } else if (line.indexOf('id:') == 0) {
  75
+              lastEventId = line.replace(/id:?\s*/, '');
  76
+            } else if (line.indexOf('id') == 0) { // this resets the id
  77
+              lastEventId = null;
  78
+            } else if (line == '') {
  79
+              if (data.length) {
  80
+                var event = new MessageEvent(data.join('\n'), eventsource.url, lastEventId);
  81
+                eventsource.dispatchEvent(eventType, event);
  82
+                data = [];
  83
+                eventType = 'message';
  84
+              }
  85
+            }
  86
+          }
  87
+
  88
+          if (this.readyState == 4) pollAgain();
  89
+          // don't need to poll again, because we're long-loading
  90
+        } else if (eventsource.readyState !== eventsource.CLOSED) {
  91
+          if (this.readyState == 4) { // and some other status
  92
+            // dispatch error
  93
+            eventsource.readyState = eventsource.CONNECTING;
  94
+            eventsource.dispatchEvent('error', { type: 'error' });
  95
+            pollAgain();
  96
+          } else if (this.readyState == 0) { // likely aborted
  97
+            pollAgain();
  98
+          } else {
  99
+          }
  100
+        }
  101
+      };
  102
+    
  103
+      xhr.send();
  104
+    
  105
+      setTimeout(function () {
  106
+        if (true || xhr.readyState == 3) xhr.abort();
  107
+      }, xhr.timeout);
  108
+      
  109
+      eventsource._xhr = xhr;
  110
+    
  111
+    } catch (e) { // in an attempt to silence the errors
  112
+      eventsource.dispatchEvent('error', { type: 'error', data: e.message }); // ???
  113
+    } 
  114
+  };
  115
+  
  116
+  poll(); // init now
  117
+};
  118
+
  119
+EventSource.prototype = {
  120
+  close: function () {
  121
+    // closes the connection - disabling the polling
  122
+    this.readyState = this.CLOSED;
  123
+    clearInterval(this._pollTimer);
  124
+    this._xhr.abort();
  125
+  },
  126
+  CONNECTING: 0,
  127
+  OPEN: 1,
  128
+  CLOSED: 2,
  129
+  dispatchEvent: function (type, event) {
  130
+    var handlers = this['_' + type + 'Handlers'];
  131
+    if (handlers) {
  132
+      for (var i = 0; i < handlers.length; i++) {
  133
+        handlers[i].call(this, event);
  134
+      }
  135
+    }
  136
+
  137
+    if (this['on' + type]) {
  138
+      this['on' + type].call(this, event);
  139
+    }
  140
+  },
  141
+  addEventListener: function (type, handler) {
  142
+    if (!this['_' + type + 'Handlers']) {
  143
+      this['_' + type + 'Handlers'] = [];
  144
+    }
  145
+    
  146
+    this['_' + type + 'Handlers'].push(handler);
  147
+  },
  148
+  removeEventListener: function () {
  149
+    // TODO
  150
+  },
  151
+  onerror: null,
  152
+  onmessage: null,
  153
+  onopen: null,
  154
+  readyState: 0,
  155
+  URL: ''
  156
+};
  157
+
  158
+var MessageEvent = function (data, origin, lastEventId) {
  159
+  this.data = data;
  160
+  this.origin = origin;
  161
+  this.lastEventId = lastEventId || '';
  162
+};
  163
+
  164
+MessageEvent.prototype = {
  165
+  data: null,
  166
+  type: 'message',
  167
+  lastEventId: '',
  168
+  origin: ''
  169
+};
  170
+
  171
+if ('module' in global) module.exports = EventSource;
  172
+global.EventSource = EventSource;
  173
+ 
  174
+})(this);
BIN  tasks/server/public/sleek.zip
Binary file not shown

No commit comments for this range

Something went wrong with that request. Please try again.