GarminDeviceDisplay.js
Summary
Garmin.DeviceDisplay is a high-level UI widget for talking
with Garmin Devices.
Version: 1.0
Author: Michael Bina michael.bina.at.garmin.com
if (Garmin == undefined) var Garmin = {};
Garmin.DeviceDisplay = function(mainElement, options){};
Garmin.DeviceDisplay = Class.create();
Garmin.DeviceDisplay.prototype = {
initialize: function(mainElement, options) {
if(typeof(mainElement) == "string") {
this.mainElement = $(mainElement);
} else {
this.mainElement = mainElement;
}
if(this.mainElement != null) {
this.options = null;
this.setOptions(options);
this.garminController = null;
this.garminRemoteTransfer = null;
this.activities = new Array();
this.factory = null;
this.tracks = null;
this.waypoints = null;
this.activityDirectory = null;
this.activitySelection = null;
this.activityQueue = null;
this.currentActivity = null;
this.finishedFirstActivity = false;
this.error = null;
this._generateElements();
if (this.options.unlockOnPageLoad) {
this.getController(true);
}
if (!this.error && this.options.autoFindDevices) {
this.startFindDevices();
}
}
},
_generateElements: function() {
if (BrowserSupport.isBrowserSupported() || !this.options.hideIfBrowserNotSupported) {
this._generateStatusElement();
if(this.options.showFindDevicesElement) {
this._generateFindDevicesElement();
}
if(this.options.showReadDataElement) {
this._generateReadDataElement();
}
if(this.options.showActivityDirectoryElement) {
this._generateActivityDirectoryElement();
}
if(this.options.showWriteDataElement) {
this._generateWriteDataElement();
}
if(this.options.showSendDataElement) {
this._generateSendDataElement();
}
this._generateAboutElement();
this.resetUI();
}
},
resetUI: function() {
this.hideProgressBar();
var noDevicesAvailable = this.garminController ? (this.getController().numDevices==0) : true;
if(this.options.showFindDevicesElement) {
if (this.findDevicesButton)
this.findDevicesButton.disabled = false;
if (this.deviceSelect)
this.deviceSelect.disabled = noDevicesAvailable;
if (this.cancelFindDevicesButton)
this.cancelFindDevicesButton.disabled = true;
if (this.readDataTypesSelect)
this.readDataTypesSelect.disabled = false;
}
if(this.options.showReadDataElement) {
if (this.readDataButton)
this.readDataButton.disabled = noDevicesAvailable;
if (this.cancelReadDataButton)
this.cancelReadDataButton.disabled = true;
}
if(this.options.showWriteDataElement) {
if (this.writeDataButton)
this.writeDataButton.disabled = noDevicesAvailable;
if (this.cancelWriteDataButton)
this.cancelWriteDataButton.disabled = true;
}
},
_generateStatusElement: function() {
this.statusElement = document.createElement("div");
Element.extend(this.statusElement);
this.statusElement.id = this.options.statusElementId;
this.statusElement.addClassName(this.options.elementClassName);
this.mainElement.appendChild(this.statusElement);
this.statusText = document.createElement("div");
Element.extend(this.statusText);
this.statusText.id = this.options.statusTextId;
this.statusElement.appendChild(this.statusText);
this.progressBar = document.createElement("div");
Element.extend(this.progressBar);
this.progressBar.id = this.options.progressBarId;
this.progressBarDisplay = document.createElement("div");
Element.extend(this.progressBarDisplay);
this.progressBarDisplay.id = this.options.progressBarDisplayId;
var wrapper = document.createElement("div");
Element.extend(wrapper);
wrapper.setStyle({position: 'relative'});
wrapper.appendChild(this.progressBarDisplay);
this.progressBar.appendChild(wrapper);
this.statusElement.appendChild(this.progressBar);
Element.hide(this.progressBar);
},
_createElement: function(id, text, type, parent) {
var elem = document.createElement(type);
Element.extend(elem);
if (type=="a") {
elem.href = location;
elem.innerHTML = text;
} else if (type=="button"){
elem.type = type;
elem.value = text;
}
elem.id = id;
parent.appendChild(elem);
return elem;
},
_generateFindDevicesElement: function() {
this.findDevicesElement = document.createElement("div");
Element.extend(this.findDevicesElement);
this.findDevicesElement.id = this.options.findDevicesElementId;
this.findDevicesElement.addClassName(this.options.elementClassName);
this.mainElement.appendChild(this.findDevicesElement);
if( this.options.showFindDevicesButton) {
this.findDevicesButton = document.createElement( this.options.useLinks ? "a" : "input" );
Element.extend(this.findDevicesButton);
if (this.options.useLinks) {
this.findDevicesButton.href = "#";
this.findDevicesButton.innerHTML = this.options.findDevicesButtonText;
} else {
this.findDevicesButton.type = "button";
this.findDevicesButton.value = this.options.findDevicesButtonText;
}
this.findDevicesButton.id = this.options.findDevicesButtonId;
this.findDevicesButton.addClassName(this.options.actionButtonClassName);
this.findDevicesElement.appendChild(this.findDevicesButton);
this.findDevicesButton.onclick = function() {
this.startFindDevices();
}.bind(this)
}
if(!this.options.showFindDevicesElementOnLoad) {
if( this.findDevicesElement) {
Element.hide(this.findDevicesElement);
}
}
if (this.options.showCancelFindDevicesButton) {
this.cancelFindDevicesButton = document.createElement( this.options.useLinks ? "a" : "input" );
Element.extend(this.cancelFindDevicesButton);
if (this.options.useLinks) {
this.cancelFindDevicesButton.href = "#";
this.cancelFindDevicesButton.innerHTML = this.options.cancelFindDevicesButtonText;
} else {
this.cancelFindDevicesButton.type = "button";
this.cancelFindDevicesButton.value = this.options.cancelFindDevicesButtonText;
}
this.cancelFindDevicesButton.id = this.options.cancelFindDevicesButtonId;
this.cancelFindDevicesButton.addClassName(this.options.actionButtonClassName);
this.cancelFindDevicesButton.disabled = true;
this.cancelFindDevicesButton.onclick = function() {
this.cancelFindDevices();
}.bind(this)
this.findDevicesElement.appendChild(this.cancelFindDevicesButton);
}
if (!this.options.showDeviceButtonsOnLoad) {
if (this.findDevicesButton) {
Element.hide(this.findDevicesButton);
}
if (this.cancelFindDevicesButton)
Element.hide(this.cancelFindDevicesButton);
}
this.deviceSelectElement = document.createElement("div");
Element.extend(this.deviceSelectElement);
this.deviceSelectElement.id = this.options.deviceSelectElementId;
this.deviceSelectElement.innerHTML = '<div id="' + this.options.deviceSelectLabelId + '">' + this.options.deviceSelectLabel + '</div>';
this.findDevicesElement.appendChild(this.deviceSelectElement);
this.deviceSelect = document.createElement("select");
Element.extend(this.deviceSelect);
this.deviceSelect.id = this.options.deviceSelectId;
this.deviceSelect.disabled = true;
this.deviceSelectElement.appendChild(this.deviceSelect);
if (!this.options.showDeviceSelectOnLoad || !this.options.showDeviceSelectOnSingle || this.options.autoSelectFirstDevice) {
Element.hide(this.deviceSelectElement);
}
},
_generateSendDataElement: function() {
this.sendDataElement = document.createElement("div");
Element.extend(this.sendDataElement);
this.sendDataElement.id = this.options.sendDataElementId;
this.sendDataElement.addClassName(this.options.elementClassName);
this.mainElement.appendChild(this.sendDataElement);
this.sendDataButton = document.createElement( this.options.useLinks ? "a" : "input" );
Element.extend(this.sendDataButton);
if (this.options.useLinks) {
this.sendDataButton.href = "#";
this.sendDataButton.innerHTML = this.options.sendDataButtonText;
} else {
this.sendDataButton.type = "button";
this.sendDataButton.value = this.options.sendDataButtonText;
}
this.sendDataButton.id = this.options.sendDataButtonId;
this.sendDataButton.addClassName(this.options.actionButtonClassName);
this.sendDataButton.onclick = function() {
this.setStatus(this.options.sendingDataToServer);
Element.hide(this.findDevicesElement);
Element.hide(this.sendDataElement);
var response;
var jsonResult;
var updatesArray;
this.showProgressBar();
response = this.garminRemoteTransfer.openRequest(this.options.sendDataRequestType, this.options.sendDataUrl,
this.options.sendDataAsynchronously, this.options.getSendParameters(this.garminController.getCurrentDeviceXml()));
if(response == null) {
throw new Error(this.options.errorHttpResponse);
}
if( response.error != null) {
this.hideProgressBar();
this.setStatus(response.error);
} else {
jsonResult = response.json;
this.options.sendDataCallback(jsonResult);
this.writeToDevice();
}
}.bind(this)
this.sendDataElement.appendChild(this.sendDataButton);
if(this.options.showSendDataElementOnDeviceFound) {
Element.hide(this.sendDataElement);
}
},
_generateReadDataElement: function() {
this.readDataElement = document.createElement("div");
Element.extend(this.readDataElement);
this.readDataElement.id = this.options.readDataElementId;
this.readDataElement.addClassName(this.options.elementClassName);
this.mainElement.appendChild(this.readDataElement);
this.readDataButton = document.createElement( this.options.useLinks ? "a" : "input" );
Element.extend(this.readDataButton);
if (this.options.useLinks) {
this.readDataButton.href = "#";
this.readDataButton.innerHTML = this.options.readDataButtonText;
} else {
this.readDataButton.type = "button";
this.readDataButton.value = this.options.readDataButtonText;
}
this.readDataButton.id = this.options.readDataButtonId;
this.readDataButton.addClassName(this.options.actionButtonClassName);
this.readDataButton.disabled = true;
this.readDataButton.onclick = function() {
var isSupportedDevice = true;
if( this.options.restrictByDevice.length > 0){
isSupportedDevice = this._restrictByDevice();
}
if( isSupportedDevice) {
if( this.options.autoHideUnusedReadElements ) {
Element.hide(this.findDevicesElement);
Element.hide(this.readDataElement);
Element.hide(this.deviceSelectElement);
Element.hide(this.activityDirectoryElement);
}
this.readDataButton.disabled = true;
this.cancelReadDataButton.disabled = false;
this.showProgressBar();
if (this.options.showReadDataTypesSelect) {
this.readSpecificTypeFromDevice(this.readDataTypesSelect.value);
} else if (this.options.readDataType != null) {
this.readSpecificTypeFromDevice(this.options.readDataType);
} else {
this.readFromDevice();
}
}
}.bind(this)
this.readDataElement.appendChild(this.readDataButton);
this.cancelReadDataButton = document.createElement( this.options.useLinks ? "a" : "input" );
Element.extend(this.cancelReadDataButton);
if (this.options.useLinks) {
this.cancelReadDataButton.href = "#";
this.cancelReadDataButton.innerHTML = this.options.cancelReadDataButtonText;
} else {
this.cancelReadDataButton.type = "button";
this.cancelReadDataButton.value = this.options.cancelReadDataButtonText;
}
this.cancelReadDataButton.id = this.options.cancelReadDataButtonId;
this.cancelReadDataButton.addClassName(this.options.actionButtonClassName);
this.cancelReadDataButton.disabled = true;
this.cancelReadDataButton.onclick = function() {
this.resetUI();
this.hideProgressBar();
this.getController().cancelReadFromDevice();
}.bind(this)
this.readDataElement.appendChild(this.cancelReadDataButton);
if(!this.options.showCancelReadDataButton) {
Element.hide(this.cancelReadDataButton);
}
this.uploadDataButton = document.createElement( this.options.useLinks ? "a" : "input" );
Element.extend(this.uploadDataButton);
if (this.options.useLinks) {
this.uploadDataButton.href = "#";
this.uploadDataButton.innerHTML = this.options.uploadDataButtonText;
} else {
this.uploadDataButton.type = "button";
this.uploadDataButton.value = this.options.uploadDataButtonText;
}
this.uploadDataButton.id = this.options.uploadDataButtonId;
this.uploadDataButton.addClassName(this.options.actionButtonClassName);
this.uploadDataButton.onclick = function() {
this.showProgressBar();
this.activities = null;
this.readDataButton.disabled = true;
this.uploadDataButton.disabled = true;
this.checkAllBox.disabled = true;
this._clearActivityTable();
this.garminController.readHistoryFromFitnessDevice();
}.bind(this)
this.readDataElement.appendChild(this.uploadDataButton);
if(!this.options.showUploadDataButton) {
Element.hide(this.uploadDataButton);
}
if(this.options.showReadDataTypesSelect) {
this.readDataTypesSelect = document.createElement("select");
Element.extend(this.readDataTypesSelect);
this.readDataTypesSelect.id = this.options.readDataTypesSelectId;
this.readDataTypesSelect.disabled = true;
this.readDataElement.appendChild(this.readDataTypesSelect);
this.readDataTypesSelect.options[0] = new Option(this.options.gpsData, Garmin.DeviceControl.FILE_TYPES.gpx);
this.readDataTypesSelect.options[1] = new Option(this.options.trainingData, Garmin.DeviceControl.FILE_TYPES.tcx);
}
if(this.options.showReadRoutesSelect) {
this.readRoutesElement = document.createElement("div");
Element.extend(this.readRoutesElement);
this.readRoutesElement.id = this.options.readRoutesElementId;
this.readRoutesElement.addClassName(this.options.readResultsElementClass);
this.readRoutesElement.innerHTML = "<span id=\"" + this.options.readRoutesSelectLabelId + "\">" + this.options.readRoutesSelectLabel + "</span>";
this.readRoutesSelect = document.createElement("select");
Element.extend(this.readRoutesSelect);
this.readRoutesSelect.id = this.options.readRoutesSelectId;
this.readRoutesSelect.addClassName(this.options.readResultsSelectClass);
this.readRoutesSelect.disabled = true;
this.readRoutesSelect.onchange = function() {
this.displayTrack( this._seriesFromSelect(this.readRoutesSelect) );
}.bind(this);
this.readRoutesElement.appendChild(this.readRoutesSelect);
this.readDataElement.appendChild(this.readRoutesElement);
if(!this.options.showReadResultsSelectOnLoad) {
Element.hide(this.readRoutesElement);
}
}
if(this.options.showReadTracksSelect) {
this.readTracksElement = document.createElement("div");
Element.extend(this.readTracksElement);
this.readTracksElement.id = this.options.readTracksElementId;
this.readTracksElement.addClassName(this.options.readResultsElementClass);
this.readTracksElement.innerHTML = "<span id=\"" + this.options.readTracksSelectLabelId + "\">" + this.options.readTracksSelectLabel + "</span>";
this.readTracksSelect = document.createElement("select");
Element.extend(this.readTracksSelect);
this.readTracksSelect.id = this.options.readTracksSelectId;
this.readTracksSelect.addClassName(this.options.readResultsSelectClass);
this.readTracksSelect.disabled = true;
this.readTracksSelect.onchange = function() {
this.displayTrack( this._seriesFromSelect(this.readTracksSelect) );
}.bind(this);
this.readTracksElement.appendChild(this.readTracksSelect);
this.readDataElement.appendChild(this.readTracksElement);
if(!this.options.showReadResultsSelectOnLoad) {
Element.hide(this.readTracksElement);
}
}
if(this.options.showReadWaypointsSelect) {
this.readWaypointsElement = document.createElement("div");
Element.extend(this.readWaypointsElement);
this.readWaypointsElement.id = this.options.readWaypointsElementId;
this.readWaypointsElement.addClassName(this.options.readResultsElementClass);
this.readWaypointsElement.innerHTML = "<span id=\"" + this.options.readWaypointsSelectLabelId + "\">" + this.options.readWaypointsSelectLabel + "</span>";
this.readWaypointsSelect = document.createElement("select");
Element.extend(this.readWaypointsSelect);
this.readWaypointsSelect.id = this.options.readWaypointsSelectId;
this.readWaypointsSelect.addClassName(this.options.readResultsSelectClass);
this.readWaypointsSelect.disabled = true;
this.readWaypointsSelect.onchange = function() {
this.displayWaypoint( this._seriesFromSelect(this.readWaypointsSelect) );
}.bind(this);
this.readWaypointsElement.appendChild(this.readWaypointsSelect);
this.readDataElement.appendChild(this.readWaypointsElement);
if(!this.options.showReadResultsSelectOnLoad) {
Element.hide(this.readWaypointsElement);
}
}
if(this.options.showReadGoogleMap) {
this.readGoogleMap = document.createElement("div");
Element.extend(this.readGoogleMap);
this.readGoogleMap.id = this.options.readGoogleMapId;
this.readGoogleMap.addClassName(this.options.readResultsElementClass);
this.readDataElement.appendChild(this.readGoogleMap);
this.readMapController = new Garmin.MapController(this.options.readGoogleMapId);
}
if(this.options.showReadDataElementOnDeviceFound) {
Element.hide(this.readDataElement);
}
},
_generateActivityDirectoryElement: function() {
this.activityDirectoryElement = document.createElement("div");
Element.extend(this.activityDirectoryElement);
this.activityDirectoryElement.id = this.options.activityDirectoryElementId;
this.activityDirectoryElement.addClassName(this.options.elementClassName);
this.mainElement.appendChild(this.activityDirectoryElement);
},
_generateActivityTableElement: function() {
this.activities = null;
this._generateActivityTableHeader();
this.uploadXmlString = document.createElement("input");
Element.extend(this.uploadXmlString);
this.uploadXmlString.id = "uploadXmlString";
this.uploadXmlString.type = "hidden";
this.uploadXmlString.value = "";
this.activityDirectoryElement.appendChild(this.uploadXmlString);
this.activityDirectoryData = document.createElement("div");
Element.extend(this.activityDirectoryData);
this.activityDirectoryData.id = this.options.activityDirectoryDataId;
this.activityDirectoryElement.appendChild(this.activityDirectoryData);
this.activityTable = document.createElement("table");
Element.extend(this.activityTable);
this.activityTable.id = "activityTable";
this.activityDirectoryData.appendChild(this.activityTable);
this.readSelectedButton = document.createElement( this.options.useLinks ? "a" : "input" );
Element.extend(this.readSelectedButton);
if (this.options.useLinks) {
this.readSelectedButton.href = "#";
this.readSelectedButton.innerHTML = this.options.readSelectedButtonText;
} else {
this.readSelectedButton.type = "button";
this.readSelectedButton.value = this.options.readSelectedButtonText;
}
this.readSelectedButton.id = this.options.readSelectedButtonId;
this.readSelectedButton.addClassName(this.options.actionButtonClassName);
this.readSelectedButton.disabled = false;
this.readSelectedButton.onclick = function() {
if( this._directoryHasSelected() == false) {
alert(this.options.errorActivitySelect);
} else {
this.activities = null;
this.readTracksSelect.length = 0;
this.readSelectedButton.disabled = true;
this.checkAllBox.disabled = false;
this.showProgressBar();
this.fileTypeRead = Garmin.DeviceControl.FILE_TYPES.tcxDetail;
this._populateActivityQueue();
setTimeout(function(){this._readNextSelected();}.bind(this), 0);
}
}.bind(this);
this.activityDirectoryElement.appendChild(this.readSelectedButton);
},
_generateActivityTableHeader: function() {
var selectIndex = 0;
var nameIndex = 1;
var durationIndex = 2;
var statusIndex = 3;
this.activityTableHeader = document.createElement("table");
Element.extend(this.activityTableHeader);
this.activityTableHeader.id = "activityTableHeader";
this.activityTableHeader.cellspacing = 0;
this.activityTableHeader.cellpadding = 0;
var row = this.activityTableHeader.insertRow(0);
var selectCell = row.insertCell(selectIndex);
var nameCell = row.insertCell(nameIndex);
var durationCell = row.insertCell(durationIndex);
var statusCell = row.insertCell(statusIndex);
selectCell.width = '5';
nameCell.width = '65';
durationCell.width = '10';
statusCell.width = '18';
nameCell.align = 'center';
durationCell.align = 'center';
nameCell.innerHTML = this.options.activityDirectoryHeaderDate;
durationCell.innerHTML = this.options.activityDirectoryHeaderDuration;
this.checkAllBox = document.createElement("input");
this.checkAllBox.id = "checkAllBox";
this.checkAllBox.type = "checkbox";
selectCell.appendChild(this.checkAllBox);
this.checkAllBox.onclick = function() { this._checkAllDirectory(); }.bind(this);
this.activityDirectoryElement.appendChild(this.activityTableHeader);
},
_generateWriteDataElement: function() {
this.writeDataElement = document.createElement("div");
Element.extend(this.writeDataElement);
this.writeDataElement.id = this.options.writeDataElementId;
this.writeDataElement.addClassName(this.options.elementClassName);
this.mainElement.appendChild(this.writeDataElement);
if (!this.options.getWriteData && !this.options.getGpiWriteDescription && !this.options.getBinaryWriteDescription)
throw new Error("Can't write data because getWriteData() function nor getGpiWriteDescription() is defined");
this.writeDataButton = document.createElement( this.options.useLinks ? "a" : "input" );
Element.extend(this.writeDataButton);
if (this.options.useLinks) {
this.writeDataButton.href = "#";
this.writeDataButton.innerHTML = this.options.writeDataButtonText;
} else {
this.writeDataButton.type = "button";
this.writeDataButton.value = this.options.writeDataButtonText;
}
this.writeDataButton.id = this.options.writeDataButtonId;
this.writeDataButton.addClassName(this.options.actionButtonClassName);
this.writeDataButton.disabled = true;
this.writeDataButton.onclick = function() {
this.writeDataButton.disabled = true;
this.cancelWriteDataButton.disabled = false;
this.showProgressBar();
this.writeToDevice();
}.bind(this);
this.writeDataElement.appendChild(this.writeDataButton);
this.cancelWriteDataButton = document.createElement( this.options.useLinks ? "a" : "input" );
Element.extend(this.cancelWriteDataButton);
if (this.options.useLinks) {
this.cancelWriteDataButton.href = "#";
this.cancelWriteDataButton.innerHTML = this.options.cancelWriteDataButtonText;
} else {
this.cancelWriteDataButton.type = "button";
this.cancelWriteDataButton.value = this.options.cancelWriteDataButtonText;
}
this.cancelWriteDataButton.id = this.options.cancelWriteDataButtonId;
this.cancelWriteDataButton.addClassName(this.options.actionButtonClassName);
this.cancelWriteDataButton.disabled = false;
this.cancelWriteDataButton.onclick = function() {
this.resetUI();
this.hideProgressBar();
this.getController().cancelWriteToDevice();
}.bind(this);
this.writeDataElement.appendChild(this.cancelWriteDataButton);
if(!this.options.showCancelWriteDataButton) {
Element.hide(this.cancelWriteDataButton);
}
if(this.options.showWriteDataElementOnDeviceFound) {
Element.hide(this.writeDataElement);
}
},
_generateAboutElement: function() {
this.aboutElement = document.createElement("div");
Element.extend(this.aboutElement);
this.aboutElement.id = "aboutElement";
this.aboutElement.addClassName(this.options.elementClassName);
this.mainElement.appendChild(this.aboutElement);
this.copyrightText = document.createElement("span");
this.copyrightText.innerHTML = this.options.poweredByGarmin;
this.aboutElement.appendChild(this.copyrightText);
},
_restrictByDevice: function() {
var device = this.getController().getDevices()[this.deviceSelect.value];
var deviceDescription = device.getDescription();
var deviceModel = deviceDescription.split(" ")[0];
var isSupportedDevice = false;
for(var model in this.options.restrictByDevice) {
if(deviceModel == model) {
isSupportedDevice = true;
}
}
if( !isSupportedDevice ) {
Element.hide(this.findDevicesElement);
Element.hide(this.readDataElement);
this.setStatus(this.options.restrictByDeviceStatusText);
}
return isSupportedDevice;
},
startFindDevices: function() {
this.getController(true);
if(this.findDevicesButton)
this.findDevicesButton.disabled = true;
if (this.cancelFindDevicesButton)
this.cancelFindDevicesButton.disabled = !this.isUnlocked();
if (this.isUnlocked()) {
this.getController().findDevices();
}
},
cancelFindDevices: function() {
this.resetUI();
this.getController().cancelFindDevices();
},
onStartFindDevices: function(json) {
this.setStatus(this.options.lookingForDevices);
},
onFinishFindDevices: function(json) {
this.resetUI();
var devices = [];
if(json.controller.numDevices > 0) {
devices = json.controller.getDevices();
var template = (devices.length == 1) ? this.options.foundDevice : this.options.foundDevices;
var values = {deviceName: devices[0].getDisplayName(), deviceCount: json.controller.numDevices};
this.setStatus( new Template(template).evaluate(values) );
if(this.options.showFindDevicesElement ) {
Element.show(this.findDevicesElement);
if (this.options.showDeviceButtonsOnFound) {
if (this.findDevicesButton && this.options.showFindDevicesButton)
Element.show(this.findDevicesButton);
if (this.cancelFindDevicesButton)
Element.show(this.cancelFindDevicesButton);
} else {
if (this.findDevicesButton)
Element.hide(this.findDevicesButton);
if (this.cancelFindDevicesButton)
Element.hide(this.cancelFindDevicesButton);
}
if ((devices.length < 2 && !this.options.showDeviceSelectOnSingle) || this.options.autoSelectFirstDevice) {
Element.hide(this.deviceSelectElement);
} else {
Element.show(this.deviceSelectElement);
}
this._listDevices(devices);
}
if(this.options.showReadDataElementOnDeviceFound) {
Element.show(this.readDataElement);
}
if(this.options.showSendDataElementOnDeviceFound) {
Element.show(this.sendDataElement);
}
if(this.options.showWriteDataElementOnDeviceFound) {
Element.show(this.writeDataElement);
}
if(this.options.autoHideUnusedReadElements) {
Element.hide(this.activityDirectoryElement);
Element.show(this.readDataElement);
}
if (this.options.autoReadData) {
this.showProgressBar();
if (this.options.showReadDataTypesSelect) {
this.readSpecificTypeFromDevice(this.readDataTypesSelect.value);
} else if (this.options.readDataType != null) {
this.readSpecificTypeFromDevice(this.options.readDataType);
} else {
this.readFromDevice();
}
}
if (this.options.autoWriteData) {
this.showProgressBar();
this.writeToDevice();
}
} else {
if ((this.options.autoReadData || this.options.autoWriteData) && !this.options.showStatusElement) {
alert(this.options.noDeviceDetectedStatusText);
}
this.setStatus(this.options.noDeviceDetectedStatusText);
if(this.options.showFindDevicesElement) {
if (this.options.showFindDevicesButton) {
Element.show(this.findDevicesButton);
}
if (this.options.showCancelFindDevicesButton) {
Element.show(this.cancelFindDevicesButton);
}
if (this.options.showDeviceSelectNoDevice && !this.options.autoSelectFirstDevice) {
Element.show(this.deviceSelectElement);
}
}
}
if (this.options.afterFinishFindDevices) {
this.options.afterFinishFindDevices(devices, this);
}
},
onCancelFindDevices: function(json) {
this.setStatus(this.options.findCancelled);
this.resetUI();
},
_listDevices: function(devices) {
this._clearHtmlSelect(this.deviceSelect);
if(this.options.showFindDevicesElement) {
for( var i=0; i < devices.length; i++ ) {
this.deviceSelect.options[i] = new Option(devices[i].getDisplayName(),devices[i].getNumber());
if(devices[i].getNumber() == this.getController().deviceNumber) {
this.deviceSelect.selectedIndex = i;
}
}
this.deviceSelect.onchange = function() {
var device = this.getController().getDevices()[this.deviceSelect.value];
this.setStatus(this.options.using + device.getDisplayName());
this.getController().setDeviceNumber(this.deviceSelect.value);
}.bind(this)
this.deviceSelect.disabled = false;
}
},
readFromDevice: function() {
var deviceNumber = this.getController().deviceNumber;
var device = this.getController().getDevices()[deviceNumber];
if (device.supportDeviceDataTypeRead(Garmin.DeviceControl.FILE_TYPES.tcx)) {
this.getController().readHistoryFromFitnessDevice();
} else if (device.supportDeviceDataTypeRead(Garmin.DeviceControl.FILE_TYPES.gpx)) {
this.getController().readFromDevice();
} else {
var error = new Error(Garmin.DeviceControl.MESSAGES.invalidFileType);
error.name = "InvalidTypeException";
this.handleException(error);
}
},
readSpecificTypeFromDevice: function(readDataType) {
var deviceNumber = this.getController().deviceNumber;
var device = this.getController().getDevices()[deviceNumber];
switch(readDataType) {
case Garmin.DeviceControl.FILE_TYPES.tcxDir:
this._generateActivityTableElement();
this._clearActivityTable();
case Garmin.DeviceControl.FILE_TYPES.gpx:
case Garmin.DeviceControl.FILE_TYPES.tcx:
case Garmin.DeviceControl.FILE_TYPES.crs:
case Garmin.DeviceControl.FILE_TYPES.wkt:
case Garmin.DeviceControl.FILE_TYPES.tcxProfile:
case Garmin.DeviceControl.FILE_TYPES.crsDir:
this.garminController.readDataFromDevice(readDataType);
break;
case Garmin.DeviceControl.FILE_TYPES.deviceXml:
this.garminController.readDataFromDevice(readDataType);
break;
default:
var error = new Error(Garmin.DeviceControl.MESSAGES.invalidFileType + readDataType);
error.name = "InvalidTypeException";
this.handleException(error);
}
},
onProgressReadFromDevice: function(json) {
if(this.options.showProgressBar) {
this.updateProgressBar(json.progress.getPercentage());
}
this.setStatus(json.progress);
},
onCancelReadFromDevice: function(json) {
this.setStatus(this.options.cancelReadStatusText);
this.resetUI();
},
onFinishReadFromDevice: function(json) {
this.fileTypeRead = json.controller.gpsDataType;
if(this.uploadXmlString != null) {
this.uploadXmlString.value = json.controller.gpsDataString;
}
this.setStatus(this.options.dataReadProcessing);
this.resetUI();
this.clearMapDisplay();
switch(this.fileTypeRead) {
case Garmin.DeviceControl.FILE_TYPES.tcx:
case Garmin.DeviceControl.FILE_TYPES.tcxDir:
case Garmin.DeviceControl.FILE_TYPES.tcxDetail:
this.factory = Garmin.TcxActivityFactory;
break;
case Garmin.DeviceControl.FILE_TYPES.gpx:
this.factory = Garmin.GpxActivityFactory;
break;
default:
var error = new Error( + this.fileTypeRead);
error.name = "InvalidTypeException";
this.handleException(error);
}
if (this.factory != null) {
if( this.activities == null) {
this.activities = new Array();
}
switch(this.fileTypeRead) {
case Garmin.DeviceControl.FILE_TYPES.tcxDir:
this.activities = this.factory.parseDocument(json.controller.gpsData);
this._createActivityDirectory();
break;
case Garmin.DeviceControl.FILE_TYPES.tcxDetail:
this.activities = this.activities.concat( this.factory.parseDocument(json.controller.gpsData) );
if(this.options.uploadSelectedActivities){
this._postActivityToServer();
}
break;
default:
this.activities = this.factory.parseDocument(json.controller.gpsData);
this._applyDataFilters();
break;
}
}
this._finishReadProcessing(json);
},
_applyDataFilters: function() {
var dataFilters = this.options.dataFilters;
if (dataFilters != null) {
for (var i = 0; i < dataFilters.length; i++) {
if (dataFilters[i].run != null) {
dataFilters[i].run(this.activities, garminFilterQueue);
}
}
}
},
_finishReadProcessing: function(json) {
if (garminFilterQueue != null && garminFilterQueue.length > 0) {
setTimeout(function(){this._finishReadProcessing(json);}.bind(this), 500);
} else {
if( this.activityQueue == null || this.activityQueue.length == 0 ) {
if( this.activities != null) {
if( this.fileTypeRead == Garmin.DeviceControl.FILE_TYPES.tcxDir) {
var summary = this._listDirectory(this.activities);
} else {
var summary = this._listActivities(this.activities);
}
this.setStatus( new Template(this.options.dataFound).evaluate(summary) );
}
switch(this.fileTypeRead) {
case Garmin.DeviceControl.FILE_TYPES.gpx:
break;
case Garmin.DeviceControl.FILE_TYPES.tcx:
case Garmin.DeviceControl.FILE_TYPES.crs:
case Garmin.DeviceControl.FILE_TYPES.tcxDir:
case Garmin.DeviceControl.FILE_TYPES.crsDir:
this.deviceSelect.disabled = true;
Element.show(this.activityDirectoryElement);
break;
case Garmin.DeviceControl.FILE_TYPES.tcxDetail:
case Garmin.DeviceControl.FILE_TYPES.crsDetail:
this.readSelectedButton.disabled = false;
this.checkAllBox.disabled = false;
break;
}
}
if (this.options.afterFinishReadFromDevice) {
var dataString = this.factory != null ? this.factory.produceString(this.activities) : json.controller.gpsDataString;
var dataDoc = this.factory != null ? Garmin.XmlConverter.toDocument(dataString): json.controller.gpsData;
this.options.afterFinishReadFromDevice(dataString, dataDoc, json.controller.gpsDataType, this.activities);
}
}
},
_readNextSelected: function() {
this.currentActivity = this.activityQueue.last();
var statusCellIdElement = $(this.currentActivity.replace(/Checkbox/,"Status"));
statusCellIdElement.innerHTML = this.options.statusCellProcessingImg;
this.setStatus(this.options.uploadingActivities);
this.garminController.readDetailFromDevice(this.fileTypeRead, $(this.currentActivity).value);
},
_postActivityToServer: function() {
this.options.postActivityHandler(this.uploadXmlString.value, this);
this.activityQueue.pop();
if(this.activityQueue.length > 0) {
setTimeout(function(){this._readNextSelected();}.bind(this), 0);
}
else {
this.setStatus(this.options.uploadsFinished + "!");
}
},
_clearActivityTable: function() {
while(this.activityTable.rows.length > 0) {
this.activityTable.deleteRow(0);
}
},
_createActivityDirectory: function() {
this.activityDirectory = new Array();
this.activityQueue = new Array();
for( var jj = 0; jj < this.activities.length; jj++) {
this.activityDirectory[jj] = this.activities[jj].getAttribute("activityName");
}
},
_populateActivityQueue: function() {
for( var jj = 0; jj < this.activityDirectory.length; jj++) {
if( $("activityItemCheckbox" + jj).checked == true){
this.activityQueue.push("activityItemCheckbox" + jj);
}
}
this.activityQueue.reverse();
},
_addToActivityTable: function(index, activity) {
var selectIndex = 0;
var nameIndex = 1;
var durationIndex = 2;
var statusIndex = 3;
var activityName = activity.getAttribute("activityName");
var row = this.activityTable.insertRow(this.activityTable.rows.length);
var selectCell = row.insertCell(selectIndex);
var nameCell = row.insertCell(nameIndex);
var durationCell = row.insertCell(durationIndex);
var statusCell = row.insertCell(statusIndex);
selectCell.width = '5';
nameCell.width = '65';
durationCell.width = '10';
statusCell.width = '18';
nameCell.align = 'center';
durationCell.align = 'center';
statusCell.align = 'left';
var checkbox = document.createElement("input");
checkbox.id = "activityItemCheckbox" + index;
checkbox.type = "checkbox";
checkbox.value = activityName;
selectCell.appendChild(checkbox);
statusCell.id = "activityItemStatus" + index;
if( this.fileTypeRead == Garmin.DeviceControl.FILE_TYPES.tcxDir) {
nameCell.innerHTML = activity.getSummaryValue(Garmin.Activity.SUMMARY_KEYS.startTime).getValue().getTimeString();
durationCell.innerHTML = activity.getStartTime().getDurationTo(activity.getEndTime());
}
else if( this.fileTypeRead == Garmin.DeviceControl.FILE_TYPES.crsDir ) {
nameCell.innerHTML = activityName;
}
},
_checkAllDirectory: function() {
for( var boxIndex=0; boxIndex < this.activityDirectory.length; boxIndex++ ) {
$("activityItemCheckbox" + boxIndex).checked = this.checkAllBox.checked;
}
},
_directoryHasSelected: function() {
for( var boxIndex=0; boxIndex < this.activityDirectory.length; boxIndex++ ) {
if ( $("activityItemCheckbox" + boxIndex).checked == true) {
return true;
}
}
return false;
},
_listDirectory: function(activities) {
var numOfTracks = 0;
this._clearHtmlSelect(this.readTracksSelect);
for (var i = 0; i < activities.length; i++) {
var activity = activities[i];
if(this.fileTypeRead == Garmin.DeviceControl.FILE_TYPES.tcxDir || this.fileTypeRead == Garmin.DeviceControl.FILE_TYPES.crsDir) {
this._addToActivityTable(i, activity);
}
numOfTracks++;
}
return {tracks: numOfTracks};
},
_listActivities: function(activities) {
var numOfRoutes = 0;
var numOfTracks = 0;
var numOfWaypoints = 0;
this._clearHtmlSelect(this.readRoutesSelect);
this._clearHtmlSelect(this.readTracksSelect);
this._clearHtmlSelect(this.readWaypointsSelect);
for (var i = 0; i < activities.length; i++) {
var activity = activities[i];
var series = activity.getSeries();
for (var j = 0; j < series.length; j++) {
var curSeries = series[j];
if (curSeries.getSeriesType() == Garmin.Series.TYPES.history) {
this._listTrack(activity, curSeries, i, j);
numOfTracks++;
} else if (curSeries.getSeriesType() == Garmin.Series.TYPES.route) {
this._listRoute(activity, curSeries, i, j);
numOfRoutes++;
} else if (curSeries.getSeriesType() == Garmin.Series.TYPES.waypoint) {
this._listWaypoint(activity, curSeries, i, j);
numOfWaypoints++;
}
}
}
if (this.options.showReadRoutesSelect) {
if(numOfRoutes > 0) {
Element.show(this.readRoutesElement);
this.readRoutesSelect.disabled = false;
this.displayTrack( this._seriesFromSelect(this.readRoutesSelect) );
} else {
Element.hide(this.readRoutesElement);
this.readRoutesSelect.disabled = true;
}
}
if (this.options.showReadTracksSelect) {
if(numOfTracks > 0) {
Element.show(this.readTracksElement);
this.readTracksSelect.disabled = false;
this.displayTrack( this._seriesFromSelect(this.readTracksSelect) );
} else {
Element.hide(this.readTracksElement);
this.readTracksSelect.disabled = true;
}
}
if (this.options.showReadWaypointsSelect) {
if(numOfWaypoints > 0) {
Element.show(this.readWaypointsElement);
this.readWaypointsSelect.disabled = false;
this.displayWaypoint( this._seriesFromSelect(this.readWaypointsSelect) );
} else {
Element.hide(this.readWaypointsElement);
this.readWaypointsSelect.disabled = true;
}
}
return {routes: numOfRoutes, tracks: numOfTracks, waypoints: numOfWaypoints};
},
_listRoute: function(activity, series, activityIndex, seriesIndex) {
if (this.readRoutesSelect) {
var routeName = activity.getAttribute(Garmin.Activity.ATTRIBUTE_KEYS.activityName);
this.readRoutesSelect.options[this.readRoutesSelect.length] = new Option(routeName, activityIndex + "," + seriesIndex);
}
},
_listTrack: function(activity, series, activityIndex, seriesIndex) {
if (this.readTracksSelect) {
var startDate = activity.getSummaryValue(Garmin.Activity.SUMMARY_KEYS.startTime).getValue();
var endDate = activity.getSummaryValue(Garmin.Activity.SUMMARY_KEYS.endTime).getValue();
var values = {date:startDate.getDateString(), duration:startDate.getDurationTo(endDate)}
var trackName = new Template(this.options.trackListing).evaluate(values);
this.readTracksSelect.options[this.readTracksSelect.length] = new Option(trackName, activityIndex + "," + seriesIndex);
}
},
_listWaypoint: function(activity, series, activityIndex, seriesIndex) {
if (this.readWaypointsSelect) {
var wptName = activity.getAttribute(Garmin.Activity.ATTRIBUTE_KEYS.activityName);
this.readWaypointsSelect.options[this.readWaypointsSelect.length] = new Option(wptName, activityIndex + "," + seriesIndex);
}
},
_seriesFromSelect: function(select) {
var indexesStr = select.options[select.selectedIndex].value;
var indexes = indexesStr.split(",", 2);
var activity = this.activities[parseInt(indexes[0])];
var series = activity.getSeries()[parseInt(indexes[1])];
return series;
},
displayTrack: function(series) {
if(this.options.showReadGoogleMap) {
this.readMapController.map.clearOverlays();
this.readMapController.drawTrack(series);
}
},
displayWaypoint: function(series) {
if(this.options.showReadGoogleMap) {
this.readMapController.map.clearOverlays();
this.readMapController.drawWaypoint(series);
}
},
clearMapDisplay: function() {
if(this.options.showReadGoogleMap) {
this.readMapController.map.clearOverlays();
}
},
writeToDevice: function() {
switch( this.options.writeDataType ) {
case Garmin.DeviceControl.FILE_TYPES.gpx :
this.getController().writeToDevice(this.options.getWriteData(), this.options.getWriteDataFileName());
break;
case Garmin.DeviceControl.FILE_TYPES.crs :
this.getController().writeFitnessToDevice(this.options.getWriteData(), this.options.getWriteDataFileName());
break;
case Garmin.DeviceControl.FILE_TYPES.gpi :
var xmlDescription = Garmin.GpiUtil.buildMultipleDeviceDownloadsXML(this.options.getGpiWriteDescription());
this.getController().downloadToDevice(xmlDescription, this.options.getWriteDataFileName());
break;
case Garmin.DeviceControl.FILE_TYPES.binary :
var xmlDescription = Garmin.GpiUtil.buildMultipleDeviceDownloadsXML(this.options.getBinaryWriteDescription());
this.getController().downloadToDevice(xmlDescription, this.options.getWriteDataFileName());
break;
default:
var error = new Error(Garmin.DeviceControl.MESSAGES.invalidFileType + this.options.writeDataType);
error.name = "InvalidTypeException";
this.handleException(error);
}
},
onStartWriteToDevice: function(json) {
this.setStatus(this.options.writingToDevice);
},
onCancelWriteToDevice: function(json) {
this.setStatus(this.options.writingCancelled);
},
onWaitingWriteToDevice: function(json) {
if(confirm(json.message.getText())) {
this.setStatus(this.options.overwritingFile);
json.controller.respondToMessageBox(true);
} else {
this.setStatus(this.options.notOverwritingFile);
json.controller.respondToMessageBox(false);
}
},
onProgressWriteToDevice: function(json) {
if(this.options.showProgressBar) {
this.updateProgressBar(json.progress.getPercentage());
}
this.setStatus( json.progress.percentage==100 ? this.options.dataDownloadProcessing : json.progress );
},
onFinishWriteToDevice: function(json) {
this.setStatus(this.options.writtenToDevice);
this.resetUI();
if (this.options.afterFinishWriteToDevice) {
this.options.afterFinishWriteToDevice(json.success, this);
}
},
getController: function(unlock) {
if (!this.garminController) {
try {
this.garminController = new Garmin.DeviceControl();
this.garminController.register(this);
this.garminController.setPluginRequiredVersion(this.options.pluginRequiredVersion);
this.garminController.setPluginLatestVersion(this.options.pluginLatestVersion);
this.garminController.validatePlugin();
} catch (e) {
this.handleException(e);
return null;
}
}
if (!this.error && unlock && !this.isUnlocked()) {
if(this.garminController.unlock(this.options.pathKeyPairsArray)) {
this.setStatus(this.options.pluginUnlocked);
} else {
this.setStatus(this.options.pluginNotUnlocked);
}
this.garminRemoteTransfer = new Garmin.RemoteTransfer();
}
return this.garminController;
},
isUnlocked: function() {
return (this.garminController && this.garminController.isUnlocked());
},
setOptions: function(options) {
for(key in options || {}) {
if ( ! (key in Garmin.DeviceDisplayDefaultOptions) ) {
var err = new Error(key+" is not a valid option name, see Garmin.DeviceDisplayDefaultOptions");
err.name = "InvalidOptionException";
throw err;
}
}
this.options = Object.extend(Garmin.DeviceDisplayDefaultOptions, options || {});
},
_clearHtmlSelect: function(select) {
if(select) {
select.length = 0;
}
},
setStatus: function(statusText) {
if(this.options.showStatusElement) {
var statusDisplayString;
if( this.options.showDetailedStatus) {
statusDisplayString = this._buildDescriptiveStatusString(statusText);
} else {
if( statusText.getText ) {
if( statusText.getText() instanceof Array) {
statusDisplayString = statusText.getText()[0];
}
} else {
statusDisplayString = statusText;
}
}
this.statusText.innerHTML = statusDisplayString;
}
},
_buildDescriptiveStatusString: function(statusText) {
var resultString = statusText;
if( statusText.getTitle ) {
resultString = statusText.getTitle() + "<br />";
}
if( statusText.getText ) {
resultString += statusText.getText();
}
return resultString;
},
showProgressBar: function() {
if(this.options.showStatusElement && this.options.showProgressBar) {
Element.show(this.progressBar);
}
},
hideProgressBar: function() {
if(this.options.showStatusElement && this.options.showProgressBar) {
Element.hide(this.progressBar);
}
},
updateProgressBar: function(value) {
if(this.options.showStatusElement && this.options.showProgressBar && value) {
var percent = (value <= 100) ? value : 100;
this.progressBarDisplay.style.width = percent + "%";
}
},
onException: function(json) {
this.handleException(json.msg);
},
handleException: function(error) {
this.error = true;
if (this.options.customExceptionHandler) {
this.options.customExceptionHandler(error, this);
} else {
this.defaultExceptionHandler(error);
}
},
defaultExceptionHandler: function(error) {
var errorStatus;
var hideFromBrowser = false;
if(error.name == "BrowserNotSupportedException") {
errorStatus = error.message;
if (this.options.hideIfBrowserNotSupported) {
hideFromBrowser = true;
}
} else if (error.name == "PluginNotInstalledException" || error.name == "OutOfDatePluginException") {
errorStatus = error.message;
errorStatus += " <a href=\""+Garmin.DeviceDisplay.LINKS.pluginDownload+"\" target=\"_blank\">" + this.options.downloadAndInstall + "</a>";
} else if (Garmin.PluginUtils.isDeviceErrorXml(error)) {
errorStatus = Garmin.PluginUtils.getDeviceErrorMessage(error);
} else {
errorStatus = error.name + ": " + error.message;
}
this.setStatus(errorStatus);
this.resetUI();
if (!this.options.showStatusElement && !hideFromBrowser) {
if (error.name == "PluginNotInstalledException" || error.name == "OutOfDatePluginException") {
if (window.confirm(error.message+"\n" + this.options.installNow)) {
window.open(Garmin.DeviceDisplay.LINKS.pluginDownload, "_blank");
}
} else {
alert(errorStatus);
}
}
}
};
Garmin.DeviceDisplay.LINKS = {
pluginDownload: "http://www.garmin.com/products/communicator/"
};
var garminFilterQueue = new Array();
Garmin.DeviceDisplayDefaultOptions = function(){};
Garmin.DeviceDisplayDefaultOptions = {
unlockOnPageLoad: true,
pathKeyPairsArray: ["file:///C:/dev/", "bd04dc1f5e97a6ff1ea76c564d133b7e"],
elementClassName: "pluginElement",
useLinks: false,
hideIfBrowserNotSupported: false,
customExceptionHandler: null,
actionButtonClassName: "actionButton",
autoHideUnusedReadElements: false,
showStatusElement: true,
showDetailedStatus: true,
statusElementId: "statusBox",
statusTextId: "statusText",
showProgressBar: true,
progressBarId: "progressBar",
progressBarDisplayId: "progressBarDisplay",
showFindDevicesElement: true,
showFindDevicesElementOnLoad: true,
autoFindDevices: false,
showDeviceButtonsOnFound: true,
showDeviceButtonsOnLoad: true,
showFindDevicesButton: true,
findDevicesElementId: "deviceBox",
findDevicesButtonId: "findDevicesButton",
findDevicesButtonText: "Find Devices",
showCancelFindDevicesButton: false,
cancelFindDevicesButtonId: "cancelFindDevicesButton",
cancelFindDevicesButtonText: "Cancel Find Devices",
showDeviceSelectOnSingle: false,
showDeviceSelectNoDevice: false,
showDeviceSelectOnLoad: true,
autoSelectFirstDevice: false,
deviceSelectElementId: "deviceSelectBox",
deviceSelectLabel: "Devices: ",
deviceSelectLabelId: "deviceSelectLabel",
deviceSelectId: "deviceSelect",
deviceSelectedElementId: "deviceSelected",
deviceSelectedLabel: "Previewing ",
deviceSelectedLabelId: "deviceSelectedLabel",
noDeviceDetectedStatusText: "No devices found.",
singleDeviceDetectedStatusText: "Found ",
afterFinishFindDevices: null,
autoReadData: false,
showReadDataElement: true,
showActivityDirectoryElement: true,
activityDirectoryElementId: "activityDirectory",
uploadDataButtonId: "uploadDataButton",
uploadDataButtonText: "Upload",
readSelectedButtonId: "readSelectedButton",
readSelectedButtonText: "Upload Selected",