Commits

Matthew Schinckel committed 08bb416

Convert over to new events.
These events are different to the Garmin.DevicePlugin events.

Comments (0)

Files changed (2)

   //
   // This will inject the plugin object into the page if it could not find it.
   //
-  // Put the non-IE version in a {{{<div>}}}, apparently there is a Safari bug that requires this.
+  // Put the non-IE version in a {{{<div>}}}, apparently there is a 
+  // Safari bug that requires this.
 
   Garmin.Plugin = function() {
     var plugin;
       // IE
       plugin = $('#GarminActiveXControl');
       if (!plugin.length) {
-        plugin = $('<object id="GarminActiveXControl" style="WIDTH: 0px; HEIGHT: 0px; visible: hidden" height="0" width="0" classid="CLSID:099B5A62-DE20-48C6-BF9E-290A9D1D8CB5">');
+        plugin = $('<object id="GarminActiveXControl" ' +
+          'style="WIDTH: 0px; HEIGHT: 0px; visible: hidden" ' +
+          'height="0" width="0" ' +
+          'classid="CLSID:099B5A62-DE20-48C6-BF9E-290A9D1D8CB5">');
         $('body').append(plugin);
         plugin = $('#GarminActiveXControl');
       }
     } else {
       plugin = $('#GarminNetscapePlugin');
       if (!plugin.length) {
-        plugin = $('<div style="height:0 px;width:0px"><object id="GarminNetscapePlugin" type="application/vnd-garmin.mygarmin" width="0" height="0">&#160;</object></div>');
+        plugin = $('<div style="height:0 px;width:0px">' +
+          '<object id="GarminNetscapePlugin" ' + 
+          'type="application/vnd-garmin.mygarmin" ' + 
+          'width="0" height="0">&#160;</object></div>');
         $('body').append(plugin);
         plugin = $('#GarminNetscapePlugin');
       }
     return plugin[0];
   };
   
-  // == Progress ==
+  // == Status ==
   // 
   // Status codes representing the progress of the current transfer.
   
-  Garmin.PROGRESS = {
+  Garmin.STATUS = {
     idle: 0,
     working: 1,
     waiting: 2,
-    finished: 3
+    finished: 3,
+    error: -1
   };
   
   // == Fitness Types ==
   // 
   // List of events that are triggered by this controller.
   //
-  // All events are jQuery events, and the sending controller can be found in {{{Event.data.controller}}}.
-  //
-  // {{{onStartXXX}}} events occur before the process starts.
-  //
-  // {{{onFinishXXX}}} events occur after the process is complete, and typically provide the expected data in an object passed as their second argument.
-  //
-  // Note that there are also {{{onStartReadActivities}}}, {{{onFinishReadActivities}}}, as well as writing version of events for all of the Fitness Types listed above. These can be used instead of the low-level ones provided here (which mirror the original Garmin events).
+  //  {{{initialisationError}}}   {message: "string"}
   Garmin.EVENTS = [
-    'onStartFindDevices', 
-    'onCancelFindDevices', 
-    'onFinishFindDevices',
-    'onSelectDevice',
-    'onException', 
-    'onInteractionWithNoDevice', 
-    'onConcurrentInteraction',
-    'onStartReadFromDevice', 
-    'onWaitingReadFromDevice', 
-    'onProgressReadFromDevice', 
-    'onCancelReadFromDevice', 
-    'onFinishReadFromDevice',
-    'onStartWriteToDevice', 
-    'onWaitingWriteToDevice', 
-    'onProgressWriteToDevice', 
-    'onCancelWriteToDevice', 
-    'onFinishWriteToDevice'
+    "initialisationError",
+    "deviceListUpdate",
+    "deviceSelected",
+    "startInteractionWithDevice",
+    "endInteractionWithDevice",
+    "progressInterationWithDevice",
+    "interactionError"
   ];
   
   _.each(Garmin.FITNESS_TYPES, function(data, name){
-    Garmin.EVENTS.push('onStartRead' + name);
-    Garmin.EVENTS.push('onFinishRead' + name);
-    Garmin.EVENTS.push('onStartWrite' + name);
-    Garmin.EVENTS.push('onFinishWrite' + name);
-  })
+    Garmin.EVENTS.push('read' + name + 'Complete');
+    Garmin.EVENTS.push('write' + name + 'Complete');
+  });
   
-  /**
+  /* 
   
-  @class Garmin.Communicator
-  **/
+  Things we need to publish.
+  
+    * Initialisation errors         {message: "string"}
+    * deviceListUpdate              {devices: [device, device]}
+    * deviceSelected                {device: device, number: <number>}
+    
+    * Transfer status
+      * startInteractionWithDevice  {type:"string", device:device}
+      * progressUpdate              {device:device, progress:{}, status:STATUS}
+      * endInteractionWithDevice    {device:device, status:STATUS, message:"string"}
+      * interactionError            {device:device, message:"string"}
+    
+    * Specific fitness events
+      * readActivitiesComplete      {device:device, data: data}
+      * writeActivitiesComplete     {device:device}
+      * <which><Whatever>Complete
+  
+  */
+  var EVENTS = [
+  ];
+  
+  // == Communicator ==
+  
   Garmin.Communicator = function Communicator(delegate, autostart) {
     
     delegate = delegate || {};
     var currentDevice = null;
     var plugin = new Garmin.Plugin();
     var $plugin = $(plugin);
-
     
     var unlockCodes = [
       "file:///","cb1492ae040612408d87cc53e3f7ff3c",
     // Data we store.
     var devices = [];
     
-    //************** Device class **************//
-    
+    // === Device ===
+    //
+    // Objects of this class will be provided by the Communicator object.
     var Device = function Device(number) {
       var deviceData = parseXML(plugin.DeviceDescription(number));
       var WRITE = 'Input';
             return $(this).text() === dataTypeName;
           }).closest('DataType').find('TransferDirection').text().match(direction) || false;
         };
-      };
+      }
       
       this.displayName = readData('DisplayName');
       this.partNumber = readData('Model PartNumber');
         this['canRead' + type] = canXY(READ, data[0]);
         this['canWrite' + type] = canXY(WRITE, data[0]);
       }, this);
-    }
+    };
     
     //************** Helpers **************//
     
+    var send = function(eventType, data) {
+      if (delegate[eventType]) {
+        delegate[eventType](data);
+      }
+      $plugin.trigger(eventType, data);
+    };
+    
     var parseXML = function(xml) {
       return $($.parseXML(xml));
     };
     
     var checkUnlocked = function() {
       if (plugin.Locked) {
-        throw new Error("Plugin is not unlocked");
+        var message = "Plugin is not unlocked.";
+        send("initialisationError", {message: message});
+        throw new Error(message);
       }
     };
     
-    var reportException = function(e) {
-      $plugin.trigger('onException', e);
-    };
-    
-    var progress = function() {
+    var getProgress = function() {
       var message = {content: []};
       var data = parseXML(plugin.ProgressXml);
       message.title = data.find('Title').text();
     this.findDevices = function() {
       checkUnlocked();
       plugin.StartFindDevices();
-      $plugin.trigger('onStartFindDevices');
-      // Check in 1 sec if we have finished.
-      setTimeout(finishFindDevices, 1000);
+      // Check in 100 ms if we have finished.
+      setTimeout(finishFindDevices, 100);
     };
     
-    this.cancelFindDevices = function() {
-      plugin.CancelFindDevices();
-      $plugin.trigger('onCancelFindDevices');
-    };
+    this.cancelFindDevices = plugin.CancelFindDevices;
     
     var finishFindDevices = function() {
-        if (plugin.FinishFindDevices()) {
-          var data = parseXML(plugin.DevicesXmlString());
-          devices = [];
-          _.each(data.find('Device'), function(el,i) {
-            devices.push(new Device(i));
-          });
-          $plugin.trigger('onFinishFindDevices', {devices: devices});
-        } else {
-          // Keep checking every .5 sec until we finish.
-          setTimeout(finishFindDevices, 500);
-        }        
+      if (plugin.FinishFindDevices()) {
+        var data = parseXML(plugin.DevicesXmlString());
+        devices = [];
+        _.each(data.find('Device'), function(el,i) {
+          devices.push(new Device(i));
+        });
+        send('deviceListUpdate', {devices: devices});
+      } else {
+        // Keep checking every .1 sec until we finish.
+        setTimeout(finishFindDevices, 100);
+      }        
     };
     
     // Simple RO accessor.
     this.selectDevice = function(d) {
       // Ensure device number is 0..devices.length;
       if (isNaN(d) || d < 0 || d >= devices.length) {
-        $plugin.trigger('onException', {message: "Invalid device number selected"});
+        // Different error type?
+        send('interactionError', {message: "Invalid device number selected"});
         currentDevice = null;
         return;
       }
       currentDevice = d;
-      $plugin.trigger('onSelectDevice', {device: devices[d], deviceNumber: d});
+      send('deviceSelected', {device: devices[d], number: d});
       return devices[d];
     };
     
             
     var baseHandler = function(readWrite, dataType, pluginMethod, name) {
       if (devices.length === 0) {
-        $plugin.trigger('')
+        send('interactionError', {message: "No devices found."});
       }
       if (currentDevice === null) {
-        $plugin.trigger('onInteractionWithNoDevice');
+        send('interactionError', {message: "No device selected."});
         return;
       }
       if (inUse) {
-        $plugin.trigger('onConcurrentInteraction');
+        send('interactionError', {message: "Process '" + inUse + "' already in progress."});
         return;
       }
       var device = devices[currentDevice];
         toFrom = "From";
         readWrite = "Read";
       }
-      inUse = true;
-      $plugin.trigger('onStart' + readWrite + toFrom + 'Device', {device:device, dataType:dataType});
-      $plugin.trigger('onStart' + readWrite + name, {device:device, dataType:dataType});
+      inUse = readWrite.toLowerCase() + name;
+      send('startInteractionWithDevice', {device:device, type:dataType});
       plugin['Start' + readWrite + pluginMethod](currentDevice, dataType);
       
       var finishHandler = function finishHandler() {
-        $plugin.trigger('onProgress' + readWrite + toFrom + 'Device', {device: device, progress: progress()});
-        switch (plugin['Finish' + readWrite + pluginMethod]()) {
-          case Garmin.PROGRESS.working:
+        var status = plugin['Finish' + readWrite + pluginMethod]();
+        send('progressInterationWithDevice', {device: device, progress: getProgress(), status: status});
+        switch (status) {
+          case Garmin.STATUS.working:
             setTimeout(finishHandler, 200);
             break;
-          case Garmin.PROGRESS.finished:
-            $plugin.trigger('onFinish' + readWrite + toFrom  + 'Device', {device:device, dataType: dataType, data: plugin.TcdXml});
-            $plugin.trigger('onFinish' + readWrite + name, {device:device, dataType: dataType, data: plugin.TcdXml});
-            console.log('onFinish' + readWrite + name);
+          case Garmin.STATUS.finished:
+            send('endInteractionWithDevice', {device:device, status: status});
+            send(readWrite.toLowerCase() + name + 'Complete', {device:device, data:plugin.TcdXml});
             inUse = false;
             break;
           default:
       this['read' + type] = readHandler(data[0], data[1], type);
       this['write' + type] = writeHandler(data[0], data[1], type);
     }, this);
-    
-    //************** Bind delegate event listeners **************//
-    
-    // Bind any listeners that we find on the delegate object
-    _.each(Garmin.EVENTS, function(evt) {
-      if (delegate[evt]) {
-        $(document).on(evt, '#' + plugin.id, {controller: this}, delegate[evt]);        
-      }
-    }, this);
-    
+        
     // See if the plugin is actually installed.
     if (!plugin.Unlock) {
-      $plugin.trigger('onMissingCommunicatorPlugin');
+      send('interactionError', {message: "Could not find Communicator Plugin"});
+      // We could have a default way of dealing with this...
       return;
     }
     
     // Unlock the plugin (or die trying)
     unlock(_.union(unlockCodes, delegate.unlockCodes || []));
     
+    // wait for other initialisation to finish, then search for devices.
     if (autostart) {
-      this.findDevices();
+      setTimeout(this.findDevices, 0);
     }
   };
 })(jQuery);

tests/basic_test.html

     <script src="../vendor/underscore-1.3.3.js"></script>
     <script src="../src/garmin.js"></script>
     <script>
-    var g;
-    var handler = {
-      onFinishFindDevices: function(evt, data) {
+    var Controller = function() {
+      var plugin = new Garmin.Communicator(this, true);
+      
+      this.interactionError = function(data) {
+        throw new Error(data.message);
+      };
+      
+      this.deviceListUpdate = function(data) {
         console.log(data.devices);
-        g.selectDevice(1);
-        g.readActivities();
-      },
-      onFinishReadActivities: function(evt, data) {
+        plugin.selectDevice(1);
+      };
+      
+      this.readActivities = plugin.readActivities;
+      
+      this.readActivitiesComplete = function(data) {
         console.log(data.data.length);
-      },
+      };
     };
-    $(function(){
-      g = new Garmin.Communicator(handler, true);
-    });
+    var c = new Controller();
     </script>
     <textarea>
       
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.