<commit_before>var transit = (function () {
    return {
        initMap : function () {
            var mapDet = {
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };

            var map = new google.maps.Map(document.getElementById('transitMap'), mapDet);
            return map;
        },

        initMarker : function (coords, mouseoverText, map) {
            mouseoverText = (typeof mouseoverText == 'undefined') ? 'Marker' : mouseoverText;
            var markerPos = new google.maps.LatLng(coords[0], coords[1]);

            var markerIcon = {
                path: google.maps.SymbolPath.CIRCLE,
                fillColor: 'red',
                fillOpacity: 0.8,
                scale: 5
            };

            var mouseoverInfo = new google.maps.InfoWindow({
                content: mouseoverText,
                map: map
            });

            var marker = {
                position: markerPos,
                title: mouseoverText,
                icon: markerIcon
            };

            marker = new google.maps.Marker(marker);

            google.maps.event.addListener(marker, 'mouseover', function() {
            	mouseoverInfo.open(map, this);
            });

            google.maps.event.addListener(marker, 'mouseout', function() {
            	mouseoverInfo.close();
            });

            return marker;
        },

        moveMarkers : function (markerSet, interval, map) {
            interval = (typeof interval == 'undefined') ? 1000 : interval;
            var transition = setInterval(
                    function () {
                        for (var counter = 0; counter < markerSet.length; counter++) {
                            for (var i = 0; i < markerSet.length; i++) {
                                var curPos = new google.maps.LatLng(markerSet[i].coordSet[counter][0],
                                    markerSet[i].coordSet[counter][1]);
                                markerSet[i].marker.position = curPos;
                                markerSet[i].marker.setMap(map);
                            }
                        }
                    },
                    interval);
        },

        constructMarkerSet : function (markers) {
            var markerSet = new Array();
            for (var counter = 0; counter < markers.length; counter++) {
                var markerObj = transit.initMarker(markers[counter].coords[0], markers[counter].title);
                var coordList = markers[counter].coords.slice(1);

                markerSet.push({
                    marker: markerObj,
                    coordSet: coordList
                });
            }
            return markerSet;
        },

        overlayKml : function (kmlUrl, map) {
            var kmlOptions = {
                map: map
            };
            var kmlLayer = new google.maps.KmlLayer(kmlUrl, kmlOptions);
        },

        routeParser : function (xmlUrl) {
            var lines = {};
            var points = {};

            $.ajax({
                url: xmlUrl,
                dataType: 'xml',
                async: false,
                success : function (data) {
                    var xmlNode = $('Document', data);

                    xmlNode.find('Placemark > LineString > coordinates').each(function () {
                        var simPts = transit.trim($(this).text()).split(' ');
                        var grpPts = new Array();
                        var routeName = $(this).closest('Placemark').find('name').text().toLowerCase();
                        for (eachPt in simPts) {
                            var xy = transit.strip(simPts[eachPt]).split(',');
                            grpPts.push({ x: xy[0], y: xy[1] });
                        }
                        lines[transit.trim(routeName)] = grpPts;
                    });

                    xmlNode.find('Point').each(function () {
                        var parentTag = $(this).closest('Placemark');

                        var xy = transit.strip(parentTag.find('Point').text()).split(',');
                        points[transit.trim(parentTag.find('name').text()).toLowerCase()] = {
                            x: xy[0],
                            y: xy[1]
                        };
                    });
                },
                error : function (data) {
                    console.log('Error');
                }
            });

            return {
                "lines": lines,
                "points": points
            };
        },

        vehicleParser : function (jsonUrl) {
            var vehicleObj = {};

            $.ajax({
                url: jsonUrl,
                dataType: 'json',
                async: false,
                success : function (data) {
                    vehicleObj.timezone = data.timezone;
                    vehicleObj.vehicles = data.vehicles;
                },
                error : function (data) {
                    console.log('Error');
                }
            });

            return vehicleObj;
        },

        schedule : function (vehicleObj, routes, timezone) {
            var vehicleArrivals = {};
            var vehicleDepartures = {};
            var vehicleTravelTimes = [];
            var vehicleRoute = vehicleObj.route;
            var stopsObj = vehicleObj.stops;
            var noOfStops = vehicleObj.stops.length;
            var firstStop = stopsObj[0];
            var firstStopName = firstStop.name.toLowerCase();
            var startTime = transit.parseTime(firstStop.departure, firstStop.day, timezone);
            var vehicleStopCoords = {};
            var points = routes.points;

            vehicleDepartures[startTime - startTime] = firstStopName;
            vehicleTravelTimes.push(startTime - startTime);
            vehicleStopCoords[firstStopName] = points[firstStopName];

            for (var eachStop = 1; eachStop < noOfStops - 1; eachStop++) {
                var temp = stopsObj[eachStop];
                var tempName = temp.name.toLowerCase();
                var currArrivalTime = transit.parseTime(temp.arrival, temp.day, timezone) - startTime;
                var currDepartureTime = transit.parseTime(temp.departure, temp.day, timezone) - startTime;
                vehicleArrivals[currArrivalTime] = tempName;
                vehicleDepartures[currDepartureTime] = tempName;
                vehicleTravelTimes.push(currArrivalTime, currDepartureTime);
                vehicleStopCoords[tempName] = points[tempName];
            }

            var lastStop = stopsObj[noOfStops - 1];
            var lastStopName = lastStop.name.toLowerCase();
            var endTime = transit.parseTime(lastStop.arrival, lastStop.day, timezone) - startTime;
            vehicleArrivals[endTime] = lastStopName;
            vehicleTravelTimes.push(endTime);
            vehicleStopCoords[lastStopName] = points[lastStopName];
            var line = transit.pointsBetweenStops(routes.lines[vehicleRoute.toLowerCase()],
                                                  points[firstStopName.toLowerCase()],
                                                  points[lastStopName.toLowerCase()]);
            var percentStopDists = transit.hashOfPercentDists(line);

            return {
                "name": vehicleObj.name,
                "info": vehicleObj.info,
                "route": line,
                "stops": vehicleStopCoords,
                "ppoints": percentStopDists,
                "days": lastStop.day - firstStop.day,
                "arrivals": vehicleArrivals,
                "departures": vehicleDepartures,
                "traveltimes": vehicleTravelTimes
            };
        },

        strip : function (string) {
            return string.replace(/\s+/g, '').replace(/\n/g, '');
        },

        trim : function (string) {
            return string.replace(/^\s+|\s+$/g, '');
        },

        // Reimplemented from http://www.movable-type.co.uk/scripts/latlong.html
        haversine : function (sourceCoords, targetCoords) {
            var R = 6371; // km

            /** Converts numeric degrees to radians */
            if (typeof(Number.prototype.toRad) === "undefined") {
              Number.prototype.toRad = function() {
                return this * Math.PI / 180;
              }
            }

            var dLat = (targetCoords.x - sourceCoords.x).toRad();
            var dLon = (targetCoords.y - sourceCoords.y).toRad();
            var lat1 = sourceCoords.x.toRad();
            var lat2 = targetCoords.x.toRad();

            var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
            Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
            var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
            var d = R * c;
            return d;
        },

        linearDist : function (sourceCoords, targetCoords) {
            return Math.sqrt(Math.pow((targetCoords.x - sourceCoords.x), 2),
                             Math.pow((targetCoords.y - sourceCoords.y), 2));
        },

        percentDist : function (sourceCoords, targetCoords, percentage) {
            var newCoords = {};
            var ratio = percentage / 100;
            newCoords.x = (1 - ratio) * sourceCoords.x + ratio * targetCoords.x;
            newCoords.y = (1 - ratio) * sourceCoords.y + ratio * targetCoords.y;
            return newCoords;
        },

        percentInRange : function (lower, upper, target) {
            return ((target - lower) / (upper - lower)) * 100;
        },

        pointsBetweenStops: function (route, start, end) {
            return route.slice(route.indexOf(start), route.indexOf(end) + 1);
        },

        hashOfPercentDists : function (points) {
            var start = points[0];
            var routeLength = points.length;
            var end = points[routeLength - 1];
            var distanceHash = {
                0 : points[0]
            };
            var distances = new Array();
            var totalDist = 0;

            for (var x = 0; x < routeLength - 1; x++) {
                totalDist += transit.haversine(points[x], points[x + 1]);
                distances.push(totalDist);
            }

            for (var x = 0; x < distances.length; x++) {
                distanceHash[transit.percentInRange(0, totalDist, distances[x])] = points[x + 1];
            }

            return distanceHash;
        },

        // Variant of binary search that returns enclosing elements of searchElement in array.
        enclosure : function (searchElement) {
            'use strict';

            var minIndex = 0;
            var maxIndex = this.length - 1;
            var currentIndex;
            var currentElement;

            while (minIndex <= maxIndex) {
                currentIndex = (minIndex + maxIndex) / 2 | 0;
                currentElement = this[currentIndex];

                if (currentElement < searchElement) {
                    minIndex = currentIndex + 1;
                }
                else if (currentElement > searchElement) {
                    maxIndex = currentIndex - 1;
                }
                else {
                    return currentIndex;
                }
            }

            if (searchElement > this[currentIndex]) {
                if (typeof this[currentIndex + 1] != 'undefined')
                    return [currentIndex, currentIndex + 1];
                else
                    return currentIndex;
            } else {
                if (typeof this[currentIndex - 1] !=  'undefined')
                    return [currentIndex - 1, currentIndex];
                else
                    return 0;
            }
        },

        parseTime : function (timeString, day, timezone) {
            var hms = timeString.split(':');
            hms = hms.map(function (x) { return parseInt(x, 10); });

            if (hms.length < 3)
                hms[2] = 0;

            return hms[0] * 3600 + hms[1] * 60 + hms[2] + (day - 1) * 86400 + timezone * 60;
        },

        currTime : function () {
            var t = new Date();
            return t.getHours().toString() + ":" +
                   t.getMinutes().toString() + ":" +
                   t.getSeconds().toString();
        },

        estimateCurrentPosition : function (vehicleObj, timezone) {
            var arrivals = vehicleObj.arrivals;
            var departures = vehicleObj.departures;
            var travelTimes = vehicleObj.traveltimes;
            var noOfDays = vehicleObj.days;
            var ppoints = vehicleObj.ppoints;

            var route = vehicleObj.route;
            var stops = vehicleObj.stops;
            var percentDists = transit.hashOfPercentDists(stops);
            var positions = new Array();

            var currPos = {
                "stationaryAt": "",
                "departureTime": 0,
                "leaving": "",
                "approaching": "",
                "leftTime": 0,
                "approachTime": 0,
                "currentCoords": null
            };

            var time = transit.currTime();

            for (var i = 1; i <= noOfDays + 1; i++) {
                var range = transit.enclosure.call(travelTimes, transit.parseTime(time, i, timezone));

                if (range[0] % 2 == 0 && range.length == 2) {
                    currPos.leftTime = travelTimes[range[0]];
                    currPos.approachTime = travelTimes[range[1]];
                    var leavingStop = departures[currPos.leftTime];
                    var approachingStop = arrivals[currPos.approachTime];
                    currPos.leaving = leavingStop;
                    currPos.approaching = approachingStop;

                    var timePercent = transit.percentInRange(travelTimes[range[0]], travelTimes[range[1]],
                                                             transit.parseTime(currTime, i, timezone));
                    var timeRange = transit.enclosure.call(ppoints, timePercent);
                    var percent = transit.percentInRange(ppoints[timeRange[0]],
                                                         ppoints[timeRange[1]], timePercentArray[i]);
                    currPos.currentCoords = transit.percentDist(ppoints[timeRange[0]],
                                                                ppoints[timeRange[1]], percent);
                } else {
                    if (typeof range[1] != 'undefined' && range[0] != 0) {
                        var currentStop = travelTimes[range[1]];
                        currPos.stationaryAt = departures[currentStop];
                        currPos.departureTime = currentStop;
                        currPos.currentCoords = stops[currentStop];
                    }
                }

                positions.push(currPos);
            }

            return positions;
        },

        mouseOverInfo : function (name, info, stationary, departTime, l, a, lT, aT) {
            var base = "Vehicle: " + name + "\n" + info + "\n"
            if (stationary) {
                return base + "\n" + "At: " + stationary + "\n" + "Departs: " + departTime;
            } else {
                return base +
                       "Leaving: " + l + "\n" + " (" + lT + ")" +
                       "Approaching: " + a + " (" + aT + ")";
            }
        },

        main : function (localKmlFile, remoteKmlFile, jsonFile) {
            var map = transit.initMap();
            transit.overlayKml(remoteKmlFile, map);
            var routeObj = transit.routeParser(localKmlFile);
            var routeLines = routeObj.lines;
            var routePoints = routeObj.points;
            var vehicleObj = transit.vehicleParser(jsonFile);
            var timezone = vehicleObj.timezone;
            var vehicles = vehicleObj.vehicles;
            var noOfVehicles = vehicles.length;

            for (var count = 0; count < noOfVehicles; count++) {
                vehicles[count] = transit.schedule(vehicles[count], routeObj, timezone);
            }

            for (var count = 0; count < noOfVehicles; count++) {
                var vehicle = vehicles[count];

                if (typeof vehicle.markers == "undefined") {
                    vehicle.markers = new Array();
                } else {
                    for (var i = 0; i < vehicle.markers.length; i++) {
                        vehicle.markers[i].setMap(null);
                    }
                }

                var currPositions = transit.estimateCurrentPosition(vehicle, timezone);

                for (var i = 0; i < currPositions.length; i++) {
                    var currPosition = currPositions[0];

                    if (!currPosition.currentCoords) continue;

                    var mouseOverInfo = transit.mouseOverInfo(vehicle.name, vehicle.info,
                                                              currPosition.stationaryAt,
                                                              currPosition.departureTime,
                                                              currPosition.leaving,
                                                              currPosition.approaching,
                                                              currPosition.leftTime,
                                                              currPosition.approachTime);
                    var currMarker = transit.initMarker(currCoords[i], mouseOverInfo, map);
                    currMarker.setMap(map);
                    vehicle.markers[i] = currMarker;
                }
            }
        },

        initialize : function (localKmlFile, remoteKmlFile, jsonFile) {
            google.maps.event.addDomListener(window, 'load',
                    function () {
                        transit.main(localKmlFile, remoteKmlFile, jsonFile);
                    });
        }
    };
})();
<commit_msg>Resolve stop points to closest points in route.<commit_after>var transit = (function () {
    return {
        initMap : function () {
            var mapDet = {
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };

            var map = new google.maps.Map(document.getElementById('transitMap'), mapDet);
            return map;
        },

        initMarker : function (coords, mouseoverText, map) {
            mouseoverText = (typeof mouseoverText == 'undefined') ? 'Marker' : mouseoverText;
            var markerPos = new google.maps.LatLng(coords[0], coords[1]);

            var markerIcon = {
                path: google.maps.SymbolPath.CIRCLE,
                fillColor: 'red',
                fillOpacity: 0.8,
                scale: 5
            };

            var mouseoverInfo = new google.maps.InfoWindow({
                content: mouseoverText,
                map: map
            });

            var marker = {
                position: markerPos,
                title: mouseoverText,
                icon: markerIcon
            };

            marker = new google.maps.Marker(marker);

            google.maps.event.addListener(marker, 'mouseover', function() {
            	mouseoverInfo.open(map, this);
            });

            google.maps.event.addListener(marker, 'mouseout', function() {
            	mouseoverInfo.close();
            });

            return marker;
        },

        moveMarkers : function (markerSet, interval, map) {
            interval = (typeof interval == 'undefined') ? 1000 : interval;
            var transition = setInterval(
                    function () {
                        for (var counter = 0; counter < markerSet.length; counter++) {
                            for (var i = 0; i < markerSet.length; i++) {
                                var curPos = new google.maps.LatLng(markerSet[i].coordSet[counter][0],
                                    markerSet[i].coordSet[counter][1]);
                                markerSet[i].marker.position = curPos;
                                markerSet[i].marker.setMap(map);
                            }
                        }
                    },
                    interval);
        },

        constructMarkerSet : function (markers) {
            var markerSet = new Array();
            for (var counter = 0; counter < markers.length; counter++) {
                var markerObj = transit.initMarker(markers[counter].coords[0], markers[counter].title);
                var coordList = markers[counter].coords.slice(1);

                markerSet.push({
                    marker: markerObj,
                    coordSet: coordList
                });
            }
            return markerSet;
        },

        overlayKml : function (kmlUrl, map) {
            var kmlOptions = {
                map: map
            };
            var kmlLayer = new google.maps.KmlLayer(kmlUrl, kmlOptions);
        },

        routeParser : function (xmlUrl) {
            var lines = {};
            var points = {};

            $.ajax({
                url: xmlUrl,
                dataType: 'xml',
                async: false,
                success : function (data) {
                    var xmlNode = $('Document', data);

                    xmlNode.find('Placemark > LineString > coordinates').each(function () {
                        var simPts = transit.trim($(this).text()).split(' ');
                        var grpPts = new Array();
                        var routeName = $(this).closest('Placemark').find('name').text().toLowerCase();
                        for (eachPt in simPts) {
                            var xy = transit.strip(simPts[eachPt]).split(',');
                            grpPts.push({ x: xy[0], y: xy[1] });
                        }
                        lines[transit.trim(routeName)] = grpPts;
                    });

                    xmlNode.find('Point').each(function () {
                        var parentTag = $(this).closest('Placemark');

                        var xy = transit.strip(parentTag.find('Point').text()).split(',');
                        points[transit.trim(parentTag.find('name').text()).toLowerCase()] = {
                            x: xy[0],
                            y: xy[1]
                        };
                    });
                },
                error : function (data) {
                    console.log('Error');
                }
            });

            return {
                "lines": lines,
                "points": points
            };
        },

        vehicleParser : function (jsonUrl) {
            var vehicleObj = {};

            $.ajax({
                url: jsonUrl,
                dataType: 'json',
                async: false,
                success : function (data) {
                    vehicleObj.timezone = data.timezone;
                    vehicleObj.vehicles = data.vehicles;
                },
                error : function (data) {
                    console.log('Error');
                }
            });

            return vehicleObj;
        },

        schedule : function (vehicleObj, routes, timezone) {
            var vehicleArrivals = {};
            var vehicleDepartures = {};
            var vehicleTravelTimes = [];
            var vehicleRoute = vehicleObj.route;
            var stopsObj = vehicleObj.stops;
            var noOfStops = vehicleObj.stops.length;
            var firstStop = stopsObj[0];
            var firstStopName = firstStop.name.toLowerCase();
            var startTime = transit.parseTime(firstStop.departure, firstStop.day, timezone);
            var vehicleStopCoords = {};
            var points = routes.points;
            var opLine = routes.lines[vehicleRoute.toLowerCase()];

            vehicleDepartures[startTime - startTime] = firstStopName;
            vehicleTravelTimes.push(startTime - startTime);
            vehicleStopCoords[firstStopName] = transit.resolvePointToLine(opLine, points[firstStopName]);

            for (var eachStop = 1; eachStop < noOfStops - 1; eachStop++) {
                var temp = stopsObj[eachStop];
                var tempName = temp.name.toLowerCase();
                var currArrivalTime = transit.parseTime(temp.arrival, temp.day, timezone) - startTime;
                var currDepartureTime = transit.parseTime(temp.departure, temp.day, timezone) - startTime;
                vehicleArrivals[currArrivalTime] = tempName;
                vehicleDepartures[currDepartureTime] = tempName;
                vehicleTravelTimes.push(currArrivalTime, currDepartureTime);
                vehicleStopCoords[tempName] = transit.resolvePointToLine(opLine, points[tempName]);
            }

            var lastStop = stopsObj[noOfStops - 1];
            var lastStopName = lastStop.name.toLowerCase();
            var endTime = transit.parseTime(lastStop.arrival, lastStop.day, timezone) - startTime;
            vehicleArrivals[endTime] = lastStopName;
            vehicleTravelTimes.push(endTime);
            vehicleStopCoords[lastStopName] = transit.resolvePointToLine(opLine, points[lastStopName]);
            var line = transit.pointsBetweenStops(opLine,
                                                  vehicleStopCoords[firstStopName],
                                                  vehicleStopCoords[lastStopName]);
            var percentStopDists = transit.hashOfPercentDists(line);

            return {
                "name": vehicleObj.name,
                "info": vehicleObj.info,
                "route": line,
                "stops": vehicleStopCoords,
                "ppoints": percentStopDists,
                "days": lastStop.day - firstStop.day,
                "arrivals": vehicleArrivals,
                "departures": vehicleDepartures,
                "traveltimes": vehicleTravelTimes
            };
        },

        strip : function (string) {
            return string.replace(/\s+/g, '').replace(/\n/g, '');
        },

        trim : function (string) {
            return string.replace(/^\s+|\s+$/g, '');
        },

        resolvePointToLine : function (line, point) {
            var closestDist = transit.linearDist(line[0], point);
            var currPt = line[0]
            for (var count = 1; count < line.length; count++) {
                var currDist = transit.linearDist(line[count], point);
                if (closestDist > currDist)
                    currPt = line[count];
            }

            return currPt;
        },

        // Reimplemented from http://www.movable-type.co.uk/scripts/latlong.html
        haversine : function (sourceCoords, targetCoords) {
            var R = 6371; // km

            /** Converts numeric degrees to radians */
            if (typeof(Number.prototype.toRad) === "undefined") {
              Number.prototype.toRad = function() {
                return this * Math.PI / 180;
              }
            }

            var dLat = (targetCoords.x - sourceCoords.x).toRad();
            var dLon = (targetCoords.y - sourceCoords.y).toRad();
            var lat1 = sourceCoords.x.toRad();
            var lat2 = targetCoords.x.toRad();

            var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
            Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
            var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
            var d = R * c;
            return d;
        },

        linearDist : function (sourceCoords, targetCoords) {
            return Math.sqrt(Math.pow((targetCoords.x - sourceCoords.x), 2),
                             Math.pow((targetCoords.y - sourceCoords.y), 2));
        },

        percentDist : function (sourceCoords, targetCoords, percentage) {
            var newCoords = {};
            var ratio = percentage / 100;
            newCoords.x = (1 - ratio) * sourceCoords.x + ratio * targetCoords.x;
            newCoords.y = (1 - ratio) * sourceCoords.y + ratio * targetCoords.y;
            return newCoords;
        },

        percentInRange : function (lower, upper, target) {
            return ((target - lower) / (upper - lower)) * 100;
        },

        pointsBetweenStops: function (route, start, end) {
            return route.slice(route.indexOf(start), route.indexOf(end) + 1);
        },

        hashOfPercentDists : function (points) {
            var start = points[0];
            var routeLength = points.length;
            var end = points[routeLength - 1];
            var distanceHash = {
                0 : points[0]
            };
            var distances = new Array();
            var totalDist = 0;

            for (var x = 0; x < routeLength - 1; x++) {
                totalDist += transit.haversine(points[x], points[x + 1]);
                distances.push(totalDist);
            }

            for (var x = 0; x < distances.length; x++) {
                distanceHash[transit.percentInRange(0, totalDist, distances[x])] = points[x + 1];
            }

            return distanceHash;
        },

        // Variant of binary search that returns enclosing elements of searchElement in array.
        enclosure : function (searchElement) {
            'use strict';

            var minIndex = 0;
            var maxIndex = this.length - 1;
            var currentIndex;
            var currentElement;

            while (minIndex <= maxIndex) {
                currentIndex = (minIndex + maxIndex) / 2 | 0;
                currentElement = this[currentIndex];

                if (currentElement < searchElement) {
                    minIndex = currentIndex + 1;
                }
                else if (currentElement > searchElement) {
                    maxIndex = currentIndex - 1;
                }
                else {
                    return currentIndex;
                }
            }

            if (searchElement > this[currentIndex]) {
                if (typeof this[currentIndex + 1] != 'undefined')
                    return [currentIndex, currentIndex + 1];
                else
                    return currentIndex;
            } else {
                if (typeof this[currentIndex - 1] !=  'undefined')
                    return [currentIndex - 1, currentIndex];
                else
                    return 0;
            }
        },

        parseTime : function (timeString, day, timezone) {
            var hms = timeString.split(':');
            hms = hms.map(function (x) { return parseInt(x, 10); });

            if (hms.length < 3)
                hms[2] = 0;

            return hms[0] * 3600 + hms[1] * 60 + hms[2] + (day - 1) * 86400 + timezone * 60;
        },

        currTime : function () {
            var t = new Date();
            return t.getHours().toString() + ":" +
                   t.getMinutes().toString() + ":" +
                   t.getSeconds().toString();
        },

        estimateCurrentPosition : function (vehicleObj, timezone) {
            var arrivals = vehicleObj.arrivals;
            var departures = vehicleObj.departures;
            var travelTimes = vehicleObj.traveltimes;
            var noOfDays = vehicleObj.days;
            var ppoints = vehicleObj.ppoints;

            var route = vehicleObj.route;
            var stops = vehicleObj.stops;
            var percentDists = transit.hashOfPercentDists(stops);
            var positions = new Array();

            var currPos = {
                "stationaryAt": "",
                "departureTime": 0,
                "leaving": "",
                "approaching": "",
                "leftTime": 0,
                "approachTime": 0,
                "currentCoords": null
            };

            var time = transit.currTime();

            for (var i = 1; i <= noOfDays + 1; i++) {
                var range = transit.enclosure.call(travelTimes, transit.parseTime(time, i, timezone));

                if (range[0] % 2 == 0 && range.length == 2) {
                    currPos.leftTime = travelTimes[range[0]];
                    currPos.approachTime = travelTimes[range[1]];
                    var leavingStop = departures[currPos.leftTime];
                    var approachingStop = arrivals[currPos.approachTime];
                    currPos.leaving = leavingStop;
                    currPos.approaching = approachingStop;

                    var timePercent = transit.percentInRange(travelTimes[range[0]], travelTimes[range[1]],
                                                             transit.parseTime(currTime, i, timezone));
                    var timeRange = transit.enclosure.call(ppoints, timePercent);
                    var percent = transit.percentInRange(ppoints[timeRange[0]],
                                                         ppoints[timeRange[1]], timePercentArray[i]);
                    currPos.currentCoords = transit.percentDist(ppoints[timeRange[0]],
                                                                ppoints[timeRange[1]], percent);
                } else {
                    if (typeof range[1] != 'undefined' && range[0] != 0) {
                        var currentStop = travelTimes[range[1]];
                        currPos.stationaryAt = departures[currentStop];
                        currPos.departureTime = currentStop;
                        currPos.currentCoords = stops[currentStop];
                    }
                }

                positions.push(currPos);
            }

            return positions;
        },

        mouseOverInfo : function (name, info, stationary, departTime, l, a, lT, aT) {
            var base = "Vehicle: " + name + "\n" + info + "\n"
            if (stationary) {
                return base + "\n" + "At: " + stationary + "\n" + "Departs: " + departTime;
            } else {
                return base +
                       "Leaving: " + l + "\n" + " (" + lT + ")" +
                       "Approaching: " + a + " (" + aT + ")";
            }
        },

        main : function (localKmlFile, remoteKmlFile, jsonFile) {
            var map = transit.initMap();
            transit.overlayKml(remoteKmlFile, map);
            var routeObj = transit.routeParser(localKmlFile);
            var routeLines = routeObj.lines;
            var routePoints = routeObj.points;
            var vehicleObj = transit.vehicleParser(jsonFile);
            var timezone = vehicleObj.timezone;
            var vehicles = vehicleObj.vehicles;
            var noOfVehicles = vehicles.length;

            for (var count = 0; count < noOfVehicles; count++) {
                vehicles[count] = transit.schedule(vehicles[count], routeObj, timezone);
            }

            for (var count = 0; count < noOfVehicles; count++) {
                var vehicle = vehicles[count];

                if (typeof vehicle.markers == "undefined") {
                    vehicle.markers = new Array();
                } else {
                    for (var i = 0; i < vehicle.markers.length; i++) {
                        vehicle.markers[i].setMap(null);
                    }
                }

                var currPositions = transit.estimateCurrentPosition(vehicle, timezone);

                for (var i = 0; i < currPositions.length; i++) {
                    var currPosition = currPositions[0];

                    if (!currPosition.currentCoords) continue;

                    var mouseOverInfo = transit.mouseOverInfo(vehicle.name, vehicle.info,
                                                              currPosition.stationaryAt,
                                                              currPosition.departureTime,
                                                              currPosition.leaving,
                                                              currPosition.approaching,
                                                              currPosition.leftTime,
                                                              currPosition.approachTime);
                    var currMarker = transit.initMarker(currCoords[i], mouseOverInfo, map);
                    currMarker.setMap(map);
                    vehicle.markers[i] = currMarker;
                }
            }
        },

        initialize : function (localKmlFile, remoteKmlFile, jsonFile) {
            google.maps.event.addDomListener(window, 'load',
                    function () {
                        transit.main(localKmlFile, remoteKmlFile, jsonFile);
                    });
        }
    };
})();
<|endoftext|>


<commit_before>/* global django,Downcoder,ContentEditor */
/* eslint indent:[2,4] */
/* eslint comma-dangle:[2,"never"] */
django.jQuery(function($){
    // Patch up urlify maps to generate nicer slugs in german
    if(typeof(Downcoder) != 'undefined'){
        Downcoder.Initialize() ;
        Downcoder.map['ö'] = Downcoder.map['Ö'] = 'oe';
        Downcoder.map['ä'] = Downcoder.map['Ä'] = 'ae';
        Downcoder.map['ü'] = Downcoder.map['Ü'] = 'ue';
    }

    var context = document.getElementById('content-editor-context');
    if (!context) return;

    window.ContentEditor = {
        addContent: function addContent(plugin) {
            $('#' + plugin + '_set-group .add-row a').click();
        },
        addPluginButton: function addPluginButton(plugin, html) {
            var doAdd = function(plugin, html, title) {
                var unit = document.querySelector('.control-unit.plugin-buttons');
                if (!unit) {
                    unit = document.createElement('div');
                    unit.className = 'control-unit plugin-buttons';
                    document.querySelector('.machine-control').appendChild(unit);
                }

                var button = document.createElement('a');
                button.className = 'plugin-button';
                button.title = title;
                button.addEventListener('click', function() {
                    ContentEditor.addContent(plugin);
                });
                button.innerHTML = html;

                unit.appendChild(button);
            };

            for (var i=0; i<ContentEditor.plugins.length; i++) {
                if (ContentEditor.plugins[i][0] == plugin) {
                    doAdd(plugin, html, ContentEditor.plugins[i][1]);
                    break;
                }
            }
        }
    };

    // .dataset.context instead of getAttribute would be nicer
    $.extend(window.ContentEditor, JSON.parse(context.getAttribute('data-context')));

    // Add basic structure. There is always at least one inline group if
    // we even have any plugins.
    $('.inline-group:first').before(
        '

' +
        '
' +
        '

' +
        '
'
    );

    var orderMachine = $('.order-machine'),
        machineEmptyMessage = $('
').text(ContentEditor.messages.empty).appendTo(orderMachine);

    function moveEmptyFormsToEnd() {
        orderMachine.append(orderMachine.find('.empty-form').detach());
    }

    function reorderInlines(context) {
        context = context || orderMachine;
        var inlines = context.find('.inline-related');
        inlines.not('.empty-form').each(function() {
            $(document).trigger('content-editor:deactivate', [$(this)]);
        });
        inlines.detach();
        inlines.sort(function inlinesCompareFunction(a, b) {
            var aOrdering = $(a).find('.field-ordering input').val() || 1e9;
            var bOrdering = $(b).find('.field-ordering input').val() || 1e9;
            return Math.sign(aOrdering - bOrdering);
        });
        orderMachine.append(inlines);
        moveEmptyFormsToEnd();
        inlines.not('.empty-form').each(function() {
            $(document).trigger('content-editor:activate', [$(this)]);
        });
    }

    function buildDropdown(contents, title) {
        var select = document.createElement('select'),
            idx = 0;

        if (title)
            select.options[idx++] = new Option(title, '', true);

        for (var i = 0; i < contents.length; i++) {
            select.options[idx++] = new Option(contents[i][1], contents[i][0]);
        }
        return select;
    }

    function attachMoveToRegionDropdown(inline) {
        if (ContentEditor.regions.length < 2) return;

        var controls = document.createElement('div'),
            select = buildDropdown(ContentEditor.regions),
            regionInput = inline.find('.field-region input');

        select.value = regionInput.val();
        controls.className = 'inline-controls';
        controls.appendChild(select);
        inline.append(controls);

        select.addEventListener('change', function() {
            inline.attr('data-region', select.value);
            regionInput.val(select.value);
            hideInlinesFromOtherRegions();
            setBiggestOrdering(inline);
            reorderInlines();
        });
    }

    // Assing data-region to all inlines.
    // We also want to the data attribute to be visible to selectors (that's why we're using $.attr)
    function assignRegionDataAttribute() {
        orderMachine.find('.inline-related:not(.empty-form)').each(function() {
            var $this = $(this),
                region = $this.find('.field-region input').val();

            $this.attr('data-region', region);
            attachMoveToRegionDropdown($this);
        });
    }

    function setBiggestOrdering(row) {
        var orderings = [];
        $('.field-ordering input').each(function() {
            if (!isNaN(+this.value)) orderings.push(+this.value);
        });
        row.find('.field-ordering input').val(10 + Math.max.apply(null, orderings));
    }

    function hideInlinesFromOtherRegions() {
        var inlines = orderMachine.find('.inline-related:not(.empty-form)');
        inlines.hide();
        var shown = inlines.filter('[data-region="' + ContentEditor.currentRegion + '"]');
        machineEmptyMessage.addClass('hidden');
        if (shown.length) {
            shown.show();
        } else {
            machineEmptyMessage.removeClass('hidden');
        }
    }

    var pluginInlineGroups = (function selectPluginInlineGroups() {
        var selector = [];
        for (var i=0; i < ContentEditor.plugins.length; i++) {
            selector.push('#' + ContentEditor.plugins[i][0] + '_set-group');
        }
        return $(selector.join(', '));
    })();

    reorderInlines(pluginInlineGroups);
    pluginInlineGroups.hide();
    assignRegionDataAttribute();

    // Always move empty forms to the end, because new plugins are inserted
    // just before its empty form. Also, assign region data.
    $(document).on('formset:added', function newForm(event, row) {
        moveEmptyFormsToEnd();

        row.find('.field-region input').val(ContentEditor.currentRegion);
        row.attr('data-region', ContentEditor.currentRegion);

        setBiggestOrdering(row);
        attachMoveToRegionDropdown(row);

        machineEmptyMessage.addClass('hidden');

        $(document).trigger('content-editor:activate', [row]);
    });

    $(document).on('formset:removed', function resetInlines() {
        if (!orderMachine.find('.inline-related[data-region="' + ContentEditor.currentRegion + '"]').length) {
            machineEmptyMessage.removeClass('hidden');
        }
        orderMachine.find('.inline-related.last-related:not(.empty-form)').each(function() {
            $(document).trigger('content-editor:deactivate', [$(this)]);
        });

        // As soon as possible, but not sooner (let the inline.js code run to the end first)
        setTimeout(function() {
            orderMachine.find('.inline-related.last-related:not(.empty-form)').each(function() {
                $(document).trigger('content-editor:activate', [$(this)]);
            });
        }, 0);

    });

    // Initialize tabs and currentRegion.
    (function() {

        var tabContainer = $('.tabs.regions');
        for (var i=0; i < ContentEditor.regions.length; i++) {
            var t = document.createElement('h2');
            t.textContent = ContentEditor.regions[i][1];
            t.setAttribute('data-region', ContentEditor.regions[i][0]);
            tabContainer.append(t);
        }

        var tabs = tabContainer.children(), tab;
        tabs.on('click', function() {
            ContentEditor.currentRegion = $(this).data('region');
            tabs.removeClass('active').filter('[data-region="' + ContentEditor.currentRegion + '"]').addClass('active');
            hideInlinesFromOtherRegions();
            window.location.hash = 'tab_' + ContentEditor.currentRegion;
        });

        // Restore tab if location hash matches.
        if (window.location.hash && (tab = tabs.filter('[data-region="' + window.location.hash.substr(5) + '"]')) && tab.length) {
            tab.click();
        } else {
            tabs.eq(0).click();
        }

    })();

    $(document).on(
        'content-editor:deactivate',
        function(event, row) {
            row.find('fieldset').hide();
        }
    ).on(
        'content-editor:activate',
        function(event, row) {
            row.find('fieldset').show();
        }
    );

    // Start sortable; hide fieldsets when dragging, and hide fieldsets of to-be-deleted inlines.
    orderMachine.sortable({
        handle: 'h3',
        placeholder: 'placeholder',
        start: function(event, ui) {
            $(document).trigger('content-editor:deactivate', [ui.item]);
        },
        stop: function(event, ui) {
            $(document).trigger('content-editor:activate', [ui.item]);
        }
    }).on('click', '.delete>input[type=checkbox]', function toggleForDeletionClass() {
        $(this).closest('.inline-related')[this.checked ? 'addClass' : 'removeClass']('for-deletion');
    });

    // Fill in ordering field and try to keep the current region tab (location hash).
    $('form').submit(function(){
        $('.field-ordering input').each(function assignOrdering(index) {
            this.value = 10 * (index + 1); // Avoid default=0 just because.
        });

        var form = $(this);
        form.attr('action', form.attr('action') + window.location.hash);
        return true;
    });

    // Cmd-S and Escape behavior.
    $(document).keydown(function handleKeys(event) {
        if (event.which == 83 && event.metaKey) {
            $('form input[name=' + (event.shiftKey ? '_continue' : '_save') + ']').click();
            return false;
        } else if (event.which == 27) {
            orderMachine.sortable('cancel');
        }
    });

    (function buildPluginDropdown() {
        var select = buildDropdown(ContentEditor.plugins, ContentEditor.messages.createNew);
        select.addEventListener('change', function() {
            ContentEditor.addContent(select.value);
            select.value = '';
        });
        $(select).appendTo('.machine-control').wrap('

');
    })();

    $(document).trigger('content-editor:ready');
});
<commit_msg>The downcoder is not globally available for quite some time<commit_after>/* global django,Downcoder,ContentEditor */
/* eslint indent:[2,4] */
/* eslint comma-dangle:[2,"never"] */
django.jQuery(function($){
    var context = document.getElementById('content-editor-context');
    if (!context) return;

    window.ContentEditor = {
        addContent: function addContent(plugin) {
            $('#' + plugin + '_set-group .add-row a').click();
        },
        addPluginButton: function addPluginButton(plugin, html) {
            var doAdd = function(plugin, html, title) {
                var unit = document.querySelector('.control-unit.plugin-buttons');
                if (!unit) {
                    unit = document.createElement('div');
                    unit.className = 'control-unit plugin-buttons';
                    document.querySelector('.machine-control').appendChild(unit);
                }

                var button = document.createElement('a');
                button.className = 'plugin-button';
                button.title = title;
                button.addEventListener('click', function() {
                    ContentEditor.addContent(plugin);
                });
                button.innerHTML = html;

                unit.appendChild(button);
            };

            for (var i=0; i<ContentEditor.plugins.length; i++) {
                if (ContentEditor.plugins[i][0] == plugin) {
                    doAdd(plugin, html, ContentEditor.plugins[i][1]);
                    break;
                }
            }
        }
    };

    // .dataset.context instead of getAttribute would be nicer
    $.extend(window.ContentEditor, JSON.parse(context.getAttribute('data-context')));

    // Add basic structure. There is always at least one inline group if
    // we even have any plugins.
    $('.inline-group:first').before(
        '

' +
        '
' +
        '

' +
        '
'
    );

    var orderMachine = $('.order-machine'),
        machineEmptyMessage = $('
').text(ContentEditor.messages.empty).appendTo(orderMachine);

    function moveEmptyFormsToEnd() {
        orderMachine.append(orderMachine.find('.empty-form').detach());
    }

    function reorderInlines(context) {
        context = context || orderMachine;
        var inlines = context.find('.inline-related');
        inlines.not('.empty-form').each(function() {
            $(document).trigger('content-editor:deactivate', [$(this)]);
        });
        inlines.detach();
        inlines.sort(function inlinesCompareFunction(a, b) {
            var aOrdering = $(a).find('.field-ordering input').val() || 1e9;
            var bOrdering = $(b).find('.field-ordering input').val() || 1e9;
            return Math.sign(aOrdering - bOrdering);
        });
        orderMachine.append(inlines);
        moveEmptyFormsToEnd();
        inlines.not('.empty-form').each(function() {
            $(document).trigger('content-editor:activate', [$(this)]);
        });
    }

    function buildDropdown(contents, title) {
        var select = document.createElement('select'),
            idx = 0;

        if (title)
            select.options[idx++] = new Option(title, '', true);

        for (var i = 0; i < contents.length; i++) {
            select.options[idx++] = new Option(contents[i][1], contents[i][0]);
        }
        return select;
    }

    function attachMoveToRegionDropdown(inline) {
        if (ContentEditor.regions.length < 2) return;

        var controls = document.createElement('div'),
            select = buildDropdown(ContentEditor.regions),
            regionInput = inline.find('.field-region input');

        select.value = regionInput.val();
        controls.className = 'inline-controls';
        controls.appendChild(select);
        inline.append(controls);

        select.addEventListener('change', function() {
            inline.attr('data-region', select.value);
            regionInput.val(select.value);
            hideInlinesFromOtherRegions();
            setBiggestOrdering(inline);
            reorderInlines();
        });
    }

    // Assing data-region to all inlines.
    // We also want to the data attribute to be visible to selectors (that's why we're using $.attr)
    function assignRegionDataAttribute() {
        orderMachine.find('.inline-related:not(.empty-form)').each(function() {
            var $this = $(this),
                region = $this.find('.field-region input').val();

            $this.attr('data-region', region);
            attachMoveToRegionDropdown($this);
        });
    }

    function setBiggestOrdering(row) {
        var orderings = [];
        $('.field-ordering input').each(function() {
            if (!isNaN(+this.value)) orderings.push(+this.value);
        });
        row.find('.field-ordering input').val(10 + Math.max.apply(null, orderings));
    }

    function hideInlinesFromOtherRegions() {
        var inlines = orderMachine.find('.inline-related:not(.empty-form)');
        inlines.hide();
        var shown = inlines.filter('[data-region="' + ContentEditor.currentRegion + '"]');
        machineEmptyMessage.addClass('hidden');
        if (shown.length) {
            shown.show();
        } else {
            machineEmptyMessage.removeClass('hidden');
        }
    }

    var pluginInlineGroups = (function selectPluginInlineGroups() {
        var selector = [];
        for (var i=0; i < ContentEditor.plugins.length; i++) {
            selector.push('#' + ContentEditor.plugins[i][0] + '_set-group');
        }
        return $(selector.join(', '));
    })();

    reorderInlines(pluginInlineGroups);
    pluginInlineGroups.hide();
    assignRegionDataAttribute();

    // Always move empty forms to the end, because new plugins are inserted
    // just before its empty form. Also, assign region data.
    $(document).on('formset:added', function newForm(event, row) {
        moveEmptyFormsToEnd();

        row.find('.field-region input').val(ContentEditor.currentRegion);
        row.attr('data-region', ContentEditor.currentRegion);

        setBiggestOrdering(row);
        attachMoveToRegionDropdown(row);

        machineEmptyMessage.addClass('hidden');

        $(document).trigger('content-editor:activate', [row]);
    });

    $(document).on('formset:removed', function resetInlines() {
        if (!orderMachine.find('.inline-related[data-region="' + ContentEditor.currentRegion + '"]').length) {
            machineEmptyMessage.removeClass('hidden');
        }
        orderMachine.find('.inline-related.last-related:not(.empty-form)').each(function() {
            $(document).trigger('content-editor:deactivate', [$(this)]);
        });

        // As soon as possible, but not sooner (let the inline.js code run to the end first)
        setTimeout(function() {
            orderMachine.find('.inline-related.last-related:not(.empty-form)').each(function() {
                $(document).trigger('content-editor:activate', [$(this)]);
            });
        }, 0);

    });

    // Initialize tabs and currentRegion.
    (function() {

        var tabContainer = $('.tabs.regions');
        for (var i=0; i < ContentEditor.regions.length; i++) {
            var t = document.createElement('h2');
            t.textContent = ContentEditor.regions[i][1];
            t.setAttribute('data-region', ContentEditor.regions[i][0]);
            tabContainer.append(t);
        }

        var tabs = tabContainer.children(), tab;
        tabs.on('click', function() {
            ContentEditor.currentRegion = $(this).data('region');
            tabs.removeClass('active').filter('[data-region="' + ContentEditor.currentRegion + '"]').addClass('active');
            hideInlinesFromOtherRegions();
            window.location.hash = 'tab_' + ContentEditor.currentRegion;
        });

        // Restore tab if location hash matches.
        if (window.location.hash && (tab = tabs.filter('[data-region="' + window.location.hash.substr(5) + '"]')) && tab.length) {
            tab.click();
        } else {
            tabs.eq(0).click();
        }

    })();

    $(document).on(
        'content-editor:deactivate',
        function(event, row) {
            row.find('fieldset').hide();
        }
    ).on(
        'content-editor:activate',
        function(event, row) {
            row.find('fieldset').show();
        }
    );

    // Start sortable; hide fieldsets when dragging, and hide fieldsets of to-be-deleted inlines.
    orderMachine.sortable({
        handle: 'h3',
        placeholder: 'placeholder',
        start: function(event, ui) {
            $(document).trigger('content-editor:deactivate', [ui.item]);
        },
        stop: function(event, ui) {
            $(document).trigger('content-editor:activate', [ui.item]);
        }
    }).on('click', '.delete>input[type=checkbox]', function toggleForDeletionClass() {
        $(this).closest('.inline-related')[this.checked ? 'addClass' : 'removeClass']('for-deletion');
    });

    // Fill in ordering field and try to keep the current region tab (location hash).
    $('form').submit(function(){
        $('.field-ordering input').each(function assignOrdering(index) {
            this.value = 10 * (index + 1); // Avoid default=0 just because.
        });

        var form = $(this);
        form.attr('action', form.attr('action') + window.location.hash);
        return true;
    });

    // Cmd-S and Escape behavior.
    $(document).keydown(function handleKeys(event) {
        if (event.which == 83 && event.metaKey) {
            $('form input[name=' + (event.shiftKey ? '_continue' : '_save') + ']').click();
            return false;
        } else if (event.which == 27) {
            orderMachine.sortable('cancel');
        }
    });

    (function buildPluginDropdown() {
        var select = buildDropdown(ContentEditor.plugins, ContentEditor.messages.createNew);
        select.addEventListener('change', function() {
            ContentEditor.addContent(select.value);
            select.value = '';
        });
        $(select).appendTo('.machine-control').wrap('

');
    })();

    $(document).trigger('content-editor:ready');
});
<|endoftext|>


<commit_before><commit_msg>[bamboo] Automated branch merge (from foundation-2016:7a5ea07acaa411b70419b7a3d0447405e64686fc)<commit_after><|endoftext|>


<commit_before>var buffers = [];
var context;
var urls = ['cat1.mp3', 'cat2.mp3', 'cat3.mp3', 'cat4.mp3', 'cat5.mp3', 'cat6.mp3', 'cat7.mp3', 'cat8.mp3'];

function init() {
  try {
    window.AudioContext = window.AudioContext||window.webkitAudioContext;
    context = new AudioContext();
  }
  catch(e) {
    alert('Web Audio API is not supported in this browser');
  }
  loadSounds();
}

function loadSounds() {
  for (i = 0; i < urls.length; ++i) {
    loadSound(i);
  }
}

function loadSound(index) {
  var url = urls[index];
  var request = new XMLHttpRequest();
  request.open('GET', url, true);
  request.responseType = 'arraybuffer';
  request.onload = function() {
    context.decodeAudioData(
      request.response,
      function (buffer) {
        buffers[index] = buffer;
        for (i = 0; i < urls.length; ++i) {
          if (!(i in buffers)) {
            return;
          }
        }
        var button = document.getElementById('playSoundsButton');
        button.disabled = false;
        button.value = 'Listen';
      },
      alert);
  }
  request.send();
}

function playSound(which, when) {
  var source = context.createBufferSource();
  source.buffer = buffers[which];
  source.connect(context.destination);
  source.start(when);
}

function isInteger(s) {
  for (i = 0; i < s.length; ++i) {
    if (s[i] >= 0 && s[i] <= 9) {
      continue;
    } else {
      return false;
    }
  }
  return true;
}

function randomSounds() {
  var startTime = context.currentTime + 1;
  var howLong = document.getElementById('howLong').value;
  if (!isInteger(howLong) || howLong < 1 || howLong > 60) {
    alert('invalid number for step 1');
    return;
  }

  var howOften = document.getElementById('howOften').value;
  if (!isInteger(howOften) || howOften < 1 || howOften > 100) {
    alert('invalid number for step 2');
    return;
  }
  for (i = 0; i < howOften; ++i) {
    var which = Math.floor(Math.random() * urls.length);
    var when = Math.random() * howLong;
    playSound(which, startTime + when);
  }
}

window.addEventListener('load', init, false);
<commit_msg>Added call to context.resume() after user clicks<commit_after>var buffers = [];
var context;
var urls = ['cat1.mp3', 'cat2.mp3', 'cat3.mp3', 'cat4.mp3', 'cat5.mp3', 'cat6.mp3', 'cat7.mp3', 'cat8.mp3'];

function init() {
  try {
    window.AudioContext = window.AudioContext||window.webkitAudioContext;
    context = new AudioContext();
  }
  catch(e) {
    alert('Web Audio API is not supported in this browser');
  }
  loadSounds();
}

function loadSounds() {
  for (i = 0; i < urls.length; ++i) {
    loadSound(i);
  }
}

function loadSound(index) {
  var url = urls[index];
  var request = new XMLHttpRequest();
  request.open('GET', url, true);
  request.responseType = 'arraybuffer';
  request.onload = function() {
    context.decodeAudioData(
      request.response,
      function (buffer) {
        buffers[index] = buffer;
        for (i = 0; i < urls.length; ++i) {
          if (!(i in buffers)) {
            return;
          }
        }
        var button = document.getElementById('playSoundsButton');
        button.disabled = false;
        button.value = 'Listen';
      },
      alert);
  }
  request.send();
}

function playSound(which, when) {
  var source = context.createBufferSource();
  source.buffer = buffers[which];
  source.connect(context.destination);
  source.start(when);
}

function isInteger(s) {
  for (i = 0; i < s.length; ++i) {
    if (s[i] >= 0 && s[i] <= 9) {
      continue;
    } else {
      return false;
    }
  }
  return true;
}

function randomSounds() {
  // The web audio API needs a user gesture before it can
  // actually play something.
  context.resume();

  var startTime = context.currentTime + 1;
  var howLong = document.getElementById('howLong').value;
  if (!isInteger(howLong) || howLong < 1 || howLong > 60) {
    alert('invalid number for step 1');
    return;
  }

  var howOften = document.getElementById('howOften').value;
  if (!isInteger(howOften) || howOften < 1 || howOften > 100) {
    alert('invalid number for step 2');
    return;
  }
  for (i = 0; i < howOften; ++i) {
    var which = Math.floor(Math.random() * urls.length);
    var when = Math.random() * howLong;
    playSound(which, startTime + when);
  }
}

window.addEventListener('load', init, false);
<|endoftext|>


<commit_before>/* eslint-disable new-cap */

const accountRouter = require('./account/routes');
const adminRouter = require('./admin/routes');
const attachmentsRouter = require('./attachments/routes');
const entriesRouter = require('./entries/routes');
const eventsRouter = require('./events/routes');
const geometryRouter = require('./geometry/routes');
const iconsRouter = require('./icons/routes');
const localesRouter = require('./locales/routes');
const locationsRouter = require('./locations/routes');
const markersRouter = require('./markers/routes');
const paymentsRouter = require('./payments/routes');
const statisticsRouter = require('./statistics/routes');
const usersRouter = require('./users/routes');

const userDal = require('./users/user/dal');

const authMiddleware = require('./auth');
const status = require('http-status-codes');
const router = require('express').Router();

// Icon routes do not require authentication. Thus before jwt middleware.
router.use('/icons', iconsRouter);

// Locale and translation do not require authentication.
router.use('/locales', localesRouter);

// Account routes only partially require JWT authentication. Thus
// the router is used before the jwt middleware.
router.use('/account', accountRouter);

// Authentication JWT Token middleware.
router.use(authMiddleware);

// Check if user is banned.
router.use((req, res, next) => {

  // Check this by querying the database, because it's SIMPLE.
  // This effectively nulls the benefits of using jwt tokens :DD
  // But what the hell...
  userDal.getOne(req.user.name, (err, storedUser) => {
    if (err) {
      return next(err);
    }

    if (storedUser) {
      if (storedUser.status === 'active') {
        return next();
      }
    }

    // User does not exist or is banned
    return res.sendStatus(status.FORBIDDEN);
  });
});

// These routes require authentication.
router.use('/admin', adminRouter);
router.use('/attachments', attachmentsRouter);
router.use('/entries', entriesRouter);
router.use('/events', eventsRouter);
router.use('/geometry', geometryRouter);
router.use('/locations', locationsRouter);
router.use('/markers', markersRouter);
router.use('/payments', paymentsRouter);
router.use('/statistics', statisticsRouter);
router.use('/users', usersRouter);

// API error handling
// See http://expressjs.com/en/guide/error-handling.html
router.use((err, req, res, next) => {
  // Token error handling
  if (err.name === 'UnauthorizedError') {
    return res.sendStatus(status.UNAUTHORIZED);
  }

  // Default error handler
  return next(err);
});

// Catch all other non-errored API calls to 404.
// Must be the final step in this router.
router.get('/*', (req, res) => {
  console.log('404 Not Found: ' + req.originalUrl);
  return res.sendStatus(status.NOT_FOUND);
});

module.exports = router;
<commit_msg>Drop payments API endpoint<commit_after>/* eslint-disable new-cap */

const accountRouter = require('./account/routes');
const adminRouter = require('./admin/routes');
const attachmentsRouter = require('./attachments/routes');
const entriesRouter = require('./entries/routes');
const eventsRouter = require('./events/routes');
const geometryRouter = require('./geometry/routes');
const iconsRouter = require('./icons/routes');
const localesRouter = require('./locales/routes');
const locationsRouter = require('./locations/routes');
const markersRouter = require('./markers/routes');
const statisticsRouter = require('./statistics/routes');
const usersRouter = require('./users/routes');

const userDal = require('./users/user/dal');

const authMiddleware = require('./auth');
const status = require('http-status-codes');
const router = require('express').Router();

// Icon routes do not require authentication. Thus before jwt middleware.
router.use('/icons', iconsRouter);

// Locale and translation do not require authentication.
router.use('/locales', localesRouter);

// Account routes only partially require JWT authentication. Thus
// the router is used before the jwt middleware.
router.use('/account', accountRouter);

// Authentication JWT Token middleware.
router.use(authMiddleware);

// Check if user is banned.
router.use((req, res, next) => {

  // Check this by querying the database, because it's SIMPLE.
  // This effectively nulls the benefits of using jwt tokens :DD
  // But what the hell...
  userDal.getOne(req.user.name, (err, storedUser) => {
    if (err) {
      return next(err);
    }

    if (storedUser) {
      if (storedUser.status === 'active') {
        return next();
      }
    }

    // User does not exist or is banned
    return res.sendStatus(status.FORBIDDEN);
  });
});

// These routes require authentication.
router.use('/admin', adminRouter);
router.use('/attachments', attachmentsRouter);
router.use('/entries', entriesRouter);
router.use('/events', eventsRouter);
router.use('/geometry', geometryRouter);
router.use('/locations', locationsRouter);
router.use('/markers', markersRouter);
router.use('/statistics', statisticsRouter);
router.use('/users', usersRouter);
// router.use('/payments', paymentsRouter); TODO is any use?

// API error handling
// See http://expressjs.com/en/guide/error-handling.html
router.use((err, req, res, next) => {
  // Token error handling
  if (err.name === 'UnauthorizedError') {
    return res.sendStatus(status.UNAUTHORIZED);
  }

  // Default error handler
  return next(err);
});

// Catch all other non-errored API calls to 404.
// Must be the final step in this router.
router.get('/*', (req, res) => {
  console.log('404 Not Found: ' + req.originalUrl);
  return res.sendStatus(status.NOT_FOUND);
});

module.exports = router;
<|endoftext|>


<commit_before>/* -*- coding: utf-8 -*- */
/* global cforum, Mustache */

cforum.tags = {
  views: {
    tag: "
<input name=\"tags[]\" type=\"hidden\" value=\"{{tag}}\">  {{tag}}
",
    tagSuggestion: "
  {{tag}}
"
  },

  autocomplete_timeout: null,
  suggestionsTimeout: null,
  maxTags: 4,

  autocomplete: function() {
    cforum.tags.autocomplete_timeout = null;

    var $tag_input = $("#replaced_tag_input");

    if($tag_input.val().length >= 2) {
      $.get(
        cforum.baseUrl + '/' + cforum.currentForum.slug + '/tags/autocomplete.json',
        's=' + encodeURIComponent($tag_input.val()),
        function(data) {
          if(data.length > 0) {
            var val = $tag_input.val();
            var val_l = $.trim(val.toLowerCase());

            for(var i = 0; i < data.length; ++i) {
              if(val_l == data[i].toLowerCase()) {
                return;
              }
            }

            var tag = data[0];

            $tag_input.val(val + tag.substring(val.length));
            $tag_input.selection(val.length, tag.length);
          }
        }
      );

    }
  },

  suggestions: function(text) {
    var tokens = text.split(/[^a-z0-9äöüß-]+/i);
    var words = {};

    for(var i = 0; i < tokens.length; ++i) {
      if(tokens[i].match(/^[a-z0-9äöüß-]+$/i) && tokens[i].length > 2) {
        words[tokens[i].toLowerCase()] = 1;
      }
    }

    return Object.keys(words);
  },

  suggestTags: function() {
    var mcnt = $(document.getElementById('cf_thread_message_content') ?
                 "#cf_thread_message_content" : "#cf_message_content").val();

    if(mcnt == "") {
      return;
    }

    var suggestions = cforum.tags.suggestions(mcnt);

    $.get(
      cforum.baseUrl + cforum.currentForum.slug + '/tags.json',
      'tags=' + encodeURIComponent(suggestions.join(",")),
      function(data) {
        var tag_list = $("#tags-suggestions");
        tag_list.html("");

        for(var i = 0; i < data.length && i < cforum.tags.maxTags; ++i) {
          if(!cforum.tags.hasTag(data[i].tag_name)) {
            cforum.tags.appendTag(data[i].tag_name, tag_list, cforum.tags.views.tagSuggestion);
          }
        }

      }
    );
  },

  addTagSuggestion: function(ev) {
    ev.preventDefault();
    var tag = $(ev.target).closest("li").attr("data-tag");

    if($("#tags-list .tag").length >= cforum.maxTags) {
      return;
    }

    if(!cforum.tags.hasTag(tag)) {
      cforum.tags.appendTag(tag);
    }
  },

  hasTag: function(name) {
    var tags = $("#tags-list input[type=hidden]")

    for(var i = 0; i < tags.length; ++i) {
      if($(tags[i]).val().toLowerCase() == name) {
        return true;
      }
    }

    return false;
  },

  addTag: function(ev) {
    ev.preventDefault();
    var $this = $(this);

    if($.trim($this.val()) && $this.val() != ',' && $("#tags-list .tag").length < cforum.maxTags) {
      var val = $.trim($this.val().replace(/[, ].*/, '').toLowerCase());

      if(!cforum.tags.hasTag(val)) {
        cforum.tags.appendTag(val);
      }

      var v = $this.val();
      $this.val(v.indexOf(String.fromCharCode(ev.keyCode)) == -1 ? '' : v.replace(/.*[, ]?/, ''));
    }

  },

  appendTag: function(tag, list, view) {
    if(!list) {
      list = $("#tags-list");
    }

    if(!view) {
      view = cforum.tags.views.tag;
    }

    list.append(Mustache.render(view, {tag: tag}));
    list.find(".tag").last().fadeIn('fast');
  },

  removeTag: function(ev) {
    var $this = $(ev.target);

    if($this.hasClass('del-tag')) {
      ev.preventDefault();
      $this.closest("li.tag").fadeOut('fast', function() { $(this).remove(); });
    }
  },

  initTags: function() {
    var el = $("#tags-input");

    if(el.length == 0) {
      return;
    }

    var tags = el.val().split(",").map(function(x) {return $.trim(x);}).filter(function(x) {
      if(x) {
        return true;
      }

      return false;
    });

    cforum.tags.suggestTags();
    for(var i = 0; i < tags.length; ++i) {
      cforum.tags.appendTag(tags[i]);
    }

    $("<input type=\"text\" id=\"replaced_tag_input\" class=\"tags-input\">").insertBefore(el);
    el.remove();
    el = $("#replaced_tag_input");

    el.on('keyup', cforum.tags.handleTagsKeyUp);
    el.on('focusout', cforum.tags.addTag);
    $("#tags-list").on('click', cforum.tags.removeTag);

    $(document.getElementById('cf_thread_message_content') ? "#cf_thread_message_content" : "#cf_message_content").on('keyup', cforum.tags.handleSuggestionsKeyUp);
    $("#tags-suggestions").on('click', cforum.tags.addTagSuggestion);
  },

  handleSuggestionsKeyUp: function() {
    // cforum.tags.suggestTags
    if(cforum.tags.suggestionsTimeout) {
      window.clearTimeout(cforum.tags.suggestionsTimeout);
    }

    cforum.tags.suggestionsTimeout = window.setTimeout(cforum.tags.suggestTags, 800);
  },

  handleTagsKeyUp: function(ev) {
    if(cforum.tags.autocomplete_timeout) {
      window.clearTimeout(cforum.tags.autocomplete_timeout);
    }

    if(ev.keyCode == 188 || ev.keyCode == 32) {
      cforum.tags.addTag.call($("#replaced_tag_input"), ev);
    }
    else {
      cforum.tags.autocomplete_timeout = window.setTimeout(cforum.tags.autocomplete, 800);
    }
  }
};

/* eof */
<commit_msg>removed bootstrap code<commit_after>/* -*- coding: utf-8 -*- */
/* global cforum, Mustache */

cforum.tags = {
  views: {
    tag: "
<input name=\"tags[]\" type=\"hidden\" value=\"{{tag}}\">  {{tag}}
",
    tagSuggestion: "
  {{tag}}
"
  },

  autocomplete_timeout: null,
  suggestionsTimeout: null,
  maxTags: 4,

  autocomplete: function() {
    cforum.tags.autocomplete_timeout = null;

    var $tag_input = $("#replaced_tag_input");

    if($tag_input.val().length >= 2) {
      $.get(
        cforum.baseUrl + '/' + cforum.currentForum.slug + '/tags/autocomplete.json',
        's=' + encodeURIComponent($tag_input.val()),
        function(data) {
          if(data.length > 0) {
            var val = $tag_input.val();
            var val_l = $.trim(val.toLowerCase());

            for(var i = 0; i < data.length; ++i) {
              if(val_l == data[i].toLowerCase()) {
                return;
              }
            }

            var tag = data[0];

            $tag_input.val(val + tag.substring(val.length));
            $tag_input.selection(val.length, tag.length);
          }
        }
      );

    }
  },

  suggestions: function(text) {
    var tokens = text.split(/[^a-z0-9äöüß-]+/i);
    var words = {};

    for(var i = 0; i < tokens.length; ++i) {
      if(tokens[i].match(/^[a-z0-9äöüß-]+$/i) && tokens[i].length > 2) {
        words[tokens[i].toLowerCase()] = 1;
      }
    }

    return Object.keys(words);
  },

  suggestTags: function() {
    var mcnt = $(document.getElementById('cf_thread_message_content') ?
                 "#cf_thread_message_content" : "#cf_message_content").val();

    if(mcnt == "") {
      return;
    }

    var suggestions = cforum.tags.suggestions(mcnt);

    $.get(
      cforum.baseUrl + cforum.currentForum.slug + '/tags.json',
      'tags=' + encodeURIComponent(suggestions.join(",")),
      function(data) {
        var tag_list = $("#tags-suggestions");
        tag_list.html("");

        for(var i = 0; i < data.length && i < cforum.tags.maxTags; ++i) {
          if(!cforum.tags.hasTag(data[i].tag_name)) {
            cforum.tags.appendTag(data[i].tag_name, tag_list, cforum.tags.views.tagSuggestion);
          }
        }

      }
    );
  },

  addTagSuggestion: function(ev) {
    ev.preventDefault();
    var tag = $(ev.target).closest("li").attr("data-tag");

    if($("#tags-list .tag").length >= cforum.maxTags) {
      return;
    }

    if(!cforum.tags.hasTag(tag)) {
      cforum.tags.appendTag(tag);
    }
  },

  hasTag: function(name) {
    var tags = $("#tags-list input[type=hidden]")

    for(var i = 0; i < tags.length; ++i) {
      if($(tags[i]).val().toLowerCase() == name) {
        return true;
      }
    }

    return false;
  },

  addTag: function(ev) {
    ev.preventDefault();
    var $this = $(this);

    if($.trim($this.val()) && $this.val() != ',' && $("#tags-list .tag").length < cforum.maxTags) {
      var val = $.trim($this.val().replace(/[, ].*/, '').toLowerCase());

      if(!cforum.tags.hasTag(val)) {
        cforum.tags.appendTag(val);
      }

      var v = $this.val();
      $this.val(v.indexOf(String.fromCharCode(ev.keyCode)) == -1 ? '' : v.replace(/.*[, ]?/, ''));
    }

  },

  appendTag: function(tag, list, view) {
    if(!list) {
      list = $("#tags-list");
    }

    if(!view) {
      view = cforum.tags.views.tag;
    }

    list.append(Mustache.render(view, {tag: tag}));
    list.find(".tag").last().fadeIn('fast');
  },

  removeTag: function(ev) {
    var $this = $(ev.target);

    if($this.hasClass('del-tag')) {
      ev.preventDefault();
      $this.closest("li.tag").fadeOut('fast', function() { $(this).remove(); });
    }
  },

  initTags: function() {
    var el = $("#tags-input");

    if(el.length == 0) {
      return;
    }

    var tags = el.val().split(",").map(function(x) {return $.trim(x);}).filter(function(x) {
      if(x) {
        return true;
      }

      return false;
    });

    cforum.tags.suggestTags();
    for(var i = 0; i < tags.length; ++i) {
      cforum.tags.appendTag(tags[i]);
    }

    $("<input type=\"text\" id=\"replaced_tag_input\" class=\"tags-input\">").insertBefore(el);
    el.remove();
    el = $("#replaced_tag_input");

    el.on('keyup', cforum.tags.handleTagsKeyUp);
    el.on('focusout', cforum.tags.addTag);
    $("#tags-list").on('click', cforum.tags.removeTag);

    $(document.getElementById('cf_thread_message_content') ? "#cf_thread_message_content" : "#cf_message_content").on('keyup', cforum.tags.handleSuggestionsKeyUp);
    $("#tags-suggestions").on('click', cforum.tags.addTagSuggestion);
  },

  handleSuggestionsKeyUp: function() {
    // cforum.tags.suggestTags
    if(cforum.tags.suggestionsTimeout) {
      window.clearTimeout(cforum.tags.suggestionsTimeout);
    }

    cforum.tags.suggestionsTimeout = window.setTimeout(cforum.tags.suggestTags, 800);
  },

  handleTagsKeyUp: function(ev) {
    if(cforum.tags.autocomplete_timeout) {
      window.clearTimeout(cforum.tags.autocomplete_timeout);
    }

    if(ev.keyCode == 188 || ev.keyCode == 32) {
      cforum.tags.addTag.call($("#replaced_tag_input"), ev);
    }
    else {
      cforum.tags.autocomplete_timeout = window.setTimeout(cforum.tags.autocomplete, 800);
    }
  }
};

/* eof */
<|endoftext|>


<commit_before>/*   RSence
 *   Copyright 2008 Riassence Inc.
 *   http://riassence.com/
 *
 *   You should have received a copy of the GNU General Public License along
 *   with this software package. If not, contact licensing@riassence.com
 */

/*** = Description
  ** Simple button component, designed to be extended for any
  ** actual functionality above regular HControl.
  ** It's limited to 24px height by the default theme, because
  ** it's much simpler to render that way.
  ***/
var//RSence.Controls
HButton = HControl.extend({

  componentName: 'button',

/** = Description
  * setStyle function for button.
  *
  **/
  setStyle: function(_name, _value){
    ELEM.setStyle(this.markupElemIds.label,_name,_value);
    return this;
  }

});

/*** = Description
  ** Simple HButton extension, operates on its value so it's useful
  ** for sending button clicks to the server and the like.
  ** For the value responder, reset the value to 0 when read to make
  ** the button clickable again.
  **
  ** = Value states
  ** +0+::     Enabled, clickable
  ** +1+::     Disabled, clicked
  ** +Other+:: Disabled, not clickable, not clicked
  ***/
var//RSence.Controls
HClickButton = HButton.extend({

  defaultEvents: {
    click: true
  },

/** = Description
  * Sets the button enabled if this.value is 0.
  *
  **/
  refreshValue: function(){
    if( this.options.inverseValue ){
      this.setEnabled( this.value === 1 );
    }
    else {
      this.setEnabled( this.value === 0 );
    }
  },
/** = Description
  * Click method, sets the value to disabled if the button is enabled.
  *
  **/
  click: function(){
    if(this.enabled){
      if( this.options.inverseValue ){
        this.setValue(0);
      }
      else {
        this.setValue(1);
      }
    }
  }

});

var//RSence.Controls
HClickValueButton = HClickButton;

<commit_msg>HClickButton supports the clickOnValue and clickOffValue options, which allows more flexible use without extending.<commit_after>/*   RSence
 *   Copyright 2008 Riassence Inc.
 *   http://riassence.com/
 *
 *   You should have received a copy of the GNU General Public License along
 *   with this software package. If not, contact licensing@riassence.com
 */

/*** = Description
  ** Simple button component, designed to be extended for any
  ** actual functionality above regular HControl.
  ** It's limited to 24px height by the default theme, because
  ** it's much simpler to render that way.
  ***/
var//RSence.Controls
HButton = HControl.extend({

  componentName: 'button',

/** = Description
  * setStyle function for button.
  *
  **/
  setStyle: function(_name, _value){
    ELEM.setStyle(this.markupElemIds.label,_name,_value);
    return this;
  }

});

/*** = Description
  ** Simple HButton extension, operates on its value so it's useful
  ** for sending button clicks to the server and the like.
  ** For the value responder, reset the value to 0 when read to make
  ** the button clickable again.
  **
  ** = Value states
  ** +0+::     Enabled, clickable
  ** +1+::     Disabled, clicked
  ** +Other+:: Disabled, not clickable, not clicked
  ***/
var//RSence.Controls
HClickButton = HButton.extend({

  defaultEvents: {
    click: true
  },

  controlDefaults: HControlDefaults.extend({
    clickOnValue: 1,
    clickOffValue: 0
  }),

/** = Description
  * Sets the button enabled if this.value is 0.
  *
  **/
  refreshValue: function(){
    if( this.options.inverseValue ){
      this.setEnabled( this.value === this.options.clickOnValue );
    }
    else {
      this.setEnabled( this.value === this.options.clickOffValue );
    }
  },
/** = Description
  * Click method, sets the value to disabled if the button is enabled.
  *
  **/
  click: function(){
    if(this.enabled){
      if( this.options.inverseValue ){
        this.setValue( this.options.clickOffValue );
      }
      else {
        this.setValue( this.options.clickOnValue );
      }
    }
  }

});

var//RSence.Controls
HClickValueButton = HClickButton;

<|endoftext|>


<commit_before>/**
 * Created by rinesnow on 16/3/29.
 */
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var crypto = require('crypto');
var session= require('express-session');
var moment = require('moment');
var authentication = require('./authentication.js');

var app = express();

//连接数据库
var mongoose = require('mongoose');
var models = require('./models/models');

var User = models.User;
var Intern = models.Intern;

mongoose.connect('mongodb://localhost:27017/interns');
mongoose.connection.on('error',console.error.bind(console,'连接数据库失败!'));

//定义EJS模版引擎和末班文件位置
app.set('views', path.join(__dirname,'views'));
app.set('view engine','ejs');

//定义静态文件目录
app.use(express.static(path.join(__dirname,'public')));

//定义数据解析器
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

//建立session模型
app.use(session({
    secret:'liuchong',//?
    name:'intern',
    //一周内免登录
    cookie:{maxAge:1000 * 60 * 60*24*7},//设置session的保存时间为 60min*24小时*7一周
    resave: false,
    saveUnintiallized:true
}));

//添加  页面提示功能
app.use(function(req, res, next) {
    res.locals.user = req.session.user;//???
    var err = req.session.error;//赋值给err变量,
    //var success = req.session.success;//赋值给err变量,

    delete req.session.error;//然后清空session内的数据
    res.locals.message = '';//初始化
    //res.locals.success = '';//初始化

    if (err) {
        //html通过js被操作,在html中用{%-message%}调用
        res.locals.message = '
' + err + '
';
    }
    //if (success) {
    //    //html通过js被操作,在html中用{%-message%}调用
    //    res.locals.success = '
' + success + '
';
    //}

    next();//?
});

   var OAuth = require('wechat-oauth');
   var client = new OAuth('wx75d11b4f981b1ded', '7a915c525f39451f3af19407012459ad');
 // var openid='hehehe';
app.use(function ifAuthorized(req,res,next){

    // var url = client.getAuthorizeURL('www.coderwitkey.com', 'STATE', 'snsapi_userinfo');
    var query = require('url').parse(req.url,true).query;
          console.log(query);

    var code = query.code;
          console.log(code);

    client.getUserByCode(code,function (err, result) {
      // var accessToken = result.data.access_token;
      // var openid = result.openid;//必须要手动点击URL，原地刷新没用的。

      console.log('这是result:'+result.openid);
      // console.log(accessToken);

      // console.log("这是openid2"+openid);

       User.findOne({openid:result.openid},function(err,user){
           if(err){
               console.log('这是err'+err);
           }
            if(user.openid=result.openid){//有这个user 那么直接跳转
                return res.redirect('/');
            }
            // //对密码进行md5加密
            // var md5 = crypto.createHash('md5'),
            //     md5newopenid = md5.update(openid).digest('hex');
            //新建user对象用于保存数据
            var newUser = new User({

                openid:result.openid,//openid 作为key存入，以后再用用户信息就用openid调。
                nickname:result.nickname,
                headimg:result.headimgurl
            });

            newUser.save(function(err,doc){
                if(err){
                    console.log("保存用户信息失败！"+err);
                }
                console.log('保存用户信息成功!');//怎么实现弹出框!!!!??????
                return res.redirect('/');
            });
        });
    });
    // req.code=code;
    next();
});

//响应首页get请求
// app.get('/',authentication.ifAuthorized);//检测是否登录了
app.get('/',function(req,res){

      console.log('首页!');
    res.render('login',{
        // user: req.session.user,//也要加?
        title:'内推推推'
    });
    // Note.find({author:openid}).exec(function(err,allNotes){
    //     if(err){
    //         console.log(err);
    //         return res.redirect('/');
    //     }
    //     res.render('index',{
    //        title:'首页',
    //         openid: openid,
    //         notes:allNotes
    //     });
    // })
});

//登出
app.get('/quit',function(req,res){
    //退出功能只需将session中的user删除即可。
    // req.session.user = null;
    console.log('退出!');
    return res.redirect('/login');
});

//发布

//响应发布get请求
// app.get('/post',authentication.ifAuthorized);//检测是否登录了
app.get('/post',function(req,res){
   console.log('res.code:'+res.code);

    client.getUserByCode(res.code,function (err, result) {
      // var accessToken = result.data.access_token;
      // var openid = result.openid;//必须要手动点击URL，原地刷新没用的。

      // console.log(result);
      // console.log(accessToken);

      // console.log("这是openid2"+openid);
      console.log('这是result:'+result.openid);

      // intern.openid=result.openid;
      // intern.company='腾讯';
      // intern.email='www.liuchong.com';
      // intern.category='Tech';
      // intern.content='I want you!';

       Intern.findOne({createTime:Date.now},function(err,intern){
           if(err){
               console.log(err);
           }

            // //对密码进行md5加密
            // var md5 = crypto.createHash('md5'),
            //     md5newopenid = md5.update(openid).digest('hex');
            //新建user对象用于保存数据
            var newIntern = new Intern({

                openid:result.openid,//用户的id
                company:'腾讯',
                email:'www.liuchong.com',
                category:'Tech',
                content:'I want you!',
            });

            newUser.save(function(err,doc){
                if(err){
                    console.log("保存实习信息失败！"+err);
                }
                console.log('保存实习信息成功!');//怎么实现弹出框!!!!??????
                return res.redirect('/');
            });
        });
    });
   console.log('发布!');
    res.render('post',{
        user: req.session.user,//也要加?
        title:'发布'
    });
});
//响应发布post请求
app.post('/post',function(req,res){

     User.findOne({openid:openid},function(err,user){
           if(err){
               console.log(err);
           }
            if(user){//有这个user 那么直接跳转
                return res.redirect('/');
            }
        });
   var note = new Note({
       title:req.body.title,
       author:openid,
       tag: req.body.tag,
       content: req.body.content
   });
    note.save(function(err,doc){
       if(err){
           console.log(err);
           return res.redirect('/post');
       }
        console.log('文章发表成功!')
        return res.redirect('/');
    });
});
//

//博客细节

// app.get('/detail/',authentication.ifAuthorized);//检测是否登录了
app.get('/detail/:_id',function(req,res){//:id?
   console.log('查看笔记!');
    Note.findOne({_id:req.params._id}).exec(function(err,art){
        if(err){
            console.log(err);
            return res.redirect('/');
        }
        if(art) {
            res.render('detail', {
                title: '笔记详情',
                user: req.session.user,
                art: art,
                moment:moment
            });
            console.log(art);
        }
    });
});

// app.get('https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx75d11b4f981b1ded&secret=7a915c525f39451f3af19407012459ad&code=CODE&grant_type=authorization_code',function(req,res){

// });//获取appid

app.listen(3000, function(req,res){
    console.log('app is running at port 3000');
});<commit_msg>yonghu id<commit_after>/**
 * Created by rinesnow on 16/3/29.
 */
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var crypto = require('crypto');
var session= require('express-session');
var moment = require('moment');
var authentication = require('./authentication.js');

var app = express();

//连接数据库
var mongoose = require('mongoose');
var models = require('./models/models');

var User = models.User;
var Intern = models.Intern;

mongoose.connect('mongodb://localhost:27017/interns');
mongoose.connection.on('error',console.error.bind(console,'连接数据库失败!'));

//定义EJS模版引擎和末班文件位置
app.set('views', path.join(__dirname,'views'));
app.set('view engine','ejs');

//定义静态文件目录
app.use(express.static(path.join(__dirname,'public')));

//定义数据解析器
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

//建立session模型
app.use(session({
    secret:'liuchong',//?
    name:'intern',
    //一周内免登录
    cookie:{maxAge:1000 * 60 * 60*24*7},//设置session的保存时间为 60min*24小时*7一周
    resave: false,
    saveUnintiallized:true
}));

//添加  页面提示功能
app.use(function(req, res, next) {
    res.locals.user = req.session.user;//???
    var err = req.session.error;//赋值给err变量,
    //var success = req.session.success;//赋值给err变量,

    delete req.session.error;//然后清空session内的数据
    res.locals.message = '';//初始化
    //res.locals.success = '';//初始化

    if (err) {
        //html通过js被操作,在html中用{%-message%}调用
        res.locals.message = '
' + err + '
';
    }
    //if (success) {
    //    //html通过js被操作,在html中用{%-message%}调用
    //    res.locals.success = '
' + success + '
';
    //}

    next();//?
});

   var OAuth = require('wechat-oauth');
   var client = new OAuth('wx75d11b4f981b1ded', '7a915c525f39451f3af19407012459ad');
 // var openid='hehehe';
app.use(function ifAuthorized(req,res,next){

    // var url = client.getAuthorizeURL('www.coderwitkey.com', 'STATE', 'snsapi_userinfo');
    var query = require('url').parse(req.url,true).query;
          console.log(query);

    var code = query.code;
          console.log(code);

    client.getUserByCode(code,function (err, result) {
      // var accessToken = result.data.access_token;
      // var openid = result.openid;//必须要手动点击URL，原地刷新没用的。

      console.log('这是result:'+result.openid);
      // console.log(accessToken);

      // console.log("这是openid2"+openid);

       User.findOne({openid:result.openid},function(err,user){
           if(err){
               console.log('这是err'+err);
           }
            if(user.openid==result.openid){//有这个user 那么直接跳转
                return res.redirect('/');
            }
            // //对密码进行md5加密
            // var md5 = crypto.createHash('md5'),
            //     md5newopenid = md5.update(openid).digest('hex');
            //新建user对象用于保存数据
            var newUser = new User({

                openid:result.openid,//openid 作为key存入，以后再用用户信息就用openid调。
                nickname:result.nickname,
                headimg:result.headimgurl
            });

            newUser.save(function(err,doc){
                if(err){
                    console.log("保存用户信息失败！"+err);
                }
                console.log('保存用户信息成功!');//怎么实现弹出框!!!!??????
                return res.redirect('/');
            });
        });
    });
    // req.code=code;
    next();
});

//响应首页get请求
// app.get('/',authentication.ifAuthorized);//检测是否登录了
app.get('/',function(req,res){

      console.log('首页!');
    res.render('login',{
        // user: req.session.user,//也要加?
        title:'内推推推'
    });
    // Note.find({author:openid}).exec(function(err,allNotes){
    //     if(err){
    //         console.log(err);
    //         return res.redirect('/');
    //     }
    //     res.render('index',{
    //        title:'首页',
    //         openid: openid,
    //         notes:allNotes
    //     });
    // })
});

//登出
app.get('/quit',function(req,res){
    //退出功能只需将session中的user删除即可。
    // req.session.user = null;
    console.log('退出!');
    return res.redirect('/login');
});

//发布

//响应发布get请求
// app.get('/post',authentication.ifAuthorized);//检测是否登录了
app.get('/post',function(req,res){
   console.log('res.code:'+res.code);

    client.getUserByCode(res.code,function (err, result) {
      // var accessToken = result.data.access_token;
      // var openid = result.openid;//必须要手动点击URL，原地刷新没用的。

      // console.log(result);
      // console.log(accessToken);

      // console.log("这是openid2"+openid);
      console.log('这是result:'+result.openid);

      // intern.openid=result.openid;
      // intern.company='腾讯';
      // intern.email='www.liuchong.com';
      // intern.category='Tech';
      // intern.content='I want you!';

       Intern.findOne({createTime:Date.now},function(err,intern){
           if(err){
               console.log(err);
           }

            // //对密码进行md5加密
            // var md5 = crypto.createHash('md5'),
            //     md5newopenid = md5.update(openid).digest('hex');
            //新建user对象用于保存数据
            var newIntern = new Intern({

                openid:result.openid,//用户的id
                company:'腾讯',
                email:'www.liuchong.com',
                category:'Tech',
                content:'I want you!',
            });

            newUser.save(function(err,doc){
                if(err){
                    console.log("保存实习信息失败！"+err);
                }
                console.log('保存实习信息成功!');//怎么实现弹出框!!!!??????
                return res.redirect('/');
            });
        });
    });
   console.log('发布!');
    res.render('post',{
        user: req.session.user,//也要加?
        title:'发布'
    });
});
//响应发布post请求
app.post('/post',function(req,res){

     User.findOne({openid:openid},function(err,user){
           if(err){
               console.log(err);
           }
            if(user){//有这个user 那么直接跳转
                return res.redirect('/');
            }
        });
   var note = new Note({
       title:req.body.title,
       author:openid,
       tag: req.body.tag,
       content: req.body.content
   });
    note.save(function(err,doc){
       if(err){
           console.log(err);
           return res.redirect('/post');
       }
        console.log('文章发表成功!')
        return res.redirect('/');
    });
});
//

//博客细节

// app.get('/detail/',authentication.ifAuthorized);//检测是否登录了
app.get('/detail/:_id',function(req,res){//:id?
   console.log('查看笔记!');
    Note.findOne({_id:req.params._id}).exec(function(err,art){
        if(err){
            console.log(err);
            return res.redirect('/');
        }
        if(art) {
            res.render('detail', {
                title: '笔记详情',
                user: req.session.user,
                art: art,
                moment:moment
            });
            console.log(art);
        }
    });
});

// app.get('https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx75d11b4f981b1ded&secret=7a915c525f39451f3af19407012459ad&code=CODE&grant_type=authorization_code',function(req,res){

// });//获取appid

app.listen(3000, function(req,res){
    console.log('app is running at port 3000');
});<|endoftext|>