;(function($){
    $.lxRemoteTimer = function(options) {
        var iTimeoutId = null;

        var iLocalTime = 0;
        var iLiveTime = 0;

        var bRunning = false;
        var bStopping = false;

        var defaults = {
            timerInterval: 1000
        };
        var o = $.extend(defaults, options);

        init();

        function init() {
        }

        function startTimer() {
            if (bRunning === false) {
                bStopping = false;
                resetWindowTimeout();
                return true;
            }

            return false;
        }

        function stopTimer() {
            if (bRunning === true && bStopping === false) {
                bStopping = true;
                return true;
            }
        }

        function resetWindowTimeout() {
            if (bStopping === false) {

                if (iTimeoutId != null) {
                    window.clearTimeout(iTimeoutId);
                    iTimeoutId = null;
                }
                if (iTimeoutId == null) {
                    iTimeoutId = window.setTimeout(onTimeout, o.timerInterval);
                }
                
            } else {
                bStopping = false;
            }
        }

        function onTimeout() {
            iLocalTime = updateLocalTime();
            $(window).trigger("timerelapsed", this);

            startTimer();
        }

        function bindOnTimerElapsed(fnCallback) {
            $(window).bind("timerelapsed", fnCallback);
        }

        function updateLiveTimeFromParticipantPositionXhr(aryData, oXhr) {
            iLocalTime = updateLocalTime();
            iLiveTime = getLivetimeFromParticipantPosition(aryData);
        }

        /*
        function getHttpDateHeaderFromXhr(oXhr) {
            if (oXhr == undefined || oXhr == null) {
                throw("No valid XMLHttpRequest object given for time determination");
            }

            var strHttpDateHeader = oXhr.getResponseHeader("Date");
            return strHttpDateHeader;
        }


        function getSrvOffsetFromDateHttpHeader(strHttpDateHeader) {
            var oSrvTimeUtc = Date.parse(new Date(Date.parse(strHttpDateHeader)).toUTCString());
            var oLocTimeUtc = getLocalTime();

            var offset = oSrvTimeUtc -  oLocTimeUtc;
            return offset;
        }
        */

        function updateLocalTime() {
            iLocalTime = parseInt(Date.parse(new Date().toUTCString()) / 1000);
            return iLocalTime;
        }

        function getLocalTime() {
            return iLocalTime;
        }

        function getLivetimeFromParticipantPosition(aryPos) {
            if (aryPos == undefined || aryPos == null)
                return 0;

            var liveTime = parseInt(aryPos.t);
            if (isNaN(liveTime)) 
                return 0;

            return liveTime;
        }

        function calculateEffectiveTime() {
            return iLocalTime - iLiveTime;
        }

        function getLiveTime() {
            return iLiveTime;
        }

        function setLiveTime(time) {
            iLiveTime = time;
        }

        function getTimerInterval() {
            return o.timerInterval;
        }

        function setTimerInterval(iIntervalInMs) {
            o.timerInterval = iIntervalInMs;
        }

        var publicInterface = {
            calculateEffectiveTime: calculateEffectiveTime,
            getLocalTime: getLocalTime,
            getLiveTime: getLiveTime,
            setLiveTime: setLiveTime,
            updateLiveTimeFromParticipantPositionXhr: updateLiveTimeFromParticipantPositionXhr,
            startTimer: startTimer,
            stopTimer: stopTimer,
            bindOnTimerElapsed: bindOnTimerElapsed,
            getTimerInterval: getTimerInterval,
            setTimerInterval: setTimerInterval
        };

        return publicInterface;
    },
    $.lxMarker = function(options) {

        var ctlGMarker = null;
        var iCurIdx = 0;

        var defaults = {
            starterId: "",
            map: {},
            coords: [],
            icon: {
                width: 32,
                height: 32,
                primaryColor: "#ff0000",
                strokeColor: "#000000",
                cornerColor: "#ffffff",
                gChartBaseUrl: "http://chart.apis.google.com/chart?cht=mm"
            }
        };

        var o = $.extend(true, defaults, options);

        init();

        function init() {
            initMarker();
        }

        function initMarker() {
            var opts = $.extend(
                            createMarkerIconAndShadowOpts(),
                            {map: o.map}
                       );
            ctlGMarker = new google.maps.Marker(opts);
        }

        function createMarkerIconAndShadowOpts() {

            var iconUrl = o.icon.gChartBaseUrl +
                          "&chs=" + o.icon.width + "x" +  o.icon.height +
                          "&chco=" +  o.icon.cornerColor.replace("#", "") + "," +
                           o.icon.primaryColor.replace("#", "") + "," +
                           o.icon.strokeColor.replace("#", "") +
                           "&ext=.png";

            var shadowUrl = o.icon.gChartBaseUrl +
                      "&chs=" +  o.icon.width + "x" + o.icon.height +
                      "&chco=" + o.icon.cornerColor.replace("#", "") + "," +
                      o.icon.primaryColor.replace("#", "") + "," +
                      o.icon.strokeColor.replace("#", "") +
                      "&chf=a,s,ffffff11&ext=.png";

            var opts = {
                icon: iconUrl,
                shadow: shadowUrl
            }

            return opts;
        }

        function updateMarkerPositionByParticipantPosition(oPos) {
            if (oPos == undefined || oPos == null) {
                return -1;
            }

            var fDistance = calculateDistanceFromParticipantPosition(oPos);
            var idx  = findBestCoordsIdxForDistance(fDistance);

            updateGMarkerPositionByCoordsIdx(oPos, idx, fDistance);

            fireCoordsIdxChangedIfNeccessary(idx);
            fireDistanceChanged(fDistance, oPos);

            return idx;
        }

        function calculateDistanceFromParticipantPosition(oPos) {

            var t  = parseFloat(oPos.t);
            var x0 = parseFloat(oPos.x);
            var v  = parseFloat(oPos.v);

            var x = x0 + v * t;
            return x;
        }

        function findBestCoordsIdxForDistance(fDist) {
            var idx;

            for (var i = 0; i < o.coords.length; i++) {
                var fCDist = o.coords[i].d;

                if (fCDist > fDist)
                    return Math.max(i - 1, 0);
            }

            return getCoordsLastIdx();
        }

        function updateGMarkerPositionByCoordsIdx(oPos, idx, fDistance) {
            var latLng = null;
            var lastIdx = getCoordsLastIdx();

            if (lastIdx < 1 || idx == lastIdx) {
                var aryLatLngCoords = o.coords[idx].c;
                latLng = createGLatLngFromCoords(aryLatLngCoords);
            } else {
                var c1 = o.coords[idx];
                var c2 = o.coords[idx + 1];

                var dir = calculateDirectionFormPoints(c1.c, c2.c);
                var lambda = calculateLambdaFromDistance(c1.d, c2.d, fDistance);

                latLng = createInterpolatedGLatLng(c1.c, dir, lambda);
            }

            ctlGMarker.setPosition(latLng);
        }

        /*
        function calculateUnitVectorFormPoints(p1, p2) {
            var v = [p2[0] - p1[0], p2[1] - p1[1]];
            var length = Math.sqrt(v[0]*v[0] + v[1]*v[1]);

            return [v[0] / length, v[1] / length];
        }
        */

        function calculateDirectionFormPoints(p1, p2) {
            var v = [p2[0] - p1[0], p2[1] - p1[1]];
            return v;
        }

        function calculateLambdaFromDistance(dp1, dp2, dpos) {
            var length = Math.abs(dp2 - dp1);
            var dist = Math.abs(dpos - dp1);

            return dist / length;
        }

        function createInterpolatedGLatLng(p1, dir, lambda) {
            var lng = p1[0] + lambda * dir[0];
            var lat = p1[1] + lambda * dir[1];

            return createGLatLngFromCoords([lng, lat]);
        }

        function createGLatLngFromCoords(aryLatLngCoords) {
            var dLng = aryLatLngCoords[0];
            var dLat = aryLatLngCoords[1];
            var latLng = new google.maps.LatLng(dLat,dLng);

            return latLng;
        }

        function getCoordsLastIdx() {
             return (o.coords.length - 1)
        }

        function fireCoordsIdxChangedIfNeccessary(idx) {
            var changed = false;

            if (idx != iCurIdx) {
                var args = {
                    starterId: getStarterId(),
                    idx: idx
                }

                $(window).trigger("coordsidxchanged", args);
                changed = true;
            }

            iCurIdx = idx;
            return changed;
        }

        function fireDistanceChanged(fDistance, oPos) {
            var args = {
                starterId: getStarterId(),
                distance: fDistance,
                pos: oPos
            }

            $(window).trigger("distancechanged", args);
        }

        function removeFromMap() {
            ctlGMarker.setMap(null);
        }

        function getStarterId() {
            return o.starterId;
        }

        function setStarterId(newStarterId) {
            o.starterId = newStarterId;
        }

        var publicInterface = {
            calculateDistanceFromParticipantPosition: calculateDistanceFromParticipantPosition,
            updateMarkerPositionByParticipantPosition: updateMarkerPositionByParticipantPosition,
            removeFromMap: removeFromMap,
            getStarterId: getStarterId,
            setStarterId: setStarterId
        };

        return publicInterface;
    },
    $.fn.extend({

        lxMarathonLive: function(options) {
            var elLive = null;
            var ctlMap = null;
            var aryMarkers = {};
            var aryKmlLayers = [];
            var oTimer = null;
            var aryPos = null;
            var iWaypointCount = 0;
            var iTimerCount = 0;
            var bUpdateRunning = false;

            var defaults = {
                participantPositionUrl: null,
                kmlLayers: [],
                timerInterval: 1000,
                coords: {},
                waypointUpdateThreshold: 2,
                timerUpdateThreshold: 12500
            };
            var o = $.extend(defaults, options);

            function init() {
                initTimer();
                initMap();
                initParticipantSelectionListener();
                updateParticipantPositions();
                initMarkerEventHandlers();
            }

            function updateParticipantPositions() {
                bUpdateRunning = true;
                var url = getPositionsQueryUrl();

                $.getJSON(url, function(oData, strTextStatus, oXhr) {
                    aryPos = oData;
                    
                    oTimer.updateLiveTimeFromParticipantPositionXhr(aryPos, oXhr);
                    oTimer.startTimer();

                    bUpdateRunning = false;
                });
            }

            function getPositionsQueryUrl() {
                if (o.participantPositionUrl == null)
                    return false;

                var starterIdsCsv = "";
                var url = o.participantPositionUrl;
                
                for(var strKey in aryMarkers) {
                    var ctlMarker = aryMarkers[strKey];
                    starterIdsCsv += ctlMarker.getStarterId() + ",";
                }
                starterIdsCsv = "" + starterIdsCsv.substring(0, starterIdsCsv.length-1);

                if (starterIdsCsv.length > 0) {
                    url += "/q/" + starterIdsCsv;
                }

                return url;
            }

            function initMap() {
                maximizeMapContainer();
                createGoogleMapsCtrl();
                addKmlLayersToMap();
                bindEventListeners();
            }

            function maximizeMapContainer() {
                var height = Math.floor($(window).height() * 0.80);

                elLive.children().remove();
                elLive.width("100%");
                elLive.height(height);
            }

            function createGoogleMapsCtrl() {
                var options = {
                      backgroundColor: "transparent",
                      disableDefaultUI: true,
                      mapTypeControl: false,
                      mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
                      navigationControl: true,
                      navigationControlOptions: {style: google.maps.NavigationControlStyle.ANDROID},
                      mapTypeId: google.maps.MapTypeId.ROADMAP
                }
                ctlMap = new google.maps.Map(elLive[0], options);
            }

            function addKmlLayersToMap() {
                for(var i = 0; i < o.kmlLayers.length; i++) {
                    var layer = new google.maps.KmlLayer(o.kmlLayers[i]);
                    layer.setMap(ctlMap);
                    aryKmlLayers.push(layer);
                }
            }

            function bindEventListeners() {
                google.maps.event.addListener(ctlMap, 'zoom_changed', onMapZoomChanged);
            }

            function onMapZoomChanged() {
                updateTimerIntervalByZoomLevel();
            }

            function updateTimerIntervalByZoomLevel() {
                var zoom = ctlMap.getZoom();
                
                if (zoom > 15) {
                    oTimer.setTimerInterval(500);
                } else if (zoom > 13) {
                    oTimer.setTimerInterval(1000);
                } else if (zoom > 11) {
                    oTimer.setTimerInterval(2000);
                } else {
                    oTimer.setTimerInterval(4000);
                }
            }

            function initTimer() {
                oTimer = $.lxRemoteTimer({
                    timerInterval: o.timerInterval
                });
                oTimer.bindOnTimerElapsed(onTimerElapsed);
            }

            function onTimerElapsed() {
                if (bUpdateRunning)
                    return;

                updateEffektiveTimesInPosAry(aryPos);

                for(var strKey in aryMarkers) {
                    if (keyExists(aryPos, strKey) == false)
                        continue;
                    
                    var oPos = aryPos[strKey];
                    var ctlMarker = aryMarkers[strKey];
                    ctlMarker.updateMarkerPositionByParticipantPosition(oPos);
                }

                updateIfNeccessaryOnTimerElapsed();
            }

            function updateEffektiveTimesInPosAry(aryPos) {
                var effTime = oTimer.calculateEffectiveTime();

                for(var strKey in aryPos) {
                    var oPosEntry = aryPos[strKey];
                    oPosEntry.t = effTime;
                }

                return aryPos;
            }

            function updateIfNeccessaryOnTimerElapsed() {
                if (bUpdateRunning)
                    return;

                iTimerCount++;

                var nMarkers = getObjectSize(aryMarkers);
                if (nMarkers == 0)
                    return;

                var effTimerCount = Math.floor(iTimerCount / Math.max(1.0, nMarkers));
                var effThreshold = Math.ceil(o.timerUpdateThreshold / oTimer.getTimerInterval())

                var shouldUpdate = effTimerCount > effThreshold ? true : false;

                if (shouldUpdate == true) {
                    if (nMarkers > 0)
                        updateParticipantPositions();
                    
                    iTimerCount = 0;
                }
            }

            function initParticipantSelectionListener() {
                $(window).bind("participantselected", onParticipantSelected);
                $(window).bind("participantunselected", onParticipantUnselected);
            }

            function onParticipantSelected(eArgs, oSelectionArgs) {
                if (keyExists(aryMarkers, oSelectionArgs.starterId))
                    return;
                
                if(createMarkerBySelectionArgs(oSelectionArgs) == true)
                    updateParticipantPositions();
            }

            function createMarkerBySelectionArgs(oSelectionArgs) {
                var starterId = oSelectionArgs.starterId;
                var eventId = oSelectionArgs.eventId;
                var coords = getCoordsByEventId(eventId);

                if (coords == null || coords.length == 0)
                    return false;

                var ctlMarker = $.lxMarker({
                    starterId: starterId,
                    map: ctlMap,
                    coords: coords,
                    icon: {
                        primaryColor: oSelectionArgs.legendColor
                    }
                });
                
                aryMarkers[starterId] = ctlMarker;
                return true;
            }

            function getCoordsByEventId(iEventId) {
                if (o.coords && o.coords[iEventId]) {
                    return o.coords[iEventId];
                }

                return [];
            }

            function keyExists(aryHaystack, strNeedle) {
                if (aryHaystack[strNeedle] != undefined && aryHaystack[strNeedle] != null)
                    return true;

                return false;
            }

            function onParticipantUnselected(eArgs, oSelectionArgs) {
                var starterId = oSelectionArgs.starterId;

                if (keyExists(aryMarkers, starterId) == false)
                    return;

                var ctlMarker = aryMarkers[starterId];
                ctlMarker.removeFromMap();

                aryMarkers[starterId] = undefined;
                delete aryMarkers[starterId];
            }

            function initMarkerEventHandlers() {
                $(window).bind("coordsidxchanged", onCoordsIdxChanged);
            }

            function onCoordsIdxChanged(elArgs, oCoordsChangedArgs) {
                if (bUpdateRunning)
                    return;

                iWaypointCount++;
                
                var idx = oCoordsChangedArgs.idx;
                var nMarkers = Math.max(1.0, getObjectSize(aryMarkers));
                var effWaypointCount = Math.floor(iWaypointCount / nMarkers);

                var shouldUpdate = effWaypointCount >= o.waypointUpdateThreshold ? true : false;
                //shouldUpdate = shouldUpdate == false ? o.coords[idx].r : shouldUpdate;
               
                if (shouldUpdate == true) {
                    updateParticipantPositions();
                    
                    iWaypointCount = 0;
                    iTimerCount = 0;
                }
            }

            function getObjectSize(aryObj) {
                var i = 0;
                for(var strKey in aryObj) {
                    i++
                }

                return i;
            }

            function shouldDoRefreshAtCoord(idx) {
                var coord = o.coords[idx];
                if (coord == null)
                    return false;

                if (coord.t == undefined || coord.t == null)
                    return false;

                if (coord.t == false || coord.t == 0)
                    return false;

                return true;
            }

            return this.each(function() {
                    elLive = $(this);
                    init();
            });
        },

        lxMarathonLiveSearch: function(options) {
            
            var elSearch = null;
            var elSearchInput = null;
            var elBtnSearchSubmit = null;
            var elBtnSearchCancel = null;
            var elBtnLiveSelectedHeader = null;

            var defaults = {
                selSearchInput: "#live-search-input",
                selBtnSearchSubmit: "#live-search-submit",
                selBtnSearchCancel: "#live-search-cancel",
                selLiveSelectedHeader: "#live-selected-header",
                selResultTable: "#live-search-results",
                selSelectedTable: "#live-selected-results",
                selLoadIndicator: ".live-search-running-indicator",
                selBtnAction: ".col-action a",
                animatedShowSelectedResultsInterval: 800,
                maxSelCount: 5
            };

            var o = $.extend(defaults, options);

            function init() {
                initAccordion();
                initSearchInput();
                initLiveSearchButtons();
                initLiveSelectedHeader();
                initMarkerEventHandlers();
            }

            function initAccordion() {
                elSearch.accordion({
                    disabled: true,
                    autoHeight: false,
                    collapsible: true,
                    active: false,
                    //animated: false,
                    event: "undefined"
                });
            }

            function initSearchInput() {
                elSearchInput = $(o.selSearchInput, elSearch);
                elSearchInput.focus(onSearchInputFocus);
                elSearchInput.placeholder();
            }

            function onSearchInputFocus() {
                elSearchInput.unbind("focus", onSearchInputFocus);

                var activeIdx = elSearch.accordion("option", "active");
                if (activeIdx !== 0) 
                    activateAccordionElement(0);

                if (searchInputIsPlaceholder())
                    elSearchInput.val("");

                elSearchInput.focus();
                elSearchInput.bind("focus", onSearchInputFocus);
            }

            function initLiveSearchButtons() {
                elBtnSearchSubmit = $(o.selBtnSearchSubmit, elSearch);
                elBtnSearchSubmit.click(onBtnSearchSubmitClick);

                elBtnSearchCancel = $(o.selBtnSearchCancel, elSearch);
                elBtnSearchCancel.click(onBtnSearchCancelClick);

                var elForm = elSearchInput.closest("form");
                elForm.submit(onSearchFormSubmit);
            }

            function onBtnSearchSubmitClick() {
                var url = getQueryUrl();
                
                if (searchInputIsPlaceholderOrEmpty())
                    return false;

                clearResultsTable();
                showLoadIndicator();
                loadSearchResultsAndAppendToTable(url);

                return false;
            }

            function onSearchFormSubmit() {
                elBtnSearchSubmit.click();
                return false;
            }

            function getQueryUrl() {
                var elForm = elSearchInput.closest("form");

                var action = elForm.attr("action");
                var query = elForm.serialize();
                var url = action + "?" + query;

                return url;
            }

            function searchInputIsPlaceholderOrEmpty() {
                var value = elSearchInput.val();

                if (value == null || value.length == 0)
                    return true;

                return searchInputIsPlaceholder();
            }

            function searchInputIsPlaceholder() {
                var value = elSearchInput.val();
                var placeholder = elSearchInput.attr("placeholder")

                if (value === placeholder)
                    return true;

                return false;
            }

            function clearResultsTable() {
                var elResultsTable = $(o.selResultTable, elSearch);
                $(o.selBtnAction, elResultsTable).unbind("click", onBtnSearchActionClick);

                elResultsTable.html("");
            }

            function showLoadIndicator() {
                var elLoadIndicator = $(o.selLoadIndicator, elSearch);
                elLoadIndicator.show("fast");
            }

            function loadSearchResultsAndAppendToTable(url) {
                var elResultsTable = $(o.selResultTable, elSearch);
                var elLoadIndicator = $(o.selLoadIndicator, elSearch);

                $.get(url, function(data) {
                            elLoadIndicator.fadeOut("fast", function() {
                                elResultsTable.html(data);
                                $(o.selBtnAction, elResultsTable).bind("click", onBtnSearchActionClick);
                            });
                });
            }

            function onBtnSearchCancelClick() {
                elSearchInput.val("");
                elSearchInput.placeholder();
                activateAccordionElement(0);
                clearResultsTable();

                return false;
            }

            function initLiveSelectedHeader() {
                elBtnLiveSelectedHeader = $(o.selLiveSelectedHeader, elSearch);
                elBtnLiveSelectedHeader.click(onLiveSelectedHeaderClick);
            }

            function onLiveSelectedHeaderClick() {
                activateAccordionElement(1);
            }

            function onBtnSearchActionClick() {
                var elBtnAction = $(this);
                moveResultsTableRowToSelectedResults(elBtnAction);

                return false;
            }

            function onBtnSelectedActionClick() {
                var elBtnAction = $(this);
                removeSelectedTableRow(elBtnAction);

                return false;
            }

            function moveResultsTableRowToSelectedResults(elBtnAction) {
                var elSelectedTable = $(o.selSelectedTable, elSearch);

                if (rowIsAlreadyInSelectedResults(elBtnAction)) {
                    return;
                }

                if (getSelectedRunnersCount() >= o.maxSelCount) {
                    return;
                }

                var elTableRow = elBtnAction.closest("tr").remove();
                elTableRow.appendTo(elSelectedTable);

                var starterId = getStarterIdFromActionButton(elBtnAction);
                var eventId = getEventIdFromActionButton(elBtnAction);
                var strColor = setLegendColorOnTableRow(elTableRow);
                fireParticipantSelected({
                    starterId: starterId,
                    legendColor: strColor,
                    eventId: eventId
                });

                elBtnAction.unbind("click", onBtnSearchActionClick);
                elBtnAction.bind("click", onBtnSelectedActionClick);

                animatedShowSelectedResults();
            }

            function rowIsAlreadyInSelectedResults(elBtnAction) {
                var elSelectedTable = $(o.selSelectedTable, elSearch);

                var filter = "a[href='" + elBtnAction.attr("href") + "']";
                if ($(o.selBtnAction, elSelectedTable).filter(filter).size() > 0)     
                    return true;
                
                return false;
            }

            function getSelectedRunnersCount() {
                var elSelectedTable = $(o.selSelectedTable, elSearch);
                return $(o.selBtnAction, elSelectedTable).size();
            }

            function setLegendColorOnTableRow(elTableRow) {
                var elTdLegend = $(".col-legend", elTableRow);
                var color = randomHexColor();
                elTdLegend.css("background-color", color);

                return color;
            }

            function randomHexColor() {
                var hexDigits = '0123456789abcdef'.split('');

                var color = "#";
                for (var i = 0; i < 6; i++) {
                    var idx = Math.round(Math.random() * 15);
                    color += hexDigits[idx];
                }

                return color;
            }

            function removeSelectedTableRow(elBtnAction) {
                elBtnAction.closest("tr").remove();
                elBtnAction.unbind("click", onBtnSelectedActionClick);

                var starterId = getStarterIdFromActionButton(elBtnAction);
                fireParticipantUnselect({
                    starterId: starterId
                });
            }

            function fireParticipantSelected(oSelectionArgs) {
                $(window).trigger("participantselected", oSelectionArgs);
            }

            function fireParticipantUnselect(oSelectionArgs) {                
                $(window).trigger("participantunselected", oSelectionArgs);
            }

            function getStarterIdFromActionButton(elBtnAction) {
                return getTokenFromActionButton(elBtnAction, 0, 0);
            }

            function getEventIdFromActionButton(elBtnAction) {
                var sEventId = getTokenFromActionButton(elBtnAction, 1, 0)
                return parseInt(sEventId, 10);
            }

            function getTokenFromActionButton(elBtnAction, idx, defValue) {
                var href = elBtnAction.attr("href").substring(1);
                var tokens = href.split(",");
                
                return tokens.length > idx ? tokens[idx] : defValue;
            }

            function animatedShowSelectedResults() {
                elBtnLiveSelectedHeader.click();
                window.setTimeout(function() {
                        elSearchInput.focus();
                }, o.animatedShowSelectedResultsInterval);
            }

            function activateAccordionElement(idx) {
                elSearch.accordion("enable");
                elSearch.accordion("activate", idx);
                elSearch.accordion("disable");
            }

            function initMarkerEventHandlers() {
                $(window).bind("distancechanged", onDistanceChanged);
            }

            function onDistanceChanged(elArgs, oDistanceChangedArgs) {
                var elTdDistance = getTableCellDinstance(oDistanceChangedArgs);

                var oPos = oDistanceChangedArgs.pos;
                var fDistance = oDistanceChangedArgs.distance;

                if (oPos != null && oPos.s < 0) {
                    elTdDistance.html("Aufgegeben");
                }
                else if (oPos != null && oPos.s == 0) {
                    elTdDistance.html("Am Start");
                }
                else if (oPos != null && oPos.s > 2) {
                    elTdDistance.html("Im Ziel");
                }
                else if (fDistance > 0.0) {
                    fDistance = fDistance / 1000.0
                    var fKmDistance = Math.round(fDistance * 10.0) / 10.0
                    var distanceStr = fKmDistance.toFixed(1) + "km";
                    elTdDistance.html(distanceStr);
                } else {
                    elTdDistance.html("");
                }
            }

            function getTableCellDinstance(oDistanceChangedArgs) {
                
                /*
                var elSelectedTable = $(o.selSelectedTable, elSearch);
                var filter = "a[href=^'#" + oDistanceChangedArgs.starterId + "']";
                var elButtonAction = $(o.selBtnAction, elSelectedTable).filter(filter);
                var elTr = elButtonAction.closest("tr");
                */

                var selector = "#starter-id-" + oDistanceChangedArgs.starterId;
                var elTr = $(selector);

                var elTdDistance = $(".col-distance", elTr);

                return elTdDistance;
            }

            return this.each(function() {
                    elSearch = $(this);
                    init();
            });

        }
    });

})(jQuery);
