Commit 0e404f006b52a3b1a6fcfe59f8b29374072b940d

Authored by 潘钊
1 parent 44718ecc

update...

Showing 47 changed files with 7189 additions and 1327 deletions
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 <modelVersion>4.0.0</modelVersion> 4 <modelVersion>4.0.0</modelVersion>
5 <groupId>com.bsth</groupId> 5 <groupId>com.bsth</groupId>
6 <artifactId>bus_park_dispatch</artifactId> 6 <artifactId>bus_park_dispatch</artifactId>
7 - <version>0.0.1-SNAPSHOT</version> 7 + <version>0.0.2-SNAPSHOT</version>
8 <packaging>jar</packaging> 8 <packaging>jar</packaging>
9 9
10 <parent> 10 <parent>
src/main/java/com/bsth/StartCommand.java
1 package com.bsth; 1 package com.bsth;
2 2
3 3
  4 +import com.bsth.data.in_out.buffer.BerthDataBuffer;
  5 +import com.bsth.data.in_out.thread.Car2BerthDataPstThread;
  6 +import com.bsth.data.in_out.thread.SignalPstThread;
4 import com.bsth.data.led_http.LedHttpPushHandler; 7 import com.bsth.data.led_http.LedHttpPushHandler;
5 import com.bsth.data.msg_queue.SignalAndAttConsumeQueue; 8 import com.bsth.data.msg_queue.SignalAndAttConsumeQueue;
6 -import com.bsth.data.real_park.CarParkRealHandler;  
7 -import com.bsth.data.real_park.thread.RealParkDataPersistenceThread;  
8 -import com.bsth.data.signal.thread.SignalPstThread; 9 +import com.bsth.data.msg_queue.WebSocketPushQueue;
9 import com.bsth.security.SecurityMetadataSourceService; 10 import com.bsth.security.SecurityMetadataSourceService;
10 -import com.bsth.service.berth.impl.BerthServiceImpl;  
11 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.beans.factory.annotation.Autowired;
12 import org.springframework.boot.CommandLineRunner; 12 import org.springframework.boot.CommandLineRunner;
13 import org.springframework.stereotype.Component; 13 import org.springframework.stereotype.Component;
@@ -27,17 +27,13 @@ public class StartCommand implements CommandLineRunner{ @@ -27,17 +27,13 @@ public class StartCommand implements CommandLineRunner{
27 @Autowired 27 @Autowired
28 SecurityMetadataSourceService invocationSecurityMetadataSourceService; 28 SecurityMetadataSourceService invocationSecurityMetadataSourceService;
29 @Autowired 29 @Autowired
30 - SignalPstThread signalPstThread;  
31 - @Autowired  
32 - RealParkDataPersistenceThread realParkDataPersistenceThread;  
33 -  
34 - @Autowired  
35 - CarParkRealHandler carParkRealHandler; 30 + SignalPstThread signalPstThread;
36 @Autowired 31 @Autowired
37 LedHttpPushHandler ledHttpPushHandler; 32 LedHttpPushHandler ledHttpPushHandler;
38 -  
39 @Autowired 33 @Autowired
40 - BerthServiceImpl.BerthCacheRefreshThread berthCacheRefreshThread; 34 + BerthDataBuffer berthDataBuffer;
  35 + @Autowired
  36 + Car2BerthDataPstThread car2BerthDataPstThread;
41 37
42 @Override 38 @Override
43 public void run(String... arg0){ 39 public void run(String... arg0){
@@ -47,23 +43,22 @@ public class StartCommand implements CommandLineRunner{ @@ -47,23 +43,22 @@ public class StartCommand implements CommandLineRunner{
47 invocationSecurityMetadataSourceService.loadResourceDefine(); 43 invocationSecurityMetadataSourceService.loadResourceDefine();
48 44
49 //同步屏 LED 推送服务 45 //同步屏 LED 推送服务
50 - ledHttpPushHandler.start(); 46 + //ledHttpPushHandler.start();
51 47
52 //signal、牌照识别、查询一体机数据消费队列 48 //signal、牌照识别、查询一体机数据消费队列
53 SignalAndAttConsumeQueue.start(); 49 SignalAndAttConsumeQueue.start();
  50 + //websocket 消费队列
  51 + WebSocketPushQueue.start();
  52 +
  53 + //初始化泊位信息
  54 + berthDataBuffer.init();
54 55
55 ScheduledExecutorService sexec = Application.mainServices; 56 ScheduledExecutorService sexec = Application.mainServices;
56 //进出场数据入库线程 57 //进出场数据入库线程
57 - sexec.scheduleWithFixedDelay(signalPstThread, 30, 10, TimeUnit.SECONDS);  
58 -  
59 - //从数据库恢复场内实时停放数据  
60 - berthCacheRefreshThread.run();  
61 - carParkRealHandler.recovery();  
62 - //实时场内停放数据入库  
63 - sexec.scheduleWithFixedDelay(realParkDataPersistenceThread, 40, 30, TimeUnit.SECONDS); 58 + sexec.scheduleWithFixedDelay(signalPstThread, 30, 100, TimeUnit.SECONDS);
  59 + //实时车辆泊位数据入库
  60 + sexec.scheduleWithFixedDelay(car2BerthDataPstThread, 20, 20, TimeUnit.SECONDS);
64 61
65 - //泊位数据刷新  
66 - sexec.scheduleWithFixedDelay(berthCacheRefreshThread, 60 * 15, 60 * 15, TimeUnit.SECONDS);  
67 } catch (Exception e) { 62 } catch (Exception e) {
68 e.printStackTrace(); 63 e.printStackTrace();
69 } 64 }
src/main/java/com/bsth/WebAppConfiguration.java
1 package com.bsth; 1 package com.bsth;
2 2
  3 +import com.bsth.websocket.WebSocketHandshakeInterceptor;
  4 +import com.bsth.websocket.handler.RealInoutSocketHandler;
3 import org.slf4j.Logger; 5 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory; 6 import org.slf4j.LoggerFactory;
5 import org.springframework.context.annotation.Bean; 7 import org.springframework.context.annotation.Bean;
@@ -46,9 +48,9 @@ public class WebAppConfiguration extends WebMvcConfigurerAdapter implements WebS @@ -46,9 +48,9 @@ public class WebAppConfiguration extends WebMvcConfigurerAdapter implements WebS
46 48
47 @Override 49 @Override
48 public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { 50 public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
49 - //线调webSocket  
50 - //registry.addHandler(new RealControlSocketHandler(), "/sockjs/").addInterceptors(new WebSocketHandshakeInterceptor())  
51 - // .withSockJS(); 51 + //webSocket
  52 + registry.addHandler(new RealInoutSocketHandler(), "/sockjs/inout").addInterceptors(new WebSocketHandshakeInterceptor())
  53 + .withSockJS();
52 } 54 }
53 55
54 /** 56 /**
src/main/java/com/bsth/controller/UpstreamEntrance.java
1 package com.bsth.controller; 1 package com.bsth.controller;
2 2
  3 +import com.alibaba.fastjson.JSON;
3 import com.bsth.data.attendance.AttendaceDataBuffer; 4 import com.bsth.data.attendance.AttendaceDataBuffer;
4 import com.bsth.data.attendance.dto.RemoteAttendaceDTO; 5 import com.bsth.data.attendance.dto.RemoteAttendaceDTO;
5 -import com.bsth.data.electric.CarElectricBuffer;  
6 -import com.bsth.data.signal.RFIDInParkDataBuffer;  
7 -import com.bsth.data.signal.dto.RfidInOutDto;  
8 -import com.bsth.entity.electric.BusElectric;  
9 -import org.springframework.beans.factory.annotation.Autowired; 6 +import com.bsth.data.in_out.buffer.ElectricDataBuffer;
  7 +import com.bsth.data.in_out.entity.Electric;
  8 +import com.bsth.data.in_out.entity.RfidInOutDto;
  9 +import com.bsth.data.msg_queue.SignalAndAttConsumeQueue;
  10 +import com.bsth.entity.ac.CarInOutEntity;
  11 +import org.apache.commons.lang3.StringUtils;
  12 +import org.slf4j.Logger;
  13 +import org.slf4j.LoggerFactory;
10 import org.springframework.web.bind.annotation.*; 14 import org.springframework.web.bind.annotation.*;
11 15
12 import java.util.List; 16 import java.util.List;
@@ -19,8 +23,7 @@ import java.util.List; @@ -19,8 +23,7 @@ import java.util.List;
19 @RequestMapping("bus_park_dispatch") 23 @RequestMapping("bus_park_dispatch")
20 public class UpstreamEntrance { 24 public class UpstreamEntrance {
21 25
22 - @Autowired  
23 - CarElectricBuffer carElectricBuffer; 26 + Logger logger = LoggerFactory.getLogger(this.getClass());
24 27
25 /** 28 /**
26 * 查询一体机实时签到 29 * 查询一体机实时签到
@@ -37,7 +40,17 @@ public class UpstreamEntrance { @@ -37,7 +40,17 @@ public class UpstreamEntrance {
37 */ 40 */
38 @RequestMapping(value = "inout_rfid", method = RequestMethod.POST) 41 @RequestMapping(value = "inout_rfid", method = RequestMethod.POST)
39 public void inOut_rfid(@RequestBody RfidInOutDto rfidInOut){ 42 public void inOut_rfid(@RequestBody RfidInOutDto rfidInOut){
40 - RFIDInParkDataBuffer.put(rfidInOut); 43 + logger.info("RFID 进出场 : " + JSON.toJSONString(rfidInOut));
  44 + if(null == rfidInOut)
  45 + return;
  46 + if(StringUtils.isEmpty(rfidInOut.getCarCard()))
  47 + return;
  48 +
  49 + if(null == rfidInOut.getReportTime())
  50 + return;
  51 +
  52 + CarInOutEntity cio = CarInOutEntity.getInstance(rfidInOut);
  53 + SignalAndAttConsumeQueue.put(cio);
41 } 54 }
42 55
43 /** 56 /**
@@ -46,7 +59,7 @@ public class UpstreamEntrance { @@ -46,7 +59,7 @@ public class UpstreamEntrance {
46 */ 59 */
47 @RequestMapping(value = "electric", method = RequestMethod.POST) 60 @RequestMapping(value = "electric", method = RequestMethod.POST)
48 @ResponseBody 61 @ResponseBody
49 - public void electric(@RequestBody List<BusElectric> list){  
50 - carElectricBuffer.putAll(list); 62 + public void electric(@RequestBody List<Electric> list){
  63 + ElectricDataBuffer.put(list);
51 } 64 }
52 } 65 }
src/main/java/com/bsth/controller/basic/BusController.java
1 package com.bsth.controller.basic; 1 package com.bsth.controller.basic;
2 2
3 -import com.bsth.data.electric.CarElectricBuffer;  
4 import com.bsth.entity.Bus; 3 import com.bsth.entity.Bus;
5 -import com.bsth.entity.electric.BusElectric;  
6 import com.bsth.service.basic.BusService; 4 import com.bsth.service.basic.BusService;
7 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.beans.factory.annotation.Autowired;
8 import org.springframework.web.bind.annotation.*; 6 import org.springframework.web.bind.annotation.*;
9 7
10 -import java.util.Collection;  
11 import java.util.Map; 8 import java.util.Map;
12 9
13 /** 10 /**
@@ -61,10 +58,12 @@ public class BusController { @@ -61,10 +58,12 @@ public class BusController {
61 return busService.save(b); 58 return busService.save(b);
62 } 59 }
63 60
  61 +/*
64 @RequestMapping("real_elec_info") 62 @RequestMapping("real_elec_info")
65 public Collection<BusElectric> realElecInfo(){ 63 public Collection<BusElectric> realElecInfo(){
66 return CarElectricBuffer.all(); 64 return CarElectricBuffer.all();
67 } 65 }
  66 +*/
68 67
69 @RequestMapping("all") 68 @RequestMapping("all")
70 public Map<String, Object> all(){ 69 public Map<String, Object> all(){
src/main/java/com/bsth/controller/berth/BerthController.java
1 package com.bsth.controller.berth; 1 package com.bsth.controller.berth;
2 2
3 import com.bsth.controller.BaseController; 3 import com.bsth.controller.BaseController;
  4 +import com.bsth.controller.berth.dto.Car2Berth;
  5 +import com.bsth.data.in_out.RealInoutHandler;
  6 +import com.bsth.data.in_out.buffer.BerthDataBuffer;
  7 +import com.bsth.data.in_out.buffer.ElectricDataBuffer;
4 import com.bsth.entity.berth.RegionBerth; 8 import com.bsth.entity.berth.RegionBerth;
5 import com.bsth.service.berth.BerthService; 9 import com.bsth.service.berth.BerthService;
6 import org.springframework.beans.factory.annotation.Autowired; 10 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.web.bind.annotation.RequestMapping; 11 import org.springframework.web.bind.annotation.RequestMapping;
  12 +import org.springframework.web.bind.annotation.RequestParam;
8 import org.springframework.web.bind.annotation.RestController; 13 import org.springframework.web.bind.annotation.RestController;
9 14
  15 +import java.util.List;
  16 +import java.util.Map;
  17 +
10 /** 18 /**
11 * Created by panzhao on 2017/8/22. 19 * Created by panzhao on 2017/8/22.
12 */ 20 */
@@ -14,12 +22,61 @@ import org.springframework.web.bind.annotation.RestController; @@ -14,12 +22,61 @@ import org.springframework.web.bind.annotation.RestController;
14 @RequestMapping("/berth") 22 @RequestMapping("/berth")
15 public class BerthController extends BaseController<RegionBerth, Integer> { 23 public class BerthController extends BaseController<RegionBerth, Integer> {
16 24
17 - @Autowired 25 +/* @Autowired
18 BerthService berthService; 26 BerthService berthService;
19 27
20 @RequestMapping("max_order_no") 28 @RequestMapping("max_order_no")
21 public String maxOrderNo() { 29 public String maxOrderNo() {
22 String rs = berthService.maxOrderNo(); 30 String rs = berthService.maxOrderNo();
23 return rs==null?"0":rs; 31 return rs==null?"0":rs;
  32 + }*/
  33 +
  34 + @Autowired
  35 + BerthService berthService;
  36 +
  37 + @Autowired
  38 + RealInoutHandler realInoutHandler;
  39 +
  40 + @Autowired
  41 + BerthDataBuffer berthDataBuffer;
  42 +
  43 + @RequestMapping("findCar2Berths")
  44 + public List<Car2Berth> findCar2Berths(){
  45 + return berthService.car2Berths();
  46 + }
  47 +
  48 + @RequestMapping("all_list")
  49 + public List<RegionBerth> all(){
  50 + return BerthDataBuffer.all();
  51 + }
  52 +
  53 + @RequestMapping("addCar")
  54 + public Map<String, Object> addCar(@RequestParam String berthName,@RequestParam String nbbm){
  55 + return realInoutHandler.addCar2Berth(nbbm, berthName);
  56 + }
  57 +
  58 + @RequestMapping("removeCar")
  59 + public Map<String, Object> removeCar(@RequestParam String b){
  60 + return realInoutHandler.removeCar2Berth(b);
  61 + }
  62 +
  63 + @RequestMapping("changeCar2Berth")
  64 + public Map<String, Object> changeCar2Berth(@RequestParam String s,@RequestParam String d){
  65 + return RealInoutHandler.changeCar2Berth(s, d);
  66 + }
  67 +
  68 + @RequestMapping("lockBerth")
  69 + public Map<String, Object> lockBerth(@RequestParam String berthName){
  70 + return berthDataBuffer.lockBerth(berthName);
  71 + }
  72 +
  73 + @RequestMapping("unlockBerth")
  74 + public Map<String, Object> unlockBerth(@RequestParam String berthName){
  75 + return berthDataBuffer.unlockBerth(berthName);
  76 + }
  77 +
  78 + @RequestMapping("elecs")
  79 + public Map<String, Double> elecs(){
  80 + return ElectricDataBuffer.elecs();
24 } 81 }
25 } 82 }
src/main/java/com/bsth/controller/berth/dto/Car2Berth.java 0 → 100644
  1 +package com.bsth.controller.berth.dto;
  2 +
  3 +import com.bsth.entity.Bus;
  4 +
  5 +/**
  6 + * 车辆和泊位 DTO
  7 + * Created by panzhao on 2017/11/4.
  8 + */
  9 +public class Car2Berth {
  10 +
  11 + //车
  12 + private Bus bus;
  13 +
  14 + //泊位名称
  15 + private String berth;
  16 +
  17 + //电
  18 + //private Electric elec;
  19 +
  20 +
  21 + public Bus getBus() {
  22 + return bus;
  23 + }
  24 +
  25 + public void setBus(Bus bus) {
  26 + this.bus = bus;
  27 + }
  28 +
  29 + public String getBerth() {
  30 + return berth;
  31 + }
  32 +
  33 + public void setBerth(String berth) {
  34 + this.berth = berth;
  35 + }
  36 +}
src/main/java/com/bsth/controller/real/CarParkRealController.java deleted 100644 → 0
1 -package com.bsth.controller.real;  
2 -  
3 -import com.bsth.data.real_park.CarParkRealHandler;  
4 -import com.bsth.entity.real.RealCarPark;  
5 -import org.springframework.beans.factory.annotation.Autowired;  
6 -import org.springframework.web.bind.annotation.RequestMapping;  
7 -import org.springframework.web.bind.annotation.RequestMethod;  
8 -import org.springframework.web.bind.annotation.RequestParam;  
9 -import org.springframework.web.bind.annotation.RestController;  
10 -  
11 -import java.util.Collection;  
12 -import java.util.Map;  
13 -  
14 -/**  
15 - * Created by panzhao on 2017/9/14.  
16 - */  
17 -@RestController  
18 -@RequestMapping("car_park_real")  
19 -public class CarParkRealController {  
20 -  
21 - @Autowired  
22 - CarParkRealHandler carParkRealHandler;  
23 -  
24 - @RequestMapping("bus")  
25 - public Collection<RealCarPark> busAll(){  
26 - return CarParkRealHandler.allBus();  
27 - }  
28 -  
29 - @RequestMapping(value = "real_change", method = RequestMethod.POST)  
30 - public Map<String, Object> realChange(@RequestParam String s, @RequestParam String d){  
31 - return carParkRealHandler.realChange(s, d);  
32 - }  
33 -  
34 - @RequestMapping(value = "add_car2berth", method = RequestMethod.POST)  
35 - public Map<String, Object> addCar2Berth(@RequestParam String berthName, @RequestParam String nbbm){  
36 - return carParkRealHandler.addCar2Berth(berthName, nbbm);  
37 - }  
38 -  
39 - @RequestMapping(value = "clear_berth", method = RequestMethod.POST)  
40 - public Map<String, Object> clear_berth(@RequestParam String b){  
41 - return carParkRealHandler.clear_berth(b);  
42 - }  
43 -}  
src/main/java/com/bsth/controller/schedule/InOutScheduleController.java
1 package com.bsth.controller.schedule; 1 package com.bsth.controller.schedule;
2 2
3 import com.bsth.data.schedule.dto.ScheduleInOut; 3 import com.bsth.data.schedule.dto.ScheduleInOut;
4 -import com.bsth.service.schedule.InOutScheduleService; 4 +import com.bsth.service.schedule.ScheduleService;
5 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.web.bind.annotation.RequestMapping; 6 import org.springframework.web.bind.annotation.RequestMapping;
7 import org.springframework.web.bind.annotation.RestController; 7 import org.springframework.web.bind.annotation.RestController;
@@ -17,7 +17,7 @@ import java.util.List; @@ -17,7 +17,7 @@ import java.util.List;
17 public class InOutScheduleController { 17 public class InOutScheduleController {
18 18
19 @Autowired 19 @Autowired
20 - InOutScheduleService inOutScheduleService; 20 + ScheduleService inOutScheduleService;
21 21
22 @RequestMapping("all") 22 @RequestMapping("all")
23 public Collection<ScheduleInOut> all(){ 23 public Collection<ScheduleInOut> all(){
src/main/java/com/bsth/data/electric/CarElectricBuffer.java deleted 100644 → 0
1 -package com.bsth.data.electric;  
2 -  
3 -import com.bsth.data.real_park.CarParkRealHandler;  
4 -import com.bsth.entity.electric.BusElectric;  
5 -import org.springframework.beans.factory.annotation.Autowired;  
6 -import org.springframework.stereotype.Component;  
7 -  
8 -import java.util.Collection;  
9 -import java.util.HashMap;  
10 -import java.util.List;  
11 -import java.util.Map;  
12 -  
13 -/**  
14 - * 车辆电量信息  
15 - * Created by panzhao on 2017/9/11.  
16 - */  
17 -@Component  
18 -public class CarElectricBuffer {  
19 -  
20 - public static Map<String, BusElectric> carElecMap = new HashMap<>();  
21 -  
22 - @Autowired  
23 - CarParkRealHandler carParkRealHandler;  
24 -  
25 - public void putAll(List<BusElectric> list){  
26 - for(BusElectric be : list){  
27 - carElecMap.put(be.getNbbm(), be);  
28 - carParkRealHandler.putElec(be);  
29 - }  
30 - }  
31 -  
32 - public static Collection<BusElectric> all(){  
33 - return carElecMap.values();  
34 - }  
35 -}  
src/main/java/com/bsth/data/in_out/DataRecoveryUtil.java 0 → 100644
  1 +package com.bsth.data.in_out;
  2 +
  3 +import com.bsth.data.in_out.buffer.BerthDataBuffer;
  4 +import com.bsth.entity.berth.RegionBerth;
  5 +import com.bsth.repository.berth.BerthRepository;
  6 +import com.google.common.collect.BiMap;
  7 +import com.google.common.collect.HashBiMap;
  8 +import org.apache.commons.lang3.StringUtils;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.stereotype.Component;
  11 +
  12 +import java.util.ArrayList;
  13 +import java.util.List;
  14 +
  15 +/**
  16 + * 启动的时候恢复数据
  17 + * Created by panzhao on 2017/11/5.
  18 + */
  19 +@Component
  20 +public class DataRecoveryUtil {
  21 +
  22 + @Autowired
  23 + BerthRepository berthRepository;
  24 +
  25 + @Autowired
  26 + RealInoutHandler realInoutHandler;
  27 +
  28 + @Autowired
  29 + BerthDataBuffer berthDataBuffer;
  30 +
  31 + public void recovery(){
  32 + List<RegionBerth> list = (List<RegionBerth>) berthRepository.findAll();
  33 +
  34 + //被禁用的泊位
  35 + List<String> locks = new ArrayList<>();
  36 + //车辆和停放泊位对照
  37 + BiMap<String, String> car2berth = HashBiMap.create();
  38 +
  39 + for(RegionBerth b : list){
  40 + if(b.getStatus()==-1)
  41 + locks.add(b.getName());
  42 +
  43 + if(StringUtils.isNotEmpty(b.getCar()))
  44 + car2berth.put(b.getCar(), b.getName());
  45 + }
  46 +
  47 + realInoutHandler.init(car2berth);
  48 + berthDataBuffer.putLocks(locks);
  49 + }
  50 +}
src/main/java/com/bsth/data/in_out/RealInoutHandler.java 0 → 100644
  1 +package com.bsth.data.in_out;
  2 +
  3 +import com.bsth.common.ResponseCode;
  4 +import com.bsth.data.basic.bus.BusDataBuffer;
  5 +import com.bsth.data.in_out.buffer.BerthDataBuffer;
  6 +import com.bsth.data.schedule.dto.ScheduleInOut;
  7 +import com.bsth.data.schedule.real.ScheduleDataBuffer;
  8 +import com.bsth.entity.Bus;
  9 +import com.bsth.entity.ac.CarInOutEntity;
  10 +import com.bsth.entity.berth.RegionBerth;
  11 +import com.bsth.websocket.handler.SendUtils;
  12 +import com.google.common.collect.BiMap;
  13 +import com.google.common.collect.HashBiMap;
  14 +import org.apache.commons.lang3.StringUtils;
  15 +import org.slf4j.Logger;
  16 +import org.slf4j.LoggerFactory;
  17 +import org.springframework.beans.factory.annotation.Autowired;
  18 +import org.springframework.stereotype.Component;
  19 +
  20 +import java.util.HashMap;
  21 +import java.util.LinkedList;
  22 +import java.util.List;
  23 +import java.util.Map;
  24 +
  25 +/**
  26 + * 实时进出场数据处理程序
  27 + * Created by panzhao on 2017/11/4.
  28 + */
  29 +@Component
  30 +public class RealInoutHandler {
  31 +
  32 + static Logger logger = LoggerFactory.getLogger(RealInoutHandler.class);
  33 +
  34 + /**
  35 + * 车辆自编号和停放泊位号对照
  36 + */
  37 + private static BiMap<String, String> car2berthMap;
  38 +
  39 + //待入库数据
  40 + public static LinkedList<CarInOutEntity> psts;
  41 +
  42 + @Autowired
  43 + SendUtils sendUtils;
  44 +
  45 + static {
  46 + car2berthMap = HashBiMap.create();
  47 + psts = new LinkedList();
  48 + }
  49 +
  50 + public void init(BiMap<String, String> map){
  51 + car2berthMap = map;
  52 + }
  53 +
  54 + /**
  55 + * 进出场
  56 + * @param cio
  57 + */
  58 + public void inOut(CarInOutEntity cio) {
  59 + //公交车
  60 + if(0 == cio.getCarType()){
  61 + //获取对应的计划排班
  62 + ScheduleInOut sch = ScheduleDataBuffer.get(cio);
  63 +
  64 + //rfid进出场时附加排班信息
  65 + if(sch != null && cio.getSignalType()==0)
  66 + addPlanFiled(cio, sch);
  67 +
  68 + //入库 -只存实进和实出
  69 + if(cio.getType() == 2 || cio.getType() == 4)
  70 + psts.add(cio);
  71 +
  72 + if (cio.getType() == 2)
  73 + busIn(cio); //公交车进场
  74 + else if (cio.getType() == 4)
  75 + busOut(cio); //公交车出场
  76 + }
  77 + }
  78 +
  79 + private void busOut(CarInOutEntity cio) {
  80 + car2berthMap.remove(cio.getNbbm());
  81 +
  82 + //通知客户端
  83 + sendUtils.sendCarOut(cio.getNbbm(), cio.getT());
  84 + }
  85 +
  86 + private void busIn(CarInOutEntity cio) {
  87 + String nbbm = cio.getNbbm();
  88 + if (StringUtils.isEmpty(nbbm))
  89 + return;
  90 +
  91 + //车辆已经在泊位上,先移除(可能没有出场信号)
  92 + if(car2berthMap.containsKey(nbbm)){
  93 + car2berthMap.remove(nbbm);
  94 + }
  95 + Bus bus = BusDataBuffer.findOne(nbbm);
  96 + //非电车,停柴油泊位区
  97 + if(!bus.isSfdc()){
  98 + //LedHttpPushHandler.busIn(bus.getCarPlate(), "柴油泊位区");
  99 + return;
  100 + }
  101 +
  102 + //是否有固定泊位
  103 + String lockBName = BerthDataBuffer.getLockBerthName(nbbm);
  104 + if(StringUtils.isNotEmpty(lockBName))
  105 + car2berthMap.put(nbbm, lockBName);
  106 + else{
  107 + //停空闲泊位
  108 + List<RegionBerth> berthList = BerthDataBuffer.allNoLock();
  109 + RegionBerth free = null;
  110 + for(RegionBerth b : berthList){
  111 + //被占用的泊位
  112 + if(car2berthMap.inverse().containsKey(b.getName()))
  113 + continue;
  114 + //被禁用的泊位
  115 + if(BerthDataBuffer.isLock(b.getName()))
  116 + continue;
  117 + free = b;
  118 + break;
  119 + }
  120 + if(null != free){
  121 + car2berthMap.put(nbbm, free.getName());
  122 + }
  123 + else
  124 + logger.info("没有空余泊位了");
  125 + }
  126 +
  127 + //通知客户端
  128 + sendUtils.sendCarIn(nbbm, car2berthMap.get(nbbm), cio.getT());
  129 + }
  130 +
  131 + private void addPlanFiled(CarInOutEntity cio, ScheduleInOut sch) {
  132 + if(null == sch.getOutTimeRfid())
  133 + sch.setOutTimeRfid(cio.getT());
  134 + //计划时间
  135 + cio.setPt(sch.getDfsjT());
  136 + cio.setLineCode(sch.getLineCode());
  137 + cio.setLineName(sch.getLineName());
  138 + cio.setCompany(sch.getGsbm());
  139 + cio.setFgsCompany(sch.getFgsbm());
  140 + cio.setTaskStatus(1);
  141 + cio.setpJsy(sch.getjGh());
  142 +
  143 + /**
  144 + * 人车是否相符
  145 + */
  146 + if(StringUtils.isNotEmpty(cio.getJsy())){
  147 + String sjGh = cio.getJsy().split("/")[0];
  148 +
  149 + if(sch.getjGh().equals(sjGh)){
  150 + cio.setPcMatch(true);
  151 + }
  152 + }
  153 + }
  154 +
  155 + public static Map<String, String> getCar2berthMap(){
  156 + return car2berthMap;
  157 + }
  158 +
  159 + /**
  160 + * 添加车辆和泊位对照
  161 + * @param nbbm
  162 + * @param berthName
  163 + * @return
  164 + */
  165 + public Map<String, Object> addCar2Berth(String nbbm, String berthName) {
  166 + Map<String, Object> rs = new HashMap<>();
  167 +
  168 + try{
  169 + if(car2berthMap.containsKey(nbbm))
  170 + car2berthMap.remove(nbbm);
  171 +
  172 + if(car2berthMap.inverse().containsKey(berthName))
  173 + car2berthMap.inverse().remove(berthName);
  174 +
  175 + car2berthMap.put(nbbm, berthName);
  176 + rs.put("status", ResponseCode.SUCCESS);
  177 + }catch (Exception e){
  178 + logger.error("", e);
  179 + rs.put("status", ResponseCode.ERROR);
  180 + }
  181 + return rs;
  182 + }
  183 +
  184 + /**
  185 + * 删除指定泊位上的车辆
  186 + * @param berthName
  187 + * @return
  188 + */
  189 + public Map<String, Object> removeCar2Berth(String berthName) {
  190 + Map<String, Object> rs = new HashMap<>();
  191 +
  192 + try{
  193 +
  194 + if(car2berthMap.inverse().containsKey(berthName))
  195 + car2berthMap.inverse().remove(berthName);
  196 +
  197 + rs.put("status", ResponseCode.SUCCESS);
  198 + }catch (Exception e){
  199 + logger.error("", e);
  200 + rs.put("status", ResponseCode.ERROR);
  201 + }
  202 + return rs;
  203 + }
  204 +
  205 + /**
  206 + * 对换指定2个泊位上的车辆
  207 + * @param s
  208 + * @param d
  209 + * @return
  210 + */
  211 + public static Map<String, Object> changeCar2Berth(String s, String d) {
  212 + Map<String, Object> rs = new HashMap<>();
  213 +
  214 + try{
  215 +
  216 + Map<String, String> inverseMap = car2berthMap.inverse();
  217 +
  218 + String sv = inverseMap.get(s);
  219 + String dv = inverseMap.get(d);
  220 +
  221 + if(sv != null){
  222 + inverseMap.remove(s);
  223 + inverseMap.put(d, sv);
  224 + }
  225 + else
  226 + inverseMap.remove(d);
  227 +
  228 + if(dv != null)
  229 + inverseMap.put(s, dv);
  230 +
  231 + rs.put("status", ResponseCode.SUCCESS);
  232 + }catch (Exception e){
  233 + logger.error("", e);
  234 + rs.put("status", ResponseCode.ERROR);
  235 + }
  236 + return rs;
  237 + }
  238 +
  239 + public boolean containsBerth(String berthName) {
  240 + return car2berthMap.inverse().containsKey(berthName);
  241 + }
  242 +}
src/main/java/com/bsth/data/in_out/buffer/BerthDataBuffer.java 0 → 100644
  1 +package com.bsth.data.in_out.buffer;
  2 +
  3 +import com.bsth.common.ResponseCode;
  4 +import com.bsth.data.in_out.RealInoutHandler;
  5 +import com.bsth.entity.berth.RegionBerth;
  6 +import com.bsth.repository.berth.BerthRepository;
  7 +import com.google.common.collect.BiMap;
  8 +import com.google.common.collect.HashBiMap;
  9 +import org.apache.commons.lang3.StringUtils;
  10 +import org.slf4j.Logger;
  11 +import org.slf4j.LoggerFactory;
  12 +import org.springframework.beans.factory.annotation.Autowired;
  13 +import org.springframework.jdbc.core.JdbcTemplate;
  14 +import org.springframework.stereotype.Component;
  15 +
  16 +import java.util.*;
  17 +
  18 +/**
  19 + * 泊位数据
  20 + * Created by panzhao on 2017/11/4.
  21 + */
  22 +@Component
  23 +public class BerthDataBuffer {
  24 +
  25 + @Autowired
  26 + JdbcTemplate jdbcTemplate;
  27 +
  28 + static Logger logger = LoggerFactory.getLogger(BerthDataBuffer.class);
  29 +
  30 + //按顺序排列的泊位集合
  31 + private static List<RegionBerth> berthList;
  32 +
  33 + private static Map<String, RegionBerth> nameMap;
  34 +
  35 + //被禁用的泊位
  36 + private static List<String> lockList;
  37 +
  38 + /**
  39 + * 固定泊位
  40 + * 32 ~ 43 号泊位 固定停放 31~42号车。 W0E-031
  41 + */
  42 + private static BiMap<String, String> lockBerthMap;
  43 +
  44 + @Autowired
  45 + RealInoutHandler realInoutHandler;
  46 +
  47 + @Autowired
  48 + private BerthComp comp;
  49 +
  50 + static {
  51 + lockBerthMap = HashBiMap.create();
  52 + lockBerthMap.put("W0E-031", "32");
  53 + lockBerthMap.put("W0E-032", "33");
  54 + lockBerthMap.put("W0E-033", "34");
  55 + lockBerthMap.put("W0E-034", "35");
  56 + lockBerthMap.put("W0E-035", "36");
  57 + lockBerthMap.put("W0E-036", "37");
  58 + lockBerthMap.put("W0E-037", "38");
  59 + lockBerthMap.put("W0E-038", "39");
  60 + lockBerthMap.put("W0E-039", "40");
  61 + lockBerthMap.put("W0E-040", "41");
  62 + lockBerthMap.put("W0E-041", "42");
  63 + lockBerthMap.put("W0E-042", "43");
  64 + lockList = new ArrayList<>();
  65 + }
  66 +
  67 + public void putLocks(List<String> list){
  68 + lockList = list;
  69 + }
  70 +
  71 + public static boolean isLock(String name){
  72 + return lockList.contains(name);
  73 + }
  74 + /**
  75 + * 所有非固定泊位
  76 + * @return
  77 + */
  78 + public static List<RegionBerth> allNoLock(){
  79 + List<RegionBerth> rs = new ArrayList<>();
  80 + for(RegionBerth b : berthList){
  81 + if(lockBerthMap.inverse().containsKey(b.getName()))
  82 + continue;
  83 + rs.add(b);
  84 + }
  85 + return rs;
  86 + }
  87 +
  88 + public static List<RegionBerth> all(){
  89 + return berthList;
  90 + }
  91 +
  92 + public static String getLockBerthName(String nbbm){
  93 + return lockBerthMap.get(nbbm);
  94 + }
  95 +
  96 + public static RegionBerth findOne(String name){
  97 + return nameMap.get(name);
  98 + }
  99 +
  100 + @Autowired
  101 + BerthRepository berthRepository;
  102 +
  103 + public void init(){
  104 +
  105 + //加载数据库的泊位数据
  106 + berthList = (List<RegionBerth>) berthRepository.findAll();
  107 +
  108 + //排序
  109 + Collections.sort(berthList, comp);
  110 + //泊位名称对照
  111 + Map<String, RegionBerth> nameMapCopy = new HashMap<>();
  112 + //被禁用的泊位
  113 + List<String> locks = new ArrayList<>();
  114 + //车辆和停放泊位对照
  115 + BiMap<String, String> car2berth = HashBiMap.create();
  116 +
  117 + for(RegionBerth berth : berthList){
  118 + nameMapCopy.put(berth.getName(), berth);
  119 +
  120 + if(berth.getStatus()==-1)
  121 + locks.add(berth.getName());
  122 +
  123 + if(StringUtils.isNotEmpty(berth.getCar()))
  124 + car2berth.put(berth.getCar(), berth.getName());
  125 + }
  126 + nameMap = nameMapCopy;
  127 + realInoutHandler.init(car2berth);
  128 + putLocks(locks);
  129 + }
  130 +
  131 + public Map<String, Object> lockBerth(String berthName) {
  132 + Map<String, Object> rs = new HashMap<>();
  133 + try{
  134 + if(realInoutHandler.containsBerth(berthName)){
  135 + rs.put("status", ResponseCode.ERROR);
  136 + rs.put("msg", "请先清除泊位上的车辆,再尝试禁用泊位");
  137 + }
  138 + else{
  139 + //修改数据库
  140 + jdbcTemplate.update("update bsth_p_berth set status=-1 where name=?", berthName);
  141 + findOne(berthName).setStatus(-1);
  142 + lockList.add(berthName);
  143 +
  144 + rs.put("status", ResponseCode.SUCCESS);
  145 + }
  146 + }catch (Exception e){
  147 + logger.error("", e);
  148 + }
  149 + return rs;
  150 + }
  151 +
  152 + public Map<String, Object> unlockBerth(String berthName) {
  153 + Map<String, Object> rs = new HashMap<>();
  154 + try{
  155 + //修改数据库
  156 + jdbcTemplate.update("update bsth_p_berth set status=0 where name=?", berthName);
  157 + findOne(berthName).setStatus(0);
  158 + lockList.remove(berthName);
  159 + rs.put("status", ResponseCode.SUCCESS);
  160 + }catch (Exception e){
  161 + logger.error("", e);
  162 + rs.put("status", ResponseCode.ERROR);
  163 + }
  164 + return rs;
  165 + }
  166 +
  167 +
  168 + @Component
  169 + public static class BerthComp implements Comparator<RegionBerth>{
  170 +
  171 + @Override
  172 + public int compare(RegionBerth b1, RegionBerth b2) {
  173 + return b1.getOrderNo().compareTo(b2.getOrderNo());
  174 + }
  175 + }
  176 +}
src/main/java/com/bsth/data/in_out/buffer/ElectricDataBuffer.java 0 → 100644
  1 +package com.bsth.data.in_out.buffer;
  2 +
  3 +import com.bsth.data.in_out.entity.Electric;
  4 +
  5 +import java.util.HashMap;
  6 +import java.util.List;
  7 +import java.util.Map;
  8 +import java.util.Set;
  9 +
  10 +/**
  11 + * 电量数据
  12 + * Created by panzhao on 2017/11/4.
  13 + */
  14 +public class ElectricDataBuffer {
  15 +
  16 + /**
  17 + * 车辆自编号和电量信息对照
  18 + */
  19 + private static Map<String, Electric> nbbm2ElecMap;
  20 +
  21 + static {
  22 + nbbm2ElecMap = new HashMap<>();
  23 + }
  24 +
  25 + public static void put(List<Electric> list) {
  26 + for(Electric be : list){
  27 + nbbm2ElecMap.put(be.getNbbm(), be);
  28 + }
  29 + }
  30 +
  31 + public static Electric findOne(String nbbm){
  32 + return nbbm2ElecMap.get(nbbm);
  33 + }
  34 +
  35 + public static Map<String, Double> elecs(){
  36 + Map<String, Double> rs = new HashMap<>();
  37 +
  38 + Set<String> ks = nbbm2ElecMap.keySet();
  39 + for(String k : ks){
  40 + rs.put(k, Double.parseDouble(nbbm2ElecMap.get(k).getSoc()));
  41 + }
  42 + return rs;
  43 + }
  44 +}
src/main/java/com/bsth/entity/electric/BusElectric.java renamed to src/main/java/com/bsth/data/in_out/entity/Electric.java
1 -package com.bsth.entity.electric; 1 +package com.bsth.data.in_out.entity;
2 2
3 /** 3 /**
4 * 公交车电量信息 4 * 公交车电量信息
5 * Created by panzhao on 2017/9/13. 5 * Created by panzhao on 2017/9/13.
6 */ 6 */
7 -public class BusElectric { 7 +public class Electric {
8 8
9 /** 9 /**
10 * 车辆自编号 10 * 车辆自编号
src/main/java/com/bsth/data/signal/dto/RfidInOutDto.java renamed to src/main/java/com/bsth/data/in_out/entity/RfidInOutDto.java
1 -package com.bsth.data.signal.dto; 1 +package com.bsth.data.in_out.entity;
2 2
3 /** 3 /**
4 * rfid 进出场 4 * rfid 进出场
src/main/java/com/bsth/data/real_park/thread/RealParkDataPersistenceThread.java renamed to src/main/java/com/bsth/data/in_out/thread/Car2BerthDataPstThread.java
1 -package com.bsth.data.real_park.thread; 1 +package com.bsth.data.in_out.thread;
2 2
3 -import com.bsth.data.real_park.CarParkRealHandler;  
4 -import com.bsth.entity.real.RealCarPark; 3 +import com.bsth.data.in_out.RealInoutHandler;
5 import org.slf4j.Logger; 4 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory; 5 import org.slf4j.LoggerFactory;
7 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.beans.factory.annotation.Autowired;
@@ -15,25 +14,27 @@ import org.springframework.transaction.support.DefaultTransactionDefinition; @@ -15,25 +14,27 @@ import org.springframework.transaction.support.DefaultTransactionDefinition;
15 14
16 import java.sql.PreparedStatement; 15 import java.sql.PreparedStatement;
17 import java.sql.SQLException; 16 import java.sql.SQLException;
18 -import java.util.Date; 17 +import java.util.ArrayList;
19 import java.util.List; 18 import java.util.List;
  19 +import java.util.Map;
20 20
21 /** 21 /**
22 - * 实时停放信息入库线程  
23 - * Created by panzhao on 2017/9/14. 22 + * 车辆停放泊位信息入库线程
  23 + * Created by panzhao on 2017/11/5.
24 */ 24 */
25 @Component 25 @Component
26 -public class RealParkDataPersistenceThread extends Thread { 26 +public class Car2BerthDataPstThread extends Thread {
  27 +
  28 + Logger logger = LoggerFactory.getLogger(this.getClass());
27 29
28 @Autowired 30 @Autowired
29 JdbcTemplate jdbcTemplate; 31 JdbcTemplate jdbcTemplate;
30 32
31 - Logger logger = LoggerFactory.getLogger(this.getClass());  
32 -  
33 @Override 33 @Override
34 public void run() { 34 public void run() {
35 try { 35 try {
36 - final List<RealCarPark> list = CarParkRealHandler.allData(); 36 + final Map<String, String> map = RealInoutHandler.getCar2berthMap();
  37 + final List<String> ks = new ArrayList<>(map.keySet());
37 38
38 //编程式事务 39 //编程式事务
39 DataSourceTransactionManager tran = new DataSourceTransactionManager(jdbcTemplate.getDataSource()); 40 DataSourceTransactionManager tran = new DataSourceTransactionManager(jdbcTemplate.getDataSource());
@@ -41,34 +42,27 @@ public class RealParkDataPersistenceThread extends Thread { @@ -41,34 +42,27 @@ public class RealParkDataPersistenceThread extends Thread {
41 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 42 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
42 TransactionStatus status = tran.getTransaction(def); 43 TransactionStatus status = tran.getTransaction(def);
43 44
44 - try {  
45 - final java.sql.Date d = new java.sql.Date(new Date().getTime());  
46 - //删除  
47 - jdbcTemplate.update("delete from bsth_real_carpark"); 45 + try{
48 //重新写入 46 //重新写入
49 - jdbcTemplate.batchUpdate("insert into bsth_real_carpark(type, nbbm, plate_no, in_time, berth_name, soc, create_time)" +  
50 - " VALUES (?, ?, ?, ?, ?, ?, SYSDATE())", new BatchPreparedStatementSetter() { 47 + jdbcTemplate.batchUpdate("update bsth_p_berth set car=? where name=?", new BatchPreparedStatementSetter() {
51 @Override 48 @Override
52 public void setValues(PreparedStatement ps, int i) throws SQLException { 49 public void setValues(PreparedStatement ps, int i) throws SQLException {
53 - RealCarPark rcp = list.get(i);  
54 - ps.setInt(1, rcp.getType());  
55 - ps.setString(2, rcp.getNbbm());  
56 - ps.setString(3, rcp.getPlateNo());  
57 - ps.setLong(4, rcp.getInTime());  
58 - ps.setString(5, rcp.getBerthName());  
59 - ps.setString(6, rcp.getSoc()); 50 + String car = ks.get(i);
  51 + String name = map.get(car);
  52 +
  53 + ps.setString(1, car);
  54 + ps.setString(2, name);
60 } 55 }
61 56
62 @Override 57 @Override
63 public int getBatchSize() { 58 public int getBatchSize() {
64 - return list.size(); 59 + return ks.size();
65 } 60 }
66 }); 61 });
67 62
68 tran.commit(status); 63 tran.commit(status);
69 - } catch (Exception e) { 64 + }catch (Exception e){
70 tran.rollback(status); 65 tran.rollback(status);
71 - logger.error("", e);  
72 } 66 }
73 } catch (Exception e) { 67 } catch (Exception e) {
74 logger.error("", e); 68 logger.error("", e);
src/main/java/com/bsth/data/signal/thread/SignalPstThread.java renamed to src/main/java/com/bsth/data/in_out/thread/SignalPstThread.java
1 -package com.bsth.data.signal.thread; 1 +package com.bsth.data.in_out.thread;
2 2
  3 +import com.bsth.data.in_out.RealInoutHandler;
3 import com.bsth.entity.ac.CarInOutEntity; 4 import com.bsth.entity.ac.CarInOutEntity;
4 import com.bsth.repository.ac.CarInOutRepository; 5 import com.bsth.repository.ac.CarInOutRepository;
5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.stereotype.Component; 7 import org.springframework.stereotype.Component;
7 8
8 import java.util.ArrayList; 9 import java.util.ArrayList;
9 -import java.util.LinkedList;  
10 import java.util.List; 10 import java.util.List;
11 11
12 /** 12 /**
@@ -19,19 +19,13 @@ public class SignalPstThread extends Thread{ @@ -19,19 +19,13 @@ public class SignalPstThread extends Thread{
19 @Autowired 19 @Autowired
20 CarInOutRepository carInOutRepository; 20 CarInOutRepository carInOutRepository;
21 21
22 - public static LinkedList<CarInOutEntity> psts;  
23 -  
24 - static {  
25 - psts = new LinkedList<>();  
26 - }  
27 -  
28 @Override 22 @Override
29 public void run() { 23 public void run() {
30 24
31 List<CarInOutEntity> list = new ArrayList<>(); 25 List<CarInOutEntity> list = new ArrayList<>();
32 CarInOutEntity cio; 26 CarInOutEntity cio;
33 for(int i = 0; i < 1000; i ++){ 27 for(int i = 0; i < 1000; i ++){
34 - cio = psts.poll(); 28 + cio = RealInoutHandler.psts.poll();
35 if(null == cio) 29 if(null == cio)
36 break; 30 break;
37 31
src/main/java/com/bsth/data/led_http/LedHttpPushHandler.java
1 package com.bsth.data.led_http; 1 package com.bsth.data.led_http;
2 2
3 -import com.bsth.data.real_park.CarParkRealHandler;  
4 -import com.bsth.data.utils.HttpClientUtils_tms;  
5 -import com.bsth.entity.ac.CarInOutEntity;  
6 -import com.bsth.entity.berth.RegionBerth;  
7 -import com.bsth.service.berth.BerthService;  
8 -import com.bsth.util.ConfigUtil;  
9 -import org.slf4j.Logger;  
10 -import org.slf4j.LoggerFactory;  
11 -import org.springframework.beans.factory.annotation.Autowired;  
12 import org.springframework.stereotype.Component; 3 import org.springframework.stereotype.Component;
13 4
14 -import java.util.LinkedList;  
15 -import java.util.List;  
16 -  
17 /** 5 /**
18 * Created by panzhao on 2017/9/26. 6 * Created by panzhao on 2017/9/26.
19 */ 7 */
20 @Component 8 @Component
21 -public class LedHttpPushHandler { 9 +public class LedHttpPushHandler {/*
22 10
23 @Autowired 11 @Autowired
24 BerthService berthService; 12 BerthService berthService;
@@ -72,10 +60,10 @@ public class LedHttpPushHandler { @@ -72,10 +60,10 @@ public class LedHttpPushHandler {
72 dataUrlLinked.add(url); 60 dataUrlLinked.add(url);
73 } 61 }
74 62
75 - /** 63 + *//**
76 * 场内停放信息 64 * 场内停放信息
77 * @return 65 * @return
78 - */ 66 + *//*
79 public void sendTfxx(){ 67 public void sendTfxx(){
80 int can=0;//可停车数 68 int can=0;//可停车数
81 int yet=0;//已停车数 69 int yet=0;//已停车数
@@ -142,5 +130,5 @@ public class LedHttpPushHandler { @@ -142,5 +130,5 @@ public class LedHttpPushHandler {
142 130
143 log.warn("Led ConsumeQueue is break..."); 131 log.warn("Led ConsumeQueue is break...");
144 } 132 }
145 - } 133 + }*/
146 } 134 }
src/main/java/com/bsth/data/msg_queue/QueueData.java 0 → 100644
  1 +package com.bsth.data.msg_queue;
  2 +
  3 +import org.springframework.web.socket.TextMessage;
  4 +import org.springframework.web.socket.WebSocketSession;
  5 +
  6 +/**
  7 + * Created by panzhao on 2017/5/11.
  8 + */
  9 +public class QueueData {
  10 +
  11 + private TextMessage message;
  12 +
  13 + private WebSocketSession session;
  14 +
  15 +
  16 + public WebSocketSession getSession() {
  17 + return session;
  18 + }
  19 +
  20 + public void setSession(WebSocketSession session) {
  21 + this.session = session;
  22 + }
  23 +
  24 + public TextMessage getMessage() {
  25 + return message;
  26 + }
  27 +
  28 + public void setMessage(TextMessage message) {
  29 + this.message = message;
  30 + }
  31 +}
src/main/java/com/bsth/data/msg_queue/SignalAndAttConsumeQueue.java
1 package com.bsth.data.msg_queue; 1 package com.bsth.data.msg_queue;
2 2
3 import com.bsth.data.attendance.entity.JsyAttendance; 3 import com.bsth.data.attendance.entity.JsyAttendance;
  4 +import com.bsth.data.in_out.RealInoutHandler;
4 import com.bsth.entity.ac.CarInOutEntity; 5 import com.bsth.entity.ac.CarInOutEntity;
5 -import com.bsth.service.schedule.InOutScheduleService; 6 +import com.bsth.service.schedule.ScheduleService;
6 import org.slf4j.Logger; 7 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory; 8 import org.slf4j.LoggerFactory;
8 import org.springframework.beans.BeansException; 9 import org.springframework.beans.BeansException;
@@ -23,7 +24,8 @@ public class SignalAndAttConsumeQueue implements ApplicationContextAware { @@ -23,7 +24,8 @@ public class SignalAndAttConsumeQueue implements ApplicationContextAware {
23 24
24 private static List<Class> clazzs; 25 private static List<Class> clazzs;
25 private static LinkedList<Object> linkedList; 26 private static LinkedList<Object> linkedList;
26 - static InOutScheduleService outScheduleService; 27 + static ScheduleService outScheduleService;
  28 + static RealInoutHandler realInoutHandler;
27 static ConsumeThread thread; 29 static ConsumeThread thread;
28 static long t; 30 static long t;
29 static final int IDLE_TIME = 1000 * 30; 31 static final int IDLE_TIME = 1000 * 30;
@@ -57,10 +59,10 @@ public class SignalAndAttConsumeQueue implements ApplicationContextAware { @@ -57,10 +59,10 @@ public class SignalAndAttConsumeQueue implements ApplicationContextAware {
57 59
58 @Override 60 @Override
59 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 61 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
60 - outScheduleService = applicationContext.getBean(InOutScheduleService.class); 62 + outScheduleService = applicationContext.getBean(ScheduleService.class);
  63 + realInoutHandler = applicationContext.getBean(RealInoutHandler.class);
61 } 64 }
62 65
63 - @Component  
64 public static class ConsumeThread extends Thread { 66 public static class ConsumeThread extends Thread {
65 67
66 Logger log = LoggerFactory.getLogger(this.getClass()); 68 Logger log = LoggerFactory.getLogger(this.getClass());
@@ -80,7 +82,7 @@ public class SignalAndAttConsumeQueue implements ApplicationContextAware { @@ -80,7 +82,7 @@ public class SignalAndAttConsumeQueue implements ApplicationContextAware {
80 outScheduleService.jsyReport((JsyAttendance) obj); 82 outScheduleService.jsyReport((JsyAttendance) obj);
81 //车辆进出场 83 //车辆进出场
82 else if(obj instanceof CarInOutEntity) 84 else if(obj instanceof CarInOutEntity)
83 - outScheduleService.inOut((CarInOutEntity)obj); 85 + realInoutHandler.inOut((CarInOutEntity)obj);
84 } else { 86 } else {
85 Thread.sleep(500); 87 Thread.sleep(500);
86 if (!sleepFlag) { 88 if (!sleepFlag) {
src/main/java/com/bsth/data/msg_queue/WebSocketPushQueue.java 0 → 100644
  1 +package com.bsth.data.msg_queue;
  2 +
  3 +import com.bsth.common.Constants;
  4 +import org.slf4j.Logger;
  5 +import org.slf4j.LoggerFactory;
  6 +import org.springframework.stereotype.Component;
  7 +import org.springframework.web.socket.TextMessage;
  8 +import org.springframework.web.socket.WebSocketSession;
  9 +
  10 +import java.util.concurrent.ConcurrentLinkedQueue;
  11 +
  12 +/**
  13 + * 线调web socket 推送队列
  14 + * Created by panzhao on 2017/5/11.
  15 + */
  16 +@Component
  17 +public class WebSocketPushQueue {
  18 +
  19 + static ConcurrentLinkedQueue<QueueData> linkedList;
  20 + static DataPushThread thread;
  21 + static Logger log = LoggerFactory.getLogger(WebSocketPushQueue.class);
  22 + static long t;
  23 + static final int IDLE_TIME = 1000 * 30;
  24 +
  25 + static {
  26 + linkedList = new ConcurrentLinkedQueue();
  27 + }
  28 +
  29 + public static boolean isIdle() {
  30 + return System.currentTimeMillis() - t > IDLE_TIME;
  31 + }
  32 +
  33 + public static void put(WebSocketSession session, TextMessage msg) {
  34 + QueueData qd = new QueueData();
  35 + qd.setMessage(msg);
  36 + qd.setSession(session);
  37 +
  38 +
  39 + log.info("put、[" + session.getAttributes().get(Constants.SESSION_USERNAME) + "] 、" + msg.getPayload());
  40 + linkedList.add(qd);
  41 + }
  42 +
  43 + public static void start() {
  44 + if (thread != null) {
  45 + thread.interrupt();
  46 + }
  47 + linkedList.clear();
  48 + thread = new DataPushThread();
  49 + thread.start();
  50 + }
  51 +
  52 + public static int size(){
  53 + return linkedList.size();
  54 + }
  55 +
  56 +
  57 + public static class DataPushThread extends Thread {
  58 +
  59 + Logger log = LoggerFactory.getLogger(this.getClass());
  60 +
  61 + @Override
  62 + public void run() {
  63 + QueueData qd;
  64 + WebSocketSession session;
  65 +
  66 + boolean sleepFlag = false;
  67 + while (true) {
  68 + try {
  69 + qd = linkedList.poll();
  70 + if (qd != null) {
  71 + sleepFlag = false;
  72 + session = qd.getSession();
  73 + if (session.isOpen()) {
  74 + log.info("push start、"+session.getRemoteAddress().getHostString()+"[" + session.getAttributes().get(Constants.SESSION_USERNAME) + "] 、" + qd.getMessage().getPayload());
  75 + session.sendMessage(qd.getMessage());
  76 + log.info("push end..");
  77 + }
  78 + } else {
  79 + Thread.sleep(500);
  80 + if (!sleepFlag) {
  81 + log.info("sleep...");
  82 + sleepFlag = true;
  83 + }
  84 + }
  85 + t = System.currentTimeMillis();
  86 + } catch (InterruptedException e) {
  87 + log.error("", e);
  88 + break;
  89 + } catch (Exception e) {
  90 + log.error("", e);
  91 + }
  92 + }
  93 +
  94 + log.warn("WebSocketPushQueue is break...");
  95 + }
  96 + }
  97 +}
src/main/java/com/bsth/data/real_park/CarParkRealHandler.java deleted 100644 → 0
1 -package com.bsth.data.real_park;  
2 -  
3 -import com.bsth.common.ResponseCode;  
4 -import com.bsth.data.basic.bus.BusDataBuffer;  
5 -import com.bsth.data.electric.CarElectricBuffer;  
6 -import com.bsth.data.led_http.LedHttpPushHandler;  
7 -import com.bsth.entity.Bus;  
8 -import com.bsth.entity.ac.CarInOutEntity;  
9 -import com.bsth.entity.berth.RegionBerth;  
10 -import com.bsth.entity.electric.BusElectric;  
11 -import com.bsth.entity.real.RealCarPark;  
12 -import com.bsth.service.berth.BerthService;  
13 -import org.apache.commons.lang3.StringUtils;  
14 -import org.slf4j.Logger;  
15 -import org.slf4j.LoggerFactory;  
16 -import org.springframework.beans.factory.annotation.Autowired;  
17 -import org.springframework.jdbc.core.BeanPropertyRowMapper;  
18 -import org.springframework.jdbc.core.JdbcTemplate;  
19 -import org.springframework.stereotype.Component;  
20 -  
21 -import java.util.*;  
22 -import java.util.concurrent.ConcurrentHashMap;  
23 -import java.util.concurrent.ConcurrentMap;  
24 -  
25 -/**  
26 - * 实时场内车辆停放数据  
27 - * Created by panzhao on 2017/9/14.  
28 - */  
29 -@Component  
30 -public class CarParkRealHandler {  
31 -  
32 - @Autowired  
33 - BerthService berthService;  
34 -  
35 - /**  
36 - * 公交车  
37 - * K: 自编号  
38 - */  
39 - private static ConcurrentMap<String, RealCarPark> busRcps;  
40 -  
41 - /**  
42 - * 非公交车  
43 - * K: 车牌号  
44 - */  
45 - private static ConcurrentMap<String, RealCarPark> carRcps;  
46 -  
47 - static Logger logger = LoggerFactory.getLogger(CarParkRealHandler.class);  
48 -  
49 - static {  
50 - busRcps = new ConcurrentHashMap<>();  
51 - carRcps = new ConcurrentHashMap<>();  
52 - }  
53 -  
54 - /**  
55 - * 公交车电量信息  
56 - *  
57 - * @param be  
58 - */  
59 - public void putElec(BusElectric be) {  
60 - RealCarPark rcp = busRcps.get(be.getNbbm());  
61 - if (null != rcp) {  
62 - rcp.setSoc(be.getSoc());  
63 - }  
64 - }  
65 -  
66 - /**  
67 - * 最大电量的泊位名称  
68 - * @return  
69 -  
70 - public String getMaxElecBerth(){  
71 - String name = null;  
72 - double maxSoc=0.0;  
73 - Collection<RealCarPark> vs = allBus();  
74 -  
75 - for(RealCarPark rcp : vs){  
76 - if(Double.parseDouble(rcp.getSoc()) > maxSoc)  
77 - name = rcp.getBerthName();  
78 - }  
79 - return name;  
80 - }*/  
81 -  
82 - public static Collection<RealCarPark> allBus() {  
83 - return busRcps.values();  
84 - }  
85 -  
86 - public static List<RealCarPark> allData(){  
87 - List<RealCarPark> all = new ArrayList<>();  
88 - all.addAll(busRcps.values());  
89 - all.addAll(carRcps.values());  
90 - return all;  
91 - }  
92 -  
93 - public void carInOut(CarInOutEntity cio) {  
94 - if (cio.getType() == 2)  
95 - carIn(cio);  
96 - else if (cio.getType() == 4)  
97 - carOut(cio);  
98 - }  
99 -  
100 - /**  
101 - * 车辆进场  
102 - *  
103 - * @param cio  
104 - */  
105 - private void carIn(CarInOutEntity cio) {  
106 - if (cio.getCarType() == 0)  
107 - busIn(cio);  
108 - else {  
109 -  
110 - }  
111 - }  
112 -  
113 - /**  
114 - * 公交车进场  
115 - *  
116 - * @param cio  
117 - */  
118 - private void busIn(CarInOutEntity cio) {  
119 - String nbbm = cio.getNbbm();  
120 - if (StringUtils.isEmpty(nbbm))  
121 - return;  
122 -  
123 - Bus bus = BusDataBuffer.findOne(nbbm);  
124 - if(!bus.isSfdc()){  
125 - LedHttpPushHandler.busIn(bus.getCarPlate(), "柴油泊位区");//柴油车  
126 - return;  
127 - }  
128 -  
129 - RealCarPark rcp = new RealCarPark();  
130 -  
131 - RegionBerth b;  
132 - //固定泊位  
133 - String lockBerthName = berthService.getLockBerthName(nbbm);  
134 - if(StringUtils.isNotEmpty(lockBerthName)){  
135 - b = berthService.get(lockBerthName);  
136 - }  
137 - else{  
138 - //泊位信息  
139 - b = berthService.next();  
140 - }  
141 -  
142 - if(null == b){  
143 - logger.info(nbbm + " 无空余泊位");  
144 - return;  
145 - }  
146 -  
147 - rcp.setPlateNo(bus.getCarPlate());  
148 - rcp.setBerthName(b.getName());  
149 - rcp.setNbbm(nbbm);  
150 - rcp.setInTime(System.currentTimeMillis());  
151 - rcp.setType(0);  
152 -  
153 - //车辆已经在场内  
154 - if(!busRcps.containsKey(nbbm) || StringUtils.isNotEmpty(busRcps.get(nbbm).getBerthName())){  
155 - //电量信息  
156 - BusElectric be = CarElectricBuffer.carElecMap.get(nbbm);  
157 - if(null != be)  
158 - rcp.setSoc(be.getSoc());  
159 - busRcps.put(nbbm, rcp);  
160 - //泊位设置车辆  
161 - berthService.set(b, nbbm);  
162 - }  
163 -  
164 - //push led  
165 - LedHttpPushHandler.busIn(rcp.getPlateNo(), rcp.getBerthName());  
166 - }  
167 -  
168 - /**  
169 - * 公交车出场  
170 - *  
171 - * @param cio  
172 - */  
173 - private void carOut(CarInOutEntity cio) {  
174 - String nbbm = cio.getNbbm();  
175 - if (StringUtils.isEmpty(nbbm))  
176 - return;  
177 -  
178 - if(busRcps.containsKey(nbbm)){  
179 - String bName = busRcps.get(nbbm).getBerthName();  
180 - if(null != bName)  
181 - clear_berth(bName);  
182 - }  
183 - LedHttpPushHandler.busOut(cio);  
184 - }  
185 -  
186 - /**  
187 - * 泊位交换  
188 - *  
189 - * @param sName 泊位名称 源  
190 - * @param dName 泊位名称 目标  
191 - * @return  
192 - */  
193 - public Map<String, Object> realChange(String sName, String dName) {  
194 - Map<String, Object> rs = new HashMap();  
195 - try {  
196 - RealCarPark rcp1 = getByBerthName(sName);  
197 - RealCarPark rcp2 = getByBerthName(dName);  
198 -  
199 - //校验泊位是否存在  
200 - if(!berthService.berthNameIsExist(sName)){  
201 - rs.put("status", ResponseCode.ERROR);  
202 - rs.put("msg", "失败,不存在泊位 " + sName);  
203 - return rs;  
204 - }  
205 - if(!berthService.berthNameIsExist(dName)){  
206 - rs.put("status", ResponseCode.ERROR);  
207 - rs.put("msg", "失败,不存在泊位 " + dName);  
208 - return rs;  
209 - }  
210 -  
211 - if(null != rcp1){  
212 - rcp1.setBerthName(dName);  
213 - berthService.set(berthService.get(dName), rcp1.getNbbm());  
214 - }  
215 - else  
216 - clear_berth2(dName);  
217 -  
218 - if(null != rcp2){  
219 - rcp2.setBerthName(sName);  
220 - berthService.set(berthService.get(sName), rcp2.getNbbm());  
221 - }  
222 - else{  
223 - clear_berth2(sName);  
224 - }  
225 -  
226 - //重新计算可用枪  
227 - berthService.reCalc();  
228 - rs.put("status", ResponseCode.SUCCESS);  
229 - rs.put("list", allBus());  
230 - } catch (Exception e) {  
231 - logger.error("", e);  
232 - rs.put("status", ResponseCode.ERROR);  
233 - }  
234 - return rs;  
235 - }  
236 -  
237 - /**  
238 - * 移除泊位上的车辆  
239 - * @param b  
240 - * @return  
241 - */  
242 - public Map<String, Object> clear_berth(String b) {  
243 - Map<String, Object> rs = new HashMap();  
244 - try {  
245 - RealCarPark rcp1 = getByBerthName(b);  
246 -  
247 - RegionBerth berth = berthService.get(b);  
248 - if(null != berth)  
249 - berth.setNbbm(null);  
250 - if(null != rcp1)  
251 - busRcps.remove(rcp1.getNbbm());  
252 -  
253 - //重新计算可用枪  
254 - berthService.reCalc();  
255 - rs.put("status", ResponseCode.SUCCESS);  
256 - rs.put("list", allBus());  
257 - } catch (Exception e) {  
258 - logger.error("", e);  
259 - rs.put("status", ResponseCode.ERROR);  
260 - }  
261 - return rs;  
262 - }  
263 -  
264 - public void clear_berth2(String b) {  
265 - RegionBerth berth = berthService.get(b);  
266 - if(null != berth)  
267 - berth.setNbbm(null);  
268 - }  
269 -  
270 - private static RealCarPark getByBerthName(String sName) {  
271 - for (RealCarPark rcp : busRcps.values()) {  
272 - if (sName.equals(rcp.getBerthName()))  
273 - return rcp;  
274 - }  
275 - return null;  
276 - }  
277 -  
278 - public Double soc(String nbbm){  
279 - RealCarPark rcp = busRcps.get(nbbm);  
280 - if(null==rcp || null==rcp.getSoc())  
281 - return 0.0;  
282 - return Double.parseDouble(rcp.getSoc());  
283 - }  
284 -  
285 - @Autowired  
286 - JdbcTemplate jdbcTemplate;  
287 -  
288 - /**  
289 - * 从数据库恢复  
290 - */  
291 - public void recovery() {  
292 - String sql = "select type, nbbm, plate_no,in_time,berth_name,soc from bsth_real_carpark";  
293 - List<RealCarPark> list = jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance(RealCarPark.class));  
294 -  
295 - for(RealCarPark rcp : list){  
296 - if(rcp.getType() == 0)  
297 - busRcps.put(rcp.getNbbm(), rcp);  
298 - else  
299 - carRcps.put(rcp.getPlateNo(), rcp);  
300 - }  
301 -  
302 - //泊位数据  
303 - RegionBerth b;  
304 - for(RealCarPark rcp : busRcps.values()){  
305 - if(StringUtils.isEmpty(rcp.getBerthName()))  
306 - continue;  
307 -  
308 - b = berthService.get(rcp.getBerthName());  
309 - berthService.set(b, rcp.getNbbm());  
310 - }  
311 - }  
312 -  
313 - /**  
314 - * 车辆添加至泊位  
315 - * @param berthName  
316 - * @param nbbm  
317 - * @return  
318 - */  
319 - public Map<String,Object> addCar2Berth(String berthName, String nbbm) {  
320 - Map<String,Object> rs = new HashMap<>();  
321 -  
322 - try{  
323 - if(busRcps.containsKey(nbbm)){  
324 - RealCarPark rcp = busRcps.get(nbbm);  
325 - //交换泊位  
326 - if(StringUtils.isNotEmpty(rcp.getBerthName()))  
327 - realChange(berthName, rcp.getBerthName());  
328 - }  
329 - else{  
330 - //让车辆进场,并停放泊位  
331 - RealCarPark rcp = new RealCarPark();  
332 - rcp.setBerthName(berthName);  
333 - rcp.setNbbm(nbbm);  
334 - rcp.setType(0);  
335 - //车牌号  
336 - Bus bus = BusDataBuffer.findOne(nbbm);  
337 - if(null != bus)  
338 - rcp.setPlateNo(bus.getCarPlate());  
339 - //电量信息  
340 - BusElectric be = CarElectricBuffer.carElecMap.get(nbbm);  
341 - if(null != be)  
342 - rcp.setSoc(be.getSoc());  
343 - busRcps.put(nbbm, rcp);  
344 - }  
345 -  
346 - //重新计算可用枪  
347 - berthService.reCalc();  
348 - rs.put("status", ResponseCode.SUCCESS);  
349 - }catch (Exception e){  
350 - logger.error("", e);  
351 - rs.put("status", ResponseCode.ERROR);  
352 - }  
353 - return rs;  
354 - }  
355 -}  
src/main/java/com/bsth/data/schedule/real/InOutScheduleDataBuffer.java renamed to src/main/java/com/bsth/data/schedule/real/ScheduleDataBuffer.java
@@ -7,6 +7,7 @@ import com.bsth.data.schedule.dto.ScheduleInOut; @@ -7,6 +7,7 @@ import com.bsth.data.schedule.dto.ScheduleInOut;
7 import com.bsth.data.utils.HttpClientUtils; 7 import com.bsth.data.utils.HttpClientUtils;
8 import com.bsth.data.utils.RsRequestUtils; 8 import com.bsth.data.utils.RsRequestUtils;
9 import com.bsth.entity.Line; 9 import com.bsth.entity.Line;
  10 +import com.bsth.entity.ac.CarInOutEntity;
10 import com.bsth.util.ConfigUtil; 11 import com.bsth.util.ConfigUtil;
11 import com.google.common.collect.ArrayListMultimap; 12 import com.google.common.collect.ArrayListMultimap;
12 import org.slf4j.Logger; 13 import org.slf4j.Logger;
@@ -27,7 +28,7 @@ import java.util.concurrent.TimeUnit; @@ -27,7 +28,7 @@ import java.util.concurrent.TimeUnit;
27 * Created by panzhao on 2017/8/24. 28 * Created by panzhao on 2017/8/24.
28 */ 29 */
29 @Component 30 @Component
30 -public class InOutScheduleDataBuffer implements CommandLineRunner { 31 +public class ScheduleDataBuffer implements CommandLineRunner {
31 32
32 private static String tccCode; 33 private static String tccCode;
33 private static String dataUrl; 34 private static String dataUrl;
@@ -43,7 +44,7 @@ public class InOutScheduleDataBuffer implements CommandLineRunner { @@ -43,7 +44,7 @@ public class InOutScheduleDataBuffer implements CommandLineRunner {
43 44
44 static final int SPACE_THRESHOLD = 1000 * 60 * 60 * 2; 45 static final int SPACE_THRESHOLD = 1000 * 60 * 60 * 2;
45 46
46 - static Logger logger = LoggerFactory.getLogger(InOutScheduleDataBuffer.class); 47 + static Logger logger = LoggerFactory.getLogger(ScheduleDataBuffer.class);
47 @Autowired 48 @Autowired
48 InoutSchFixedRefreshThread fixedRefreshThread; 49 InoutSchFixedRefreshThread fixedRefreshThread;
49 50
@@ -251,6 +252,22 @@ public class InOutScheduleDataBuffer implements CommandLineRunner { @@ -251,6 +252,22 @@ public class InOutScheduleDataBuffer implements CommandLineRunner {
251 return rs; 252 return rs;
252 } 253 }
253 254
  255 + /**
  256 + * 根据进出场信息 获取对应排班
  257 + * @param cio
  258 + * @return
  259 + */
  260 + public static ScheduleInOut get(CarInOutEntity cio) {
  261 + ScheduleInOut rs = null;
  262 + if(cio.getType() == 2){
  263 + rs = getCurrExecIn(cio.getNbbm(), cio.getT());
  264 + }
  265 + else if(cio.getType() == 4){
  266 + rs = getCurrExecOut(cio.getNbbm(), cio.getT());
  267 + }
  268 + return rs;
  269 + }
  270 +
254 @Component 271 @Component
255 public class InoutSchFixedRefreshThread extends Thread { 272 public class InoutSchFixedRefreshThread extends Thread {
256 273
@@ -289,7 +306,7 @@ public class InOutScheduleDataBuffer implements CommandLineRunner { @@ -289,7 +306,7 @@ public class InOutScheduleDataBuffer implements CommandLineRunner {
289 } 306 }
290 307
291 logger.info("同步进出场班数量 " + listCopy.size()); 308 logger.info("同步进出场班数量 " + listCopy.size());
292 - InOutScheduleDataBuffer.putAll(listCopy); 309 + ScheduleDataBuffer.putAll(listCopy);
293 310
294 } catch (Exception e) { 311 } catch (Exception e) {
295 e.printStackTrace(); 312 e.printStackTrace();
src/main/java/com/bsth/data/signal/RFIDInParkDataBuffer.java deleted 100644 → 0
1 -package com.bsth.data.signal;  
2 -  
3 -import com.bsth.data.signal.dto.RfidInOutDto;  
4 -import com.bsth.data.msg_queue.SignalAndAttConsumeQueue;  
5 -import com.bsth.entity.ac.CarInOutEntity;  
6 -import org.apache.commons.lang3.StringUtils;  
7 -import org.slf4j.Logger;  
8 -import org.slf4j.LoggerFactory;  
9 -  
10 -import java.util.LinkedList;  
11 -  
12 -/**  
13 - * 场内 RFID 数据缓存  
14 - * Created by panzhao on 2017/9/5.  
15 - */  
16 -public class RFIDInParkDataBuffer {  
17 -  
18 - static Logger logger = LoggerFactory.getLogger(RFIDInParkDataBuffer.class);  
19 -  
20 - private static LinkedList<RfidInOutDto> list;  
21 -  
22 - static{  
23 - list = new LinkedList<>();  
24 - }  
25 -  
26 - public static void put(RfidInOutDto rfidInOut){  
27 - if(null == rfidInOut)  
28 - return;  
29 - if(StringUtils.isEmpty(rfidInOut.getCarCard()))  
30 - return;  
31 -  
32 - if(null == rfidInOut.getReportTime())  
33 - return;  
34 -  
35 - list.add(rfidInOut);  
36 - CarInOutEntity cio = CarInOutEntity.getInstance(rfidInOut);  
37 - SignalAndAttConsumeQueue.put(cio);  
38 - }  
39 -}  
src/main/java/com/bsth/entity/ac/CarInOutEntity.java
@@ -2,7 +2,7 @@ package com.bsth.entity.ac; @@ -2,7 +2,7 @@ package com.bsth.entity.ac;
2 2
3 import com.bsth.data.basic.bus.BusDataBuffer; 3 import com.bsth.data.basic.bus.BusDataBuffer;
4 import com.bsth.data.basic.person.PersonDataBuffer; 4 import com.bsth.data.basic.person.PersonDataBuffer;
5 -import com.bsth.data.signal.dto.RfidInOutDto; 5 +import com.bsth.data.in_out.entity.RfidInOutDto;
6 import com.bsth.entity.Bus; 6 import com.bsth.entity.Bus;
7 import com.bsth.entity.Person; 7 import com.bsth.entity.Person;
8 import com.bsth.util.HexCardTransform; 8 import com.bsth.util.HexCardTransform;
src/main/java/com/bsth/entity/berth/RegionBerth.java
1 package com.bsth.entity.berth; 1 package com.bsth.entity.berth;
2 2
3 -import com.bsth.entity.electric.BusElectric;  
4 -  
5 import javax.persistence.*; 3 import javax.persistence.*;
6 import java.util.Date; 4 import java.util.Date;
7 5
@@ -66,11 +64,9 @@ public class RegionBerth implements Cloneable{ @@ -66,11 +64,9 @@ public class RegionBerth implements Cloneable{
66 */ 64 */
67 private int status; 65 private int status;
68 66
69 - private String remark;  
70 -  
71 - @Transient  
72 - private BusElectric be; 67 + private String car;
73 68
  69 + private String remark;
74 70
75 @Column(updatable = false, name = "create_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP") 71 @Column(updatable = false, name = "create_date", columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
76 private Date createDate; 72 private Date createDate;
@@ -78,12 +74,6 @@ public class RegionBerth implements Cloneable{ @@ -78,12 +74,6 @@ public class RegionBerth implements Cloneable{
78 @Column(name = "update_date", columnDefinition = "timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP") 74 @Column(name = "update_date", columnDefinition = "timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
79 private Date updateDate; 75 private Date updateDate;
80 76
81 - /**  
82 - * 停放车辆  
83 - */  
84 - @Transient  
85 - private String nbbm;  
86 -  
87 @Override 77 @Override
88 public int hashCode() { 78 public int hashCode() {
89 return this.toString().hashCode(); 79 return this.toString().hashCode();
@@ -163,14 +153,6 @@ public class RegionBerth implements Cloneable{ @@ -163,14 +153,6 @@ public class RegionBerth implements Cloneable{
163 this.remark = remark; 153 this.remark = remark;
164 } 154 }
165 155
166 - public BusElectric getBe() {  
167 - return be;  
168 - }  
169 -  
170 - public void setBe(BusElectric be) {  
171 - this.be = be;  
172 - }  
173 -  
174 public String getSt() { 156 public String getSt() {
175 return st; 157 return st;
176 } 158 }
@@ -203,11 +185,11 @@ public class RegionBerth implements Cloneable{ @@ -203,11 +185,11 @@ public class RegionBerth implements Cloneable{
203 this.chargePile = chargePile; 185 this.chargePile = chargePile;
204 } 186 }
205 187
206 - public String getNbbm() {  
207 - return nbbm; 188 + public String getCar() {
  189 + return car;
208 } 190 }
209 191
210 - public void setNbbm(String nbbm) {  
211 - this.nbbm = nbbm; 192 + public void setCar(String car) {
  193 + this.car = car;
212 } 194 }
213 } 195 }
src/main/java/com/bsth/entity/real/RealCarPark.java deleted 100644 → 0
1 -package com.bsth.entity.real;  
2 -  
3 -/**  
4 - * 实时场内车辆停放情况  
5 - * Created by panzhao on 2017/9/14.  
6 - */  
7 -public class RealCarPark {  
8 -  
9 - /**  
10 - * 车辆类型  
11 - * 0 公交车  
12 - * 1 小车  
13 - * 2 其他  
14 - */  
15 - private int type;  
16 -  
17 - /**  
18 - * 公交车车辆自编号  
19 - */  
20 - private String nbbm;  
21 -  
22 - /**  
23 - * 车牌号  
24 - */  
25 - private String plateNo;  
26 -  
27 - /**  
28 - * 进场时间  
29 - */  
30 - private Long inTime;  
31 -  
32 - /**  
33 - * 停放泊位名称  
34 - */  
35 - private String berthName;  
36 -  
37 - /**  
38 - * 实时电量  
39 - */  
40 - private String soc;  
41 -  
42 -  
43 - public String getNbbm() {  
44 - return nbbm;  
45 - }  
46 -  
47 - public void setNbbm(String nbbm) {  
48 - this.nbbm = nbbm;  
49 - }  
50 -  
51 - public String getPlateNo() {  
52 - return plateNo;  
53 - }  
54 -  
55 - public void setPlateNo(String plateNo) {  
56 - this.plateNo = plateNo;  
57 - }  
58 -  
59 - public Long getInTime() {  
60 - return inTime;  
61 - }  
62 -  
63 - public void setInTime(Long inTime) {  
64 - this.inTime = inTime;  
65 - }  
66 -  
67 - public String getBerthName() {  
68 - return berthName;  
69 - }  
70 -  
71 - public void setBerthName(String berthName) {  
72 - this.berthName = berthName;  
73 - }  
74 -  
75 - public String getSoc() {  
76 - return soc;  
77 - }  
78 -  
79 - public void setSoc(String soc) {  
80 - this.soc = soc;  
81 - }  
82 -  
83 - public int getType() {  
84 - return type;  
85 - }  
86 -  
87 - public void setType(int type) {  
88 - this.type = type;  
89 - }  
90 -  
91 - @Override  
92 - public int hashCode() {  
93 - return toString().hashCode();  
94 - }  
95 -  
96 - @Override  
97 - public boolean equals(Object obj) {  
98 - RealCarPark rcp = (RealCarPark) obj;  
99 - if(this.getType() != rcp.getType())  
100 - return false;  
101 - else{  
102 - if(this.getNbbm().equals(rcp.getNbbm()) || this.getPlateNo().equals(rcp.getPlateNo()))  
103 - return true;  
104 - }  
105 - return super.equals(obj);  
106 - }  
107 -  
108 - @Override  
109 - public String toString() {  
110 - return this.getType() + "_" + this.getNbbm() + "_" + this.getPlateNo();  
111 - }  
112 -}  
src/main/java/com/bsth/service/berth/BerthService.java
1 package com.bsth.service.berth; 1 package com.bsth.service.berth;
2 2
  3 +import com.bsth.controller.berth.dto.Car2Berth;
3 import com.bsth.entity.berth.RegionBerth; 4 import com.bsth.entity.berth.RegionBerth;
4 import com.bsth.service.BaseService; 5 import com.bsth.service.BaseService;
5 6
@@ -9,7 +10,8 @@ import java.util.List; @@ -9,7 +10,8 @@ import java.util.List;
9 * Created by panzhao on 2017/8/22. 10 * Created by panzhao on 2017/8/22.
10 */ 11 */
11 public interface BerthService extends BaseService<RegionBerth, Integer>{ 12 public interface BerthService extends BaseService<RegionBerth, Integer>{
12 - RegionBerth next(); 13 + List<Car2Berth> car2Berths();
  14 + /*RegionBerth next();
13 15
14 String getLockBerthName(String nbbm); 16 String getLockBerthName(String nbbm);
15 17
@@ -23,7 +25,7 @@ public interface BerthService extends BaseService&lt;RegionBerth, Integer&gt;{ @@ -23,7 +25,7 @@ public interface BerthService extends BaseService&lt;RegionBerth, Integer&gt;{
23 25
24 void set(RegionBerth b, String nbbm); 26 void set(RegionBerth b, String nbbm);
25 27
26 - void reCalc(); 28 + void reCalc();*/
27 29
28 //void berthInOut(Bus bus); 30 //void berthInOut(Bus bus);
29 31
src/main/java/com/bsth/service/berth/impl/BerthServiceImpl.java
1 package com.bsth.service.berth.impl; 1 package com.bsth.service.berth.impl;
2 2
3 -import com.bsth.data.real_park.CarParkRealHandler; 3 +import com.bsth.controller.berth.dto.Car2Berth;
  4 +import com.bsth.data.basic.bus.BusDataBuffer;
  5 +import com.bsth.data.in_out.RealInoutHandler;
4 import com.bsth.entity.berth.RegionBerth; 6 import com.bsth.entity.berth.RegionBerth;
5 -import com.bsth.repository.berth.BerthRepository;  
6 import com.bsth.service.berth.BerthService; 7 import com.bsth.service.berth.BerthService;
7 import com.bsth.service.impl.BaseServiceImpl; 8 import com.bsth.service.impl.BaseServiceImpl;
8 -import com.bsth.util.ConvertUtil;  
9 -import com.google.common.collect.ArrayListMultimap;  
10 -import com.google.common.collect.BiMap;  
11 -import com.google.common.collect.HashBiMap;  
12 -import org.apache.commons.lang3.StringUtils;  
13 -import org.slf4j.Logger;  
14 -import org.slf4j.LoggerFactory;  
15 -import org.springframework.beans.factory.annotation.Autowired;  
16 -import org.springframework.stereotype.Component;  
17 import org.springframework.stereotype.Service; 9 import org.springframework.stereotype.Service;
18 10
19 -import java.util.*; 11 +import java.util.ArrayList;
  12 +import java.util.List;
  13 +import java.util.Map;
  14 +import java.util.Set;
20 15
21 /** 16 /**
22 * Created by panzhao on 2017/8/22. 17 * Created by panzhao on 2017/8/22.
@@ -24,300 +19,20 @@ import java.util.*; @@ -24,300 +19,20 @@ import java.util.*;
24 @Service 19 @Service
25 public class BerthServiceImpl extends BaseServiceImpl<RegionBerth, Integer> implements BerthService { 20 public class BerthServiceImpl extends BaseServiceImpl<RegionBerth, Integer> implements BerthService {
26 21
27 - //泊位集合  
28 - private static List<RegionBerth> berthList;  
29 -  
30 - @Autowired  
31 - CarParkRealHandler carParkRealHandler;  
32 -  
33 - @Autowired  
34 - BerthRepository berthRepository;  
35 -  
36 - /**  
37 - * 固定泊位  
38 - * 32 ~ 43 号泊位 固定停放 31~42号车。 W0E-031  
39 - */  
40 - private static BiMap<String, String> lockBerthMap;  
41 -  
42 - static {  
43 - lockBerthMap = HashBiMap.create();  
44 - lockBerthMap.put("W0E-031", "32");  
45 - lockBerthMap.put("W0E-032", "33");  
46 - lockBerthMap.put("W0E-033", "34");  
47 - lockBerthMap.put("W0E-034", "35");  
48 - lockBerthMap.put("W0E-035", "36");  
49 - lockBerthMap.put("W0E-036", "37");  
50 - lockBerthMap.put("W0E-037", "38");  
51 - lockBerthMap.put("W0E-038", "39");  
52 - lockBerthMap.put("W0E-039", "40");  
53 - lockBerthMap.put("W0E-040", "41");  
54 - lockBerthMap.put("W0E-041", "42");  
55 - lockBerthMap.put("W0E-042", "43");  
56 - }  
57 -  
58 - @Override  
59 - public String getLockBerthName(String nbbm){  
60 - return lockBerthMap.get(nbbm);  
61 - }  
62 -  
63 - @Override  
64 - public String maxOrderNo() {  
65 - return berthRepository.maxOrderNo();  
66 - }  
67 -  
68 - /**  
69 - * 充电枪状态 K: 枪号 V: 1 充电中  
70 - */  
71 - private static Map<Integer, Integer> chargeMap;  
72 - Logger logger = LoggerFactory.getLogger(this.getClass());  
73 -  
74 -  
75 - static {  
76 - berthList = new ArrayList<>();  
77 - chargeMap = new HashMap<>();  
78 - }  
79 -  
80 - /**  
81 - * 获取下一个可用泊位  
82 - *  
83 - * @return  
84 - */  
85 @Override 22 @Override
86 - public RegionBerth next() {  
87 - RegionBerth b = null;  
88 -  
89 - try {  
90 - /*b = nextChargeBerth();  
91 - if (null != b)  
92 - return b;  
93 -  
94 - //最快充电完成枪的空余泊位  
95 - b = maxElecBerth();*/  
96 -  
97 - //获取按顺序排列的下一个泊位  
98 - b = nextByOrder();  
99 - } catch (Exception e) {  
100 - logger.error("", e);  
101 - }  
102 - return b;  
103 - }  
104 -  
105 - @Override  
106 - public boolean berthNameIsExist(String berthName){  
107 - for(RegionBerth b : berthList){  
108 - if(b.getName().equals(berthName))  
109 - return true;  
110 - }  
111 - return false;  
112 - }  
113 -  
114 - @Override  
115 - public List<RegionBerth> all(){  
116 - return berthList;  
117 - }  
118 -  
119 - /**  
120 - * 根据名称获取泊位  
121 - * @param lockBerthName  
122 - * @return  
123 - */  
124 - @Override  
125 - public RegionBerth get(String name) {  
126 - for(RegionBerth b : berthList){  
127 - if(b.getName().equals(name))  
128 - return b;  
129 - }  
130 - return null;  
131 - }  
132 -  
133 - @Override  
134 - public void set(RegionBerth b, String nbbm) {  
135 - b.setNbbm(nbbm);  
136 - chargeMap.put(b.getChargePile(), 1);  
137 - }  
138 -  
139 - private RegionBerth maxElecBerth() {  
140 - RegionBerth near = null;  
141 - //按充电桩分组  
142 - try {  
143 - //跳过固定泊位  
144 - List<RegionBerth> templist = new ArrayList<>();  
145 - for(RegionBerth b : berthList){  
146 - if(!lockBerthMap.inverse().containsKey(b.getName()))  
147 - templist.add(b);  
148 - }  
149 -  
150 - ArrayListMultimap<String, RegionBerth> multimap = new ConvertUtil<RegionBerth>()  
151 - .groupMultiList(templist, "", RegionBerth.class.getDeclaredField("chargePile"));  
152 -  
153 - Set<String> ks = multimap.keySet();  
154 - //排序  
155 - List<String> cps = new ArrayList<>(ks);  
156 - Collections.sort(cps, new Comparator<String>() {  
157 - @Override  
158 - public int compare(String s1, String s2) {  
159 - return Integer.parseInt(s1) - Integer.parseInt(s2);  
160 - }  
161 - });  
162 -  
163 - int status;  
164 - double maxSoc = -1;  
165 - List<RegionBerth> list;  
166 - for (String cp : cps) {  
167 - list = multimap.get(cp);  
168 - //充电枪状态  
169 - status = calcCpStatus(list);  
170 - if (status == 1) {  
171 - double soc = calcCpMaxSoc(list);  
172 - RegionBerth tempBerth = nearBerthByCp(list);  
173 -  
174 - if (soc > maxSoc) {  
175 - maxSoc = soc;  
176 - near = tempBerth;  
177 - }  
178 - }  
179 - }  
180 - } catch (NoSuchFieldException e) {  
181 - logger.error("", e);  
182 - }  
183 - return near;  
184 - }  
185 -  
186 - private RegionBerth nextByOrder(){  
187 - //跳过固定泊位  
188 - List<RegionBerth> templist = new ArrayList<>();  
189 - for(RegionBerth b : berthList){  
190 - if(!lockBerthMap.inverse().containsKey(b.getName()))  
191 - templist.add(b);  
192 - }  
193 -  
194 - Collections.sort(templist, new Comparator<RegionBerth>() {  
195 - @Override  
196 - public int compare(RegionBerth b1, RegionBerth b2) {  
197 - return Integer.parseInt(b1.getOrderNo()) - Integer.parseInt(b2.getOrderNo());  
198 - }  
199 - });  
200 -  
201 - for(RegionBerth b : templist){  
202 - if(StringUtils.isEmpty(b.getNbbm()))  
203 - return b;  
204 - }  
205 - return null;  
206 - }  
207 -  
208 - private RegionBerth nearBerthByCp(List<RegionBerth> list) {  
209 - Collections.sort(list, new Comparator<RegionBerth>() {  
210 - @Override  
211 - public int compare(RegionBerth b1, RegionBerth b2) {  
212 - return b1.getOrderNo().compareTo(b2.getOrderNo());  
213 - }  
214 - });  
215 - for (RegionBerth b : list) {  
216 - if (null == b.getNbbm())  
217 - return b;  
218 - }  
219 - return null;  
220 - }  
221 -  
222 - private double calcCpMaxSoc(List<RegionBerth> list) {  
223 - Double maxSoc = 0.0, soc;  
224 - for (RegionBerth b : list) {  
225 - if(StringUtils.isEmpty(b.getNbbm()))  
226 - continue;  
227 - soc = carParkRealHandler.soc(b.getNbbm());  
228 - if (null != soc && soc > maxSoc)  
229 - maxSoc = soc;  
230 - }  
231 - return maxSoc;  
232 - }  
233 -  
234 - /**  
235 - * 充电桩状态  
236 - * 0:枪空闲(2个泊位都空闲)  
237 - * 1:有车充电且有空余泊位  
238 - * 2:无空余泊位  
239 - *  
240 - * @param regionBerths  
241 - * @return  
242 - */  
243 - private int calcCpStatus(List<RegionBerth> list) {  
244 - int count = 0;  
245 - for (RegionBerth b : list) {  
246 - if (null != b.getNbbm())  
247 - count++;  
248 - }  
249 -  
250 - if (count == 0)  
251 - return 0;  
252 -  
253 - if (count >= list.size())  
254 - return 2;  
255 - return 1;  
256 - }  
257 -  
258 - /**  
259 - * 获取下一个可充电的泊位  
260 - *  
261 - * @return  
262 - */  
263 - private RegionBerth nextChargeBerth() {  
264 - for (RegionBerth b : berthList) {  
265 - //跳过固定泊位  
266 - if(lockBerthMap.inverse().containsKey(b.getName()))  
267 - continue;  
268 -  
269 - if (null == b.getNbbm()  
270 - && (!chargeMap.containsKey(b.getChargePile()) || chargeMap.get(b.getChargePile())!=1))  
271 - return b;  
272 -  
273 - }  
274 - return null;  
275 - }  
276 -  
277 - /**  
278 - * 重新计算可用枪  
279 - */  
280 - @Override  
281 - public void reCalc(){  
282 - Map<Integer, Integer> map = new HashMap<>();  
283 - for(RegionBerth b : berthList ){  
284 - if(StringUtils.isNotEmpty(b.getNbbm()))  
285 - map.put(b.getChargePile(), 1);  
286 - }  
287 -  
288 - chargeMap = map;  
289 - }  
290 -  
291 - /**  
292 - * 定时将泊位数据load 到内存  
293 - */  
294 - @Component  
295 - public static class BerthCacheRefreshThread extends Thread {  
296 -  
297 - @Autowired  
298 - BerthRepository berthRepository;  
299 -  
300 - @Override  
301 - public void run() {  
302 - List<RegionBerth> list = (List<RegionBerth>) berthRepository.findAll();  
303 -  
304 - List<RegionBerth> listCopy = new ArrayList<>();  
305 - Collections.copy(listCopy, berthList);  
306 -  
307 - for (RegionBerth b : list) {  
308 - if (!listCopy.contains(b))  
309 - listCopy.add(b);  
310 - }  
311 -  
312 - //排序  
313 - Collections.sort(listCopy, new Comparator<RegionBerth>() {  
314 - @Override  
315 - public int compare(RegionBerth b1, RegionBerth b2) {  
316 - return b1.getOrderNo().compareTo(b2.getOrderNo());  
317 - }  
318 - });  
319 -  
320 - berthList = listCopy;  
321 - } 23 + public List<Car2Berth> car2Berths() {
  24 + List<Car2Berth> list = new ArrayList<>();
  25 + //车辆自编号和停放泊位名称对照
  26 + Map<String, String> map = RealInoutHandler.getCar2berthMap();
  27 + Car2Berth c2b;
  28 + Set<String> ks = map.keySet();
  29 + for(String nbbm : ks){
  30 + c2b = new Car2Berth();
  31 + c2b.setBus(BusDataBuffer.findOne(nbbm));
  32 + c2b.setBerth(map.get(nbbm));
  33 + //c2b.setElec(ElectricDataBuffer.findOne(nbbm));
  34 + list.add(c2b);
  35 + }
  36 + return list;
322 } 37 }
323 } 38 }
src/main/java/com/bsth/service/schedule/InOutScheduleService.java renamed to src/main/java/com/bsth/service/schedule/ScheduleService.java
@@ -2,7 +2,6 @@ package com.bsth.service.schedule; @@ -2,7 +2,6 @@ package com.bsth.service.schedule;
2 2
3 import com.bsth.data.attendance.entity.JsyAttendance; 3 import com.bsth.data.attendance.entity.JsyAttendance;
4 import com.bsth.data.schedule.dto.ScheduleInOut; 4 import com.bsth.data.schedule.dto.ScheduleInOut;
5 -import com.bsth.entity.ac.CarInOutEntity;  
6 5
7 import java.util.Collection; 6 import java.util.Collection;
8 import java.util.List; 7 import java.util.List;
@@ -10,7 +9,7 @@ import java.util.List; @@ -10,7 +9,7 @@ import java.util.List;
10 /** 9 /**
11 * Created by panzhao on 2017/8/30. 10 * Created by panzhao on 2017/8/30.
12 */ 11 */
13 -public interface InOutScheduleService { 12 +public interface ScheduleService {
14 13
15 List<ScheduleInOut> findByCurrentTime(); 14 List<ScheduleInOut> findByCurrentTime();
16 15
@@ -24,9 +23,9 @@ public interface InOutScheduleService { @@ -24,9 +23,9 @@ public interface InOutScheduleService {
24 */ 23 */
25 void jsyReport(JsyAttendance att); 24 void jsyReport(JsyAttendance att);
26 25
27 - void inOut(CarInOutEntity obj); 26 + //void inOut(CarInOutEntity obj);
28 27
29 - void busInOut(CarInOutEntity obj); 28 + //void busInOut(CarInOutEntity obj);
30 29
31 - void busInOutRfid(CarInOutEntity cio, ScheduleInOut sio); 30 + //void busInOutRfid(CarInOutEntity cio, ScheduleInOut sio);
32 } 31 }
src/main/java/com/bsth/service/schedule/impl/InOutScheduleServiceImpl.java renamed to src/main/java/com/bsth/service/schedule/impl/ScheduleServiceImpl.java
1 package com.bsth.service.schedule.impl; 1 package com.bsth.service.schedule.impl;
2 2
3 import com.bsth.data.attendance.entity.JsyAttendance; 3 import com.bsth.data.attendance.entity.JsyAttendance;
4 -import com.bsth.data.real_park.CarParkRealHandler;  
5 import com.bsth.data.schedule.dto.ScheduleInOut; 4 import com.bsth.data.schedule.dto.ScheduleInOut;
6 -import com.bsth.data.schedule.real.InOutScheduleDataBuffer;  
7 -import com.bsth.data.signal.thread.SignalPstThread;  
8 -import com.bsth.entity.ac.CarInOutEntity;  
9 -import com.bsth.service.schedule.InOutScheduleService;  
10 -import org.apache.commons.lang3.StringUtils;  
11 -import org.springframework.beans.factory.annotation.Autowired; 5 +import com.bsth.data.schedule.real.ScheduleDataBuffer;
  6 +import com.bsth.service.schedule.ScheduleService;
12 import org.springframework.stereotype.Service; 7 import org.springframework.stereotype.Service;
13 8
14 import java.util.Collection; 9 import java.util.Collection;
@@ -18,15 +13,12 @@ import java.util.List; @@ -18,15 +13,12 @@ import java.util.List;
18 * Created by panzhao on 2017/9/4. 13 * Created by panzhao on 2017/9/4.
19 */ 14 */
20 @Service 15 @Service
21 -public class InOutScheduleServiceImpl implements InOutScheduleService { 16 +public class ScheduleServiceImpl implements ScheduleService {
22 17
23 18
24 /* @Autowired 19 /* @Autowired
25 BerthService berthService;*/ 20 BerthService berthService;*/
26 21
27 - @Autowired  
28 - CarParkRealHandler carParkRealHandler;  
29 -  
30 @Override 22 @Override
31 public List<ScheduleInOut> findByCurrentTime() { 23 public List<ScheduleInOut> findByCurrentTime() {
32 return null; 24 return null;
@@ -34,12 +26,12 @@ public class InOutScheduleServiceImpl implements InOutScheduleService { @@ -34,12 +26,12 @@ public class InOutScheduleServiceImpl implements InOutScheduleService {
34 26
35 @Override 27 @Override
36 public Collection<ScheduleInOut> findAll() { 28 public Collection<ScheduleInOut> findAll() {
37 - return InOutScheduleDataBuffer.all(); 29 + return ScheduleDataBuffer.all();
38 } 30 }
39 31
40 @Override 32 @Override
41 public List<ScheduleInOut> all_out() { 33 public List<ScheduleInOut> all_out() {
42 - return InOutScheduleDataBuffer.all_out(); 34 + return ScheduleDataBuffer.all_out();
43 } 35 }
44 36
45 /** 37 /**
@@ -50,7 +42,7 @@ public class InOutScheduleServiceImpl implements InOutScheduleService { @@ -50,7 +42,7 @@ public class InOutScheduleServiceImpl implements InOutScheduleService {
50 @Override 42 @Override
51 public void jsyReport(JsyAttendance att) { 43 public void jsyReport(JsyAttendance att) {
52 //驾驶员的出场计划 44 //驾驶员的出场计划
53 - ScheduleInOut sio = InOutScheduleDataBuffer.getCurrExecOut(att.getCompany(), att.getUserId(), att.getAt()); 45 + ScheduleInOut sio = ScheduleDataBuffer.getCurrExecOut(att.getCompany(), att.getUserId(), att.getAt());
54 46
55 //报到时间不覆盖 47 //报到时间不覆盖
56 if(sio.getAttSjTime() != null) 48 if(sio.getAttSjTime() != null)
@@ -60,65 +52,4 @@ public class InOutScheduleServiceImpl implements InOutScheduleService { @@ -60,65 +52,4 @@ public class InOutScheduleServiceImpl implements InOutScheduleService {
60 //通知页面 52 //通知页面
61 53
62 } 54 }
63 -  
64 - @Override  
65 - public void inOut(CarInOutEntity cio) {  
66 - if(0 == cio.getCarType())  
67 - busInOut(cio);  
68 -  
69 - //准备入库 -只存实进和实出  
70 - if(cio.getType() == 2 || cio.getType() == 4)  
71 - SignalPstThread.psts.add(cio);  
72 - }  
73 -  
74 - @Override  
75 - public void busInOut(CarInOutEntity cio) {  
76 - //车辆的出场计划  
77 - ScheduleInOut sio = null;  
78 - if(cio.getType() == 2){  
79 - sio = InOutScheduleDataBuffer.getCurrExecIn(cio.getNbbm(), cio.getT());  
80 - }  
81 - else if(cio.getType() == 4){  
82 - sio = InOutScheduleDataBuffer.getCurrExecOut(cio.getNbbm(), cio.getT());  
83 - }  
84 -  
85 -  
86 - //实时车辆进出场处理程序  
87 - carParkRealHandler.carInOut(cio);  
88 - if(null == sio)  
89 - return;  
90 -  
91 - switch (cio.getSignalType()){  
92 - case 0:  
93 - busInOutRfid(cio, sio);  
94 - break;  
95 - }  
96 - }  
97 -  
98 - @Override  
99 - public void busInOutRfid(CarInOutEntity cio, ScheduleInOut sch) {  
100 - /*if(sch.getOutTimeRfid() != null)  
101 - return;*/  
102 - if(null == sch.getOutTimeRfid())  
103 - sch.setOutTimeRfid(cio.getT());  
104 - //计划时间  
105 - cio.setPt(sch.getDfsjT());  
106 - cio.setLineCode(sch.getLineCode());  
107 - cio.setLineName(sch.getLineName());  
108 - cio.setCompany(sch.getGsbm());  
109 - cio.setFgsCompany(sch.getFgsbm());  
110 - cio.setTaskStatus(1);  
111 - cio.setpJsy(sch.getjGh());  
112 -  
113 - /**  
114 - * 人车是否相符  
115 - */  
116 - if(StringUtils.isNotEmpty(cio.getJsy())){  
117 - String sjGh = cio.getJsy().split("/")[0];  
118 -  
119 - if(sch.getjGh().equals(sjGh)){  
120 - cio.setPcMatch(true);  
121 - }  
122 - }  
123 - }  
124 } 55 }
src/main/java/com/bsth/websocket/handler/SocketHandler.java renamed to src/main/java/com/bsth/websocket/handler/RealInoutSocketHandler.java
1 package com.bsth.websocket.handler; 1 package com.bsth.websocket.handler;
2 2
  3 +import com.bsth.data.msg_queue.WebSocketPushQueue;
3 import org.slf4j.Logger; 4 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory; 5 import org.slf4j.LoggerFactory;
5 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
6 import org.springframework.web.socket.*; 7 import org.springframework.web.socket.*;
7 8
8 import java.util.ArrayList; 9 import java.util.ArrayList;
9 -import java.util.Collection;  
10 import java.util.Iterator; 10 import java.util.Iterator;
11 -import java.util.List;  
12 import java.util.concurrent.ConcurrentHashMap; 11 import java.util.concurrent.ConcurrentHashMap;
13 import java.util.concurrent.CopyOnWriteArrayList; 12 import java.util.concurrent.CopyOnWriteArrayList;
14 13
@@ -16,7 +15,7 @@ import java.util.concurrent.CopyOnWriteArrayList; @@ -16,7 +15,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
16 * @author PanZhao 15 * @author PanZhao
17 */ 16 */
18 @Component 17 @Component
19 -public class SocketHandler implements WebSocketHandler { 18 +public class RealInoutSocketHandler implements WebSocketHandler {
20 19
21 Logger logger = LoggerFactory.getLogger(this.getClass()); 20 Logger logger = LoggerFactory.getLogger(this.getClass());
22 21
@@ -32,15 +31,6 @@ public class SocketHandler implements WebSocketHandler { @@ -32,15 +31,6 @@ public class SocketHandler implements WebSocketHandler {
32 public void afterConnectionClosed(WebSocketSession session, CloseStatus arg1) 31 public void afterConnectionClosed(WebSocketSession session, CloseStatus arg1)
33 throws Exception { 32 throws Exception {
34 users.remove(session); 33 users.remove(session);
35 - //清理监听  
36 - int vsCount=0;  
37 - Collection<CopyOnWriteArrayList<WebSocketSession>> vs = listenMap.values();  
38 - for(CopyOnWriteArrayList<WebSocketSession> list : vs){  
39 - list.remove(session);  
40 -  
41 - vsCount += list.size();  
42 - }  
43 - logger.info("listen values size: " + vsCount + " -CloseStatus:" + arg1 + "conn: " + users.size());  
44 } 34 }
45 35
46 @Override 36 @Override
@@ -52,24 +42,6 @@ public class SocketHandler implements WebSocketHandler { @@ -52,24 +42,6 @@ public class SocketHandler implements WebSocketHandler {
52 @Override 42 @Override
53 public void handleMessage(WebSocketSession session, WebSocketMessage<?> msg) 43 public void handleMessage(WebSocketSession session, WebSocketMessage<?> msg)
54 throws Exception { 44 throws Exception {
55 - /*JSONObject jsonObj = JSONObject.parseObject(msg.getPayload().toString());  
56 - switch (jsonObj.getString("operCode")) {  
57 - case "register_line":  
58 - //注册线路监听  
59 - List<String> idx = Splitter.on(",").splitToList(jsonObj.getString("idx"));  
60 - for(String lineCode : idx){  
61 - if(BasicData.lineCode2NameMap.containsKey(lineCode)){  
62 - if(!listenMap.containsKey(lineCode)){  
63 - listenMap.put(lineCode, new CopyOnWriteArrayList<WebSocketSession>());  
64 - }  
65 - listenMap.get(lineCode).add(session);  
66 - }  
67 - }  
68 - break;  
69 -  
70 - default:  
71 - break;  
72 - }*/  
73 logger.info(msg.getPayload().toString()); 45 logger.info(msg.getPayload().toString());
74 } 46 }
75 47
@@ -89,23 +61,6 @@ public class SocketHandler implements WebSocketHandler { @@ -89,23 +61,6 @@ public class SocketHandler implements WebSocketHandler {
89 61
90 62
91 /** 63 /**
92 - * 根据线路推送消息  
93 - */  
94 - public void sendMessageToLine(String lineCode, String msg) {  
95 -  
96 - TextMessage message = new TextMessage(msg.getBytes());  
97 - List<WebSocketSession> list = listenMap.get(lineCode);  
98 - if(list == null || list.size() == 0)  
99 - return;  
100 -  
101 - for(WebSocketSession user : list){  
102 - //WebSocketPushQueue.put(user, message);  
103 - }  
104 - }  
105 -  
106 -  
107 -  
108 - /**  
109 * 全局推送 64 * 全局推送
110 */ 65 */
111 public void sendMessage(String msg) { 66 public void sendMessage(String msg) {
@@ -117,7 +72,7 @@ public class SocketHandler implements WebSocketHandler { @@ -117,7 +72,7 @@ public class SocketHandler implements WebSocketHandler {
117 WebSocketSession user; 72 WebSocketSession user;
118 while(iterator.hasNext()){ 73 while(iterator.hasNext()){
119 user = iterator.next(); 74 user = iterator.next();
120 - //WebSocketPushQueue.put(user, message); 75 + WebSocketPushQueue.put(user, message);
121 } 76 }
122 } 77 }
123 } 78 }
src/main/java/com/bsth/websocket/handler/SendUtils.java 0 → 100644
  1 +package com.bsth.websocket.handler;
  2 +
  3 +import com.fasterxml.jackson.databind.ObjectMapper;
  4 +import org.slf4j.Logger;
  5 +import org.slf4j.LoggerFactory;
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +import java.text.SimpleDateFormat;
  10 +import java.util.Date;
  11 +import java.util.HashMap;
  12 +import java.util.Map;
  13 +
  14 +@Component
  15 +public class SendUtils{
  16 +
  17 + @Autowired
  18 + private RealInoutSocketHandler socketHandler;
  19 +
  20 + private static Logger logger = LoggerFactory.getLogger(SendUtils.class);
  21 +
  22 + private static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
  23 +
  24 + public void sendCarIn(String nbbm, String berthName, Long t){
  25 + Map<String, Object> map = new HashMap<>();
  26 + map.put("fn", "carIn");
  27 + map.put("nbbm", nbbm);
  28 + map.put("berthName", berthName);
  29 + map.put("dataStr", sdf.format(new Date(t)));
  30 +
  31 + ObjectMapper mapper = new ObjectMapper();
  32 +
  33 + try {
  34 + socketHandler.sendMessage(mapper.writeValueAsString(map));
  35 + } catch (Exception e) {
  36 + logger.error("", e);
  37 + }
  38 + }
  39 +
  40 + public void sendCarOut(String nbbm, Long t){
  41 + Map<String, Object> map = new HashMap<>();
  42 + map.put("fn", "carOut");
  43 + map.put("nbbm", nbbm);
  44 + map.put("dataStr", sdf.format(new Date(t)));
  45 +
  46 + ObjectMapper mapper = new ObjectMapper();
  47 +
  48 + try {
  49 + socketHandler.sendMessage(mapper.writeValueAsString(map));
  50 + } catch (Exception e) {
  51 + logger.error("", e);
  52 + }
  53 + }
  54 +}
src/main/resources/static/assets/css/main.css
@@ -24,6 +24,10 @@ input::-webkit-input-placeholder { @@ -24,6 +24,10 @@ input::-webkit-input-placeholder {
24 margin-top: -2px; 24 margin-top: -2px;
25 } 25 }
26 26
  27 +.top_tools.scok-colse{
  28 + background: #f4b7b7;
  29 +}
  30 +
27 .top_tools .ct-btn-list { 31 .top_tools .ct-btn-list {
28 display: inline-block; 32 display: inline-block;
29 width: calc(100% - 180px); 33 width: calc(100% - 180px);
@@ -618,33 +622,33 @@ table tr th, table tr td{ @@ -618,33 +622,33 @@ table tr th, table tr td{
618 padding: 25px; 622 padding: 25px;
619 overflow-x: hidden; 623 overflow-x: hidden;
620 overflow-y: auto; 624 overflow-y: auto;
621 -  
622 -webkit-user-select: none; 625 -webkit-user-select: none;
623 user-select: none; 626 user-select: none;
624 overflow: auto; 627 overflow: auto;
625 - height: calc(100% - 50px); 628 + height: calc(100% - 68px);
626 position: relative; 629 position: relative;
  630 + padding-top: 10px;
627 } 631 }
628 632
629 -.berth_card_list>.berth_card{ 633 +.berth_card_list .berth_card{
630 display: inline-block; 634 display: inline-block;
631 width: 160px; 635 width: 160px;
632 height: 160px; 636 height: 160px;
633 background: #fff; 637 background: #fff;
634 color: #666; 638 color: #666;
635 box-shadow: 0 5px 15px rgba(0,0,0,0.08); 639 box-shadow: 0 5px 15px rgba(0,0,0,0.08);
636 - margin: 11px; 640 + margin: 0;
637 } 641 }
638 642
639 -.berth_card_list>.berth_card>.car_blank{ 643 +.berth_card_list .berth_card>.car_blank{
640 height: 70%; 644 height: 70%;
641 } 645 }
642 646
643 -.berth_card_list>.berth_card>.car_blank.free{ 647 +.berth_card_list .berth_card>.car_blank.free{
644 background: #f9f9f9; 648 background: #f9f9f9;
645 } 649 }
646 650
647 -.berth_card_list>.berth_card>.car_blank.free:before{ 651 +.berth_card_list .berth_card>.car_blank.free:before{
648 content: '空闲'; 652 content: '空闲';
649 width: 100%; 653 width: 100%;
650 height: 70%; 654 height: 70%;
@@ -657,7 +661,23 @@ table tr th, table tr td{ @@ -657,7 +661,23 @@ table tr th, table tr td{
657 padding-left: 44%; 661 padding-left: 44%;
658 } 662 }
659 663
660 -.berth_card_list>.berth_card>.berth_info{ 664 +.berth_card_list .berth_card>.car_blank.free.lock:before{
  665 + content: '';
  666 + width: 100%;
  667 + height: 70%;
  668 + display: block;
  669 + padding-top: 29%;
  670 + color: #a1a0a0;
  671 + background: url(/assets/icon/lock.png);
  672 + background-repeat: no-repeat;
  673 + background-position: 32% 46%;
  674 +}
  675 +
  676 +/*.berth_card_list .berth_card>.car_blank.free.lock {
  677 + background: #bababa;
  678 +}*/
  679 +
  680 +.berth_card_list .berth_card>.berth_info{
661 height: calc(30% - 11px); 681 height: calc(30% - 11px);
662 font-size: 18px; 682 font-size: 18px;
663 font-family: 微软雅黑; 683 font-family: 微软雅黑;
@@ -668,11 +688,11 @@ table tr th, table tr td{ @@ -668,11 +688,11 @@ table tr th, table tr td{
668 position: relative; 688 position: relative;
669 } 689 }
670 690
671 -.berth_card_list>.berth_card>.car_blank.charging{ 691 +.berth_card_list .berth_card>.car_blank.charging{
672 background: rgb(223, 167, 85); 692 background: rgb(223, 167, 85);
673 } 693 }
674 694
675 -.berth_card_list>.berth_card>.car_blank.charging:before{ 695 +.berth_card_list .berth_card>.car_blank.charging:before{
676 content: "正在充电..."; 696 content: "正在充电...";
677 width: 100%; 697 width: 100%;
678 height: 20px; 698 height: 20px;
@@ -686,23 +706,16 @@ table tr th, table tr td{ @@ -686,23 +706,16 @@ table tr th, table tr td{
686 background-position: 42px 11px; 706 background-position: 42px 11px;
687 } 707 }
688 708
689 -.berth_card_list>.berth_card>.car_blank.no_elec{ 709 +.berth_card_list .berth_card>.car_blank.no_elec{
690 background: #9f9f9f; 710 background: #9f9f9f;
691 } 711 }
692 712
693 -.berth_card_list>.berth_card>.car_blank.draging{ 713 +.berth_card_list .berth_card>.car_blank.draging{
694 box-shadow: inset 0px 0px 15px 3px rgba(86, 84, 84, 0.59); 714 box-shadow: inset 0px 0px 15px 3px rgba(86, 84, 84, 0.59);
695 } 715 }
696 716
697 -/*.berth_card_list>.berth_card>.car_blank.draging:before{  
698 - visibility: hidden !important;  
699 -}*/  
700 717
701 -/*.berth_card_list>.berth_card .draging .car_name{  
702 - color: #adadad;  
703 -}*/  
704 -  
705 -.berth_card_list>.berth_card>.car_blank.no_elec:before{ 718 +.berth_card_list .berth_card>.car_blank.no_elec:before{
706 content: "无电量信息"; 719 content: "无电量信息";
707 width: 100%; 720 width: 100%;
708 height: 20px; 721 height: 20px;
@@ -717,7 +730,7 @@ table tr th, table tr td{ @@ -717,7 +730,7 @@ table tr th, table tr td{
717 } 730 }
718 731
719 732
720 -.berth_card_list>.berth_card .car_name{ 733 +.berth_card_list .berth_card .car_name{
721 height: calc(100% - 20px); 734 height: calc(100% - 20px);
722 text-align: center; 735 text-align: center;
723 color: #2a2a2a; 736 color: #2a2a2a;
@@ -728,7 +741,7 @@ table tr th, table tr td{ @@ -728,7 +741,7 @@ table tr th, table tr td{
728 font-family: 微软雅黑; 741 font-family: 微软雅黑;
729 } 742 }
730 743
731 -.berth_card_list>.berth_card .car_name>.elec_perc{ 744 +.berth_card_list .berth_card .car_name>.elec_perc{
732 position: absolute; 745 position: absolute;
733 bottom: 15px; 746 bottom: 15px;
734 text-align: center; 747 text-align: center;
@@ -739,11 +752,11 @@ table tr th, table tr td{ @@ -739,11 +752,11 @@ table tr th, table tr td{
739 } 752 }
740 753
741 754
742 -.berth_card_list>.berth_card>.car_blank.over{ 755 +.berth_card_list .berth_card>.car_blank.over{
743 background: #3db6ed; 756 background: #3db6ed;
744 } 757 }
745 758
746 -.berth_card_list>.berth_card>.car_blank.over:before{ 759 +.berth_card_list .berth_card>.car_blank.over:before{
747 content: ""; 760 content: "";
748 width: 100%; 761 width: 100%;
749 height: 20px; 762 height: 20px;
@@ -912,15 +925,31 @@ table tr th, table tr td{ @@ -912,15 +925,31 @@ table tr th, table tr td{
912 } 925 }
913 926
914 .charge_pile{ 927 .charge_pile{
915 - position: absolute;  
916 - top: 11px;  
917 - left: 4px;  
918 color: #FFFFFF; 928 color: #FFFFFF;
919 font-weight: 600; 929 font-weight: 600;
920 font-size: 14px; 930 font-size: 14px;
921 - background: #E04343;  
922 - border-radius: 50%; 931 + background: #7676e8;
923 width: 25px; 932 width: 25px;
924 height: 25px; 933 height: 25px;
925 line-height: 25px; 934 line-height: 25px;
  935 + display: block;
  936 + text-align: center;
  937 + position: absolute;
  938 + left: 0;
  939 + top: 0;
  940 +}
  941 +
  942 +.charge_pile_wrap{
  943 + display: inline-block;
  944 + background: #efefef;
  945 + margin: 5px 5px 11px;
  946 + padding: 32px 7px 7px;
  947 + position: relative;
  948 + border: 1px solid #cfcfcf;
  949 + box-shadow: 0 5px 12px rgba(0, 0, 0, 0.05);
  950 + border-radius: 5px;
  951 +}
  952 +
  953 +.charge_pile_wrap>.berth_card:nth-of-type(1){
  954 + margin-right: 4px;
926 } 955 }
927 \ No newline at end of file 956 \ No newline at end of file
src/main/resources/static/assets/icon/lock.png 0 → 100644

849 Bytes

src/main/resources/static/assets/js/tts.js 0 → 100644
  1 +var gb_tts = (function() {
  2 +
  3 + var storage = window.localStorage;
  4 + var defaultConfig = {
  5 + //发音速度 1 ~ 10
  6 + rate: 1.2,
  7 + //播放队列 1:覆盖式(总是播放最新) -1:完整的按顺序播报
  8 + queueModel: 1,
  9 + enable: 1
  10 + };
  11 +
  12 + var readLocal = function() {
  13 + //从本地客户端读取配置信息
  14 + var cofig = storage.getItem('tts_cofig');
  15 + if (cofig) {
  16 + cofig = JSON.parse(cofig);
  17 + defaultConfig = cofig;
  18 + }
  19 + };
  20 +
  21 + var writeConfig = function(newConfig) {
  22 + storage.setItem('tts_cofig', JSON.stringify(newConfig));
  23 + defaultConfig = newConfig;
  24 + };
  25 +
  26 + var synth = window.speechSynthesis;
  27 + readLocal();
  28 +
  29 + var speak = function(t) {
  30 + if (defaultConfig.enable != 1)
  31 + return;
  32 + if (defaultConfig.queueModel == 1)
  33 + synth.cancel();
  34 +
  35 + //延迟100毫秒,防止中断旧语音时 将新的语音也中断
  36 + setTimeout(function() {
  37 + var msg = new SpeechSynthesisUtterance(t);
  38 + msg.rate = defaultConfig.rate;
  39 + synth.speak(msg);
  40 + }, 100);
  41 + };
  42 +
  43 + var audition = function(t, rate) {
  44 + var msg = new SpeechSynthesisUtterance(t);
  45 + msg.rate = rate;
  46 + synth.speak(msg);
  47 + };
  48 +
  49 + return {
  50 + readLocal: readLocal,
  51 + writeConfig: writeConfig,
  52 + defaultConfig: function() {
  53 + return defaultConfig
  54 + },
  55 + speak: speak,
  56 + audition: audition
  57 + };
  58 +})();
0 \ No newline at end of file 59 \ No newline at end of file
src/main/resources/static/assets/plugins/sockjs-client/sockjs.js 0 → 100644
  1 +/* sockjs-client v1.1.2 | http://sockjs.org | MIT license */
  2 +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.SockJS = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  3 +(function (global){
  4 +'use strict';
  5 +
  6 +var transportList = require('./transport-list');
  7 +
  8 +module.exports = require('./main')(transportList);
  9 +
  10 +// TODO can't get rid of this until all servers do
  11 +if ('_sockjs_onload' in global) {
  12 + setTimeout(global._sockjs_onload, 1);
  13 +}
  14 +
  15 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  16 +
  17 +},{"./main":14,"./transport-list":16}],2:[function(require,module,exports){
  18 +'use strict';
  19 +
  20 +var inherits = require('inherits')
  21 + , Event = require('./event')
  22 + ;
  23 +
  24 +function CloseEvent() {
  25 + Event.call(this);
  26 + this.initEvent('close', false, false);
  27 + this.wasClean = false;
  28 + this.code = 0;
  29 + this.reason = '';
  30 +}
  31 +
  32 +inherits(CloseEvent, Event);
  33 +
  34 +module.exports = CloseEvent;
  35 +
  36 +},{"./event":4,"inherits":56}],3:[function(require,module,exports){
  37 +'use strict';
  38 +
  39 +var inherits = require('inherits')
  40 + , EventTarget = require('./eventtarget')
  41 + ;
  42 +
  43 +function EventEmitter() {
  44 + EventTarget.call(this);
  45 +}
  46 +
  47 +inherits(EventEmitter, EventTarget);
  48 +
  49 +EventEmitter.prototype.removeAllListeners = function(type) {
  50 + if (type) {
  51 + delete this._listeners[type];
  52 + } else {
  53 + this._listeners = {};
  54 + }
  55 +};
  56 +
  57 +EventEmitter.prototype.once = function(type, listener) {
  58 + var self = this
  59 + , fired = false;
  60 +
  61 + function g() {
  62 + self.removeListener(type, g);
  63 +
  64 + if (!fired) {
  65 + fired = true;
  66 + listener.apply(this, arguments);
  67 + }
  68 + }
  69 +
  70 + this.on(type, g);
  71 +};
  72 +
  73 +EventEmitter.prototype.emit = function() {
  74 + var type = arguments[0];
  75 + var listeners = this._listeners[type];
  76 + if (!listeners) {
  77 + return;
  78 + }
  79 + // equivalent of Array.prototype.slice.call(arguments, 1);
  80 + var l = arguments.length;
  81 + var args = new Array(l - 1);
  82 + for (var ai = 1; ai < l; ai++) {
  83 + args[ai - 1] = arguments[ai];
  84 + }
  85 + for (var i = 0; i < listeners.length; i++) {
  86 + listeners[i].apply(this, args);
  87 + }
  88 +};
  89 +
  90 +EventEmitter.prototype.on = EventEmitter.prototype.addListener = EventTarget.prototype.addEventListener;
  91 +EventEmitter.prototype.removeListener = EventTarget.prototype.removeEventListener;
  92 +
  93 +module.exports.EventEmitter = EventEmitter;
  94 +
  95 +},{"./eventtarget":5,"inherits":56}],4:[function(require,module,exports){
  96 +'use strict';
  97 +
  98 +function Event(eventType) {
  99 + this.type = eventType;
  100 +}
  101 +
  102 +Event.prototype.initEvent = function(eventType, canBubble, cancelable) {
  103 + this.type = eventType;
  104 + this.bubbles = canBubble;
  105 + this.cancelable = cancelable;
  106 + this.timeStamp = +new Date();
  107 + return this;
  108 +};
  109 +
  110 +Event.prototype.stopPropagation = function() {};
  111 +Event.prototype.preventDefault = function() {};
  112 +
  113 +Event.CAPTURING_PHASE = 1;
  114 +Event.AT_TARGET = 2;
  115 +Event.BUBBLING_PHASE = 3;
  116 +
  117 +module.exports = Event;
  118 +
  119 +},{}],5:[function(require,module,exports){
  120 +'use strict';
  121 +
  122 +/* Simplified implementation of DOM2 EventTarget.
  123 + * http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget
  124 + */
  125 +
  126 +function EventTarget() {
  127 + this._listeners = {};
  128 +}
  129 +
  130 +EventTarget.prototype.addEventListener = function(eventType, listener) {
  131 + if (!(eventType in this._listeners)) {
  132 + this._listeners[eventType] = [];
  133 + }
  134 + var arr = this._listeners[eventType];
  135 + // #4
  136 + if (arr.indexOf(listener) === -1) {
  137 + // Make a copy so as not to interfere with a current dispatchEvent.
  138 + arr = arr.concat([listener]);
  139 + }
  140 + this._listeners[eventType] = arr;
  141 +};
  142 +
  143 +EventTarget.prototype.removeEventListener = function(eventType, listener) {
  144 + var arr = this._listeners[eventType];
  145 + if (!arr) {
  146 + return;
  147 + }
  148 + var idx = arr.indexOf(listener);
  149 + if (idx !== -1) {
  150 + if (arr.length > 1) {
  151 + // Make a copy so as not to interfere with a current dispatchEvent.
  152 + this._listeners[eventType] = arr.slice(0, idx).concat(arr.slice(idx + 1));
  153 + } else {
  154 + delete this._listeners[eventType];
  155 + }
  156 + return;
  157 + }
  158 +};
  159 +
  160 +EventTarget.prototype.dispatchEvent = function() {
  161 + var event = arguments[0];
  162 + var t = event.type;
  163 + // equivalent of Array.prototype.slice.call(arguments, 0);
  164 + var args = arguments.length === 1 ? [event] : Array.apply(null, arguments);
  165 + // TODO: This doesn't match the real behavior; per spec, onfoo get
  166 + // their place in line from the /first/ time they're set from
  167 + // non-null. Although WebKit bumps it to the end every time it's
  168 + // set.
  169 + if (this['on' + t]) {
  170 + this['on' + t].apply(this, args);
  171 + }
  172 + if (t in this._listeners) {
  173 + // Grab a reference to the listeners list. removeEventListener may alter the list.
  174 + var listeners = this._listeners[t];
  175 + for (var i = 0; i < listeners.length; i++) {
  176 + listeners[i].apply(this, args);
  177 + }
  178 + }
  179 +};
  180 +
  181 +module.exports = EventTarget;
  182 +
  183 +},{}],6:[function(require,module,exports){
  184 +'use strict';
  185 +
  186 +var inherits = require('inherits')
  187 + , Event = require('./event')
  188 + ;
  189 +
  190 +function TransportMessageEvent(data) {
  191 + Event.call(this);
  192 + this.initEvent('message', false, false);
  193 + this.data = data;
  194 +}
  195 +
  196 +inherits(TransportMessageEvent, Event);
  197 +
  198 +module.exports = TransportMessageEvent;
  199 +
  200 +},{"./event":4,"inherits":56}],7:[function(require,module,exports){
  201 +'use strict';
  202 +
  203 +var JSON3 = require('json3')
  204 + , iframeUtils = require('./utils/iframe')
  205 + ;
  206 +
  207 +function FacadeJS(transport) {
  208 + this._transport = transport;
  209 + transport.on('message', this._transportMessage.bind(this));
  210 + transport.on('close', this._transportClose.bind(this));
  211 +}
  212 +
  213 +FacadeJS.prototype._transportClose = function(code, reason) {
  214 + iframeUtils.postMessage('c', JSON3.stringify([code, reason]));
  215 +};
  216 +FacadeJS.prototype._transportMessage = function(frame) {
  217 + iframeUtils.postMessage('t', frame);
  218 +};
  219 +FacadeJS.prototype._send = function(data) {
  220 + this._transport.send(data);
  221 +};
  222 +FacadeJS.prototype._close = function() {
  223 + this._transport.close();
  224 + this._transport.removeAllListeners();
  225 +};
  226 +
  227 +module.exports = FacadeJS;
  228 +
  229 +},{"./utils/iframe":47,"json3":57}],8:[function(require,module,exports){
  230 +(function (process){
  231 +'use strict';
  232 +
  233 +var urlUtils = require('./utils/url')
  234 + , eventUtils = require('./utils/event')
  235 + , JSON3 = require('json3')
  236 + , FacadeJS = require('./facade')
  237 + , InfoIframeReceiver = require('./info-iframe-receiver')
  238 + , iframeUtils = require('./utils/iframe')
  239 + , loc = require('./location')
  240 + ;
  241 +
  242 +var debug = function() {};
  243 +if (process.env.NODE_ENV !== 'production') {
  244 + debug = require('debug')('sockjs-client:iframe-bootstrap');
  245 +}
  246 +
  247 +module.exports = function(SockJS, availableTransports) {
  248 + var transportMap = {};
  249 + availableTransports.forEach(function(at) {
  250 + if (at.facadeTransport) {
  251 + transportMap[at.facadeTransport.transportName] = at.facadeTransport;
  252 + }
  253 + });
  254 +
  255 + // hard-coded for the info iframe
  256 + // TODO see if we can make this more dynamic
  257 + transportMap[InfoIframeReceiver.transportName] = InfoIframeReceiver;
  258 + var parentOrigin;
  259 +
  260 + /* eslint-disable camelcase */
  261 + SockJS.bootstrap_iframe = function() {
  262 + /* eslint-enable camelcase */
  263 + var facade;
  264 + iframeUtils.currentWindowId = loc.hash.slice(1);
  265 + var onMessage = function(e) {
  266 + if (e.source !== parent) {
  267 + return;
  268 + }
  269 + if (typeof parentOrigin === 'undefined') {
  270 + parentOrigin = e.origin;
  271 + }
  272 + if (e.origin !== parentOrigin) {
  273 + return;
  274 + }
  275 +
  276 + var iframeMessage;
  277 + try {
  278 + iframeMessage = JSON3.parse(e.data);
  279 + } catch (ignored) {
  280 + debug('bad json', e.data);
  281 + return;
  282 + }
  283 +
  284 + if (iframeMessage.windowId !== iframeUtils.currentWindowId) {
  285 + return;
  286 + }
  287 + switch (iframeMessage.type) {
  288 + case 's':
  289 + var p;
  290 + try {
  291 + p = JSON3.parse(iframeMessage.data);
  292 + } catch (ignored) {
  293 + debug('bad json', iframeMessage.data);
  294 + break;
  295 + }
  296 + var version = p[0];
  297 + var transport = p[1];
  298 + var transUrl = p[2];
  299 + var baseUrl = p[3];
  300 + debug(version, transport, transUrl, baseUrl);
  301 + // change this to semver logic
  302 + if (version !== SockJS.version) {
  303 + throw new Error('Incompatible SockJS! Main site uses:' +
  304 + ' "' + version + '", the iframe:' +
  305 + ' "' + SockJS.version + '".');
  306 + }
  307 +
  308 + if (!urlUtils.isOriginEqual(transUrl, loc.href) ||
  309 + !urlUtils.isOriginEqual(baseUrl, loc.href)) {
  310 + throw new Error('Can\'t connect to different domain from within an ' +
  311 + 'iframe. (' + loc.href + ', ' + transUrl + ', ' + baseUrl + ')');
  312 + }
  313 + facade = new FacadeJS(new transportMap[transport](transUrl, baseUrl));
  314 + break;
  315 + case 'm':
  316 + facade._send(iframeMessage.data);
  317 + break;
  318 + case 'c':
  319 + if (facade) {
  320 + facade._close();
  321 + }
  322 + facade = null;
  323 + break;
  324 + }
  325 + };
  326 +
  327 + eventUtils.attachEvent('message', onMessage);
  328 +
  329 + // Start
  330 + iframeUtils.postMessage('s');
  331 + };
  332 +};
  333 +
  334 +}).call(this,{ env: {} })
  335 +
  336 +},{"./facade":7,"./info-iframe-receiver":10,"./location":13,"./utils/event":46,"./utils/iframe":47,"./utils/url":52,"debug":54,"json3":57}],9:[function(require,module,exports){
  337 +(function (process){
  338 +'use strict';
  339 +
  340 +var EventEmitter = require('events').EventEmitter
  341 + , inherits = require('inherits')
  342 + , JSON3 = require('json3')
  343 + , objectUtils = require('./utils/object')
  344 + ;
  345 +
  346 +var debug = function() {};
  347 +if (process.env.NODE_ENV !== 'production') {
  348 + debug = require('debug')('sockjs-client:info-ajax');
  349 +}
  350 +
  351 +function InfoAjax(url, AjaxObject) {
  352 + EventEmitter.call(this);
  353 +
  354 + var self = this;
  355 + var t0 = +new Date();
  356 + this.xo = new AjaxObject('GET', url);
  357 +
  358 + this.xo.once('finish', function(status, text) {
  359 + var info, rtt;
  360 + if (status === 200) {
  361 + rtt = (+new Date()) - t0;
  362 + if (text) {
  363 + try {
  364 + info = JSON3.parse(text);
  365 + } catch (e) {
  366 + debug('bad json', text);
  367 + }
  368 + }
  369 +
  370 + if (!objectUtils.isObject(info)) {
  371 + info = {};
  372 + }
  373 + }
  374 + self.emit('finish', info, rtt);
  375 + self.removeAllListeners();
  376 + });
  377 +}
  378 +
  379 +inherits(InfoAjax, EventEmitter);
  380 +
  381 +InfoAjax.prototype.close = function() {
  382 + this.removeAllListeners();
  383 + this.xo.close();
  384 +};
  385 +
  386 +module.exports = InfoAjax;
  387 +
  388 +}).call(this,{ env: {} })
  389 +
  390 +},{"./utils/object":49,"debug":54,"events":3,"inherits":56,"json3":57}],10:[function(require,module,exports){
  391 +'use strict';
  392 +
  393 +var inherits = require('inherits')
  394 + , EventEmitter = require('events').EventEmitter
  395 + , JSON3 = require('json3')
  396 + , XHRLocalObject = require('./transport/sender/xhr-local')
  397 + , InfoAjax = require('./info-ajax')
  398 + ;
  399 +
  400 +function InfoReceiverIframe(transUrl) {
  401 + var self = this;
  402 + EventEmitter.call(this);
  403 +
  404 + this.ir = new InfoAjax(transUrl, XHRLocalObject);
  405 + this.ir.once('finish', function(info, rtt) {
  406 + self.ir = null;
  407 + self.emit('message', JSON3.stringify([info, rtt]));
  408 + });
  409 +}
  410 +
  411 +inherits(InfoReceiverIframe, EventEmitter);
  412 +
  413 +InfoReceiverIframe.transportName = 'iframe-info-receiver';
  414 +
  415 +InfoReceiverIframe.prototype.close = function() {
  416 + if (this.ir) {
  417 + this.ir.close();
  418 + this.ir = null;
  419 + }
  420 + this.removeAllListeners();
  421 +};
  422 +
  423 +module.exports = InfoReceiverIframe;
  424 +
  425 +},{"./info-ajax":9,"./transport/sender/xhr-local":37,"events":3,"inherits":56,"json3":57}],11:[function(require,module,exports){
  426 +(function (process,global){
  427 +'use strict';
  428 +
  429 +var EventEmitter = require('events').EventEmitter
  430 + , inherits = require('inherits')
  431 + , JSON3 = require('json3')
  432 + , utils = require('./utils/event')
  433 + , IframeTransport = require('./transport/iframe')
  434 + , InfoReceiverIframe = require('./info-iframe-receiver')
  435 + ;
  436 +
  437 +var debug = function() {};
  438 +if (process.env.NODE_ENV !== 'production') {
  439 + debug = require('debug')('sockjs-client:info-iframe');
  440 +}
  441 +
  442 +function InfoIframe(baseUrl, url) {
  443 + var self = this;
  444 + EventEmitter.call(this);
  445 +
  446 + var go = function() {
  447 + var ifr = self.ifr = new IframeTransport(InfoReceiverIframe.transportName, url, baseUrl);
  448 +
  449 + ifr.once('message', function(msg) {
  450 + if (msg) {
  451 + var d;
  452 + try {
  453 + d = JSON3.parse(msg);
  454 + } catch (e) {
  455 + debug('bad json', msg);
  456 + self.emit('finish');
  457 + self.close();
  458 + return;
  459 + }
  460 +
  461 + var info = d[0], rtt = d[1];
  462 + self.emit('finish', info, rtt);
  463 + }
  464 + self.close();
  465 + });
  466 +
  467 + ifr.once('close', function() {
  468 + self.emit('finish');
  469 + self.close();
  470 + });
  471 + };
  472 +
  473 + // TODO this seems the same as the 'needBody' from transports
  474 + if (!global.document.body) {
  475 + utils.attachEvent('load', go);
  476 + } else {
  477 + go();
  478 + }
  479 +}
  480 +
  481 +inherits(InfoIframe, EventEmitter);
  482 +
  483 +InfoIframe.enabled = function() {
  484 + return IframeTransport.enabled();
  485 +};
  486 +
  487 +InfoIframe.prototype.close = function() {
  488 + if (this.ifr) {
  489 + this.ifr.close();
  490 + }
  491 + this.removeAllListeners();
  492 + this.ifr = null;
  493 +};
  494 +
  495 +module.exports = InfoIframe;
  496 +
  497 +}).call(this,{ env: {} },typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  498 +
  499 +},{"./info-iframe-receiver":10,"./transport/iframe":22,"./utils/event":46,"debug":54,"events":3,"inherits":56,"json3":57}],12:[function(require,module,exports){
  500 +(function (process){
  501 +'use strict';
  502 +
  503 +var EventEmitter = require('events').EventEmitter
  504 + , inherits = require('inherits')
  505 + , urlUtils = require('./utils/url')
  506 + , XDR = require('./transport/sender/xdr')
  507 + , XHRCors = require('./transport/sender/xhr-cors')
  508 + , XHRLocal = require('./transport/sender/xhr-local')
  509 + , XHRFake = require('./transport/sender/xhr-fake')
  510 + , InfoIframe = require('./info-iframe')
  511 + , InfoAjax = require('./info-ajax')
  512 + ;
  513 +
  514 +var debug = function() {};
  515 +if (process.env.NODE_ENV !== 'production') {
  516 + debug = require('debug')('sockjs-client:info-receiver');
  517 +}
  518 +
  519 +function InfoReceiver(baseUrl, urlInfo) {
  520 + debug(baseUrl);
  521 + var self = this;
  522 + EventEmitter.call(this);
  523 +
  524 + setTimeout(function() {
  525 + self.doXhr(baseUrl, urlInfo);
  526 + }, 0);
  527 +}
  528 +
  529 +inherits(InfoReceiver, EventEmitter);
  530 +
  531 +// TODO this is currently ignoring the list of available transports and the whitelist
  532 +
  533 +InfoReceiver._getReceiver = function(baseUrl, url, urlInfo) {
  534 + // determine method of CORS support (if needed)
  535 + if (urlInfo.sameOrigin) {
  536 + return new InfoAjax(url, XHRLocal);
  537 + }
  538 + if (XHRCors.enabled) {
  539 + return new InfoAjax(url, XHRCors);
  540 + }
  541 + if (XDR.enabled && urlInfo.sameScheme) {
  542 + return new InfoAjax(url, XDR);
  543 + }
  544 + if (InfoIframe.enabled()) {
  545 + return new InfoIframe(baseUrl, url);
  546 + }
  547 + return new InfoAjax(url, XHRFake);
  548 +};
  549 +
  550 +InfoReceiver.prototype.doXhr = function(baseUrl, urlInfo) {
  551 + var self = this
  552 + , url = urlUtils.addPath(baseUrl, '/info')
  553 + ;
  554 + debug('doXhr', url);
  555 +
  556 + this.xo = InfoReceiver._getReceiver(baseUrl, url, urlInfo);
  557 +
  558 + this.timeoutRef = setTimeout(function() {
  559 + debug('timeout');
  560 + self._cleanup(false);
  561 + self.emit('finish');
  562 + }, InfoReceiver.timeout);
  563 +
  564 + this.xo.once('finish', function(info, rtt) {
  565 + debug('finish', info, rtt);
  566 + self._cleanup(true);
  567 + self.emit('finish', info, rtt);
  568 + });
  569 +};
  570 +
  571 +InfoReceiver.prototype._cleanup = function(wasClean) {
  572 + debug('_cleanup');
  573 + clearTimeout(this.timeoutRef);
  574 + this.timeoutRef = null;
  575 + if (!wasClean && this.xo) {
  576 + this.xo.close();
  577 + }
  578 + this.xo = null;
  579 +};
  580 +
  581 +InfoReceiver.prototype.close = function() {
  582 + debug('close');
  583 + this.removeAllListeners();
  584 + this._cleanup(false);
  585 +};
  586 +
  587 +InfoReceiver.timeout = 8000;
  588 +
  589 +module.exports = InfoReceiver;
  590 +
  591 +}).call(this,{ env: {} })
  592 +
  593 +},{"./info-ajax":9,"./info-iframe":11,"./transport/sender/xdr":34,"./transport/sender/xhr-cors":35,"./transport/sender/xhr-fake":36,"./transport/sender/xhr-local":37,"./utils/url":52,"debug":54,"events":3,"inherits":56}],13:[function(require,module,exports){
  594 +(function (global){
  595 +'use strict';
  596 +
  597 +module.exports = global.location || {
  598 + origin: 'http://localhost:80'
  599 +, protocol: 'http'
  600 +, host: 'localhost'
  601 +, port: 80
  602 +, href: 'http://localhost/'
  603 +, hash: ''
  604 +};
  605 +
  606 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  607 +
  608 +},{}],14:[function(require,module,exports){
  609 +(function (process,global){
  610 +'use strict';
  611 +
  612 +require('./shims');
  613 +
  614 +var URL = require('url-parse')
  615 + , inherits = require('inherits')
  616 + , JSON3 = require('json3')
  617 + , random = require('./utils/random')
  618 + , escape = require('./utils/escape')
  619 + , urlUtils = require('./utils/url')
  620 + , eventUtils = require('./utils/event')
  621 + , transport = require('./utils/transport')
  622 + , objectUtils = require('./utils/object')
  623 + , browser = require('./utils/browser')
  624 + , log = require('./utils/log')
  625 + , Event = require('./event/event')
  626 + , EventTarget = require('./event/eventtarget')
  627 + , loc = require('./location')
  628 + , CloseEvent = require('./event/close')
  629 + , TransportMessageEvent = require('./event/trans-message')
  630 + , InfoReceiver = require('./info-receiver')
  631 + ;
  632 +
  633 +var debug = function() {};
  634 +if (process.env.NODE_ENV !== 'production') {
  635 + debug = require('debug')('sockjs-client:main');
  636 +}
  637 +
  638 +var transports;
  639 +
  640 +// follow constructor steps defined at http://dev.w3.org/html5/websockets/#the-websocket-interface
  641 +function SockJS(url, protocols, options) {
  642 + if (!(this instanceof SockJS)) {
  643 + return new SockJS(url, protocols, options);
  644 + }
  645 + if (arguments.length < 1) {
  646 + throw new TypeError("Failed to construct 'SockJS: 1 argument required, but only 0 present");
  647 + }
  648 + EventTarget.call(this);
  649 +
  650 + this.readyState = SockJS.CONNECTING;
  651 + this.extensions = '';
  652 + this.protocol = '';
  653 +
  654 + // non-standard extension
  655 + options = options || {};
  656 + if (options.protocols_whitelist) {
  657 + log.warn("'protocols_whitelist' is DEPRECATED. Use 'transports' instead.");
  658 + }
  659 + this._transportsWhitelist = options.transports;
  660 + this._transportOptions = options.transportOptions || {};
  661 +
  662 + var sessionId = options.sessionId || 8;
  663 + if (typeof sessionId === 'function') {
  664 + this._generateSessionId = sessionId;
  665 + } else if (typeof sessionId === 'number') {
  666 + this._generateSessionId = function() {
  667 + return random.string(sessionId);
  668 + };
  669 + } else {
  670 + throw new TypeError('If sessionId is used in the options, it needs to be a number or a function.');
  671 + }
  672 +
  673 + this._server = options.server || random.numberString(1000);
  674 +
  675 + // Step 1 of WS spec - parse and validate the url. Issue #8
  676 + var parsedUrl = new URL(url);
  677 + if (!parsedUrl.host || !parsedUrl.protocol) {
  678 + throw new SyntaxError("The URL '" + url + "' is invalid");
  679 + } else if (parsedUrl.hash) {
  680 + throw new SyntaxError('The URL must not contain a fragment');
  681 + } else if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
  682 + throw new SyntaxError("The URL's scheme must be either 'http:' or 'https:'. '" + parsedUrl.protocol + "' is not allowed.");
  683 + }
  684 +
  685 + var secure = parsedUrl.protocol === 'https:';
  686 + // Step 2 - don't allow secure origin with an insecure protocol
  687 + if (loc.protocol === 'https' && !secure) {
  688 + throw new Error('SecurityError: An insecure SockJS connection may not be initiated from a page loaded over HTTPS');
  689 + }
  690 +
  691 + // Step 3 - check port access - no need here
  692 + // Step 4 - parse protocols argument
  693 + if (!protocols) {
  694 + protocols = [];
  695 + } else if (!Array.isArray(protocols)) {
  696 + protocols = [protocols];
  697 + }
  698 +
  699 + // Step 5 - check protocols argument
  700 + var sortedProtocols = protocols.sort();
  701 + sortedProtocols.forEach(function(proto, i) {
  702 + if (!proto) {
  703 + throw new SyntaxError("The protocols entry '" + proto + "' is invalid.");
  704 + }
  705 + if (i < (sortedProtocols.length - 1) && proto === sortedProtocols[i + 1]) {
  706 + throw new SyntaxError("The protocols entry '" + proto + "' is duplicated.");
  707 + }
  708 + });
  709 +
  710 + // Step 6 - convert origin
  711 + var o = urlUtils.getOrigin(loc.href);
  712 + this._origin = o ? o.toLowerCase() : null;
  713 +
  714 + // remove the trailing slash
  715 + parsedUrl.set('pathname', parsedUrl.pathname.replace(/\/+$/, ''));
  716 +
  717 + // store the sanitized url
  718 + this.url = parsedUrl.href;
  719 + debug('using url', this.url);
  720 +
  721 + // Step 7 - start connection in background
  722 + // obtain server info
  723 + // http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html#section-26
  724 + this._urlInfo = {
  725 + nullOrigin: !browser.hasDomain()
  726 + , sameOrigin: urlUtils.isOriginEqual(this.url, loc.href)
  727 + , sameScheme: urlUtils.isSchemeEqual(this.url, loc.href)
  728 + };
  729 +
  730 + this._ir = new InfoReceiver(this.url, this._urlInfo);
  731 + this._ir.once('finish', this._receiveInfo.bind(this));
  732 +}
  733 +
  734 +inherits(SockJS, EventTarget);
  735 +
  736 +function userSetCode(code) {
  737 + return code === 1000 || (code >= 3000 && code <= 4999);
  738 +}
  739 +
  740 +SockJS.prototype.close = function(code, reason) {
  741 + // Step 1
  742 + if (code && !userSetCode(code)) {
  743 + throw new Error('InvalidAccessError: Invalid code');
  744 + }
  745 + // Step 2.4 states the max is 123 bytes, but we are just checking length
  746 + if (reason && reason.length > 123) {
  747 + throw new SyntaxError('reason argument has an invalid length');
  748 + }
  749 +
  750 + // Step 3.1
  751 + if (this.readyState === SockJS.CLOSING || this.readyState === SockJS.CLOSED) {
  752 + return;
  753 + }
  754 +
  755 + // TODO look at docs to determine how to set this
  756 + var wasClean = true;
  757 + this._close(code || 1000, reason || 'Normal closure', wasClean);
  758 +};
  759 +
  760 +SockJS.prototype.send = function(data) {
  761 + // #13 - convert anything non-string to string
  762 + // TODO this currently turns objects into [object Object]
  763 + if (typeof data !== 'string') {
  764 + data = '' + data;
  765 + }
  766 + if (this.readyState === SockJS.CONNECTING) {
  767 + throw new Error('InvalidStateError: The connection has not been established yet');
  768 + }
  769 + if (this.readyState !== SockJS.OPEN) {
  770 + return;
  771 + }
  772 + this._transport.send(escape.quote(data));
  773 +};
  774 +
  775 +SockJS.version = require('./version');
  776 +
  777 +SockJS.CONNECTING = 0;
  778 +SockJS.OPEN = 1;
  779 +SockJS.CLOSING = 2;
  780 +SockJS.CLOSED = 3;
  781 +
  782 +SockJS.prototype._receiveInfo = function(info, rtt) {
  783 + debug('_receiveInfo', rtt);
  784 + this._ir = null;
  785 + if (!info) {
  786 + this._close(1002, 'Cannot connect to server');
  787 + return;
  788 + }
  789 +
  790 + // establish a round-trip timeout (RTO) based on the
  791 + // round-trip time (RTT)
  792 + this._rto = this.countRTO(rtt);
  793 + // allow server to override url used for the actual transport
  794 + this._transUrl = info.base_url ? info.base_url : this.url;
  795 + info = objectUtils.extend(info, this._urlInfo);
  796 + debug('info', info);
  797 + // determine list of desired and supported transports
  798 + var enabledTransports = transports.filterToEnabled(this._transportsWhitelist, info);
  799 + this._transports = enabledTransports.main;
  800 + debug(this._transports.length + ' enabled transports');
  801 +
  802 + this._connect();
  803 +};
  804 +
  805 +SockJS.prototype._connect = function() {
  806 + for (var Transport = this._transports.shift(); Transport; Transport = this._transports.shift()) {
  807 + debug('attempt', Transport.transportName);
  808 + if (Transport.needBody) {
  809 + if (!global.document.body ||
  810 + (typeof global.document.readyState !== 'undefined' &&
  811 + global.document.readyState !== 'complete' &&
  812 + global.document.readyState !== 'interactive')) {
  813 + debug('waiting for body');
  814 + this._transports.unshift(Transport);
  815 + eventUtils.attachEvent('load', this._connect.bind(this));
  816 + return;
  817 + }
  818 + }
  819 +
  820 + // calculate timeout based on RTO and round trips. Default to 5s
  821 + var timeoutMs = (this._rto * Transport.roundTrips) || 5000;
  822 + this._transportTimeoutId = setTimeout(this._transportTimeout.bind(this), timeoutMs);
  823 + debug('using timeout', timeoutMs);
  824 +
  825 + var transportUrl = urlUtils.addPath(this._transUrl, '/' + this._server + '/' + this._generateSessionId());
  826 + var options = this._transportOptions[Transport.transportName];
  827 + debug('transport url', transportUrl);
  828 + var transportObj = new Transport(transportUrl, this._transUrl, options);
  829 + transportObj.on('message', this._transportMessage.bind(this));
  830 + transportObj.once('close', this._transportClose.bind(this));
  831 + transportObj.transportName = Transport.transportName;
  832 + this._transport = transportObj;
  833 +
  834 + return;
  835 + }
  836 + this._close(2000, 'All transports failed', false);
  837 +};
  838 +
  839 +SockJS.prototype._transportTimeout = function() {
  840 + debug('_transportTimeout');
  841 + if (this.readyState === SockJS.CONNECTING) {
  842 + this._transportClose(2007, 'Transport timed out');
  843 + }
  844 +};
  845 +
  846 +SockJS.prototype._transportMessage = function(msg) {
  847 + debug('_transportMessage', msg);
  848 + var self = this
  849 + , type = msg.slice(0, 1)
  850 + , content = msg.slice(1)
  851 + , payload
  852 + ;
  853 +
  854 + // first check for messages that don't need a payload
  855 + switch (type) {
  856 + case 'o':
  857 + this._open();
  858 + return;
  859 + case 'h':
  860 + this.dispatchEvent(new Event('heartbeat'));
  861 + debug('heartbeat', this.transport);
  862 + return;
  863 + }
  864 +
  865 + if (content) {
  866 + try {
  867 + payload = JSON3.parse(content);
  868 + } catch (e) {
  869 + debug('bad json', content);
  870 + }
  871 + }
  872 +
  873 + if (typeof payload === 'undefined') {
  874 + debug('empty payload', content);
  875 + return;
  876 + }
  877 +
  878 + switch (type) {
  879 + case 'a':
  880 + if (Array.isArray(payload)) {
  881 + payload.forEach(function(p) {
  882 + debug('message', self.transport, p);
  883 + self.dispatchEvent(new TransportMessageEvent(p));
  884 + });
  885 + }
  886 + break;
  887 + case 'm':
  888 + debug('message', this.transport, payload);
  889 + this.dispatchEvent(new TransportMessageEvent(payload));
  890 + break;
  891 + case 'c':
  892 + if (Array.isArray(payload) && payload.length === 2) {
  893 + this._close(payload[0], payload[1], true);
  894 + }
  895 + break;
  896 + }
  897 +};
  898 +
  899 +SockJS.prototype._transportClose = function(code, reason) {
  900 + debug('_transportClose', this.transport, code, reason);
  901 + if (this._transport) {
  902 + this._transport.removeAllListeners();
  903 + this._transport = null;
  904 + this.transport = null;
  905 + }
  906 +
  907 + if (!userSetCode(code) && code !== 2000 && this.readyState === SockJS.CONNECTING) {
  908 + this._connect();
  909 + return;
  910 + }
  911 +
  912 + this._close(code, reason);
  913 +};
  914 +
  915 +SockJS.prototype._open = function() {
  916 + debug('_open', this._transport.transportName, this.readyState);
  917 + if (this.readyState === SockJS.CONNECTING) {
  918 + if (this._transportTimeoutId) {
  919 + clearTimeout(this._transportTimeoutId);
  920 + this._transportTimeoutId = null;
  921 + }
  922 + this.readyState = SockJS.OPEN;
  923 + this.transport = this._transport.transportName;
  924 + this.dispatchEvent(new Event('open'));
  925 + debug('connected', this.transport);
  926 + } else {
  927 + // The server might have been restarted, and lost track of our
  928 + // connection.
  929 + this._close(1006, 'Server lost session');
  930 + }
  931 +};
  932 +
  933 +SockJS.prototype._close = function(code, reason, wasClean) {
  934 + debug('_close', this.transport, code, reason, wasClean, this.readyState);
  935 + var forceFail = false;
  936 +
  937 + if (this._ir) {
  938 + forceFail = true;
  939 + this._ir.close();
  940 + this._ir = null;
  941 + }
  942 + if (this._transport) {
  943 + this._transport.close();
  944 + this._transport = null;
  945 + this.transport = null;
  946 + }
  947 +
  948 + if (this.readyState === SockJS.CLOSED) {
  949 + throw new Error('InvalidStateError: SockJS has already been closed');
  950 + }
  951 +
  952 + this.readyState = SockJS.CLOSING;
  953 + setTimeout(function() {
  954 + this.readyState = SockJS.CLOSED;
  955 +
  956 + if (forceFail) {
  957 + this.dispatchEvent(new Event('error'));
  958 + }
  959 +
  960 + var e = new CloseEvent('close');
  961 + e.wasClean = wasClean || false;
  962 + e.code = code || 1000;
  963 + e.reason = reason;
  964 +
  965 + this.dispatchEvent(e);
  966 + this.onmessage = this.onclose = this.onerror = null;
  967 + debug('disconnected');
  968 + }.bind(this), 0);
  969 +};
  970 +
  971 +// See: http://www.erg.abdn.ac.uk/~gerrit/dccp/notes/ccid2/rto_estimator/
  972 +// and RFC 2988.
  973 +SockJS.prototype.countRTO = function(rtt) {
  974 + // In a local environment, when using IE8/9 and the `jsonp-polling`
  975 + // transport the time needed to establish a connection (the time that pass
  976 + // from the opening of the transport to the call of `_dispatchOpen`) is
  977 + // around 200msec (the lower bound used in the article above) and this
  978 + // causes spurious timeouts. For this reason we calculate a value slightly
  979 + // larger than that used in the article.
  980 + if (rtt > 100) {
  981 + return 4 * rtt; // rto > 400msec
  982 + }
  983 + return 300 + rtt; // 300msec < rto <= 400msec
  984 +};
  985 +
  986 +module.exports = function(availableTransports) {
  987 + transports = transport(availableTransports);
  988 + require('./iframe-bootstrap')(SockJS, availableTransports);
  989 + return SockJS;
  990 +};
  991 +
  992 +}).call(this,{ env: {} },typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  993 +
  994 +},{"./event/close":2,"./event/event":4,"./event/eventtarget":5,"./event/trans-message":6,"./iframe-bootstrap":8,"./info-receiver":12,"./location":13,"./shims":15,"./utils/browser":44,"./utils/escape":45,"./utils/event":46,"./utils/log":48,"./utils/object":49,"./utils/random":50,"./utils/transport":51,"./utils/url":52,"./version":53,"debug":54,"inherits":56,"json3":57,"url-parse":61}],15:[function(require,module,exports){
  995 +/* eslint-disable */
  996 +/* jscs: disable */
  997 +'use strict';
  998 +
  999 +// pulled specific shims from https://github.com/es-shims/es5-shim
  1000 +
  1001 +var ArrayPrototype = Array.prototype;
  1002 +var ObjectPrototype = Object.prototype;
  1003 +var FunctionPrototype = Function.prototype;
  1004 +var StringPrototype = String.prototype;
  1005 +var array_slice = ArrayPrototype.slice;
  1006 +
  1007 +var _toString = ObjectPrototype.toString;
  1008 +var isFunction = function (val) {
  1009 + return ObjectPrototype.toString.call(val) === '[object Function]';
  1010 +};
  1011 +var isArray = function isArray(obj) {
  1012 + return _toString.call(obj) === '[object Array]';
  1013 +};
  1014 +var isString = function isString(obj) {
  1015 + return _toString.call(obj) === '[object String]';
  1016 +};
  1017 +
  1018 +var supportsDescriptors = Object.defineProperty && (function () {
  1019 + try {
  1020 + Object.defineProperty({}, 'x', {});
  1021 + return true;
  1022 + } catch (e) { /* this is ES3 */
  1023 + return false;
  1024 + }
  1025 +}());
  1026 +
  1027 +// Define configurable, writable and non-enumerable props
  1028 +// if they don't exist.
  1029 +var defineProperty;
  1030 +if (supportsDescriptors) {
  1031 + defineProperty = function (object, name, method, forceAssign) {
  1032 + if (!forceAssign && (name in object)) { return; }
  1033 + Object.defineProperty(object, name, {
  1034 + configurable: true,
  1035 + enumerable: false,
  1036 + writable: true,
  1037 + value: method
  1038 + });
  1039 + };
  1040 +} else {
  1041 + defineProperty = function (object, name, method, forceAssign) {
  1042 + if (!forceAssign && (name in object)) { return; }
  1043 + object[name] = method;
  1044 + };
  1045 +}
  1046 +var defineProperties = function (object, map, forceAssign) {
  1047 + for (var name in map) {
  1048 + if (ObjectPrototype.hasOwnProperty.call(map, name)) {
  1049 + defineProperty(object, name, map[name], forceAssign);
  1050 + }
  1051 + }
  1052 +};
  1053 +
  1054 +var toObject = function (o) {
  1055 + if (o == null) { // this matches both null and undefined
  1056 + throw new TypeError("can't convert " + o + ' to object');
  1057 + }
  1058 + return Object(o);
  1059 +};
  1060 +
  1061 +//
  1062 +// Util
  1063 +// ======
  1064 +//
  1065 +
  1066 +// ES5 9.4
  1067 +// http://es5.github.com/#x9.4
  1068 +// http://jsperf.com/to-integer
  1069 +
  1070 +function toInteger(num) {
  1071 + var n = +num;
  1072 + if (n !== n) { // isNaN
  1073 + n = 0;
  1074 + } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
  1075 + n = (n > 0 || -1) * Math.floor(Math.abs(n));
  1076 + }
  1077 + return n;
  1078 +}
  1079 +
  1080 +function ToUint32(x) {
  1081 + return x >>> 0;
  1082 +}
  1083 +
  1084 +//
  1085 +// Function
  1086 +// ========
  1087 +//
  1088 +
  1089 +// ES-5 15.3.4.5
  1090 +// http://es5.github.com/#x15.3.4.5
  1091 +
  1092 +function Empty() {}
  1093 +
  1094 +defineProperties(FunctionPrototype, {
  1095 + bind: function bind(that) { // .length is 1
  1096 + // 1. Let Target be the this value.
  1097 + var target = this;
  1098 + // 2. If IsCallable(Target) is false, throw a TypeError exception.
  1099 + if (!isFunction(target)) {
  1100 + throw new TypeError('Function.prototype.bind called on incompatible ' + target);
  1101 + }
  1102 + // 3. Let A be a new (possibly empty) internal list of all of the
  1103 + // argument values provided after thisArg (arg1, arg2 etc), in order.
  1104 + // XXX slicedArgs will stand in for "A" if used
  1105 + var args = array_slice.call(arguments, 1); // for normal call
  1106 + // 4. Let F be a new native ECMAScript object.
  1107 + // 11. Set the [[Prototype]] internal property of F to the standard
  1108 + // built-in Function prototype object as specified in 15.3.3.1.
  1109 + // 12. Set the [[Call]] internal property of F as described in
  1110 + // 15.3.4.5.1.
  1111 + // 13. Set the [[Construct]] internal property of F as described in
  1112 + // 15.3.4.5.2.
  1113 + // 14. Set the [[HasInstance]] internal property of F as described in
  1114 + // 15.3.4.5.3.
  1115 + var binder = function () {
  1116 +
  1117 + if (this instanceof bound) {
  1118 + // 15.3.4.5.2 [[Construct]]
  1119 + // When the [[Construct]] internal method of a function object,
  1120 + // F that was created using the bind function is called with a
  1121 + // list of arguments ExtraArgs, the following steps are taken:
  1122 + // 1. Let target be the value of F's [[TargetFunction]]
  1123 + // internal property.
  1124 + // 2. If target has no [[Construct]] internal method, a
  1125 + // TypeError exception is thrown.
  1126 + // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
  1127 + // property.
  1128 + // 4. Let args be a new list containing the same values as the
  1129 + // list boundArgs in the same order followed by the same
  1130 + // values as the list ExtraArgs in the same order.
  1131 + // 5. Return the result of calling the [[Construct]] internal
  1132 + // method of target providing args as the arguments.
  1133 +
  1134 + var result = target.apply(
  1135 + this,
  1136 + args.concat(array_slice.call(arguments))
  1137 + );
  1138 + if (Object(result) === result) {
  1139 + return result;
  1140 + }
  1141 + return this;
  1142 +
  1143 + } else {
  1144 + // 15.3.4.5.1 [[Call]]
  1145 + // When the [[Call]] internal method of a function object, F,
  1146 + // which was created using the bind function is called with a
  1147 + // this value and a list of arguments ExtraArgs, the following
  1148 + // steps are taken:
  1149 + // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
  1150 + // property.
  1151 + // 2. Let boundThis be the value of F's [[BoundThis]] internal
  1152 + // property.
  1153 + // 3. Let target be the value of F's [[TargetFunction]] internal
  1154 + // property.
  1155 + // 4. Let args be a new list containing the same values as the
  1156 + // list boundArgs in the same order followed by the same
  1157 + // values as the list ExtraArgs in the same order.
  1158 + // 5. Return the result of calling the [[Call]] internal method
  1159 + // of target providing boundThis as the this value and
  1160 + // providing args as the arguments.
  1161 +
  1162 + // equiv: target.call(this, ...boundArgs, ...args)
  1163 + return target.apply(
  1164 + that,
  1165 + args.concat(array_slice.call(arguments))
  1166 + );
  1167 +
  1168 + }
  1169 +
  1170 + };
  1171 +
  1172 + // 15. If the [[Class]] internal property of Target is "Function", then
  1173 + // a. Let L be the length property of Target minus the length of A.
  1174 + // b. Set the length own property of F to either 0 or L, whichever is
  1175 + // larger.
  1176 + // 16. Else set the length own property of F to 0.
  1177 +
  1178 + var boundLength = Math.max(0, target.length - args.length);
  1179 +
  1180 + // 17. Set the attributes of the length own property of F to the values
  1181 + // specified in 15.3.5.1.
  1182 + var boundArgs = [];
  1183 + for (var i = 0; i < boundLength; i++) {
  1184 + boundArgs.push('$' + i);
  1185 + }
  1186 +
  1187 + // XXX Build a dynamic function with desired amount of arguments is the only
  1188 + // way to set the length property of a function.
  1189 + // In environments where Content Security Policies enabled (Chrome extensions,
  1190 + // for ex.) all use of eval or Function costructor throws an exception.
  1191 + // However in all of these environments Function.prototype.bind exists
  1192 + // and so this code will never be executed.
  1193 + var bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder);
  1194 +
  1195 + if (target.prototype) {
  1196 + Empty.prototype = target.prototype;
  1197 + bound.prototype = new Empty();
  1198 + // Clean up dangling references.
  1199 + Empty.prototype = null;
  1200 + }
  1201 +
  1202 + // TODO
  1203 + // 18. Set the [[Extensible]] internal property of F to true.
  1204 +
  1205 + // TODO
  1206 + // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
  1207 + // 20. Call the [[DefineOwnProperty]] internal method of F with
  1208 + // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
  1209 + // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
  1210 + // false.
  1211 + // 21. Call the [[DefineOwnProperty]] internal method of F with
  1212 + // arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
  1213 + // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
  1214 + // and false.
  1215 +
  1216 + // TODO
  1217 + // NOTE Function objects created using Function.prototype.bind do not
  1218 + // have a prototype property or the [[Code]], [[FormalParameters]], and
  1219 + // [[Scope]] internal properties.
  1220 + // XXX can't delete prototype in pure-js.
  1221 +
  1222 + // 22. Return F.
  1223 + return bound;
  1224 + }
  1225 +});
  1226 +
  1227 +//
  1228 +// Array
  1229 +// =====
  1230 +//
  1231 +
  1232 +// ES5 15.4.3.2
  1233 +// http://es5.github.com/#x15.4.3.2
  1234 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
  1235 +defineProperties(Array, { isArray: isArray });
  1236 +
  1237 +
  1238 +var boxedString = Object('a');
  1239 +var splitString = boxedString[0] !== 'a' || !(0 in boxedString);
  1240 +
  1241 +var properlyBoxesContext = function properlyBoxed(method) {
  1242 + // Check node 0.6.21 bug where third parameter is not boxed
  1243 + var properlyBoxesNonStrict = true;
  1244 + var properlyBoxesStrict = true;
  1245 + if (method) {
  1246 + method.call('foo', function (_, __, context) {
  1247 + if (typeof context !== 'object') { properlyBoxesNonStrict = false; }
  1248 + });
  1249 +
  1250 + method.call([1], function () {
  1251 + 'use strict';
  1252 + properlyBoxesStrict = typeof this === 'string';
  1253 + }, 'x');
  1254 + }
  1255 + return !!method && properlyBoxesNonStrict && properlyBoxesStrict;
  1256 +};
  1257 +
  1258 +defineProperties(ArrayPrototype, {
  1259 + forEach: function forEach(fun /*, thisp*/) {
  1260 + var object = toObject(this),
  1261 + self = splitString && isString(this) ? this.split('') : object,
  1262 + thisp = arguments[1],
  1263 + i = -1,
  1264 + length = self.length >>> 0;
  1265 +
  1266 + // If no callback function or if callback is not a callable function
  1267 + if (!isFunction(fun)) {
  1268 + throw new TypeError(); // TODO message
  1269 + }
  1270 +
  1271 + while (++i < length) {
  1272 + if (i in self) {
  1273 + // Invoke the callback function with call, passing arguments:
  1274 + // context, property value, property key, thisArg object
  1275 + // context
  1276 + fun.call(thisp, self[i], i, object);
  1277 + }
  1278 + }
  1279 + }
  1280 +}, !properlyBoxesContext(ArrayPrototype.forEach));
  1281 +
  1282 +// ES5 15.4.4.14
  1283 +// http://es5.github.com/#x15.4.4.14
  1284 +// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
  1285 +var hasFirefox2IndexOfBug = Array.prototype.indexOf && [0, 1].indexOf(1, 2) !== -1;
  1286 +defineProperties(ArrayPrototype, {
  1287 + indexOf: function indexOf(sought /*, fromIndex */ ) {
  1288 + var self = splitString && isString(this) ? this.split('') : toObject(this),
  1289 + length = self.length >>> 0;
  1290 +
  1291 + if (!length) {
  1292 + return -1;
  1293 + }
  1294 +
  1295 + var i = 0;
  1296 + if (arguments.length > 1) {
  1297 + i = toInteger(arguments[1]);
  1298 + }
  1299 +
  1300 + // handle negative indices
  1301 + i = i >= 0 ? i : Math.max(0, length + i);
  1302 + for (; i < length; i++) {
  1303 + if (i in self && self[i] === sought) {
  1304 + return i;
  1305 + }
  1306 + }
  1307 + return -1;
  1308 + }
  1309 +}, hasFirefox2IndexOfBug);
  1310 +
  1311 +//
  1312 +// String
  1313 +// ======
  1314 +//
  1315 +
  1316 +// ES5 15.5.4.14
  1317 +// http://es5.github.com/#x15.5.4.14
  1318 +
  1319 +// [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers]
  1320 +// Many browsers do not split properly with regular expressions or they
  1321 +// do not perform the split correctly under obscure conditions.
  1322 +// See http://blog.stevenlevithan.com/archives/cross-browser-split
  1323 +// I've tested in many browsers and this seems to cover the deviant ones:
  1324 +// 'ab'.split(/(?:ab)*/) should be ["", ""], not [""]
  1325 +// '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""]
  1326 +// 'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not
  1327 +// [undefined, "t", undefined, "e", ...]
  1328 +// ''.split(/.?/) should be [], not [""]
  1329 +// '.'.split(/()()/) should be ["."], not ["", "", "."]
  1330 +
  1331 +var string_split = StringPrototype.split;
  1332 +if (
  1333 + 'ab'.split(/(?:ab)*/).length !== 2 ||
  1334 + '.'.split(/(.?)(.?)/).length !== 4 ||
  1335 + 'tesst'.split(/(s)*/)[1] === 't' ||
  1336 + 'test'.split(/(?:)/, -1).length !== 4 ||
  1337 + ''.split(/.?/).length ||
  1338 + '.'.split(/()()/).length > 1
  1339 +) {
  1340 + (function () {
  1341 + var compliantExecNpcg = /()??/.exec('')[1] === void 0; // NPCG: nonparticipating capturing group
  1342 +
  1343 + StringPrototype.split = function (separator, limit) {
  1344 + var string = this;
  1345 + if (separator === void 0 && limit === 0) {
  1346 + return [];
  1347 + }
  1348 +
  1349 + // If `separator` is not a regex, use native split
  1350 + if (_toString.call(separator) !== '[object RegExp]') {
  1351 + return string_split.call(this, separator, limit);
  1352 + }
  1353 +
  1354 + var output = [],
  1355 + flags = (separator.ignoreCase ? 'i' : '') +
  1356 + (separator.multiline ? 'm' : '') +
  1357 + (separator.extended ? 'x' : '') + // Proposed for ES6
  1358 + (separator.sticky ? 'y' : ''), // Firefox 3+
  1359 + lastLastIndex = 0,
  1360 + // Make `global` and avoid `lastIndex` issues by working with a copy
  1361 + separator2, match, lastIndex, lastLength;
  1362 + separator = new RegExp(separator.source, flags + 'g');
  1363 + string += ''; // Type-convert
  1364 + if (!compliantExecNpcg) {
  1365 + // Doesn't need flags gy, but they don't hurt
  1366 + separator2 = new RegExp('^' + separator.source + '$(?!\\s)', flags);
  1367 + }
  1368 + /* Values for `limit`, per the spec:
  1369 + * If undefined: 4294967295 // Math.pow(2, 32) - 1
  1370 + * If 0, Infinity, or NaN: 0
  1371 + * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
  1372 + * If negative number: 4294967296 - Math.floor(Math.abs(limit))
  1373 + * If other: Type-convert, then use the above rules
  1374 + */
  1375 + limit = limit === void 0 ?
  1376 + -1 >>> 0 : // Math.pow(2, 32) - 1
  1377 + ToUint32(limit);
  1378 + while (match = separator.exec(string)) {
  1379 + // `separator.lastIndex` is not reliable cross-browser
  1380 + lastIndex = match.index + match[0].length;
  1381 + if (lastIndex > lastLastIndex) {
  1382 + output.push(string.slice(lastLastIndex, match.index));
  1383 + // Fix browsers whose `exec` methods don't consistently return `undefined` for
  1384 + // nonparticipating capturing groups
  1385 + if (!compliantExecNpcg && match.length > 1) {
  1386 + match[0].replace(separator2, function () {
  1387 + for (var i = 1; i < arguments.length - 2; i++) {
  1388 + if (arguments[i] === void 0) {
  1389 + match[i] = void 0;
  1390 + }
  1391 + }
  1392 + });
  1393 + }
  1394 + if (match.length > 1 && match.index < string.length) {
  1395 + ArrayPrototype.push.apply(output, match.slice(1));
  1396 + }
  1397 + lastLength = match[0].length;
  1398 + lastLastIndex = lastIndex;
  1399 + if (output.length >= limit) {
  1400 + break;
  1401 + }
  1402 + }
  1403 + if (separator.lastIndex === match.index) {
  1404 + separator.lastIndex++; // Avoid an infinite loop
  1405 + }
  1406 + }
  1407 + if (lastLastIndex === string.length) {
  1408 + if (lastLength || !separator.test('')) {
  1409 + output.push('');
  1410 + }
  1411 + } else {
  1412 + output.push(string.slice(lastLastIndex));
  1413 + }
  1414 + return output.length > limit ? output.slice(0, limit) : output;
  1415 + };
  1416 + }());
  1417 +
  1418 +// [bugfix, chrome]
  1419 +// If separator is undefined, then the result array contains just one String,
  1420 +// which is the this value (converted to a String). If limit is not undefined,
  1421 +// then the output array is truncated so that it contains no more than limit
  1422 +// elements.
  1423 +// "0".split(undefined, 0) -> []
  1424 +} else if ('0'.split(void 0, 0).length) {
  1425 + StringPrototype.split = function split(separator, limit) {
  1426 + if (separator === void 0 && limit === 0) { return []; }
  1427 + return string_split.call(this, separator, limit);
  1428 + };
  1429 +}
  1430 +
  1431 +// ECMA-262, 3rd B.2.3
  1432 +// Not an ECMAScript standard, although ECMAScript 3rd Edition has a
  1433 +// non-normative section suggesting uniform semantics and it should be
  1434 +// normalized across all browsers
  1435 +// [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE
  1436 +var string_substr = StringPrototype.substr;
  1437 +var hasNegativeSubstrBug = ''.substr && '0b'.substr(-1) !== 'b';
  1438 +defineProperties(StringPrototype, {
  1439 + substr: function substr(start, length) {
  1440 + return string_substr.call(
  1441 + this,
  1442 + start < 0 ? ((start = this.length + start) < 0 ? 0 : start) : start,
  1443 + length
  1444 + );
  1445 + }
  1446 +}, hasNegativeSubstrBug);
  1447 +
  1448 +},{}],16:[function(require,module,exports){
  1449 +'use strict';
  1450 +
  1451 +module.exports = [
  1452 + // streaming transports
  1453 + require('./transport/websocket')
  1454 +, require('./transport/xhr-streaming')
  1455 +, require('./transport/xdr-streaming')
  1456 +, require('./transport/eventsource')
  1457 +, require('./transport/lib/iframe-wrap')(require('./transport/eventsource'))
  1458 +
  1459 + // polling transports
  1460 +, require('./transport/htmlfile')
  1461 +, require('./transport/lib/iframe-wrap')(require('./transport/htmlfile'))
  1462 +, require('./transport/xhr-polling')
  1463 +, require('./transport/xdr-polling')
  1464 +, require('./transport/lib/iframe-wrap')(require('./transport/xhr-polling'))
  1465 +, require('./transport/jsonp-polling')
  1466 +];
  1467 +
  1468 +},{"./transport/eventsource":20,"./transport/htmlfile":21,"./transport/jsonp-polling":23,"./transport/lib/iframe-wrap":26,"./transport/websocket":38,"./transport/xdr-polling":39,"./transport/xdr-streaming":40,"./transport/xhr-polling":41,"./transport/xhr-streaming":42}],17:[function(require,module,exports){
  1469 +(function (process,global){
  1470 +'use strict';
  1471 +
  1472 +var EventEmitter = require('events').EventEmitter
  1473 + , inherits = require('inherits')
  1474 + , utils = require('../../utils/event')
  1475 + , urlUtils = require('../../utils/url')
  1476 + , XHR = global.XMLHttpRequest
  1477 + ;
  1478 +
  1479 +var debug = function() {};
  1480 +if (process.env.NODE_ENV !== 'production') {
  1481 + debug = require('debug')('sockjs-client:browser:xhr');
  1482 +}
  1483 +
  1484 +function AbstractXHRObject(method, url, payload, opts) {
  1485 + debug(method, url);
  1486 + var self = this;
  1487 + EventEmitter.call(this);
  1488 +
  1489 + setTimeout(function () {
  1490 + self._start(method, url, payload, opts);
  1491 + }, 0);
  1492 +}
  1493 +
  1494 +inherits(AbstractXHRObject, EventEmitter);
  1495 +
  1496 +AbstractXHRObject.prototype._start = function(method, url, payload, opts) {
  1497 + var self = this;
  1498 +
  1499 + try {
  1500 + this.xhr = new XHR();
  1501 + } catch (x) {
  1502 + // intentionally empty
  1503 + }
  1504 +
  1505 + if (!this.xhr) {
  1506 + debug('no xhr');
  1507 + this.emit('finish', 0, 'no xhr support');
  1508 + this._cleanup();
  1509 + return;
  1510 + }
  1511 +
  1512 + // several browsers cache POSTs
  1513 + url = urlUtils.addQuery(url, 't=' + (+new Date()));
  1514 +
  1515 + // Explorer tends to keep connection open, even after the
  1516 + // tab gets closed: http://bugs.jquery.com/ticket/5280
  1517 + this.unloadRef = utils.unloadAdd(function() {
  1518 + debug('unload cleanup');
  1519 + self._cleanup(true);
  1520 + });
  1521 + try {
  1522 + this.xhr.open(method, url, true);
  1523 + if (this.timeout && 'timeout' in this.xhr) {
  1524 + this.xhr.timeout = this.timeout;
  1525 + this.xhr.ontimeout = function() {
  1526 + debug('xhr timeout');
  1527 + self.emit('finish', 0, '');
  1528 + self._cleanup(false);
  1529 + };
  1530 + }
  1531 + } catch (e) {
  1532 + debug('exception', e);
  1533 + // IE raises an exception on wrong port.
  1534 + this.emit('finish', 0, '');
  1535 + this._cleanup(false);
  1536 + return;
  1537 + }
  1538 +
  1539 + if ((!opts || !opts.noCredentials) && AbstractXHRObject.supportsCORS) {
  1540 + debug('withCredentials');
  1541 + // Mozilla docs says https://developer.mozilla.org/en/XMLHttpRequest :
  1542 + // "This never affects same-site requests."
  1543 +
  1544 + this.xhr.withCredentials = 'true';
  1545 + }
  1546 + if (opts && opts.headers) {
  1547 + for (var key in opts.headers) {
  1548 + this.xhr.setRequestHeader(key, opts.headers[key]);
  1549 + }
  1550 + }
  1551 +
  1552 + this.xhr.onreadystatechange = function() {
  1553 + if (self.xhr) {
  1554 + var x = self.xhr;
  1555 + var text, status;
  1556 + debug('readyState', x.readyState);
  1557 + switch (x.readyState) {
  1558 + case 3:
  1559 + // IE doesn't like peeking into responseText or status
  1560 + // on Microsoft.XMLHTTP and readystate=3
  1561 + try {
  1562 + status = x.status;
  1563 + text = x.responseText;
  1564 + } catch (e) {
  1565 + // intentionally empty
  1566 + }
  1567 + debug('status', status);
  1568 + // IE returns 1223 for 204: http://bugs.jquery.com/ticket/1450
  1569 + if (status === 1223) {
  1570 + status = 204;
  1571 + }
  1572 +
  1573 + // IE does return readystate == 3 for 404 answers.
  1574 + if (status === 200 && text && text.length > 0) {
  1575 + debug('chunk');
  1576 + self.emit('chunk', status, text);
  1577 + }
  1578 + break;
  1579 + case 4:
  1580 + status = x.status;
  1581 + debug('status', status);
  1582 + // IE returns 1223 for 204: http://bugs.jquery.com/ticket/1450
  1583 + if (status === 1223) {
  1584 + status = 204;
  1585 + }
  1586 + // IE returns this for a bad port
  1587 + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa383770(v=vs.85).aspx
  1588 + if (status === 12005 || status === 12029) {
  1589 + status = 0;
  1590 + }
  1591 +
  1592 + debug('finish', status, x.responseText);
  1593 + self.emit('finish', status, x.responseText);
  1594 + self._cleanup(false);
  1595 + break;
  1596 + }
  1597 + }
  1598 + };
  1599 +
  1600 + try {
  1601 + self.xhr.send(payload);
  1602 + } catch (e) {
  1603 + self.emit('finish', 0, '');
  1604 + self._cleanup(false);
  1605 + }
  1606 +};
  1607 +
  1608 +AbstractXHRObject.prototype._cleanup = function(abort) {
  1609 + debug('cleanup');
  1610 + if (!this.xhr) {
  1611 + return;
  1612 + }
  1613 + this.removeAllListeners();
  1614 + utils.unloadDel(this.unloadRef);
  1615 +
  1616 + // IE needs this field to be a function
  1617 + this.xhr.onreadystatechange = function() {};
  1618 + if (this.xhr.ontimeout) {
  1619 + this.xhr.ontimeout = null;
  1620 + }
  1621 +
  1622 + if (abort) {
  1623 + try {
  1624 + this.xhr.abort();
  1625 + } catch (x) {
  1626 + // intentionally empty
  1627 + }
  1628 + }
  1629 + this.unloadRef = this.xhr = null;
  1630 +};
  1631 +
  1632 +AbstractXHRObject.prototype.close = function() {
  1633 + debug('close');
  1634 + this._cleanup(true);
  1635 +};
  1636 +
  1637 +AbstractXHRObject.enabled = !!XHR;
  1638 +// override XMLHttpRequest for IE6/7
  1639 +// obfuscate to avoid firewalls
  1640 +var axo = ['Active'].concat('Object').join('X');
  1641 +if (!AbstractXHRObject.enabled && (axo in global)) {
  1642 + debug('overriding xmlhttprequest');
  1643 + XHR = function() {
  1644 + try {
  1645 + return new global[axo]('Microsoft.XMLHTTP');
  1646 + } catch (e) {
  1647 + return null;
  1648 + }
  1649 + };
  1650 + AbstractXHRObject.enabled = !!new XHR();
  1651 +}
  1652 +
  1653 +var cors = false;
  1654 +try {
  1655 + cors = 'withCredentials' in new XHR();
  1656 +} catch (ignored) {
  1657 + // intentionally empty
  1658 +}
  1659 +
  1660 +AbstractXHRObject.supportsCORS = cors;
  1661 +
  1662 +module.exports = AbstractXHRObject;
  1663 +
  1664 +}).call(this,{ env: {} },typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  1665 +
  1666 +},{"../../utils/event":46,"../../utils/url":52,"debug":54,"events":3,"inherits":56}],18:[function(require,module,exports){
  1667 +(function (global){
  1668 +module.exports = global.EventSource;
  1669 +
  1670 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  1671 +
  1672 +},{}],19:[function(require,module,exports){
  1673 +(function (global){
  1674 +'use strict';
  1675 +
  1676 +var Driver = global.WebSocket || global.MozWebSocket;
  1677 +if (Driver) {
  1678 + module.exports = function WebSocketBrowserDriver(url) {
  1679 + return new Driver(url);
  1680 + };
  1681 +} else {
  1682 + module.exports = undefined;
  1683 +}
  1684 +
  1685 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  1686 +
  1687 +},{}],20:[function(require,module,exports){
  1688 +'use strict';
  1689 +
  1690 +var inherits = require('inherits')
  1691 + , AjaxBasedTransport = require('./lib/ajax-based')
  1692 + , EventSourceReceiver = require('./receiver/eventsource')
  1693 + , XHRCorsObject = require('./sender/xhr-cors')
  1694 + , EventSourceDriver = require('eventsource')
  1695 + ;
  1696 +
  1697 +function EventSourceTransport(transUrl) {
  1698 + if (!EventSourceTransport.enabled()) {
  1699 + throw new Error('Transport created when disabled');
  1700 + }
  1701 +
  1702 + AjaxBasedTransport.call(this, transUrl, '/eventsource', EventSourceReceiver, XHRCorsObject);
  1703 +}
  1704 +
  1705 +inherits(EventSourceTransport, AjaxBasedTransport);
  1706 +
  1707 +EventSourceTransport.enabled = function() {
  1708 + return !!EventSourceDriver;
  1709 +};
  1710 +
  1711 +EventSourceTransport.transportName = 'eventsource';
  1712 +EventSourceTransport.roundTrips = 2;
  1713 +
  1714 +module.exports = EventSourceTransport;
  1715 +
  1716 +},{"./lib/ajax-based":24,"./receiver/eventsource":29,"./sender/xhr-cors":35,"eventsource":18,"inherits":56}],21:[function(require,module,exports){
  1717 +'use strict';
  1718 +
  1719 +var inherits = require('inherits')
  1720 + , HtmlfileReceiver = require('./receiver/htmlfile')
  1721 + , XHRLocalObject = require('./sender/xhr-local')
  1722 + , AjaxBasedTransport = require('./lib/ajax-based')
  1723 + ;
  1724 +
  1725 +function HtmlFileTransport(transUrl) {
  1726 + if (!HtmlfileReceiver.enabled) {
  1727 + throw new Error('Transport created when disabled');
  1728 + }
  1729 + AjaxBasedTransport.call(this, transUrl, '/htmlfile', HtmlfileReceiver, XHRLocalObject);
  1730 +}
  1731 +
  1732 +inherits(HtmlFileTransport, AjaxBasedTransport);
  1733 +
  1734 +HtmlFileTransport.enabled = function(info) {
  1735 + return HtmlfileReceiver.enabled && info.sameOrigin;
  1736 +};
  1737 +
  1738 +HtmlFileTransport.transportName = 'htmlfile';
  1739 +HtmlFileTransport.roundTrips = 2;
  1740 +
  1741 +module.exports = HtmlFileTransport;
  1742 +
  1743 +},{"./lib/ajax-based":24,"./receiver/htmlfile":30,"./sender/xhr-local":37,"inherits":56}],22:[function(require,module,exports){
  1744 +(function (process){
  1745 +'use strict';
  1746 +
  1747 +// Few cool transports do work only for same-origin. In order to make
  1748 +// them work cross-domain we shall use iframe, served from the
  1749 +// remote domain. New browsers have capabilities to communicate with
  1750 +// cross domain iframe using postMessage(). In IE it was implemented
  1751 +// from IE 8+, but of course, IE got some details wrong:
  1752 +// http://msdn.microsoft.com/en-us/library/cc197015(v=VS.85).aspx
  1753 +// http://stevesouders.com/misc/test-postmessage.php
  1754 +
  1755 +var inherits = require('inherits')
  1756 + , JSON3 = require('json3')
  1757 + , EventEmitter = require('events').EventEmitter
  1758 + , version = require('../version')
  1759 + , urlUtils = require('../utils/url')
  1760 + , iframeUtils = require('../utils/iframe')
  1761 + , eventUtils = require('../utils/event')
  1762 + , random = require('../utils/random')
  1763 + ;
  1764 +
  1765 +var debug = function() {};
  1766 +if (process.env.NODE_ENV !== 'production') {
  1767 + debug = require('debug')('sockjs-client:transport:iframe');
  1768 +}
  1769 +
  1770 +function IframeTransport(transport, transUrl, baseUrl) {
  1771 + if (!IframeTransport.enabled()) {
  1772 + throw new Error('Transport created when disabled');
  1773 + }
  1774 + EventEmitter.call(this);
  1775 +
  1776 + var self = this;
  1777 + this.origin = urlUtils.getOrigin(baseUrl);
  1778 + this.baseUrl = baseUrl;
  1779 + this.transUrl = transUrl;
  1780 + this.transport = transport;
  1781 + this.windowId = random.string(8);
  1782 +
  1783 + var iframeUrl = urlUtils.addPath(baseUrl, '/iframe.html') + '#' + this.windowId;
  1784 + debug(transport, transUrl, iframeUrl);
  1785 +
  1786 + this.iframeObj = iframeUtils.createIframe(iframeUrl, function(r) {
  1787 + debug('err callback');
  1788 + self.emit('close', 1006, 'Unable to load an iframe (' + r + ')');
  1789 + self.close();
  1790 + });
  1791 +
  1792 + this.onmessageCallback = this._message.bind(this);
  1793 + eventUtils.attachEvent('message', this.onmessageCallback);
  1794 +}
  1795 +
  1796 +inherits(IframeTransport, EventEmitter);
  1797 +
  1798 +IframeTransport.prototype.close = function() {
  1799 + debug('close');
  1800 + this.removeAllListeners();
  1801 + if (this.iframeObj) {
  1802 + eventUtils.detachEvent('message', this.onmessageCallback);
  1803 + try {
  1804 + // When the iframe is not loaded, IE raises an exception
  1805 + // on 'contentWindow'.
  1806 + this.postMessage('c');
  1807 + } catch (x) {
  1808 + // intentionally empty
  1809 + }
  1810 + this.iframeObj.cleanup();
  1811 + this.iframeObj = null;
  1812 + this.onmessageCallback = this.iframeObj = null;
  1813 + }
  1814 +};
  1815 +
  1816 +IframeTransport.prototype._message = function(e) {
  1817 + debug('message', e.data);
  1818 + if (!urlUtils.isOriginEqual(e.origin, this.origin)) {
  1819 + debug('not same origin', e.origin, this.origin);
  1820 + return;
  1821 + }
  1822 +
  1823 + var iframeMessage;
  1824 + try {
  1825 + iframeMessage = JSON3.parse(e.data);
  1826 + } catch (ignored) {
  1827 + debug('bad json', e.data);
  1828 + return;
  1829 + }
  1830 +
  1831 + if (iframeMessage.windowId !== this.windowId) {
  1832 + debug('mismatched window id', iframeMessage.windowId, this.windowId);
  1833 + return;
  1834 + }
  1835 +
  1836 + switch (iframeMessage.type) {
  1837 + case 's':
  1838 + this.iframeObj.loaded();
  1839 + // window global dependency
  1840 + this.postMessage('s', JSON3.stringify([
  1841 + version
  1842 + , this.transport
  1843 + , this.transUrl
  1844 + , this.baseUrl
  1845 + ]));
  1846 + break;
  1847 + case 't':
  1848 + this.emit('message', iframeMessage.data);
  1849 + break;
  1850 + case 'c':
  1851 + var cdata;
  1852 + try {
  1853 + cdata = JSON3.parse(iframeMessage.data);
  1854 + } catch (ignored) {
  1855 + debug('bad json', iframeMessage.data);
  1856 + return;
  1857 + }
  1858 + this.emit('close', cdata[0], cdata[1]);
  1859 + this.close();
  1860 + break;
  1861 + }
  1862 +};
  1863 +
  1864 +IframeTransport.prototype.postMessage = function(type, data) {
  1865 + debug('postMessage', type, data);
  1866 + this.iframeObj.post(JSON3.stringify({
  1867 + windowId: this.windowId
  1868 + , type: type
  1869 + , data: data || ''
  1870 + }), this.origin);
  1871 +};
  1872 +
  1873 +IframeTransport.prototype.send = function(message) {
  1874 + debug('send', message);
  1875 + this.postMessage('m', message);
  1876 +};
  1877 +
  1878 +IframeTransport.enabled = function() {
  1879 + return iframeUtils.iframeEnabled;
  1880 +};
  1881 +
  1882 +IframeTransport.transportName = 'iframe';
  1883 +IframeTransport.roundTrips = 2;
  1884 +
  1885 +module.exports = IframeTransport;
  1886 +
  1887 +}).call(this,{ env: {} })
  1888 +
  1889 +},{"../utils/event":46,"../utils/iframe":47,"../utils/random":50,"../utils/url":52,"../version":53,"debug":54,"events":3,"inherits":56,"json3":57}],23:[function(require,module,exports){
  1890 +(function (global){
  1891 +'use strict';
  1892 +
  1893 +// The simplest and most robust transport, using the well-know cross
  1894 +// domain hack - JSONP. This transport is quite inefficient - one
  1895 +// message could use up to one http request. But at least it works almost
  1896 +// everywhere.
  1897 +// Known limitations:
  1898 +// o you will get a spinning cursor
  1899 +// o for Konqueror a dumb timer is needed to detect errors
  1900 +
  1901 +var inherits = require('inherits')
  1902 + , SenderReceiver = require('./lib/sender-receiver')
  1903 + , JsonpReceiver = require('./receiver/jsonp')
  1904 + , jsonpSender = require('./sender/jsonp')
  1905 + ;
  1906 +
  1907 +function JsonPTransport(transUrl) {
  1908 + if (!JsonPTransport.enabled()) {
  1909 + throw new Error('Transport created when disabled');
  1910 + }
  1911 + SenderReceiver.call(this, transUrl, '/jsonp', jsonpSender, JsonpReceiver);
  1912 +}
  1913 +
  1914 +inherits(JsonPTransport, SenderReceiver);
  1915 +
  1916 +JsonPTransport.enabled = function() {
  1917 + return !!global.document;
  1918 +};
  1919 +
  1920 +JsonPTransport.transportName = 'jsonp-polling';
  1921 +JsonPTransport.roundTrips = 1;
  1922 +JsonPTransport.needBody = true;
  1923 +
  1924 +module.exports = JsonPTransport;
  1925 +
  1926 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  1927 +
  1928 +},{"./lib/sender-receiver":28,"./receiver/jsonp":31,"./sender/jsonp":33,"inherits":56}],24:[function(require,module,exports){
  1929 +(function (process){
  1930 +'use strict';
  1931 +
  1932 +var inherits = require('inherits')
  1933 + , urlUtils = require('../../utils/url')
  1934 + , SenderReceiver = require('./sender-receiver')
  1935 + ;
  1936 +
  1937 +var debug = function() {};
  1938 +if (process.env.NODE_ENV !== 'production') {
  1939 + debug = require('debug')('sockjs-client:ajax-based');
  1940 +}
  1941 +
  1942 +function createAjaxSender(AjaxObject) {
  1943 + return function(url, payload, callback) {
  1944 + debug('create ajax sender', url, payload);
  1945 + var opt = {};
  1946 + if (typeof payload === 'string') {
  1947 + opt.headers = {'Content-type': 'text/plain'};
  1948 + }
  1949 + var ajaxUrl = urlUtils.addPath(url, '/xhr_send');
  1950 + var xo = new AjaxObject('POST', ajaxUrl, payload, opt);
  1951 + xo.once('finish', function(status) {
  1952 + debug('finish', status);
  1953 + xo = null;
  1954 +
  1955 + if (status !== 200 && status !== 204) {
  1956 + return callback(new Error('http status ' + status));
  1957 + }
  1958 + callback();
  1959 + });
  1960 + return function() {
  1961 + debug('abort');
  1962 + xo.close();
  1963 + xo = null;
  1964 +
  1965 + var err = new Error('Aborted');
  1966 + err.code = 1000;
  1967 + callback(err);
  1968 + };
  1969 + };
  1970 +}
  1971 +
  1972 +function AjaxBasedTransport(transUrl, urlSuffix, Receiver, AjaxObject) {
  1973 + SenderReceiver.call(this, transUrl, urlSuffix, createAjaxSender(AjaxObject), Receiver, AjaxObject);
  1974 +}
  1975 +
  1976 +inherits(AjaxBasedTransport, SenderReceiver);
  1977 +
  1978 +module.exports = AjaxBasedTransport;
  1979 +
  1980 +}).call(this,{ env: {} })
  1981 +
  1982 +},{"../../utils/url":52,"./sender-receiver":28,"debug":54,"inherits":56}],25:[function(require,module,exports){
  1983 +(function (process){
  1984 +'use strict';
  1985 +
  1986 +var inherits = require('inherits')
  1987 + , EventEmitter = require('events').EventEmitter
  1988 + ;
  1989 +
  1990 +var debug = function() {};
  1991 +if (process.env.NODE_ENV !== 'production') {
  1992 + debug = require('debug')('sockjs-client:buffered-sender');
  1993 +}
  1994 +
  1995 +function BufferedSender(url, sender) {
  1996 + debug(url);
  1997 + EventEmitter.call(this);
  1998 + this.sendBuffer = [];
  1999 + this.sender = sender;
  2000 + this.url = url;
  2001 +}
  2002 +
  2003 +inherits(BufferedSender, EventEmitter);
  2004 +
  2005 +BufferedSender.prototype.send = function(message) {
  2006 + debug('send', message);
  2007 + this.sendBuffer.push(message);
  2008 + if (!this.sendStop) {
  2009 + this.sendSchedule();
  2010 + }
  2011 +};
  2012 +
  2013 +// For polling transports in a situation when in the message callback,
  2014 +// new message is being send. If the sending connection was started
  2015 +// before receiving one, it is possible to saturate the network and
  2016 +// timeout due to the lack of receiving socket. To avoid that we delay
  2017 +// sending messages by some small time, in order to let receiving
  2018 +// connection be started beforehand. This is only a halfmeasure and
  2019 +// does not fix the big problem, but it does make the tests go more
  2020 +// stable on slow networks.
  2021 +BufferedSender.prototype.sendScheduleWait = function() {
  2022 + debug('sendScheduleWait');
  2023 + var self = this;
  2024 + var tref;
  2025 + this.sendStop = function() {
  2026 + debug('sendStop');
  2027 + self.sendStop = null;
  2028 + clearTimeout(tref);
  2029 + };
  2030 + tref = setTimeout(function() {
  2031 + debug('timeout');
  2032 + self.sendStop = null;
  2033 + self.sendSchedule();
  2034 + }, 25);
  2035 +};
  2036 +
  2037 +BufferedSender.prototype.sendSchedule = function() {
  2038 + debug('sendSchedule', this.sendBuffer.length);
  2039 + var self = this;
  2040 + if (this.sendBuffer.length > 0) {
  2041 + var payload = '[' + this.sendBuffer.join(',') + ']';
  2042 + this.sendStop = this.sender(this.url, payload, function(err) {
  2043 + self.sendStop = null;
  2044 + if (err) {
  2045 + debug('error', err);
  2046 + self.emit('close', err.code || 1006, 'Sending error: ' + err);
  2047 + self.close();
  2048 + } else {
  2049 + self.sendScheduleWait();
  2050 + }
  2051 + });
  2052 + this.sendBuffer = [];
  2053 + }
  2054 +};
  2055 +
  2056 +BufferedSender.prototype._cleanup = function() {
  2057 + debug('_cleanup');
  2058 + this.removeAllListeners();
  2059 +};
  2060 +
  2061 +BufferedSender.prototype.close = function() {
  2062 + debug('close');
  2063 + this._cleanup();
  2064 + if (this.sendStop) {
  2065 + this.sendStop();
  2066 + this.sendStop = null;
  2067 + }
  2068 +};
  2069 +
  2070 +module.exports = BufferedSender;
  2071 +
  2072 +}).call(this,{ env: {} })
  2073 +
  2074 +},{"debug":54,"events":3,"inherits":56}],26:[function(require,module,exports){
  2075 +(function (global){
  2076 +'use strict';
  2077 +
  2078 +var inherits = require('inherits')
  2079 + , IframeTransport = require('../iframe')
  2080 + , objectUtils = require('../../utils/object')
  2081 + ;
  2082 +
  2083 +module.exports = function(transport) {
  2084 +
  2085 + function IframeWrapTransport(transUrl, baseUrl) {
  2086 + IframeTransport.call(this, transport.transportName, transUrl, baseUrl);
  2087 + }
  2088 +
  2089 + inherits(IframeWrapTransport, IframeTransport);
  2090 +
  2091 + IframeWrapTransport.enabled = function(url, info) {
  2092 + if (!global.document) {
  2093 + return false;
  2094 + }
  2095 +
  2096 + var iframeInfo = objectUtils.extend({}, info);
  2097 + iframeInfo.sameOrigin = true;
  2098 + return transport.enabled(iframeInfo) && IframeTransport.enabled();
  2099 + };
  2100 +
  2101 + IframeWrapTransport.transportName = 'iframe-' + transport.transportName;
  2102 + IframeWrapTransport.needBody = true;
  2103 + IframeWrapTransport.roundTrips = IframeTransport.roundTrips + transport.roundTrips - 1; // html, javascript (2) + transport - no CORS (1)
  2104 +
  2105 + IframeWrapTransport.facadeTransport = transport;
  2106 +
  2107 + return IframeWrapTransport;
  2108 +};
  2109 +
  2110 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  2111 +
  2112 +},{"../../utils/object":49,"../iframe":22,"inherits":56}],27:[function(require,module,exports){
  2113 +(function (process){
  2114 +'use strict';
  2115 +
  2116 +var inherits = require('inherits')
  2117 + , EventEmitter = require('events').EventEmitter
  2118 + ;
  2119 +
  2120 +var debug = function() {};
  2121 +if (process.env.NODE_ENV !== 'production') {
  2122 + debug = require('debug')('sockjs-client:polling');
  2123 +}
  2124 +
  2125 +function Polling(Receiver, receiveUrl, AjaxObject) {
  2126 + debug(receiveUrl);
  2127 + EventEmitter.call(this);
  2128 + this.Receiver = Receiver;
  2129 + this.receiveUrl = receiveUrl;
  2130 + this.AjaxObject = AjaxObject;
  2131 + this._scheduleReceiver();
  2132 +}
  2133 +
  2134 +inherits(Polling, EventEmitter);
  2135 +
  2136 +Polling.prototype._scheduleReceiver = function() {
  2137 + debug('_scheduleReceiver');
  2138 + var self = this;
  2139 + var poll = this.poll = new this.Receiver(this.receiveUrl, this.AjaxObject);
  2140 +
  2141 + poll.on('message', function(msg) {
  2142 + debug('message', msg);
  2143 + self.emit('message', msg);
  2144 + });
  2145 +
  2146 + poll.once('close', function(code, reason) {
  2147 + debug('close', code, reason, self.pollIsClosing);
  2148 + self.poll = poll = null;
  2149 +
  2150 + if (!self.pollIsClosing) {
  2151 + if (reason === 'network') {
  2152 + self._scheduleReceiver();
  2153 + } else {
  2154 + self.emit('close', code || 1006, reason);
  2155 + self.removeAllListeners();
  2156 + }
  2157 + }
  2158 + });
  2159 +};
  2160 +
  2161 +Polling.prototype.abort = function() {
  2162 + debug('abort');
  2163 + this.removeAllListeners();
  2164 + this.pollIsClosing = true;
  2165 + if (this.poll) {
  2166 + this.poll.abort();
  2167 + }
  2168 +};
  2169 +
  2170 +module.exports = Polling;
  2171 +
  2172 +}).call(this,{ env: {} })
  2173 +
  2174 +},{"debug":54,"events":3,"inherits":56}],28:[function(require,module,exports){
  2175 +(function (process){
  2176 +'use strict';
  2177 +
  2178 +var inherits = require('inherits')
  2179 + , urlUtils = require('../../utils/url')
  2180 + , BufferedSender = require('./buffered-sender')
  2181 + , Polling = require('./polling')
  2182 + ;
  2183 +
  2184 +var debug = function() {};
  2185 +if (process.env.NODE_ENV !== 'production') {
  2186 + debug = require('debug')('sockjs-client:sender-receiver');
  2187 +}
  2188 +
  2189 +function SenderReceiver(transUrl, urlSuffix, senderFunc, Receiver, AjaxObject) {
  2190 + var pollUrl = urlUtils.addPath(transUrl, urlSuffix);
  2191 + debug(pollUrl);
  2192 + var self = this;
  2193 + BufferedSender.call(this, transUrl, senderFunc);
  2194 +
  2195 + this.poll = new Polling(Receiver, pollUrl, AjaxObject);
  2196 + this.poll.on('message', function(msg) {
  2197 + debug('poll message', msg);
  2198 + self.emit('message', msg);
  2199 + });
  2200 + this.poll.once('close', function(code, reason) {
  2201 + debug('poll close', code, reason);
  2202 + self.poll = null;
  2203 + self.emit('close', code, reason);
  2204 + self.close();
  2205 + });
  2206 +}
  2207 +
  2208 +inherits(SenderReceiver, BufferedSender);
  2209 +
  2210 +SenderReceiver.prototype.close = function() {
  2211 + BufferedSender.prototype.close.call(this);
  2212 + debug('close');
  2213 + this.removeAllListeners();
  2214 + if (this.poll) {
  2215 + this.poll.abort();
  2216 + this.poll = null;
  2217 + }
  2218 +};
  2219 +
  2220 +module.exports = SenderReceiver;
  2221 +
  2222 +}).call(this,{ env: {} })
  2223 +
  2224 +},{"../../utils/url":52,"./buffered-sender":25,"./polling":27,"debug":54,"inherits":56}],29:[function(require,module,exports){
  2225 +(function (process){
  2226 +'use strict';
  2227 +
  2228 +var inherits = require('inherits')
  2229 + , EventEmitter = require('events').EventEmitter
  2230 + , EventSourceDriver = require('eventsource')
  2231 + ;
  2232 +
  2233 +var debug = function() {};
  2234 +if (process.env.NODE_ENV !== 'production') {
  2235 + debug = require('debug')('sockjs-client:receiver:eventsource');
  2236 +}
  2237 +
  2238 +function EventSourceReceiver(url) {
  2239 + debug(url);
  2240 + EventEmitter.call(this);
  2241 +
  2242 + var self = this;
  2243 + var es = this.es = new EventSourceDriver(url);
  2244 + es.onmessage = function(e) {
  2245 + debug('message', e.data);
  2246 + self.emit('message', decodeURI(e.data));
  2247 + };
  2248 + es.onerror = function(e) {
  2249 + debug('error', es.readyState, e);
  2250 + // ES on reconnection has readyState = 0 or 1.
  2251 + // on network error it's CLOSED = 2
  2252 + var reason = (es.readyState !== 2 ? 'network' : 'permanent');
  2253 + self._cleanup();
  2254 + self._close(reason);
  2255 + };
  2256 +}
  2257 +
  2258 +inherits(EventSourceReceiver, EventEmitter);
  2259 +
  2260 +EventSourceReceiver.prototype.abort = function() {
  2261 + debug('abort');
  2262 + this._cleanup();
  2263 + this._close('user');
  2264 +};
  2265 +
  2266 +EventSourceReceiver.prototype._cleanup = function() {
  2267 + debug('cleanup');
  2268 + var es = this.es;
  2269 + if (es) {
  2270 + es.onmessage = es.onerror = null;
  2271 + es.close();
  2272 + this.es = null;
  2273 + }
  2274 +};
  2275 +
  2276 +EventSourceReceiver.prototype._close = function(reason) {
  2277 + debug('close', reason);
  2278 + var self = this;
  2279 + // Safari and chrome < 15 crash if we close window before
  2280 + // waiting for ES cleanup. See:
  2281 + // https://code.google.com/p/chromium/issues/detail?id=89155
  2282 + setTimeout(function() {
  2283 + self.emit('close', null, reason);
  2284 + self.removeAllListeners();
  2285 + }, 200);
  2286 +};
  2287 +
  2288 +module.exports = EventSourceReceiver;
  2289 +
  2290 +}).call(this,{ env: {} })
  2291 +
  2292 +},{"debug":54,"events":3,"eventsource":18,"inherits":56}],30:[function(require,module,exports){
  2293 +(function (process,global){
  2294 +'use strict';
  2295 +
  2296 +var inherits = require('inherits')
  2297 + , iframeUtils = require('../../utils/iframe')
  2298 + , urlUtils = require('../../utils/url')
  2299 + , EventEmitter = require('events').EventEmitter
  2300 + , random = require('../../utils/random')
  2301 + ;
  2302 +
  2303 +var debug = function() {};
  2304 +if (process.env.NODE_ENV !== 'production') {
  2305 + debug = require('debug')('sockjs-client:receiver:htmlfile');
  2306 +}
  2307 +
  2308 +function HtmlfileReceiver(url) {
  2309 + debug(url);
  2310 + EventEmitter.call(this);
  2311 + var self = this;
  2312 + iframeUtils.polluteGlobalNamespace();
  2313 +
  2314 + this.id = 'a' + random.string(6);
  2315 + url = urlUtils.addQuery(url, 'c=' + decodeURIComponent(iframeUtils.WPrefix + '.' + this.id));
  2316 +
  2317 + debug('using htmlfile', HtmlfileReceiver.htmlfileEnabled);
  2318 + var constructFunc = HtmlfileReceiver.htmlfileEnabled ?
  2319 + iframeUtils.createHtmlfile : iframeUtils.createIframe;
  2320 +
  2321 + global[iframeUtils.WPrefix][this.id] = {
  2322 + start: function() {
  2323 + debug('start');
  2324 + self.iframeObj.loaded();
  2325 + }
  2326 + , message: function(data) {
  2327 + debug('message', data);
  2328 + self.emit('message', data);
  2329 + }
  2330 + , stop: function() {
  2331 + debug('stop');
  2332 + self._cleanup();
  2333 + self._close('network');
  2334 + }
  2335 + };
  2336 + this.iframeObj = constructFunc(url, function() {
  2337 + debug('callback');
  2338 + self._cleanup();
  2339 + self._close('permanent');
  2340 + });
  2341 +}
  2342 +
  2343 +inherits(HtmlfileReceiver, EventEmitter);
  2344 +
  2345 +HtmlfileReceiver.prototype.abort = function() {
  2346 + debug('abort');
  2347 + this._cleanup();
  2348 + this._close('user');
  2349 +};
  2350 +
  2351 +HtmlfileReceiver.prototype._cleanup = function() {
  2352 + debug('_cleanup');
  2353 + if (this.iframeObj) {
  2354 + this.iframeObj.cleanup();
  2355 + this.iframeObj = null;
  2356 + }
  2357 + delete global[iframeUtils.WPrefix][this.id];
  2358 +};
  2359 +
  2360 +HtmlfileReceiver.prototype._close = function(reason) {
  2361 + debug('_close', reason);
  2362 + this.emit('close', null, reason);
  2363 + this.removeAllListeners();
  2364 +};
  2365 +
  2366 +HtmlfileReceiver.htmlfileEnabled = false;
  2367 +
  2368 +// obfuscate to avoid firewalls
  2369 +var axo = ['Active'].concat('Object').join('X');
  2370 +if (axo in global) {
  2371 + try {
  2372 + HtmlfileReceiver.htmlfileEnabled = !!new global[axo]('htmlfile');
  2373 + } catch (x) {
  2374 + // intentionally empty
  2375 + }
  2376 +}
  2377 +
  2378 +HtmlfileReceiver.enabled = HtmlfileReceiver.htmlfileEnabled || iframeUtils.iframeEnabled;
  2379 +
  2380 +module.exports = HtmlfileReceiver;
  2381 +
  2382 +}).call(this,{ env: {} },typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  2383 +
  2384 +},{"../../utils/iframe":47,"../../utils/random":50,"../../utils/url":52,"debug":54,"events":3,"inherits":56}],31:[function(require,module,exports){
  2385 +(function (process,global){
  2386 +'use strict';
  2387 +
  2388 +var utils = require('../../utils/iframe')
  2389 + , random = require('../../utils/random')
  2390 + , browser = require('../../utils/browser')
  2391 + , urlUtils = require('../../utils/url')
  2392 + , inherits = require('inherits')
  2393 + , EventEmitter = require('events').EventEmitter
  2394 + ;
  2395 +
  2396 +var debug = function() {};
  2397 +if (process.env.NODE_ENV !== 'production') {
  2398 + debug = require('debug')('sockjs-client:receiver:jsonp');
  2399 +}
  2400 +
  2401 +function JsonpReceiver(url) {
  2402 + debug(url);
  2403 + var self = this;
  2404 + EventEmitter.call(this);
  2405 +
  2406 + utils.polluteGlobalNamespace();
  2407 +
  2408 + this.id = 'a' + random.string(6);
  2409 + var urlWithId = urlUtils.addQuery(url, 'c=' + encodeURIComponent(utils.WPrefix + '.' + this.id));
  2410 +
  2411 + global[utils.WPrefix][this.id] = this._callback.bind(this);
  2412 + this._createScript(urlWithId);
  2413 +
  2414 + // Fallback mostly for Konqueror - stupid timer, 35 seconds shall be plenty.
  2415 + this.timeoutId = setTimeout(function() {
  2416 + debug('timeout');
  2417 + self._abort(new Error('JSONP script loaded abnormally (timeout)'));
  2418 + }, JsonpReceiver.timeout);
  2419 +}
  2420 +
  2421 +inherits(JsonpReceiver, EventEmitter);
  2422 +
  2423 +JsonpReceiver.prototype.abort = function() {
  2424 + debug('abort');
  2425 + if (global[utils.WPrefix][this.id]) {
  2426 + var err = new Error('JSONP user aborted read');
  2427 + err.code = 1000;
  2428 + this._abort(err);
  2429 + }
  2430 +};
  2431 +
  2432 +JsonpReceiver.timeout = 35000;
  2433 +JsonpReceiver.scriptErrorTimeout = 1000;
  2434 +
  2435 +JsonpReceiver.prototype._callback = function(data) {
  2436 + debug('_callback', data);
  2437 + this._cleanup();
  2438 +
  2439 + if (this.aborting) {
  2440 + return;
  2441 + }
  2442 +
  2443 + if (data) {
  2444 + debug('message', data);
  2445 + this.emit('message', data);
  2446 + }
  2447 + this.emit('close', null, 'network');
  2448 + this.removeAllListeners();
  2449 +};
  2450 +
  2451 +JsonpReceiver.prototype._abort = function(err) {
  2452 + debug('_abort', err);
  2453 + this._cleanup();
  2454 + this.aborting = true;
  2455 + this.emit('close', err.code, err.message);
  2456 + this.removeAllListeners();
  2457 +};
  2458 +
  2459 +JsonpReceiver.prototype._cleanup = function() {
  2460 + debug('_cleanup');
  2461 + clearTimeout(this.timeoutId);
  2462 + if (this.script2) {
  2463 + this.script2.parentNode.removeChild(this.script2);
  2464 + this.script2 = null;
  2465 + }
  2466 + if (this.script) {
  2467 + var script = this.script;
  2468 + // Unfortunately, you can't really abort script loading of
  2469 + // the script.
  2470 + script.parentNode.removeChild(script);
  2471 + script.onreadystatechange = script.onerror =
  2472 + script.onload = script.onclick = null;
  2473 + this.script = null;
  2474 + }
  2475 + delete global[utils.WPrefix][this.id];
  2476 +};
  2477 +
  2478 +JsonpReceiver.prototype._scriptError = function() {
  2479 + debug('_scriptError');
  2480 + var self = this;
  2481 + if (this.errorTimer) {
  2482 + return;
  2483 + }
  2484 +
  2485 + this.errorTimer = setTimeout(function() {
  2486 + if (!self.loadedOkay) {
  2487 + self._abort(new Error('JSONP script loaded abnormally (onerror)'));
  2488 + }
  2489 + }, JsonpReceiver.scriptErrorTimeout);
  2490 +};
  2491 +
  2492 +JsonpReceiver.prototype._createScript = function(url) {
  2493 + debug('_createScript', url);
  2494 + var self = this;
  2495 + var script = this.script = global.document.createElement('script');
  2496 + var script2; // Opera synchronous load trick.
  2497 +
  2498 + script.id = 'a' + random.string(8);
  2499 + script.src = url;
  2500 + script.type = 'text/javascript';
  2501 + script.charset = 'UTF-8';
  2502 + script.onerror = this._scriptError.bind(this);
  2503 + script.onload = function() {
  2504 + debug('onload');
  2505 + self._abort(new Error('JSONP script loaded abnormally (onload)'));
  2506 + };
  2507 +
  2508 + // IE9 fires 'error' event after onreadystatechange or before, in random order.
  2509 + // Use loadedOkay to determine if actually errored
  2510 + script.onreadystatechange = function() {
  2511 + debug('onreadystatechange', script.readyState);
  2512 + if (/loaded|closed/.test(script.readyState)) {
  2513 + if (script && script.htmlFor && script.onclick) {
  2514 + self.loadedOkay = true;
  2515 + try {
  2516 + // In IE, actually execute the script.
  2517 + script.onclick();
  2518 + } catch (x) {
  2519 + // intentionally empty
  2520 + }
  2521 + }
  2522 + if (script) {
  2523 + self._abort(new Error('JSONP script loaded abnormally (onreadystatechange)'));
  2524 + }
  2525 + }
  2526 + };
  2527 + // IE: event/htmlFor/onclick trick.
  2528 + // One can't rely on proper order for onreadystatechange. In order to
  2529 + // make sure, set a 'htmlFor' and 'event' properties, so that
  2530 + // script code will be installed as 'onclick' handler for the
  2531 + // script object. Later, onreadystatechange, manually execute this
  2532 + // code. FF and Chrome doesn't work with 'event' and 'htmlFor'
  2533 + // set. For reference see:
  2534 + // http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
  2535 + // Also, read on that about script ordering:
  2536 + // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
  2537 + if (typeof script.async === 'undefined' && global.document.attachEvent) {
  2538 + // According to mozilla docs, in recent browsers script.async defaults
  2539 + // to 'true', so we may use it to detect a good browser:
  2540 + // https://developer.mozilla.org/en/HTML/Element/script
  2541 + if (!browser.isOpera()) {
  2542 + // Naively assume we're in IE
  2543 + try {
  2544 + script.htmlFor = script.id;
  2545 + script.event = 'onclick';
  2546 + } catch (x) {
  2547 + // intentionally empty
  2548 + }
  2549 + script.async = true;
  2550 + } else {
  2551 + // Opera, second sync script hack
  2552 + script2 = this.script2 = global.document.createElement('script');
  2553 + script2.text = "try{var a = document.getElementById('" + script.id + "'); if(a)a.onerror();}catch(x){};";
  2554 + script.async = script2.async = false;
  2555 + }
  2556 + }
  2557 + if (typeof script.async !== 'undefined') {
  2558 + script.async = true;
  2559 + }
  2560 +
  2561 + var head = global.document.getElementsByTagName('head')[0];
  2562 + head.insertBefore(script, head.firstChild);
  2563 + if (script2) {
  2564 + head.insertBefore(script2, head.firstChild);
  2565 + }
  2566 +};
  2567 +
  2568 +module.exports = JsonpReceiver;
  2569 +
  2570 +}).call(this,{ env: {} },typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  2571 +
  2572 +},{"../../utils/browser":44,"../../utils/iframe":47,"../../utils/random":50,"../../utils/url":52,"debug":54,"events":3,"inherits":56}],32:[function(require,module,exports){
  2573 +(function (process){
  2574 +'use strict';
  2575 +
  2576 +var inherits = require('inherits')
  2577 + , EventEmitter = require('events').EventEmitter
  2578 + ;
  2579 +
  2580 +var debug = function() {};
  2581 +if (process.env.NODE_ENV !== 'production') {
  2582 + debug = require('debug')('sockjs-client:receiver:xhr');
  2583 +}
  2584 +
  2585 +function XhrReceiver(url, AjaxObject) {
  2586 + debug(url);
  2587 + EventEmitter.call(this);
  2588 + var self = this;
  2589 +
  2590 + this.bufferPosition = 0;
  2591 +
  2592 + this.xo = new AjaxObject('POST', url, null);
  2593 + this.xo.on('chunk', this._chunkHandler.bind(this));
  2594 + this.xo.once('finish', function(status, text) {
  2595 + debug('finish', status, text);
  2596 + self._chunkHandler(status, text);
  2597 + self.xo = null;
  2598 + var reason = status === 200 ? 'network' : 'permanent';
  2599 + debug('close', reason);
  2600 + self.emit('close', null, reason);
  2601 + self._cleanup();
  2602 + });
  2603 +}
  2604 +
  2605 +inherits(XhrReceiver, EventEmitter);
  2606 +
  2607 +XhrReceiver.prototype._chunkHandler = function(status, text) {
  2608 + debug('_chunkHandler', status);
  2609 + if (status !== 200 || !text) {
  2610 + return;
  2611 + }
  2612 +
  2613 + for (var idx = -1; ; this.bufferPosition += idx + 1) {
  2614 + var buf = text.slice(this.bufferPosition);
  2615 + idx = buf.indexOf('\n');
  2616 + if (idx === -1) {
  2617 + break;
  2618 + }
  2619 + var msg = buf.slice(0, idx);
  2620 + if (msg) {
  2621 + debug('message', msg);
  2622 + this.emit('message', msg);
  2623 + }
  2624 + }
  2625 +};
  2626 +
  2627 +XhrReceiver.prototype._cleanup = function() {
  2628 + debug('_cleanup');
  2629 + this.removeAllListeners();
  2630 +};
  2631 +
  2632 +XhrReceiver.prototype.abort = function() {
  2633 + debug('abort');
  2634 + if (this.xo) {
  2635 + this.xo.close();
  2636 + debug('close');
  2637 + this.emit('close', null, 'user');
  2638 + this.xo = null;
  2639 + }
  2640 + this._cleanup();
  2641 +};
  2642 +
  2643 +module.exports = XhrReceiver;
  2644 +
  2645 +}).call(this,{ env: {} })
  2646 +
  2647 +},{"debug":54,"events":3,"inherits":56}],33:[function(require,module,exports){
  2648 +(function (process,global){
  2649 +'use strict';
  2650 +
  2651 +var random = require('../../utils/random')
  2652 + , urlUtils = require('../../utils/url')
  2653 + ;
  2654 +
  2655 +var debug = function() {};
  2656 +if (process.env.NODE_ENV !== 'production') {
  2657 + debug = require('debug')('sockjs-client:sender:jsonp');
  2658 +}
  2659 +
  2660 +var form, area;
  2661 +
  2662 +function createIframe(id) {
  2663 + debug('createIframe', id);
  2664 + try {
  2665 + // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
  2666 + return global.document.createElement('<iframe name="' + id + '">');
  2667 + } catch (x) {
  2668 + var iframe = global.document.createElement('iframe');
  2669 + iframe.name = id;
  2670 + return iframe;
  2671 + }
  2672 +}
  2673 +
  2674 +function createForm() {
  2675 + debug('createForm');
  2676 + form = global.document.createElement('form');
  2677 + form.style.display = 'none';
  2678 + form.style.position = 'absolute';
  2679 + form.method = 'POST';
  2680 + form.enctype = 'application/x-www-form-urlencoded';
  2681 + form.acceptCharset = 'UTF-8';
  2682 +
  2683 + area = global.document.createElement('textarea');
  2684 + area.name = 'd';
  2685 + form.appendChild(area);
  2686 +
  2687 + global.document.body.appendChild(form);
  2688 +}
  2689 +
  2690 +module.exports = function(url, payload, callback) {
  2691 + debug(url, payload);
  2692 + if (!form) {
  2693 + createForm();
  2694 + }
  2695 + var id = 'a' + random.string(8);
  2696 + form.target = id;
  2697 + form.action = urlUtils.addQuery(urlUtils.addPath(url, '/jsonp_send'), 'i=' + id);
  2698 +
  2699 + var iframe = createIframe(id);
  2700 + iframe.id = id;
  2701 + iframe.style.display = 'none';
  2702 + form.appendChild(iframe);
  2703 +
  2704 + try {
  2705 + area.value = payload;
  2706 + } catch (e) {
  2707 + // seriously broken browsers get here
  2708 + }
  2709 + form.submit();
  2710 +
  2711 + var completed = function(err) {
  2712 + debug('completed', id, err);
  2713 + if (!iframe.onerror) {
  2714 + return;
  2715 + }
  2716 + iframe.onreadystatechange = iframe.onerror = iframe.onload = null;
  2717 + // Opera mini doesn't like if we GC iframe
  2718 + // immediately, thus this timeout.
  2719 + setTimeout(function() {
  2720 + debug('cleaning up', id);
  2721 + iframe.parentNode.removeChild(iframe);
  2722 + iframe = null;
  2723 + }, 500);
  2724 + area.value = '';
  2725 + // It is not possible to detect if the iframe succeeded or
  2726 + // failed to submit our form.
  2727 + callback(err);
  2728 + };
  2729 + iframe.onerror = function() {
  2730 + debug('onerror', id);
  2731 + completed();
  2732 + };
  2733 + iframe.onload = function() {
  2734 + debug('onload', id);
  2735 + completed();
  2736 + };
  2737 + iframe.onreadystatechange = function(e) {
  2738 + debug('onreadystatechange', id, iframe.readyState, e);
  2739 + if (iframe.readyState === 'complete') {
  2740 + completed();
  2741 + }
  2742 + };
  2743 + return function() {
  2744 + debug('aborted', id);
  2745 + completed(new Error('Aborted'));
  2746 + };
  2747 +};
  2748 +
  2749 +}).call(this,{ env: {} },typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  2750 +
  2751 +},{"../../utils/random":50,"../../utils/url":52,"debug":54}],34:[function(require,module,exports){
  2752 +(function (process,global){
  2753 +'use strict';
  2754 +
  2755 +var EventEmitter = require('events').EventEmitter
  2756 + , inherits = require('inherits')
  2757 + , eventUtils = require('../../utils/event')
  2758 + , browser = require('../../utils/browser')
  2759 + , urlUtils = require('../../utils/url')
  2760 + ;
  2761 +
  2762 +var debug = function() {};
  2763 +if (process.env.NODE_ENV !== 'production') {
  2764 + debug = require('debug')('sockjs-client:sender:xdr');
  2765 +}
  2766 +
  2767 +// References:
  2768 +// http://ajaxian.com/archives/100-line-ajax-wrapper
  2769 +// http://msdn.microsoft.com/en-us/library/cc288060(v=VS.85).aspx
  2770 +
  2771 +function XDRObject(method, url, payload) {
  2772 + debug(method, url);
  2773 + var self = this;
  2774 + EventEmitter.call(this);
  2775 +
  2776 + setTimeout(function() {
  2777 + self._start(method, url, payload);
  2778 + }, 0);
  2779 +}
  2780 +
  2781 +inherits(XDRObject, EventEmitter);
  2782 +
  2783 +XDRObject.prototype._start = function(method, url, payload) {
  2784 + debug('_start');
  2785 + var self = this;
  2786 + var xdr = new global.XDomainRequest();
  2787 + // IE caches even POSTs
  2788 + url = urlUtils.addQuery(url, 't=' + (+new Date()));
  2789 +
  2790 + xdr.onerror = function() {
  2791 + debug('onerror');
  2792 + self._error();
  2793 + };
  2794 + xdr.ontimeout = function() {
  2795 + debug('ontimeout');
  2796 + self._error();
  2797 + };
  2798 + xdr.onprogress = function() {
  2799 + debug('progress', xdr.responseText);
  2800 + self.emit('chunk', 200, xdr.responseText);
  2801 + };
  2802 + xdr.onload = function() {
  2803 + debug('load');
  2804 + self.emit('finish', 200, xdr.responseText);
  2805 + self._cleanup(false);
  2806 + };
  2807 + this.xdr = xdr;
  2808 + this.unloadRef = eventUtils.unloadAdd(function() {
  2809 + self._cleanup(true);
  2810 + });
  2811 + try {
  2812 + // Fails with AccessDenied if port number is bogus
  2813 + this.xdr.open(method, url);
  2814 + if (this.timeout) {
  2815 + this.xdr.timeout = this.timeout;
  2816 + }
  2817 + this.xdr.send(payload);
  2818 + } catch (x) {
  2819 + this._error();
  2820 + }
  2821 +};
  2822 +
  2823 +XDRObject.prototype._error = function() {
  2824 + this.emit('finish', 0, '');
  2825 + this._cleanup(false);
  2826 +};
  2827 +
  2828 +XDRObject.prototype._cleanup = function(abort) {
  2829 + debug('cleanup', abort);
  2830 + if (!this.xdr) {
  2831 + return;
  2832 + }
  2833 + this.removeAllListeners();
  2834 + eventUtils.unloadDel(this.unloadRef);
  2835 +
  2836 + this.xdr.ontimeout = this.xdr.onerror = this.xdr.onprogress = this.xdr.onload = null;
  2837 + if (abort) {
  2838 + try {
  2839 + this.xdr.abort();
  2840 + } catch (x) {
  2841 + // intentionally empty
  2842 + }
  2843 + }
  2844 + this.unloadRef = this.xdr = null;
  2845 +};
  2846 +
  2847 +XDRObject.prototype.close = function() {
  2848 + debug('close');
  2849 + this._cleanup(true);
  2850 +};
  2851 +
  2852 +// IE 8/9 if the request target uses the same scheme - #79
  2853 +XDRObject.enabled = !!(global.XDomainRequest && browser.hasDomain());
  2854 +
  2855 +module.exports = XDRObject;
  2856 +
  2857 +}).call(this,{ env: {} },typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  2858 +
  2859 +},{"../../utils/browser":44,"../../utils/event":46,"../../utils/url":52,"debug":54,"events":3,"inherits":56}],35:[function(require,module,exports){
  2860 +'use strict';
  2861 +
  2862 +var inherits = require('inherits')
  2863 + , XhrDriver = require('../driver/xhr')
  2864 + ;
  2865 +
  2866 +function XHRCorsObject(method, url, payload, opts) {
  2867 + XhrDriver.call(this, method, url, payload, opts);
  2868 +}
  2869 +
  2870 +inherits(XHRCorsObject, XhrDriver);
  2871 +
  2872 +XHRCorsObject.enabled = XhrDriver.enabled && XhrDriver.supportsCORS;
  2873 +
  2874 +module.exports = XHRCorsObject;
  2875 +
  2876 +},{"../driver/xhr":17,"inherits":56}],36:[function(require,module,exports){
  2877 +'use strict';
  2878 +
  2879 +var EventEmitter = require('events').EventEmitter
  2880 + , inherits = require('inherits')
  2881 + ;
  2882 +
  2883 +function XHRFake(/* method, url, payload, opts */) {
  2884 + var self = this;
  2885 + EventEmitter.call(this);
  2886 +
  2887 + this.to = setTimeout(function() {
  2888 + self.emit('finish', 200, '{}');
  2889 + }, XHRFake.timeout);
  2890 +}
  2891 +
  2892 +inherits(XHRFake, EventEmitter);
  2893 +
  2894 +XHRFake.prototype.close = function() {
  2895 + clearTimeout(this.to);
  2896 +};
  2897 +
  2898 +XHRFake.timeout = 2000;
  2899 +
  2900 +module.exports = XHRFake;
  2901 +
  2902 +},{"events":3,"inherits":56}],37:[function(require,module,exports){
  2903 +'use strict';
  2904 +
  2905 +var inherits = require('inherits')
  2906 + , XhrDriver = require('../driver/xhr')
  2907 + ;
  2908 +
  2909 +function XHRLocalObject(method, url, payload /*, opts */) {
  2910 + XhrDriver.call(this, method, url, payload, {
  2911 + noCredentials: true
  2912 + });
  2913 +}
  2914 +
  2915 +inherits(XHRLocalObject, XhrDriver);
  2916 +
  2917 +XHRLocalObject.enabled = XhrDriver.enabled;
  2918 +
  2919 +module.exports = XHRLocalObject;
  2920 +
  2921 +},{"../driver/xhr":17,"inherits":56}],38:[function(require,module,exports){
  2922 +(function (process){
  2923 +'use strict';
  2924 +
  2925 +var utils = require('../utils/event')
  2926 + , urlUtils = require('../utils/url')
  2927 + , inherits = require('inherits')
  2928 + , EventEmitter = require('events').EventEmitter
  2929 + , WebsocketDriver = require('./driver/websocket')
  2930 + ;
  2931 +
  2932 +var debug = function() {};
  2933 +if (process.env.NODE_ENV !== 'production') {
  2934 + debug = require('debug')('sockjs-client:websocket');
  2935 +}
  2936 +
  2937 +function WebSocketTransport(transUrl, ignore, options) {
  2938 + if (!WebSocketTransport.enabled()) {
  2939 + throw new Error('Transport created when disabled');
  2940 + }
  2941 +
  2942 + EventEmitter.call(this);
  2943 + debug('constructor', transUrl);
  2944 +
  2945 + var self = this;
  2946 + var url = urlUtils.addPath(transUrl, '/websocket');
  2947 + if (url.slice(0, 5) === 'https') {
  2948 + url = 'wss' + url.slice(5);
  2949 + } else {
  2950 + url = 'ws' + url.slice(4);
  2951 + }
  2952 + this.url = url;
  2953 +
  2954 + this.ws = new WebsocketDriver(this.url, [], options);
  2955 + this.ws.onmessage = function(e) {
  2956 + debug('message event', e.data);
  2957 + self.emit('message', e.data);
  2958 + };
  2959 + // Firefox has an interesting bug. If a websocket connection is
  2960 + // created after onunload, it stays alive even when user
  2961 + // navigates away from the page. In such situation let's lie -
  2962 + // let's not open the ws connection at all. See:
  2963 + // https://github.com/sockjs/sockjs-client/issues/28
  2964 + // https://bugzilla.mozilla.org/show_bug.cgi?id=696085
  2965 + this.unloadRef = utils.unloadAdd(function() {
  2966 + debug('unload');
  2967 + self.ws.close();
  2968 + });
  2969 + this.ws.onclose = function(e) {
  2970 + debug('close event', e.code, e.reason);
  2971 + self.emit('close', e.code, e.reason);
  2972 + self._cleanup();
  2973 + };
  2974 + this.ws.onerror = function(e) {
  2975 + debug('error event', e);
  2976 + self.emit('close', 1006, 'WebSocket connection broken');
  2977 + self._cleanup();
  2978 + };
  2979 +}
  2980 +
  2981 +inherits(WebSocketTransport, EventEmitter);
  2982 +
  2983 +WebSocketTransport.prototype.send = function(data) {
  2984 + var msg = '[' + data + ']';
  2985 + debug('send', msg);
  2986 + this.ws.send(msg);
  2987 +};
  2988 +
  2989 +WebSocketTransport.prototype.close = function() {
  2990 + debug('close');
  2991 + var ws = this.ws;
  2992 + this._cleanup();
  2993 + if (ws) {
  2994 + ws.close();
  2995 + }
  2996 +};
  2997 +
  2998 +WebSocketTransport.prototype._cleanup = function() {
  2999 + debug('_cleanup');
  3000 + var ws = this.ws;
  3001 + if (ws) {
  3002 + ws.onmessage = ws.onclose = ws.onerror = null;
  3003 + }
  3004 + utils.unloadDel(this.unloadRef);
  3005 + this.unloadRef = this.ws = null;
  3006 + this.removeAllListeners();
  3007 +};
  3008 +
  3009 +WebSocketTransport.enabled = function() {
  3010 + debug('enabled');
  3011 + return !!WebsocketDriver;
  3012 +};
  3013 +WebSocketTransport.transportName = 'websocket';
  3014 +
  3015 +// In theory, ws should require 1 round trip. But in chrome, this is
  3016 +// not very stable over SSL. Most likely a ws connection requires a
  3017 +// separate SSL connection, in which case 2 round trips are an
  3018 +// absolute minumum.
  3019 +WebSocketTransport.roundTrips = 2;
  3020 +
  3021 +module.exports = WebSocketTransport;
  3022 +
  3023 +}).call(this,{ env: {} })
  3024 +
  3025 +},{"../utils/event":46,"../utils/url":52,"./driver/websocket":19,"debug":54,"events":3,"inherits":56}],39:[function(require,module,exports){
  3026 +'use strict';
  3027 +
  3028 +var inherits = require('inherits')
  3029 + , AjaxBasedTransport = require('./lib/ajax-based')
  3030 + , XdrStreamingTransport = require('./xdr-streaming')
  3031 + , XhrReceiver = require('./receiver/xhr')
  3032 + , XDRObject = require('./sender/xdr')
  3033 + ;
  3034 +
  3035 +function XdrPollingTransport(transUrl) {
  3036 + if (!XDRObject.enabled) {
  3037 + throw new Error('Transport created when disabled');
  3038 + }
  3039 + AjaxBasedTransport.call(this, transUrl, '/xhr', XhrReceiver, XDRObject);
  3040 +}
  3041 +
  3042 +inherits(XdrPollingTransport, AjaxBasedTransport);
  3043 +
  3044 +XdrPollingTransport.enabled = XdrStreamingTransport.enabled;
  3045 +XdrPollingTransport.transportName = 'xdr-polling';
  3046 +XdrPollingTransport.roundTrips = 2; // preflight, ajax
  3047 +
  3048 +module.exports = XdrPollingTransport;
  3049 +
  3050 +},{"./lib/ajax-based":24,"./receiver/xhr":32,"./sender/xdr":34,"./xdr-streaming":40,"inherits":56}],40:[function(require,module,exports){
  3051 +'use strict';
  3052 +
  3053 +var inherits = require('inherits')
  3054 + , AjaxBasedTransport = require('./lib/ajax-based')
  3055 + , XhrReceiver = require('./receiver/xhr')
  3056 + , XDRObject = require('./sender/xdr')
  3057 + ;
  3058 +
  3059 +// According to:
  3060 +// http://stackoverflow.com/questions/1641507/detect-browser-support-for-cross-domain-xmlhttprequests
  3061 +// http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
  3062 +
  3063 +function XdrStreamingTransport(transUrl) {
  3064 + if (!XDRObject.enabled) {
  3065 + throw new Error('Transport created when disabled');
  3066 + }
  3067 + AjaxBasedTransport.call(this, transUrl, '/xhr_streaming', XhrReceiver, XDRObject);
  3068 +}
  3069 +
  3070 +inherits(XdrStreamingTransport, AjaxBasedTransport);
  3071 +
  3072 +XdrStreamingTransport.enabled = function(info) {
  3073 + if (info.cookie_needed || info.nullOrigin) {
  3074 + return false;
  3075 + }
  3076 + return XDRObject.enabled && info.sameScheme;
  3077 +};
  3078 +
  3079 +XdrStreamingTransport.transportName = 'xdr-streaming';
  3080 +XdrStreamingTransport.roundTrips = 2; // preflight, ajax
  3081 +
  3082 +module.exports = XdrStreamingTransport;
  3083 +
  3084 +},{"./lib/ajax-based":24,"./receiver/xhr":32,"./sender/xdr":34,"inherits":56}],41:[function(require,module,exports){
  3085 +'use strict';
  3086 +
  3087 +var inherits = require('inherits')
  3088 + , AjaxBasedTransport = require('./lib/ajax-based')
  3089 + , XhrReceiver = require('./receiver/xhr')
  3090 + , XHRCorsObject = require('./sender/xhr-cors')
  3091 + , XHRLocalObject = require('./sender/xhr-local')
  3092 + ;
  3093 +
  3094 +function XhrPollingTransport(transUrl) {
  3095 + if (!XHRLocalObject.enabled && !XHRCorsObject.enabled) {
  3096 + throw new Error('Transport created when disabled');
  3097 + }
  3098 + AjaxBasedTransport.call(this, transUrl, '/xhr', XhrReceiver, XHRCorsObject);
  3099 +}
  3100 +
  3101 +inherits(XhrPollingTransport, AjaxBasedTransport);
  3102 +
  3103 +XhrPollingTransport.enabled = function(info) {
  3104 + if (info.nullOrigin) {
  3105 + return false;
  3106 + }
  3107 +
  3108 + if (XHRLocalObject.enabled && info.sameOrigin) {
  3109 + return true;
  3110 + }
  3111 + return XHRCorsObject.enabled;
  3112 +};
  3113 +
  3114 +XhrPollingTransport.transportName = 'xhr-polling';
  3115 +XhrPollingTransport.roundTrips = 2; // preflight, ajax
  3116 +
  3117 +module.exports = XhrPollingTransport;
  3118 +
  3119 +},{"./lib/ajax-based":24,"./receiver/xhr":32,"./sender/xhr-cors":35,"./sender/xhr-local":37,"inherits":56}],42:[function(require,module,exports){
  3120 +(function (global){
  3121 +'use strict';
  3122 +
  3123 +var inherits = require('inherits')
  3124 + , AjaxBasedTransport = require('./lib/ajax-based')
  3125 + , XhrReceiver = require('./receiver/xhr')
  3126 + , XHRCorsObject = require('./sender/xhr-cors')
  3127 + , XHRLocalObject = require('./sender/xhr-local')
  3128 + , browser = require('../utils/browser')
  3129 + ;
  3130 +
  3131 +function XhrStreamingTransport(transUrl) {
  3132 + if (!XHRLocalObject.enabled && !XHRCorsObject.enabled) {
  3133 + throw new Error('Transport created when disabled');
  3134 + }
  3135 + AjaxBasedTransport.call(this, transUrl, '/xhr_streaming', XhrReceiver, XHRCorsObject);
  3136 +}
  3137 +
  3138 +inherits(XhrStreamingTransport, AjaxBasedTransport);
  3139 +
  3140 +XhrStreamingTransport.enabled = function(info) {
  3141 + if (info.nullOrigin) {
  3142 + return false;
  3143 + }
  3144 + // Opera doesn't support xhr-streaming #60
  3145 + // But it might be able to #92
  3146 + if (browser.isOpera()) {
  3147 + return false;
  3148 + }
  3149 +
  3150 + return XHRCorsObject.enabled;
  3151 +};
  3152 +
  3153 +XhrStreamingTransport.transportName = 'xhr-streaming';
  3154 +XhrStreamingTransport.roundTrips = 2; // preflight, ajax
  3155 +
  3156 +// Safari gets confused when a streaming ajax request is started
  3157 +// before onload. This causes the load indicator to spin indefinetely.
  3158 +// Only require body when used in a browser
  3159 +XhrStreamingTransport.needBody = !!global.document;
  3160 +
  3161 +module.exports = XhrStreamingTransport;
  3162 +
  3163 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  3164 +
  3165 +},{"../utils/browser":44,"./lib/ajax-based":24,"./receiver/xhr":32,"./sender/xhr-cors":35,"./sender/xhr-local":37,"inherits":56}],43:[function(require,module,exports){
  3166 +(function (global){
  3167 +'use strict';
  3168 +
  3169 +if (global.crypto && global.crypto.getRandomValues) {
  3170 + module.exports.randomBytes = function(length) {
  3171 + var bytes = new Uint8Array(length);
  3172 + global.crypto.getRandomValues(bytes);
  3173 + return bytes;
  3174 + };
  3175 +} else {
  3176 + module.exports.randomBytes = function(length) {
  3177 + var bytes = new Array(length);
  3178 + for (var i = 0; i < length; i++) {
  3179 + bytes[i] = Math.floor(Math.random() * 256);
  3180 + }
  3181 + return bytes;
  3182 + };
  3183 +}
  3184 +
  3185 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  3186 +
  3187 +},{}],44:[function(require,module,exports){
  3188 +(function (global){
  3189 +'use strict';
  3190 +
  3191 +module.exports = {
  3192 + isOpera: function() {
  3193 + return global.navigator &&
  3194 + /opera/i.test(global.navigator.userAgent);
  3195 + }
  3196 +
  3197 +, isKonqueror: function() {
  3198 + return global.navigator &&
  3199 + /konqueror/i.test(global.navigator.userAgent);
  3200 + }
  3201 +
  3202 + // #187 wrap document.domain in try/catch because of WP8 from file:///
  3203 +, hasDomain: function () {
  3204 + // non-browser client always has a domain
  3205 + if (!global.document) {
  3206 + return true;
  3207 + }
  3208 +
  3209 + try {
  3210 + return !!global.document.domain;
  3211 + } catch (e) {
  3212 + return false;
  3213 + }
  3214 + }
  3215 +};
  3216 +
  3217 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  3218 +
  3219 +},{}],45:[function(require,module,exports){
  3220 +'use strict';
  3221 +
  3222 +var JSON3 = require('json3');
  3223 +
  3224 +// Some extra characters that Chrome gets wrong, and substitutes with
  3225 +// something else on the wire.
  3226 +// eslint-disable-next-line no-control-regex
  3227 +var extraEscapable = /[\x00-\x1f\ud800-\udfff\ufffe\uffff\u0300-\u0333\u033d-\u0346\u034a-\u034c\u0350-\u0352\u0357-\u0358\u035c-\u0362\u0374\u037e\u0387\u0591-\u05af\u05c4\u0610-\u0617\u0653-\u0654\u0657-\u065b\u065d-\u065e\u06df-\u06e2\u06eb-\u06ec\u0730\u0732-\u0733\u0735-\u0736\u073a\u073d\u073f-\u0741\u0743\u0745\u0747\u07eb-\u07f1\u0951\u0958-\u095f\u09dc-\u09dd\u09df\u0a33\u0a36\u0a59-\u0a5b\u0a5e\u0b5c-\u0b5d\u0e38-\u0e39\u0f43\u0f4d\u0f52\u0f57\u0f5c\u0f69\u0f72-\u0f76\u0f78\u0f80-\u0f83\u0f93\u0f9d\u0fa2\u0fa7\u0fac\u0fb9\u1939-\u193a\u1a17\u1b6b\u1cda-\u1cdb\u1dc0-\u1dcf\u1dfc\u1dfe\u1f71\u1f73\u1f75\u1f77\u1f79\u1f7b\u1f7d\u1fbb\u1fbe\u1fc9\u1fcb\u1fd3\u1fdb\u1fe3\u1feb\u1fee-\u1fef\u1ff9\u1ffb\u1ffd\u2000-\u2001\u20d0-\u20d1\u20d4-\u20d7\u20e7-\u20e9\u2126\u212a-\u212b\u2329-\u232a\u2adc\u302b-\u302c\uaab2-\uaab3\uf900-\ufa0d\ufa10\ufa12\ufa15-\ufa1e\ufa20\ufa22\ufa25-\ufa26\ufa2a-\ufa2d\ufa30-\ufa6d\ufa70-\ufad9\ufb1d\ufb1f\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufb4e\ufff0-\uffff]/g
  3228 + , extraLookup;
  3229 +
  3230 +// This may be quite slow, so let's delay until user actually uses bad
  3231 +// characters.
  3232 +var unrollLookup = function(escapable) {
  3233 + var i;
  3234 + var unrolled = {};
  3235 + var c = [];
  3236 + for (i = 0; i < 65536; i++) {
  3237 + c.push( String.fromCharCode(i) );
  3238 + }
  3239 + escapable.lastIndex = 0;
  3240 + c.join('').replace(escapable, function(a) {
  3241 + unrolled[ a ] = '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
  3242 + return '';
  3243 + });
  3244 + escapable.lastIndex = 0;
  3245 + return unrolled;
  3246 +};
  3247 +
  3248 +// Quote string, also taking care of unicode characters that browsers
  3249 +// often break. Especially, take care of unicode surrogates:
  3250 +// http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters#Surrogates
  3251 +module.exports = {
  3252 + quote: function(string) {
  3253 + var quoted = JSON3.stringify(string);
  3254 +
  3255 + // In most cases this should be very fast and good enough.
  3256 + extraEscapable.lastIndex = 0;
  3257 + if (!extraEscapable.test(quoted)) {
  3258 + return quoted;
  3259 + }
  3260 +
  3261 + if (!extraLookup) {
  3262 + extraLookup = unrollLookup(extraEscapable);
  3263 + }
  3264 +
  3265 + return quoted.replace(extraEscapable, function(a) {
  3266 + return extraLookup[a];
  3267 + });
  3268 + }
  3269 +};
  3270 +
  3271 +},{"json3":57}],46:[function(require,module,exports){
  3272 +(function (global){
  3273 +'use strict';
  3274 +
  3275 +var random = require('./random');
  3276 +
  3277 +var onUnload = {}
  3278 + , afterUnload = false
  3279 + // detect google chrome packaged apps because they don't allow the 'unload' event
  3280 + , isChromePackagedApp = global.chrome && global.chrome.app && global.chrome.app.runtime
  3281 + ;
  3282 +
  3283 +module.exports = {
  3284 + attachEvent: function(event, listener) {
  3285 + if (typeof global.addEventListener !== 'undefined') {
  3286 + global.addEventListener(event, listener, false);
  3287 + } else if (global.document && global.attachEvent) {
  3288 + // IE quirks.
  3289 + // According to: http://stevesouders.com/misc/test-postmessage.php
  3290 + // the message gets delivered only to 'document', not 'window'.
  3291 + global.document.attachEvent('on' + event, listener);
  3292 + // I get 'window' for ie8.
  3293 + global.attachEvent('on' + event, listener);
  3294 + }
  3295 + }
  3296 +
  3297 +, detachEvent: function(event, listener) {
  3298 + if (typeof global.addEventListener !== 'undefined') {
  3299 + global.removeEventListener(event, listener, false);
  3300 + } else if (global.document && global.detachEvent) {
  3301 + global.document.detachEvent('on' + event, listener);
  3302 + global.detachEvent('on' + event, listener);
  3303 + }
  3304 + }
  3305 +
  3306 +, unloadAdd: function(listener) {
  3307 + if (isChromePackagedApp) {
  3308 + return null;
  3309 + }
  3310 +
  3311 + var ref = random.string(8);
  3312 + onUnload[ref] = listener;
  3313 + if (afterUnload) {
  3314 + setTimeout(this.triggerUnloadCallbacks, 0);
  3315 + }
  3316 + return ref;
  3317 + }
  3318 +
  3319 +, unloadDel: function(ref) {
  3320 + if (ref in onUnload) {
  3321 + delete onUnload[ref];
  3322 + }
  3323 + }
  3324 +
  3325 +, triggerUnloadCallbacks: function() {
  3326 + for (var ref in onUnload) {
  3327 + onUnload[ref]();
  3328 + delete onUnload[ref];
  3329 + }
  3330 + }
  3331 +};
  3332 +
  3333 +var unloadTriggered = function() {
  3334 + if (afterUnload) {
  3335 + return;
  3336 + }
  3337 + afterUnload = true;
  3338 + module.exports.triggerUnloadCallbacks();
  3339 +};
  3340 +
  3341 +// 'unload' alone is not reliable in opera within an iframe, but we
  3342 +// can't use `beforeunload` as IE fires it on javascript: links.
  3343 +if (!isChromePackagedApp) {
  3344 + module.exports.attachEvent('unload', unloadTriggered);
  3345 +}
  3346 +
  3347 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  3348 +
  3349 +},{"./random":50}],47:[function(require,module,exports){
  3350 +(function (process,global){
  3351 +'use strict';
  3352 +
  3353 +var eventUtils = require('./event')
  3354 + , JSON3 = require('json3')
  3355 + , browser = require('./browser')
  3356 + ;
  3357 +
  3358 +var debug = function() {};
  3359 +if (process.env.NODE_ENV !== 'production') {
  3360 + debug = require('debug')('sockjs-client:utils:iframe');
  3361 +}
  3362 +
  3363 +module.exports = {
  3364 + WPrefix: '_jp'
  3365 +, currentWindowId: null
  3366 +
  3367 +, polluteGlobalNamespace: function() {
  3368 + if (!(module.exports.WPrefix in global)) {
  3369 + global[module.exports.WPrefix] = {};
  3370 + }
  3371 + }
  3372 +
  3373 +, postMessage: function(type, data) {
  3374 + if (global.parent !== global) {
  3375 + global.parent.postMessage(JSON3.stringify({
  3376 + windowId: module.exports.currentWindowId
  3377 + , type: type
  3378 + , data: data || ''
  3379 + }), '*');
  3380 + } else {
  3381 + debug('Cannot postMessage, no parent window.', type, data);
  3382 + }
  3383 + }
  3384 +
  3385 +, createIframe: function(iframeUrl, errorCallback) {
  3386 + var iframe = global.document.createElement('iframe');
  3387 + var tref, unloadRef;
  3388 + var unattach = function() {
  3389 + debug('unattach');
  3390 + clearTimeout(tref);
  3391 + // Explorer had problems with that.
  3392 + try {
  3393 + iframe.onload = null;
  3394 + } catch (x) {
  3395 + // intentionally empty
  3396 + }
  3397 + iframe.onerror = null;
  3398 + };
  3399 + var cleanup = function() {
  3400 + debug('cleanup');
  3401 + if (iframe) {
  3402 + unattach();
  3403 + // This timeout makes chrome fire onbeforeunload event
  3404 + // within iframe. Without the timeout it goes straight to
  3405 + // onunload.
  3406 + setTimeout(function() {
  3407 + if (iframe) {
  3408 + iframe.parentNode.removeChild(iframe);
  3409 + }
  3410 + iframe = null;
  3411 + }, 0);
  3412 + eventUtils.unloadDel(unloadRef);
  3413 + }
  3414 + };
  3415 + var onerror = function(err) {
  3416 + debug('onerror', err);
  3417 + if (iframe) {
  3418 + cleanup();
  3419 + errorCallback(err);
  3420 + }
  3421 + };
  3422 + var post = function(msg, origin) {
  3423 + debug('post', msg, origin);
  3424 + try {
  3425 + // When the iframe is not loaded, IE raises an exception
  3426 + // on 'contentWindow'.
  3427 + setTimeout(function() {
  3428 + if (iframe && iframe.contentWindow) {
  3429 + iframe.contentWindow.postMessage(msg, origin);
  3430 + }
  3431 + }, 0);
  3432 + } catch (x) {
  3433 + // intentionally empty
  3434 + }
  3435 + };
  3436 +
  3437 + iframe.src = iframeUrl;
  3438 + iframe.style.display = 'none';
  3439 + iframe.style.position = 'absolute';
  3440 + iframe.onerror = function() {
  3441 + onerror('onerror');
  3442 + };
  3443 + iframe.onload = function() {
  3444 + debug('onload');
  3445 + // `onload` is triggered before scripts on the iframe are
  3446 + // executed. Give it few seconds to actually load stuff.
  3447 + clearTimeout(tref);
  3448 + tref = setTimeout(function() {
  3449 + onerror('onload timeout');
  3450 + }, 2000);
  3451 + };
  3452 + global.document.body.appendChild(iframe);
  3453 + tref = setTimeout(function() {
  3454 + onerror('timeout');
  3455 + }, 15000);
  3456 + unloadRef = eventUtils.unloadAdd(cleanup);
  3457 + return {
  3458 + post: post
  3459 + , cleanup: cleanup
  3460 + , loaded: unattach
  3461 + };
  3462 + }
  3463 +
  3464 +/* eslint no-undef: "off", new-cap: "off" */
  3465 +, createHtmlfile: function(iframeUrl, errorCallback) {
  3466 + var axo = ['Active'].concat('Object').join('X');
  3467 + var doc = new global[axo]('htmlfile');
  3468 + var tref, unloadRef;
  3469 + var iframe;
  3470 + var unattach = function() {
  3471 + clearTimeout(tref);
  3472 + iframe.onerror = null;
  3473 + };
  3474 + var cleanup = function() {
  3475 + if (doc) {
  3476 + unattach();
  3477 + eventUtils.unloadDel(unloadRef);
  3478 + iframe.parentNode.removeChild(iframe);
  3479 + iframe = doc = null;
  3480 + CollectGarbage();
  3481 + }
  3482 + };
  3483 + var onerror = function(r) {
  3484 + debug('onerror', r);
  3485 + if (doc) {
  3486 + cleanup();
  3487 + errorCallback(r);
  3488 + }
  3489 + };
  3490 + var post = function(msg, origin) {
  3491 + try {
  3492 + // When the iframe is not loaded, IE raises an exception
  3493 + // on 'contentWindow'.
  3494 + setTimeout(function() {
  3495 + if (iframe && iframe.contentWindow) {
  3496 + iframe.contentWindow.postMessage(msg, origin);
  3497 + }
  3498 + }, 0);
  3499 + } catch (x) {
  3500 + // intentionally empty
  3501 + }
  3502 + };
  3503 +
  3504 + doc.open();
  3505 + doc.write('<html><s' + 'cript>' +
  3506 + 'document.domain="' + global.document.domain + '";' +
  3507 + '</s' + 'cript></html>');
  3508 + doc.close();
  3509 + doc.parentWindow[module.exports.WPrefix] = global[module.exports.WPrefix];
  3510 + var c = doc.createElement('div');
  3511 + doc.body.appendChild(c);
  3512 + iframe = doc.createElement('iframe');
  3513 + c.appendChild(iframe);
  3514 + iframe.src = iframeUrl;
  3515 + iframe.onerror = function() {
  3516 + onerror('onerror');
  3517 + };
  3518 + tref = setTimeout(function() {
  3519 + onerror('timeout');
  3520 + }, 15000);
  3521 + unloadRef = eventUtils.unloadAdd(cleanup);
  3522 + return {
  3523 + post: post
  3524 + , cleanup: cleanup
  3525 + , loaded: unattach
  3526 + };
  3527 + }
  3528 +};
  3529 +
  3530 +module.exports.iframeEnabled = false;
  3531 +if (global.document) {
  3532 + // postMessage misbehaves in konqueror 4.6.5 - the messages are delivered with
  3533 + // huge delay, or not at all.
  3534 + module.exports.iframeEnabled = (typeof global.postMessage === 'function' ||
  3535 + typeof global.postMessage === 'object') && (!browser.isKonqueror());
  3536 +}
  3537 +
  3538 +}).call(this,{ env: {} },typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  3539 +
  3540 +},{"./browser":44,"./event":46,"debug":54,"json3":57}],48:[function(require,module,exports){
  3541 +(function (global){
  3542 +'use strict';
  3543 +
  3544 +var logObject = {};
  3545 +['log', 'debug', 'warn'].forEach(function (level) {
  3546 + var levelExists;
  3547 +
  3548 + try {
  3549 + levelExists = global.console && global.console[level] && global.console[level].apply;
  3550 + } catch(e) {
  3551 + // do nothing
  3552 + }
  3553 +
  3554 + logObject[level] = levelExists ? function () {
  3555 + return global.console[level].apply(global.console, arguments);
  3556 + } : (level === 'log' ? function () {} : logObject.log);
  3557 +});
  3558 +
  3559 +module.exports = logObject;
  3560 +
  3561 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  3562 +
  3563 +},{}],49:[function(require,module,exports){
  3564 +'use strict';
  3565 +
  3566 +module.exports = {
  3567 + isObject: function(obj) {
  3568 + var type = typeof obj;
  3569 + return type === 'function' || type === 'object' && !!obj;
  3570 + }
  3571 +
  3572 +, extend: function(obj) {
  3573 + if (!this.isObject(obj)) {
  3574 + return obj;
  3575 + }
  3576 + var source, prop;
  3577 + for (var i = 1, length = arguments.length; i < length; i++) {
  3578 + source = arguments[i];
  3579 + for (prop in source) {
  3580 + if (Object.prototype.hasOwnProperty.call(source, prop)) {
  3581 + obj[prop] = source[prop];
  3582 + }
  3583 + }
  3584 + }
  3585 + return obj;
  3586 + }
  3587 +};
  3588 +
  3589 +},{}],50:[function(require,module,exports){
  3590 +'use strict';
  3591 +
  3592 +/* global crypto:true */
  3593 +var crypto = require('crypto');
  3594 +
  3595 +// This string has length 32, a power of 2, so the modulus doesn't introduce a
  3596 +// bias.
  3597 +var _randomStringChars = 'abcdefghijklmnopqrstuvwxyz012345';
  3598 +module.exports = {
  3599 + string: function(length) {
  3600 + var max = _randomStringChars.length;
  3601 + var bytes = crypto.randomBytes(length);
  3602 + var ret = [];
  3603 + for (var i = 0; i < length; i++) {
  3604 + ret.push(_randomStringChars.substr(bytes[i] % max, 1));
  3605 + }
  3606 + return ret.join('');
  3607 + }
  3608 +
  3609 +, number: function(max) {
  3610 + return Math.floor(Math.random() * max);
  3611 + }
  3612 +
  3613 +, numberString: function(max) {
  3614 + var t = ('' + (max - 1)).length;
  3615 + var p = new Array(t + 1).join('0');
  3616 + return (p + this.number(max)).slice(-t);
  3617 + }
  3618 +};
  3619 +
  3620 +},{"crypto":43}],51:[function(require,module,exports){
  3621 +(function (process){
  3622 +'use strict';
  3623 +
  3624 +var debug = function() {};
  3625 +if (process.env.NODE_ENV !== 'production') {
  3626 + debug = require('debug')('sockjs-client:utils:transport');
  3627 +}
  3628 +
  3629 +module.exports = function(availableTransports) {
  3630 + return {
  3631 + filterToEnabled: function(transportsWhitelist, info) {
  3632 + var transports = {
  3633 + main: []
  3634 + , facade: []
  3635 + };
  3636 + if (!transportsWhitelist) {
  3637 + transportsWhitelist = [];
  3638 + } else if (typeof transportsWhitelist === 'string') {
  3639 + transportsWhitelist = [transportsWhitelist];
  3640 + }
  3641 +
  3642 + availableTransports.forEach(function(trans) {
  3643 + if (!trans) {
  3644 + return;
  3645 + }
  3646 +
  3647 + if (trans.transportName === 'websocket' && info.websocket === false) {
  3648 + debug('disabled from server', 'websocket');
  3649 + return;
  3650 + }
  3651 +
  3652 + if (transportsWhitelist.length &&
  3653 + transportsWhitelist.indexOf(trans.transportName) === -1) {
  3654 + debug('not in whitelist', trans.transportName);
  3655 + return;
  3656 + }
  3657 +
  3658 + if (trans.enabled(info)) {
  3659 + debug('enabled', trans.transportName);
  3660 + transports.main.push(trans);
  3661 + if (trans.facadeTransport) {
  3662 + transports.facade.push(trans.facadeTransport);
  3663 + }
  3664 + } else {
  3665 + debug('disabled', trans.transportName);
  3666 + }
  3667 + });
  3668 + return transports;
  3669 + }
  3670 + };
  3671 +};
  3672 +
  3673 +}).call(this,{ env: {} })
  3674 +
  3675 +},{"debug":54}],52:[function(require,module,exports){
  3676 +(function (process){
  3677 +'use strict';
  3678 +
  3679 +var URL = require('url-parse');
  3680 +
  3681 +var debug = function() {};
  3682 +if (process.env.NODE_ENV !== 'production') {
  3683 + debug = require('debug')('sockjs-client:utils:url');
  3684 +}
  3685 +
  3686 +module.exports = {
  3687 + getOrigin: function(url) {
  3688 + if (!url) {
  3689 + return null;
  3690 + }
  3691 +
  3692 + var p = new URL(url);
  3693 + if (p.protocol === 'file:') {
  3694 + return null;
  3695 + }
  3696 +
  3697 + var port = p.port;
  3698 + if (!port) {
  3699 + port = (p.protocol === 'https:') ? '443' : '80';
  3700 + }
  3701 +
  3702 + return p.protocol + '//' + p.hostname + ':' + port;
  3703 + }
  3704 +
  3705 +, isOriginEqual: function(a, b) {
  3706 + var res = this.getOrigin(a) === this.getOrigin(b);
  3707 + debug('same', a, b, res);
  3708 + return res;
  3709 + }
  3710 +
  3711 +, isSchemeEqual: function(a, b) {
  3712 + return (a.split(':')[0] === b.split(':')[0]);
  3713 + }
  3714 +
  3715 +, addPath: function (url, path) {
  3716 + var qs = url.split('?');
  3717 + return qs[0] + path + (qs[1] ? '?' + qs[1] : '');
  3718 + }
  3719 +
  3720 +, addQuery: function (url, q) {
  3721 + return url + (url.indexOf('?') === -1 ? ('?' + q) : ('&' + q));
  3722 + }
  3723 +};
  3724 +
  3725 +}).call(this,{ env: {} })
  3726 +
  3727 +},{"debug":54,"url-parse":61}],53:[function(require,module,exports){
  3728 +module.exports = '1.1.2';
  3729 +
  3730 +},{}],54:[function(require,module,exports){
  3731 +(function (process){
  3732 +/**
  3733 + * This is the web browser implementation of `debug()`.
  3734 + *
  3735 + * Expose `debug()` as the module.
  3736 + */
  3737 +
  3738 +exports = module.exports = require('./debug');
  3739 +exports.log = log;
  3740 +exports.formatArgs = formatArgs;
  3741 +exports.save = save;
  3742 +exports.load = load;
  3743 +exports.useColors = useColors;
  3744 +exports.storage = 'undefined' != typeof chrome
  3745 + && 'undefined' != typeof chrome.storage
  3746 + ? chrome.storage.local
  3747 + : localstorage();
  3748 +
  3749 +/**
  3750 + * Colors.
  3751 + */
  3752 +
  3753 +exports.colors = [
  3754 + 'lightseagreen',
  3755 + 'forestgreen',
  3756 + 'goldenrod',
  3757 + 'dodgerblue',
  3758 + 'darkorchid',
  3759 + 'crimson'
  3760 +];
  3761 +
  3762 +/**
  3763 + * Currently only WebKit-based Web Inspectors, Firefox >= v31,
  3764 + * and the Firebug extension (any Firefox version) are known
  3765 + * to support "%c" CSS customizations.
  3766 + *
  3767 + * TODO: add a `localStorage` variable to explicitly enable/disable colors
  3768 + */
  3769 +
  3770 +function useColors() {
  3771 + // NB: In an Electron preload script, document will be defined but not fully
  3772 + // initialized. Since we know we're in Chrome, we'll just detect this case
  3773 + // explicitly
  3774 + if (typeof window !== 'undefined' && window && typeof window.process !== 'undefined' && window.process.type === 'renderer') {
  3775 + return true;
  3776 + }
  3777 +
  3778 + // is webkit? http://stackoverflow.com/a/16459606/376773
  3779 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
  3780 + return (typeof document !== 'undefined' && document && 'WebkitAppearance' in document.documentElement.style) ||
  3781 + // is firebug? http://stackoverflow.com/a/398120/376773
  3782 + (typeof window !== 'undefined' && window && window.console && (console.firebug || (console.exception && console.table))) ||
  3783 + // is firefox >= v31?
  3784 + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
  3785 + (typeof navigator !== 'undefined' && navigator && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
  3786 + // double check webkit in userAgent just in case we are in a worker
  3787 + (typeof navigator !== 'undefined' && navigator && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
  3788 +}
  3789 +
  3790 +/**
  3791 + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
  3792 + */
  3793 +
  3794 +exports.formatters.j = function(v) {
  3795 + try {
  3796 + return JSON.stringify(v);
  3797 + } catch (err) {
  3798 + return '[UnexpectedJSONParseError]: ' + err.message;
  3799 + }
  3800 +};
  3801 +
  3802 +
  3803 +/**
  3804 + * Colorize log arguments if enabled.
  3805 + *
  3806 + * @api public
  3807 + */
  3808 +
  3809 +function formatArgs(args) {
  3810 + var useColors = this.useColors;
  3811 +
  3812 + args[0] = (useColors ? '%c' : '')
  3813 + + this.namespace
  3814 + + (useColors ? ' %c' : ' ')
  3815 + + args[0]
  3816 + + (useColors ? '%c ' : ' ')
  3817 + + '+' + exports.humanize(this.diff);
  3818 +
  3819 + if (!useColors) return;
  3820 +
  3821 + var c = 'color: ' + this.color;
  3822 + args.splice(1, 0, c, 'color: inherit')
  3823 +
  3824 + // the final "%c" is somewhat tricky, because there could be other
  3825 + // arguments passed either before or after the %c, so we need to
  3826 + // figure out the correct index to insert the CSS into
  3827 + var index = 0;
  3828 + var lastC = 0;
  3829 + args[0].replace(/%[a-zA-Z%]/g, function(match) {
  3830 + if ('%%' === match) return;
  3831 + index++;
  3832 + if ('%c' === match) {
  3833 + // we only are interested in the *last* %c
  3834 + // (the user may have provided their own)
  3835 + lastC = index;
  3836 + }
  3837 + });
  3838 +
  3839 + args.splice(lastC, 0, c);
  3840 +}
  3841 +
  3842 +/**
  3843 + * Invokes `console.log()` when available.
  3844 + * No-op when `console.log` is not a "function".
  3845 + *
  3846 + * @api public
  3847 + */
  3848 +
  3849 +function log() {
  3850 + // this hackery is required for IE8/9, where
  3851 + // the `console.log` function doesn't have 'apply'
  3852 + return 'object' === typeof console
  3853 + && console.log
  3854 + && Function.prototype.apply.call(console.log, console, arguments);
  3855 +}
  3856 +
  3857 +/**
  3858 + * Save `namespaces`.
  3859 + *
  3860 + * @param {String} namespaces
  3861 + * @api private
  3862 + */
  3863 +
  3864 +function save(namespaces) {
  3865 + try {
  3866 + if (null == namespaces) {
  3867 + exports.storage.removeItem('debug');
  3868 + } else {
  3869 + exports.storage.debug = namespaces;
  3870 + }
  3871 + } catch(e) {}
  3872 +}
  3873 +
  3874 +/**
  3875 + * Load `namespaces`.
  3876 + *
  3877 + * @return {String} returns the previously persisted debug modes
  3878 + * @api private
  3879 + */
  3880 +
  3881 +function load() {
  3882 + try {
  3883 + return exports.storage.debug;
  3884 + } catch(e) {}
  3885 +
  3886 + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
  3887 + if (typeof process !== 'undefined' && 'env' in process) {
  3888 + return process.env.DEBUG;
  3889 + }
  3890 +}
  3891 +
  3892 +/**
  3893 + * Enable namespaces listed in `localStorage.debug` initially.
  3894 + */
  3895 +
  3896 +exports.enable(load());
  3897 +
  3898 +/**
  3899 + * Localstorage attempts to return the localstorage.
  3900 + *
  3901 + * This is necessary because safari throws
  3902 + * when a user disables cookies/localstorage
  3903 + * and you attempt to access it.
  3904 + *
  3905 + * @return {LocalStorage}
  3906 + * @api private
  3907 + */
  3908 +
  3909 +function localstorage() {
  3910 + try {
  3911 + return window.localStorage;
  3912 + } catch (e) {}
  3913 +}
  3914 +
  3915 +}).call(this,{ env: {} })
  3916 +
  3917 +},{"./debug":55}],55:[function(require,module,exports){
  3918 +
  3919 +/**
  3920 + * This is the common logic for both the Node.js and web browser
  3921 + * implementations of `debug()`.
  3922 + *
  3923 + * Expose `debug()` as the module.
  3924 + */
  3925 +
  3926 +exports = module.exports = createDebug.debug = createDebug.default = createDebug;
  3927 +exports.coerce = coerce;
  3928 +exports.disable = disable;
  3929 +exports.enable = enable;
  3930 +exports.enabled = enabled;
  3931 +exports.humanize = require('ms');
  3932 +
  3933 +/**
  3934 + * The currently active debug mode names, and names to skip.
  3935 + */
  3936 +
  3937 +exports.names = [];
  3938 +exports.skips = [];
  3939 +
  3940 +/**
  3941 + * Map of special "%n" handling functions, for the debug "format" argument.
  3942 + *
  3943 + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
  3944 + */
  3945 +
  3946 +exports.formatters = {};
  3947 +
  3948 +/**
  3949 + * Previous log timestamp.
  3950 + */
  3951 +
  3952 +var prevTime;
  3953 +
  3954 +/**
  3955 + * Select a color.
  3956 + * @param {String} namespace
  3957 + * @return {Number}
  3958 + * @api private
  3959 + */
  3960 +
  3961 +function selectColor(namespace) {
  3962 + var hash = 0, i;
  3963 +
  3964 + for (i in namespace) {
  3965 + hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
  3966 + hash |= 0; // Convert to 32bit integer
  3967 + }
  3968 +
  3969 + return exports.colors[Math.abs(hash) % exports.colors.length];
  3970 +}
  3971 +
  3972 +/**
  3973 + * Create a debugger with the given `namespace`.
  3974 + *
  3975 + * @param {String} namespace
  3976 + * @return {Function}
  3977 + * @api public
  3978 + */
  3979 +
  3980 +function createDebug(namespace) {
  3981 +
  3982 + function debug() {
  3983 + // disabled?
  3984 + if (!debug.enabled) return;
  3985 +
  3986 + var self = debug;
  3987 +
  3988 + // set `diff` timestamp
  3989 + var curr = +new Date();
  3990 + var ms = curr - (prevTime || curr);
  3991 + self.diff = ms;
  3992 + self.prev = prevTime;
  3993 + self.curr = curr;
  3994 + prevTime = curr;
  3995 +
  3996 + // turn the `arguments` into a proper Array
  3997 + var args = new Array(arguments.length);
  3998 + for (var i = 0; i < args.length; i++) {
  3999 + args[i] = arguments[i];
  4000 + }
  4001 +
  4002 + args[0] = exports.coerce(args[0]);
  4003 +
  4004 + if ('string' !== typeof args[0]) {
  4005 + // anything else let's inspect with %O
  4006 + args.unshift('%O');
  4007 + }
  4008 +
  4009 + // apply any `formatters` transformations
  4010 + var index = 0;
  4011 + args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
  4012 + // if we encounter an escaped % then don't increase the array index
  4013 + if (match === '%%') return match;
  4014 + index++;
  4015 + var formatter = exports.formatters[format];
  4016 + if ('function' === typeof formatter) {
  4017 + var val = args[index];
  4018 + match = formatter.call(self, val);
  4019 +
  4020 + // now we need to remove `args[index]` since it's inlined in the `format`
  4021 + args.splice(index, 1);
  4022 + index--;
  4023 + }
  4024 + return match;
  4025 + });
  4026 +
  4027 + // apply env-specific formatting (colors, etc.)
  4028 + exports.formatArgs.call(self, args);
  4029 +
  4030 + var logFn = debug.log || exports.log || console.log.bind(console);
  4031 + logFn.apply(self, args);
  4032 + }
  4033 +
  4034 + debug.namespace = namespace;
  4035 + debug.enabled = exports.enabled(namespace);
  4036 + debug.useColors = exports.useColors();
  4037 + debug.color = selectColor(namespace);
  4038 +
  4039 + // env-specific initialization logic for debug instances
  4040 + if ('function' === typeof exports.init) {
  4041 + exports.init(debug);
  4042 + }
  4043 +
  4044 + return debug;
  4045 +}
  4046 +
  4047 +/**
  4048 + * Enables a debug mode by namespaces. This can include modes
  4049 + * separated by a colon and wildcards.
  4050 + *
  4051 + * @param {String} namespaces
  4052 + * @api public
  4053 + */
  4054 +
  4055 +function enable(namespaces) {
  4056 + exports.save(namespaces);
  4057 +
  4058 + var split = (namespaces || '').split(/[\s,]+/);
  4059 + var len = split.length;
  4060 +
  4061 + for (var i = 0; i < len; i++) {
  4062 + if (!split[i]) continue; // ignore empty strings
  4063 + namespaces = split[i].replace(/\*/g, '.*?');
  4064 + if (namespaces[0] === '-') {
  4065 + exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
  4066 + } else {
  4067 + exports.names.push(new RegExp('^' + namespaces + '$'));
  4068 + }
  4069 + }
  4070 +}
  4071 +
  4072 +/**
  4073 + * Disable debug output.
  4074 + *
  4075 + * @api public
  4076 + */
  4077 +
  4078 +function disable() {
  4079 + exports.enable('');
  4080 +}
  4081 +
  4082 +/**
  4083 + * Returns true if the given mode name is enabled, false otherwise.
  4084 + *
  4085 + * @param {String} name
  4086 + * @return {Boolean}
  4087 + * @api public
  4088 + */
  4089 +
  4090 +function enabled(name) {
  4091 + var i, len;
  4092 + for (i = 0, len = exports.skips.length; i < len; i++) {
  4093 + if (exports.skips[i].test(name)) {
  4094 + return false;
  4095 + }
  4096 + }
  4097 + for (i = 0, len = exports.names.length; i < len; i++) {
  4098 + if (exports.names[i].test(name)) {
  4099 + return true;
  4100 + }
  4101 + }
  4102 + return false;
  4103 +}
  4104 +
  4105 +/**
  4106 + * Coerce `val`.
  4107 + *
  4108 + * @param {Mixed} val
  4109 + * @return {Mixed}
  4110 + * @api private
  4111 + */
  4112 +
  4113 +function coerce(val) {
  4114 + if (val instanceof Error) return val.stack || val.message;
  4115 + return val;
  4116 +}
  4117 +
  4118 +},{"ms":58}],56:[function(require,module,exports){
  4119 +if (typeof Object.create === 'function') {
  4120 + // implementation from standard node.js 'util' module
  4121 + module.exports = function inherits(ctor, superCtor) {
  4122 + ctor.super_ = superCtor
  4123 + ctor.prototype = Object.create(superCtor.prototype, {
  4124 + constructor: {
  4125 + value: ctor,
  4126 + enumerable: false,
  4127 + writable: true,
  4128 + configurable: true
  4129 + }
  4130 + });
  4131 + };
  4132 +} else {
  4133 + // old school shim for old browsers
  4134 + module.exports = function inherits(ctor, superCtor) {
  4135 + ctor.super_ = superCtor
  4136 + var TempCtor = function () {}
  4137 + TempCtor.prototype = superCtor.prototype
  4138 + ctor.prototype = new TempCtor()
  4139 + ctor.prototype.constructor = ctor
  4140 + }
  4141 +}
  4142 +
  4143 +},{}],57:[function(require,module,exports){
  4144 +(function (global){
  4145 +/*! JSON v3.3.2 | http://bestiejs.github.io/json3 | Copyright 2012-2014, Kit Cambridge | http://kit.mit-license.org */
  4146 +;(function () {
  4147 + // Detect the `define` function exposed by asynchronous module loaders. The
  4148 + // strict `define` check is necessary for compatibility with `r.js`.
  4149 + var isLoader = typeof define === "function" && define.amd;
  4150 +
  4151 + // A set of types used to distinguish objects from primitives.
  4152 + var objectTypes = {
  4153 + "function": true,
  4154 + "object": true
  4155 + };
  4156 +
  4157 + // Detect the `exports` object exposed by CommonJS implementations.
  4158 + var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
  4159 +
  4160 + // Use the `global` object exposed by Node (including Browserify via
  4161 + // `insert-module-globals`), Narwhal, and Ringo as the default context,
  4162 + // and the `window` object in browsers. Rhino exports a `global` function
  4163 + // instead.
  4164 + var root = objectTypes[typeof window] && window || this,
  4165 + freeGlobal = freeExports && objectTypes[typeof module] && module && !module.nodeType && typeof global == "object" && global;
  4166 +
  4167 + if (freeGlobal && (freeGlobal["global"] === freeGlobal || freeGlobal["window"] === freeGlobal || freeGlobal["self"] === freeGlobal)) {
  4168 + root = freeGlobal;
  4169 + }
  4170 +
  4171 + // Public: Initializes JSON 3 using the given `context` object, attaching the
  4172 + // `stringify` and `parse` functions to the specified `exports` object.
  4173 + function runInContext(context, exports) {
  4174 + context || (context = root["Object"]());
  4175 + exports || (exports = root["Object"]());
  4176 +
  4177 + // Native constructor aliases.
  4178 + var Number = context["Number"] || root["Number"],
  4179 + String = context["String"] || root["String"],
  4180 + Object = context["Object"] || root["Object"],
  4181 + Date = context["Date"] || root["Date"],
  4182 + SyntaxError = context["SyntaxError"] || root["SyntaxError"],
  4183 + TypeError = context["TypeError"] || root["TypeError"],
  4184 + Math = context["Math"] || root["Math"],
  4185 + nativeJSON = context["JSON"] || root["JSON"];
  4186 +
  4187 + // Delegate to the native `stringify` and `parse` implementations.
  4188 + if (typeof nativeJSON == "object" && nativeJSON) {
  4189 + exports.stringify = nativeJSON.stringify;
  4190 + exports.parse = nativeJSON.parse;
  4191 + }
  4192 +
  4193 + // Convenience aliases.
  4194 + var objectProto = Object.prototype,
  4195 + getClass = objectProto.toString,
  4196 + isProperty, forEach, undef;
  4197 +
  4198 + // Test the `Date#getUTC*` methods. Based on work by @Yaffle.
  4199 + var isExtended = new Date(-3509827334573292);
  4200 + try {
  4201 + // The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical
  4202 + // results for certain dates in Opera >= 10.53.
  4203 + isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 &&
  4204 + // Safari < 2.0.2 stores the internal millisecond time value correctly,
  4205 + // but clips the values returned by the date methods to the range of
  4206 + // signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]).
  4207 + isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708;
  4208 + } catch (exception) {}
  4209 +
  4210 + // Internal: Determines whether the native `JSON.stringify` and `parse`
  4211 + // implementations are spec-compliant. Based on work by Ken Snyder.
  4212 + function has(name) {
  4213 + if (has[name] !== undef) {
  4214 + // Return cached feature test result.
  4215 + return has[name];
  4216 + }
  4217 + var isSupported;
  4218 + if (name == "bug-string-char-index") {
  4219 + // IE <= 7 doesn't support accessing string characters using square
  4220 + // bracket notation. IE 8 only supports this for primitives.
  4221 + isSupported = "a"[0] != "a";
  4222 + } else if (name == "json") {
  4223 + // Indicates whether both `JSON.stringify` and `JSON.parse` are
  4224 + // supported.
  4225 + isSupported = has("json-stringify") && has("json-parse");
  4226 + } else {
  4227 + var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';
  4228 + // Test `JSON.stringify`.
  4229 + if (name == "json-stringify") {
  4230 + var stringify = exports.stringify, stringifySupported = typeof stringify == "function" && isExtended;
  4231 + if (stringifySupported) {
  4232 + // A test function object with a custom `toJSON` method.
  4233 + (value = function () {
  4234 + return 1;
  4235 + }).toJSON = value;
  4236 + try {
  4237 + stringifySupported =
  4238 + // Firefox 3.1b1 and b2 serialize string, number, and boolean
  4239 + // primitives as object literals.
  4240 + stringify(0) === "0" &&
  4241 + // FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object
  4242 + // literals.
  4243 + stringify(new Number()) === "0" &&
  4244 + stringify(new String()) == '""' &&
  4245 + // FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or
  4246 + // does not define a canonical JSON representation (this applies to
  4247 + // objects with `toJSON` properties as well, *unless* they are nested
  4248 + // within an object or array).
  4249 + stringify(getClass) === undef &&
  4250 + // IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and
  4251 + // FF 3.1b3 pass this test.
  4252 + stringify(undef) === undef &&
  4253 + // Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s,
  4254 + // respectively, if the value is omitted entirely.
  4255 + stringify() === undef &&
  4256 + // FF 3.1b1, 2 throw an error if the given value is not a number,
  4257 + // string, array, object, Boolean, or `null` literal. This applies to
  4258 + // objects with custom `toJSON` methods as well, unless they are nested
  4259 + // inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON`
  4260 + // methods entirely.
  4261 + stringify(value) === "1" &&
  4262 + stringify([value]) == "[1]" &&
  4263 + // Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of
  4264 + // `"[null]"`.
  4265 + stringify([undef]) == "[null]" &&
  4266 + // YUI 3.0.0b1 fails to serialize `null` literals.
  4267 + stringify(null) == "null" &&
  4268 + // FF 3.1b1, 2 halts serialization if an array contains a function:
  4269 + // `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3
  4270 + // elides non-JSON values from objects and arrays, unless they
  4271 + // define custom `toJSON` methods.
  4272 + stringify([undef, getClass, null]) == "[null,null,null]" &&
  4273 + // Simple serialization test. FF 3.1b1 uses Unicode escape sequences
  4274 + // where character escape codes are expected (e.g., `\b` => `\u0008`).
  4275 + stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized &&
  4276 + // FF 3.1b1 and b2 ignore the `filter` and `width` arguments.
  4277 + stringify(null, value) === "1" &&
  4278 + stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" &&
  4279 + // JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly
  4280 + // serialize extended years.
  4281 + stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' &&
  4282 + // The milliseconds are optional in ES 5, but required in 5.1.
  4283 + stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' &&
  4284 + // Firefox <= 11.0 incorrectly serializes years prior to 0 as negative
  4285 + // four-digit years instead of six-digit years. Credits: @Yaffle.
  4286 + stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' &&
  4287 + // Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond
  4288 + // values less than 1000. Credits: @Yaffle.
  4289 + stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"';
  4290 + } catch (exception) {
  4291 + stringifySupported = false;
  4292 + }
  4293 + }
  4294 + isSupported = stringifySupported;
  4295 + }
  4296 + // Test `JSON.parse`.
  4297 + if (name == "json-parse") {
  4298 + var parse = exports.parse;
  4299 + if (typeof parse == "function") {
  4300 + try {
  4301 + // FF 3.1b1, b2 will throw an exception if a bare literal is provided.
  4302 + // Conforming implementations should also coerce the initial argument to
  4303 + // a string prior to parsing.
  4304 + if (parse("0") === 0 && !parse(false)) {
  4305 + // Simple parsing test.
  4306 + value = parse(serialized);
  4307 + var parseSupported = value["a"].length == 5 && value["a"][0] === 1;
  4308 + if (parseSupported) {
  4309 + try {
  4310 + // Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings.
  4311 + parseSupported = !parse('"\t"');
  4312 + } catch (exception) {}
  4313 + if (parseSupported) {
  4314 + try {
  4315 + // FF 4.0 and 4.0.1 allow leading `+` signs and leading
  4316 + // decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow
  4317 + // certain octal literals.
  4318 + parseSupported = parse("01") !== 1;
  4319 + } catch (exception) {}
  4320 + }
  4321 + if (parseSupported) {
  4322 + try {
  4323 + // FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal
  4324 + // points. These environments, along with FF 3.1b1 and 2,
  4325 + // also allow trailing commas in JSON objects and arrays.
  4326 + parseSupported = parse("1.") !== 1;
  4327 + } catch (exception) {}
  4328 + }
  4329 + }
  4330 + }
  4331 + } catch (exception) {
  4332 + parseSupported = false;
  4333 + }
  4334 + }
  4335 + isSupported = parseSupported;
  4336 + }
  4337 + }
  4338 + return has[name] = !!isSupported;
  4339 + }
  4340 +
  4341 + if (!has("json")) {
  4342 + // Common `[[Class]]` name aliases.
  4343 + var functionClass = "[object Function]",
  4344 + dateClass = "[object Date]",
  4345 + numberClass = "[object Number]",
  4346 + stringClass = "[object String]",
  4347 + arrayClass = "[object Array]",
  4348 + booleanClass = "[object Boolean]";
  4349 +
  4350 + // Detect incomplete support for accessing string characters by index.
  4351 + var charIndexBuggy = has("bug-string-char-index");
  4352 +
  4353 + // Define additional utility methods if the `Date` methods are buggy.
  4354 + if (!isExtended) {
  4355 + var floor = Math.floor;
  4356 + // A mapping between the months of the year and the number of days between
  4357 + // January 1st and the first of the respective month.
  4358 + var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
  4359 + // Internal: Calculates the number of days between the Unix epoch and the
  4360 + // first day of the given month.
  4361 + var getDay = function (year, month) {
  4362 + return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400);
  4363 + };
  4364 + }
  4365 +
  4366 + // Internal: Determines if a property is a direct property of the given
  4367 + // object. Delegates to the native `Object#hasOwnProperty` method.
  4368 + if (!(isProperty = objectProto.hasOwnProperty)) {
  4369 + isProperty = function (property) {
  4370 + var members = {}, constructor;
  4371 + if ((members.__proto__ = null, members.__proto__ = {
  4372 + // The *proto* property cannot be set multiple times in recent
  4373 + // versions of Firefox and SeaMonkey.
  4374 + "toString": 1
  4375 + }, members).toString != getClass) {
  4376 + // Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but
  4377 + // supports the mutable *proto* property.
  4378 + isProperty = function (property) {
  4379 + // Capture and break the object's prototype chain (see section 8.6.2
  4380 + // of the ES 5.1 spec). The parenthesized expression prevents an
  4381 + // unsafe transformation by the Closure Compiler.
  4382 + var original = this.__proto__, result = property in (this.__proto__ = null, this);
  4383 + // Restore the original prototype chain.
  4384 + this.__proto__ = original;
  4385 + return result;
  4386 + };
  4387 + } else {
  4388 + // Capture a reference to the top-level `Object` constructor.
  4389 + constructor = members.constructor;
  4390 + // Use the `constructor` property to simulate `Object#hasOwnProperty` in
  4391 + // other environments.
  4392 + isProperty = function (property) {
  4393 + var parent = (this.constructor || constructor).prototype;
  4394 + return property in this && !(property in parent && this[property] === parent[property]);
  4395 + };
  4396 + }
  4397 + members = null;
  4398 + return isProperty.call(this, property);
  4399 + };
  4400 + }
  4401 +
  4402 + // Internal: Normalizes the `for...in` iteration algorithm across
  4403 + // environments. Each enumerated key is yielded to a `callback` function.
  4404 + forEach = function (object, callback) {
  4405 + var size = 0, Properties, members, property;
  4406 +
  4407 + // Tests for bugs in the current environment's `for...in` algorithm. The
  4408 + // `valueOf` property inherits the non-enumerable flag from
  4409 + // `Object.prototype` in older versions of IE, Netscape, and Mozilla.
  4410 + (Properties = function () {
  4411 + this.valueOf = 0;
  4412 + }).prototype.valueOf = 0;
  4413 +
  4414 + // Iterate over a new instance of the `Properties` class.
  4415 + members = new Properties();
  4416 + for (property in members) {
  4417 + // Ignore all properties inherited from `Object.prototype`.
  4418 + if (isProperty.call(members, property)) {
  4419 + size++;
  4420 + }
  4421 + }
  4422 + Properties = members = null;
  4423 +
  4424 + // Normalize the iteration algorithm.
  4425 + if (!size) {
  4426 + // A list of non-enumerable properties inherited from `Object.prototype`.
  4427 + members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"];
  4428 + // IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable
  4429 + // properties.
  4430 + forEach = function (object, callback) {
  4431 + var isFunction = getClass.call(object) == functionClass, property, length;
  4432 + var hasProperty = !isFunction && typeof object.constructor != "function" && objectTypes[typeof object.hasOwnProperty] && object.hasOwnProperty || isProperty;
  4433 + for (property in object) {
  4434 + // Gecko <= 1.0 enumerates the `prototype` property of functions under
  4435 + // certain conditions; IE does not.
  4436 + if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) {
  4437 + callback(property);
  4438 + }
  4439 + }
  4440 + // Manually invoke the callback for each non-enumerable property.
  4441 + for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property));
  4442 + };
  4443 + } else if (size == 2) {
  4444 + // Safari <= 2.0.4 enumerates shadowed properties twice.
  4445 + forEach = function (object, callback) {
  4446 + // Create a set of iterated properties.
  4447 + var members = {}, isFunction = getClass.call(object) == functionClass, property;
  4448 + for (property in object) {
  4449 + // Store each property name to prevent double enumeration. The
  4450 + // `prototype` property of functions is not enumerated due to cross-
  4451 + // environment inconsistencies.
  4452 + if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) {
  4453 + callback(property);
  4454 + }
  4455 + }
  4456 + };
  4457 + } else {
  4458 + // No bugs detected; use the standard `for...in` algorithm.
  4459 + forEach = function (object, callback) {
  4460 + var isFunction = getClass.call(object) == functionClass, property, isConstructor;
  4461 + for (property in object) {
  4462 + if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) {
  4463 + callback(property);
  4464 + }
  4465 + }
  4466 + // Manually invoke the callback for the `constructor` property due to
  4467 + // cross-environment inconsistencies.
  4468 + if (isConstructor || isProperty.call(object, (property = "constructor"))) {
  4469 + callback(property);
  4470 + }
  4471 + };
  4472 + }
  4473 + return forEach(object, callback);
  4474 + };
  4475 +
  4476 + // Public: Serializes a JavaScript `value` as a JSON string. The optional
  4477 + // `filter` argument may specify either a function that alters how object and
  4478 + // array members are serialized, or an array of strings and numbers that
  4479 + // indicates which properties should be serialized. The optional `width`
  4480 + // argument may be either a string or number that specifies the indentation
  4481 + // level of the output.
  4482 + if (!has("json-stringify")) {
  4483 + // Internal: A map of control characters and their escaped equivalents.
  4484 + var Escapes = {
  4485 + 92: "\\\\",
  4486 + 34: '\\"',
  4487 + 8: "\\b",
  4488 + 12: "\\f",
  4489 + 10: "\\n",
  4490 + 13: "\\r",
  4491 + 9: "\\t"
  4492 + };
  4493 +
  4494 + // Internal: Converts `value` into a zero-padded string such that its
  4495 + // length is at least equal to `width`. The `width` must be <= 6.
  4496 + var leadingZeroes = "000000";
  4497 + var toPaddedString = function (width, value) {
  4498 + // The `|| 0` expression is necessary to work around a bug in
  4499 + // Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`.
  4500 + return (leadingZeroes + (value || 0)).slice(-width);
  4501 + };
  4502 +
  4503 + // Internal: Double-quotes a string `value`, replacing all ASCII control
  4504 + // characters (characters with code unit values between 0 and 31) with
  4505 + // their escaped equivalents. This is an implementation of the
  4506 + // `Quote(value)` operation defined in ES 5.1 section 15.12.3.
  4507 + var unicodePrefix = "\\u00";
  4508 + var quote = function (value) {
  4509 + var result = '"', index = 0, length = value.length, useCharIndex = !charIndexBuggy || length > 10;
  4510 + var symbols = useCharIndex && (charIndexBuggy ? value.split("") : value);
  4511 + for (; index < length; index++) {
  4512 + var charCode = value.charCodeAt(index);
  4513 + // If the character is a control character, append its Unicode or
  4514 + // shorthand escape sequence; otherwise, append the character as-is.
  4515 + switch (charCode) {
  4516 + case 8: case 9: case 10: case 12: case 13: case 34: case 92:
  4517 + result += Escapes[charCode];
  4518 + break;
  4519 + default:
  4520 + if (charCode < 32) {
  4521 + result += unicodePrefix + toPaddedString(2, charCode.toString(16));
  4522 + break;
  4523 + }
  4524 + result += useCharIndex ? symbols[index] : value.charAt(index);
  4525 + }
  4526 + }
  4527 + return result + '"';
  4528 + };
  4529 +
  4530 + // Internal: Recursively serializes an object. Implements the
  4531 + // `Str(key, holder)`, `JO(value)`, and `JA(value)` operations.
  4532 + var serialize = function (property, object, callback, properties, whitespace, indentation, stack) {
  4533 + var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result;
  4534 + try {
  4535 + // Necessary for host object support.
  4536 + value = object[property];
  4537 + } catch (exception) {}
  4538 + if (typeof value == "object" && value) {
  4539 + className = getClass.call(value);
  4540 + if (className == dateClass && !isProperty.call(value, "toJSON")) {
  4541 + if (value > -1 / 0 && value < 1 / 0) {
  4542 + // Dates are serialized according to the `Date#toJSON` method
  4543 + // specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15
  4544 + // for the ISO 8601 date time string format.
  4545 + if (getDay) {
  4546 + // Manually compute the year, month, date, hours, minutes,
  4547 + // seconds, and milliseconds if the `getUTC*` methods are
  4548 + // buggy. Adapted from @Yaffle's `date-shim` project.
  4549 + date = floor(value / 864e5);
  4550 + for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++);
  4551 + for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++);
  4552 + date = 1 + date - getDay(year, month);
  4553 + // The `time` value specifies the time within the day (see ES
  4554 + // 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used
  4555 + // to compute `A modulo B`, as the `%` operator does not
  4556 + // correspond to the `modulo` operation for negative numbers.
  4557 + time = (value % 864e5 + 864e5) % 864e5;
  4558 + // The hours, minutes, seconds, and milliseconds are obtained by
  4559 + // decomposing the time within the day. See section 15.9.1.10.
  4560 + hours = floor(time / 36e5) % 24;
  4561 + minutes = floor(time / 6e4) % 60;
  4562 + seconds = floor(time / 1e3) % 60;
  4563 + milliseconds = time % 1e3;
  4564 + } else {
  4565 + year = value.getUTCFullYear();
  4566 + month = value.getUTCMonth();
  4567 + date = value.getUTCDate();
  4568 + hours = value.getUTCHours();
  4569 + minutes = value.getUTCMinutes();
  4570 + seconds = value.getUTCSeconds();
  4571 + milliseconds = value.getUTCMilliseconds();
  4572 + }
  4573 + // Serialize extended years correctly.
  4574 + value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) +
  4575 + "-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) +
  4576 + // Months, dates, hours, minutes, and seconds should have two
  4577 + // digits; milliseconds should have three.
  4578 + "T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) +
  4579 + // Milliseconds are optional in ES 5.0, but required in 5.1.
  4580 + "." + toPaddedString(3, milliseconds) + "Z";
  4581 + } else {
  4582 + value = null;
  4583 + }
  4584 + } else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) {
  4585 + // Prototype <= 1.6.1 adds non-standard `toJSON` methods to the
  4586 + // `Number`, `String`, `Date`, and `Array` prototypes. JSON 3
  4587 + // ignores all `toJSON` methods on these objects unless they are
  4588 + // defined directly on an instance.
  4589 + value = value.toJSON(property);
  4590 + }
  4591 + }
  4592 + if (callback) {
  4593 + // If a replacement function was provided, call it to obtain the value
  4594 + // for serialization.
  4595 + value = callback.call(object, property, value);
  4596 + }
  4597 + if (value === null) {
  4598 + return "null";
  4599 + }
  4600 + className = getClass.call(value);
  4601 + if (className == booleanClass) {
  4602 + // Booleans are represented literally.
  4603 + return "" + value;
  4604 + } else if (className == numberClass) {
  4605 + // JSON numbers must be finite. `Infinity` and `NaN` are serialized as
  4606 + // `"null"`.
  4607 + return value > -1 / 0 && value < 1 / 0 ? "" + value : "null";
  4608 + } else if (className == stringClass) {
  4609 + // Strings are double-quoted and escaped.
  4610 + return quote("" + value);
  4611 + }
  4612 + // Recursively serialize objects and arrays.
  4613 + if (typeof value == "object") {
  4614 + // Check for cyclic structures. This is a linear search; performance
  4615 + // is inversely proportional to the number of unique nested objects.
  4616 + for (length = stack.length; length--;) {
  4617 + if (stack[length] === value) {
  4618 + // Cyclic structures cannot be serialized by `JSON.stringify`.
  4619 + throw TypeError();
  4620 + }
  4621 + }
  4622 + // Add the object to the stack of traversed objects.
  4623 + stack.push(value);
  4624 + results = [];
  4625 + // Save the current indentation level and indent one additional level.
  4626 + prefix = indentation;
  4627 + indentation += whitespace;
  4628 + if (className == arrayClass) {
  4629 + // Recursively serialize array elements.
  4630 + for (index = 0, length = value.length; index < length; index++) {
  4631 + element = serialize(index, value, callback, properties, whitespace, indentation, stack);
  4632 + results.push(element === undef ? "null" : element);
  4633 + }
  4634 + result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]";
  4635 + } else {
  4636 + // Recursively serialize object members. Members are selected from
  4637 + // either a user-specified list of property names, or the object
  4638 + // itself.
  4639 + forEach(properties || value, function (property) {
  4640 + var element = serialize(property, value, callback, properties, whitespace, indentation, stack);
  4641 + if (element !== undef) {
  4642 + // According to ES 5.1 section 15.12.3: "If `gap` {whitespace}
  4643 + // is not the empty string, let `member` {quote(property) + ":"}
  4644 + // be the concatenation of `member` and the `space` character."
  4645 + // The "`space` character" refers to the literal space
  4646 + // character, not the `space` {width} argument provided to
  4647 + // `JSON.stringify`.
  4648 + results.push(quote(property) + ":" + (whitespace ? " " : "") + element);
  4649 + }
  4650 + });
  4651 + result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}";
  4652 + }
  4653 + // Remove the object from the traversed object stack.
  4654 + stack.pop();
  4655 + return result;
  4656 + }
  4657 + };
  4658 +
  4659 + // Public: `JSON.stringify`. See ES 5.1 section 15.12.3.
  4660 + exports.stringify = function (source, filter, width) {
  4661 + var whitespace, callback, properties, className;
  4662 + if (objectTypes[typeof filter] && filter) {
  4663 + if ((className = getClass.call(filter)) == functionClass) {
  4664 + callback = filter;
  4665 + } else if (className == arrayClass) {
  4666 + // Convert the property names array into a makeshift set.
  4667 + properties = {};
  4668 + for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1));
  4669 + }
  4670 + }
  4671 + if (width) {
  4672 + if ((className = getClass.call(width)) == numberClass) {
  4673 + // Convert the `width` to an integer and create a string containing
  4674 + // `width` number of space characters.
  4675 + if ((width -= width % 1) > 0) {
  4676 + for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " ");
  4677 + }
  4678 + } else if (className == stringClass) {
  4679 + whitespace = width.length <= 10 ? width : width.slice(0, 10);
  4680 + }
  4681 + }
  4682 + // Opera <= 7.54u2 discards the values associated with empty string keys
  4683 + // (`""`) only if they are used directly within an object member list
  4684 + // (e.g., `!("" in { "": 1})`).
  4685 + return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []);
  4686 + };
  4687 + }
  4688 +
  4689 + // Public: Parses a JSON source string.
  4690 + if (!has("json-parse")) {
  4691 + var fromCharCode = String.fromCharCode;
  4692 +
  4693 + // Internal: A map of escaped control characters and their unescaped
  4694 + // equivalents.
  4695 + var Unescapes = {
  4696 + 92: "\\",
  4697 + 34: '"',
  4698 + 47: "/",
  4699 + 98: "\b",
  4700 + 116: "\t",
  4701 + 110: "\n",
  4702 + 102: "\f",
  4703 + 114: "\r"
  4704 + };
  4705 +
  4706 + // Internal: Stores the parser state.
  4707 + var Index, Source;
  4708 +
  4709 + // Internal: Resets the parser state and throws a `SyntaxError`.
  4710 + var abort = function () {
  4711 + Index = Source = null;
  4712 + throw SyntaxError();
  4713 + };
  4714 +
  4715 + // Internal: Returns the next token, or `"$"` if the parser has reached
  4716 + // the end of the source string. A token may be a string, number, `null`
  4717 + // literal, or Boolean literal.
  4718 + var lex = function () {
  4719 + var source = Source, length = source.length, value, begin, position, isSigned, charCode;
  4720 + while (Index < length) {
  4721 + charCode = source.charCodeAt(Index);
  4722 + switch (charCode) {
  4723 + case 9: case 10: case 13: case 32:
  4724 + // Skip whitespace tokens, including tabs, carriage returns, line
  4725 + // feeds, and space characters.
  4726 + Index++;
  4727 + break;
  4728 + case 123: case 125: case 91: case 93: case 58: case 44:
  4729 + // Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at
  4730 + // the current position.
  4731 + value = charIndexBuggy ? source.charAt(Index) : source[Index];
  4732 + Index++;
  4733 + return value;
  4734 + case 34:
  4735 + // `"` delimits a JSON string; advance to the next character and
  4736 + // begin parsing the string. String tokens are prefixed with the
  4737 + // sentinel `@` character to distinguish them from punctuators and
  4738 + // end-of-string tokens.
  4739 + for (value = "@", Index++; Index < length;) {
  4740 + charCode = source.charCodeAt(Index);
  4741 + if (charCode < 32) {
  4742 + // Unescaped ASCII control characters (those with a code unit
  4743 + // less than the space character) are not permitted.
  4744 + abort();
  4745 + } else if (charCode == 92) {
  4746 + // A reverse solidus (`\`) marks the beginning of an escaped
  4747 + // control character (including `"`, `\`, and `/`) or Unicode
  4748 + // escape sequence.
  4749 + charCode = source.charCodeAt(++Index);
  4750 + switch (charCode) {
  4751 + case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114:
  4752 + // Revive escaped control characters.
  4753 + value += Unescapes[charCode];
  4754 + Index++;
  4755 + break;
  4756 + case 117:
  4757 + // `\u` marks the beginning of a Unicode escape sequence.
  4758 + // Advance to the first character and validate the
  4759 + // four-digit code point.
  4760 + begin = ++Index;
  4761 + for (position = Index + 4; Index < position; Index++) {
  4762 + charCode = source.charCodeAt(Index);
  4763 + // A valid sequence comprises four hexdigits (case-
  4764 + // insensitive) that form a single hexadecimal value.
  4765 + if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) {
  4766 + // Invalid Unicode escape sequence.
  4767 + abort();
  4768 + }
  4769 + }
  4770 + // Revive the escaped character.
  4771 + value += fromCharCode("0x" + source.slice(begin, Index));
  4772 + break;
  4773 + default:
  4774 + // Invalid escape sequence.
  4775 + abort();
  4776 + }
  4777 + } else {
  4778 + if (charCode == 34) {
  4779 + // An unescaped double-quote character marks the end of the
  4780 + // string.
  4781 + break;
  4782 + }
  4783 + charCode = source.charCodeAt(Index);
  4784 + begin = Index;
  4785 + // Optimize for the common case where a string is valid.
  4786 + while (charCode >= 32 && charCode != 92 && charCode != 34) {
  4787 + charCode = source.charCodeAt(++Index);
  4788 + }
  4789 + // Append the string as-is.
  4790 + value += source.slice(begin, Index);
  4791 + }
  4792 + }
  4793 + if (source.charCodeAt(Index) == 34) {
  4794 + // Advance to the next character and return the revived string.
  4795 + Index++;
  4796 + return value;
  4797 + }
  4798 + // Unterminated string.
  4799 + abort();
  4800 + default:
  4801 + // Parse numbers and literals.
  4802 + begin = Index;
  4803 + // Advance past the negative sign, if one is specified.
  4804 + if (charCode == 45) {
  4805 + isSigned = true;
  4806 + charCode = source.charCodeAt(++Index);
  4807 + }
  4808 + // Parse an integer or floating-point value.
  4809 + if (charCode >= 48 && charCode <= 57) {
  4810 + // Leading zeroes are interpreted as octal literals.
  4811 + if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) {
  4812 + // Illegal octal literal.
  4813 + abort();
  4814 + }
  4815 + isSigned = false;
  4816 + // Parse the integer component.
  4817 + for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++);
  4818 + // Floats cannot contain a leading decimal point; however, this
  4819 + // case is already accounted for by the parser.
  4820 + if (source.charCodeAt(Index) == 46) {
  4821 + position = ++Index;
  4822 + // Parse the decimal component.
  4823 + for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
  4824 + if (position == Index) {
  4825 + // Illegal trailing decimal.
  4826 + abort();
  4827 + }
  4828 + Index = position;
  4829 + }
  4830 + // Parse exponents. The `e` denoting the exponent is
  4831 + // case-insensitive.
  4832 + charCode = source.charCodeAt(Index);
  4833 + if (charCode == 101 || charCode == 69) {
  4834 + charCode = source.charCodeAt(++Index);
  4835 + // Skip past the sign following the exponent, if one is
  4836 + // specified.
  4837 + if (charCode == 43 || charCode == 45) {
  4838 + Index++;
  4839 + }
  4840 + // Parse the exponential component.
  4841 + for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
  4842 + if (position == Index) {
  4843 + // Illegal empty exponent.
  4844 + abort();
  4845 + }
  4846 + Index = position;
  4847 + }
  4848 + // Coerce the parsed value to a JavaScript number.
  4849 + return +source.slice(begin, Index);
  4850 + }
  4851 + // A negative sign may only precede numbers.
  4852 + if (isSigned) {
  4853 + abort();
  4854 + }
  4855 + // `true`, `false`, and `null` literals.
  4856 + if (source.slice(Index, Index + 4) == "true") {
  4857 + Index += 4;
  4858 + return true;
  4859 + } else if (source.slice(Index, Index + 5) == "false") {
  4860 + Index += 5;
  4861 + return false;
  4862 + } else if (source.slice(Index, Index + 4) == "null") {
  4863 + Index += 4;
  4864 + return null;
  4865 + }
  4866 + // Unrecognized token.
  4867 + abort();
  4868 + }
  4869 + }
  4870 + // Return the sentinel `$` character if the parser has reached the end
  4871 + // of the source string.
  4872 + return "$";
  4873 + };
  4874 +
  4875 + // Internal: Parses a JSON `value` token.
  4876 + var get = function (value) {
  4877 + var results, hasMembers;
  4878 + if (value == "$") {
  4879 + // Unexpected end of input.
  4880 + abort();
  4881 + }
  4882 + if (typeof value == "string") {
  4883 + if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") {
  4884 + // Remove the sentinel `@` character.
  4885 + return value.slice(1);
  4886 + }
  4887 + // Parse object and array literals.
  4888 + if (value == "[") {
  4889 + // Parses a JSON array, returning a new JavaScript array.
  4890 + results = [];
  4891 + for (;; hasMembers || (hasMembers = true)) {
  4892 + value = lex();
  4893 + // A closing square bracket marks the end of the array literal.
  4894 + if (value == "]") {
  4895 + break;
  4896 + }
  4897 + // If the array literal contains elements, the current token
  4898 + // should be a comma separating the previous element from the
  4899 + // next.
  4900 + if (hasMembers) {
  4901 + if (value == ",") {
  4902 + value = lex();
  4903 + if (value == "]") {
  4904 + // Unexpected trailing `,` in array literal.
  4905 + abort();
  4906 + }
  4907 + } else {
  4908 + // A `,` must separate each array element.
  4909 + abort();
  4910 + }
  4911 + }
  4912 + // Elisions and leading commas are not permitted.
  4913 + if (value == ",") {
  4914 + abort();
  4915 + }
  4916 + results.push(get(value));
  4917 + }
  4918 + return results;
  4919 + } else if (value == "{") {
  4920 + // Parses a JSON object, returning a new JavaScript object.
  4921 + results = {};
  4922 + for (;; hasMembers || (hasMembers = true)) {
  4923 + value = lex();
  4924 + // A closing curly brace marks the end of the object literal.
  4925 + if (value == "}") {
  4926 + break;
  4927 + }
  4928 + // If the object literal contains members, the current token
  4929 + // should be a comma separator.
  4930 + if (hasMembers) {
  4931 + if (value == ",") {
  4932 + value = lex();
  4933 + if (value == "}") {
  4934 + // Unexpected trailing `,` in object literal.
  4935 + abort();
  4936 + }
  4937 + } else {
  4938 + // A `,` must separate each object member.
  4939 + abort();
  4940 + }
  4941 + }
  4942 + // Leading commas are not permitted, object property names must be
  4943 + // double-quoted strings, and a `:` must separate each property
  4944 + // name and value.
  4945 + if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") {
  4946 + abort();
  4947 + }
  4948 + results[value.slice(1)] = get(lex());
  4949 + }
  4950 + return results;
  4951 + }
  4952 + // Unexpected token encountered.
  4953 + abort();
  4954 + }
  4955 + return value;
  4956 + };
  4957 +
  4958 + // Internal: Updates a traversed object member.
  4959 + var update = function (source, property, callback) {
  4960 + var element = walk(source, property, callback);
  4961 + if (element === undef) {
  4962 + delete source[property];
  4963 + } else {
  4964 + source[property] = element;
  4965 + }
  4966 + };
  4967 +
  4968 + // Internal: Recursively traverses a parsed JSON object, invoking the
  4969 + // `callback` function for each value. This is an implementation of the
  4970 + // `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2.
  4971 + var walk = function (source, property, callback) {
  4972 + var value = source[property], length;
  4973 + if (typeof value == "object" && value) {
  4974 + // `forEach` can't be used to traverse an array in Opera <= 8.54
  4975 + // because its `Object#hasOwnProperty` implementation returns `false`
  4976 + // for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`).
  4977 + if (getClass.call(value) == arrayClass) {
  4978 + for (length = value.length; length--;) {
  4979 + update(value, length, callback);
  4980 + }
  4981 + } else {
  4982 + forEach(value, function (property) {
  4983 + update(value, property, callback);
  4984 + });
  4985 + }
  4986 + }
  4987 + return callback.call(source, property, value);
  4988 + };
  4989 +
  4990 + // Public: `JSON.parse`. See ES 5.1 section 15.12.2.
  4991 + exports.parse = function (source, callback) {
  4992 + var result, value;
  4993 + Index = 0;
  4994 + Source = "" + source;
  4995 + result = get(lex());
  4996 + // If a JSON string contains multiple tokens, it is invalid.
  4997 + if (lex() != "$") {
  4998 + abort();
  4999 + }
  5000 + // Reset the parser state.
  5001 + Index = Source = null;
  5002 + return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result;
  5003 + };
  5004 + }
  5005 + }
  5006 +
  5007 + exports["runInContext"] = runInContext;
  5008 + return exports;
  5009 + }
  5010 +
  5011 + if (freeExports && !isLoader) {
  5012 + // Export for CommonJS environments.
  5013 + runInContext(root, freeExports);
  5014 + } else {
  5015 + // Export for web browsers and JavaScript engines.
  5016 + var nativeJSON = root.JSON,
  5017 + previousJSON = root["JSON3"],
  5018 + isRestored = false;
  5019 +
  5020 + var JSON3 = runInContext(root, (root["JSON3"] = {
  5021 + // Public: Restores the original value of the global `JSON` object and
  5022 + // returns a reference to the `JSON3` object.
  5023 + "noConflict": function () {
  5024 + if (!isRestored) {
  5025 + isRestored = true;
  5026 + root.JSON = nativeJSON;
  5027 + root["JSON3"] = previousJSON;
  5028 + nativeJSON = previousJSON = null;
  5029 + }
  5030 + return JSON3;
  5031 + }
  5032 + }));
  5033 +
  5034 + root.JSON = {
  5035 + "parse": JSON3.parse,
  5036 + "stringify": JSON3.stringify
  5037 + };
  5038 + }
  5039 +
  5040 + // Export for asynchronous module loaders.
  5041 + if (isLoader) {
  5042 + define(function () {
  5043 + return JSON3;
  5044 + });
  5045 + }
  5046 +}).call(this);
  5047 +
  5048 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  5049 +
  5050 +},{}],58:[function(require,module,exports){
  5051 +/**
  5052 + * Helpers.
  5053 + */
  5054 +
  5055 +var s = 1000
  5056 +var m = s * 60
  5057 +var h = m * 60
  5058 +var d = h * 24
  5059 +var y = d * 365.25
  5060 +
  5061 +/**
  5062 + * Parse or format the given `val`.
  5063 + *
  5064 + * Options:
  5065 + *
  5066 + * - `long` verbose formatting [false]
  5067 + *
  5068 + * @param {String|Number} val
  5069 + * @param {Object} options
  5070 + * @throws {Error} throw an error if val is not a non-empty string or a number
  5071 + * @return {String|Number}
  5072 + * @api public
  5073 + */
  5074 +
  5075 +module.exports = function (val, options) {
  5076 + options = options || {}
  5077 + var type = typeof val
  5078 + if (type === 'string' && val.length > 0) {
  5079 + return parse(val)
  5080 + } else if (type === 'number' && isNaN(val) === false) {
  5081 + return options.long ?
  5082 + fmtLong(val) :
  5083 + fmtShort(val)
  5084 + }
  5085 + throw new Error('val is not a non-empty string or a valid number. val=' + JSON.stringify(val))
  5086 +}
  5087 +
  5088 +/**
  5089 + * Parse the given `str` and return milliseconds.
  5090 + *
  5091 + * @param {String} str
  5092 + * @return {Number}
  5093 + * @api private
  5094 + */
  5095 +
  5096 +function parse(str) {
  5097 + str = String(str)
  5098 + if (str.length > 10000) {
  5099 + return
  5100 + }
  5101 + var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str)
  5102 + if (!match) {
  5103 + return
  5104 + }
  5105 + var n = parseFloat(match[1])
  5106 + var type = (match[2] || 'ms').toLowerCase()
  5107 + switch (type) {
  5108 + case 'years':
  5109 + case 'year':
  5110 + case 'yrs':
  5111 + case 'yr':
  5112 + case 'y':
  5113 + return n * y
  5114 + case 'days':
  5115 + case 'day':
  5116 + case 'd':
  5117 + return n * d
  5118 + case 'hours':
  5119 + case 'hour':
  5120 + case 'hrs':
  5121 + case 'hr':
  5122 + case 'h':
  5123 + return n * h
  5124 + case 'minutes':
  5125 + case 'minute':
  5126 + case 'mins':
  5127 + case 'min':
  5128 + case 'm':
  5129 + return n * m
  5130 + case 'seconds':
  5131 + case 'second':
  5132 + case 'secs':
  5133 + case 'sec':
  5134 + case 's':
  5135 + return n * s
  5136 + case 'milliseconds':
  5137 + case 'millisecond':
  5138 + case 'msecs':
  5139 + case 'msec':
  5140 + case 'ms':
  5141 + return n
  5142 + default:
  5143 + return undefined
  5144 + }
  5145 +}
  5146 +
  5147 +/**
  5148 + * Short format for `ms`.
  5149 + *
  5150 + * @param {Number} ms
  5151 + * @return {String}
  5152 + * @api private
  5153 + */
  5154 +
  5155 +function fmtShort(ms) {
  5156 + if (ms >= d) {
  5157 + return Math.round(ms / d) + 'd'
  5158 + }
  5159 + if (ms >= h) {
  5160 + return Math.round(ms / h) + 'h'
  5161 + }
  5162 + if (ms >= m) {
  5163 + return Math.round(ms / m) + 'm'
  5164 + }
  5165 + if (ms >= s) {
  5166 + return Math.round(ms / s) + 's'
  5167 + }
  5168 + return ms + 'ms'
  5169 +}
  5170 +
  5171 +/**
  5172 + * Long format for `ms`.
  5173 + *
  5174 + * @param {Number} ms
  5175 + * @return {String}
  5176 + * @api private
  5177 + */
  5178 +
  5179 +function fmtLong(ms) {
  5180 + return plural(ms, d, 'day') ||
  5181 + plural(ms, h, 'hour') ||
  5182 + plural(ms, m, 'minute') ||
  5183 + plural(ms, s, 'second') ||
  5184 + ms + ' ms'
  5185 +}
  5186 +
  5187 +/**
  5188 + * Pluralization helper.
  5189 + */
  5190 +
  5191 +function plural(ms, n, name) {
  5192 + if (ms < n) {
  5193 + return
  5194 + }
  5195 + if (ms < n * 1.5) {
  5196 + return Math.floor(ms / n) + ' ' + name
  5197 + }
  5198 + return Math.ceil(ms / n) + ' ' + name + 's'
  5199 +}
  5200 +
  5201 +},{}],59:[function(require,module,exports){
  5202 +'use strict';
  5203 +
  5204 +var has = Object.prototype.hasOwnProperty;
  5205 +
  5206 +/**
  5207 + * Simple query string parser.
  5208 + *
  5209 + * @param {String} query The query string that needs to be parsed.
  5210 + * @returns {Object}
  5211 + * @api public
  5212 + */
  5213 +function querystring(query) {
  5214 + var parser = /([^=?&]+)=?([^&]*)/g
  5215 + , result = {}
  5216 + , part;
  5217 +
  5218 + //
  5219 + // Little nifty parsing hack, leverage the fact that RegExp.exec increments
  5220 + // the lastIndex property so we can continue executing this loop until we've
  5221 + // parsed all results.
  5222 + //
  5223 + for (;
  5224 + part = parser.exec(query);
  5225 + result[decodeURIComponent(part[1])] = decodeURIComponent(part[2])
  5226 + );
  5227 +
  5228 + return result;
  5229 +}
  5230 +
  5231 +/**
  5232 + * Transform a query string to an object.
  5233 + *
  5234 + * @param {Object} obj Object that should be transformed.
  5235 + * @param {String} prefix Optional prefix.
  5236 + * @returns {String}
  5237 + * @api public
  5238 + */
  5239 +function querystringify(obj, prefix) {
  5240 + prefix = prefix || '';
  5241 +
  5242 + var pairs = [];
  5243 +
  5244 + //
  5245 + // Optionally prefix with a '?' if needed
  5246 + //
  5247 + if ('string' !== typeof prefix) prefix = '?';
  5248 +
  5249 + for (var key in obj) {
  5250 + if (has.call(obj, key)) {
  5251 + pairs.push(encodeURIComponent(key) +'='+ encodeURIComponent(obj[key]));
  5252 + }
  5253 + }
  5254 +
  5255 + return pairs.length ? prefix + pairs.join('&') : '';
  5256 +}
  5257 +
  5258 +//
  5259 +// Expose the module.
  5260 +//
  5261 +exports.stringify = querystringify;
  5262 +exports.parse = querystring;
  5263 +
  5264 +},{}],60:[function(require,module,exports){
  5265 +'use strict';
  5266 +
  5267 +/**
  5268 + * Check if we're required to add a port number.
  5269 + *
  5270 + * @see https://url.spec.whatwg.org/#default-port
  5271 + * @param {Number|String} port Port number we need to check
  5272 + * @param {String} protocol Protocol we need to check against.
  5273 + * @returns {Boolean} Is it a default port for the given protocol
  5274 + * @api private
  5275 + */
  5276 +module.exports = function required(port, protocol) {
  5277 + protocol = protocol.split(':')[0];
  5278 + port = +port;
  5279 +
  5280 + if (!port) return false;
  5281 +
  5282 + switch (protocol) {
  5283 + case 'http':
  5284 + case 'ws':
  5285 + return port !== 80;
  5286 +
  5287 + case 'https':
  5288 + case 'wss':
  5289 + return port !== 443;
  5290 +
  5291 + case 'ftp':
  5292 + return port !== 21;
  5293 +
  5294 + case 'gopher':
  5295 + return port !== 70;
  5296 +
  5297 + case 'file':
  5298 + return false;
  5299 + }
  5300 +
  5301 + return port !== 0;
  5302 +};
  5303 +
  5304 +},{}],61:[function(require,module,exports){
  5305 +'use strict';
  5306 +
  5307 +var required = require('requires-port')
  5308 + , lolcation = require('./lolcation')
  5309 + , qs = require('querystringify')
  5310 + , protocolre = /^([a-z][a-z0-9.+-]*:)?(\/\/)?([\S\s]*)/i;
  5311 +
  5312 +/**
  5313 + * These are the parse rules for the URL parser, it informs the parser
  5314 + * about:
  5315 + *
  5316 + * 0. The char it Needs to parse, if it's a string it should be done using
  5317 + * indexOf, RegExp using exec and NaN means set as current value.
  5318 + * 1. The property we should set when parsing this value.
  5319 + * 2. Indication if it's backwards or forward parsing, when set as number it's
  5320 + * the value of extra chars that should be split off.
  5321 + * 3. Inherit from location if non existing in the parser.
  5322 + * 4. `toLowerCase` the resulting value.
  5323 + */
  5324 +var rules = [
  5325 + ['#', 'hash'], // Extract from the back.
  5326 + ['?', 'query'], // Extract from the back.
  5327 + ['/', 'pathname'], // Extract from the back.
  5328 + ['@', 'auth', 1], // Extract from the front.
  5329 + [NaN, 'host', undefined, 1, 1], // Set left over value.
  5330 + [/:(\d+)$/, 'port', undefined, 1], // RegExp the back.
  5331 + [NaN, 'hostname', undefined, 1, 1] // Set left over.
  5332 +];
  5333 +
  5334 +/**
  5335 + * @typedef ProtocolExtract
  5336 + * @type Object
  5337 + * @property {String} protocol Protocol matched in the URL, in lowercase.
  5338 + * @property {Boolean} slashes `true` if protocol is followed by "//", else `false`.
  5339 + * @property {String} rest Rest of the URL that is not part of the protocol.
  5340 + */
  5341 +
  5342 +/**
  5343 + * Extract protocol information from a URL with/without double slash ("//").
  5344 + *
  5345 + * @param {String} address URL we want to extract from.
  5346 + * @return {ProtocolExtract} Extracted information.
  5347 + * @api private
  5348 + */
  5349 +function extractProtocol(address) {
  5350 + var match = protocolre.exec(address);
  5351 +
  5352 + return {
  5353 + protocol: match[1] ? match[1].toLowerCase() : '',
  5354 + slashes: !!match[2],
  5355 + rest: match[3]
  5356 + };
  5357 +}
  5358 +
  5359 +/**
  5360 + * Resolve a relative URL pathname against a base URL pathname.
  5361 + *
  5362 + * @param {String} relative Pathname of the relative URL.
  5363 + * @param {String} base Pathname of the base URL.
  5364 + * @return {String} Resolved pathname.
  5365 + * @api private
  5366 + */
  5367 +function resolve(relative, base) {
  5368 + var path = (base || '/').split('/').slice(0, -1).concat(relative.split('/'))
  5369 + , i = path.length
  5370 + , last = path[i - 1]
  5371 + , unshift = false
  5372 + , up = 0;
  5373 +
  5374 + while (i--) {
  5375 + if (path[i] === '.') {
  5376 + path.splice(i, 1);
  5377 + } else if (path[i] === '..') {
  5378 + path.splice(i, 1);
  5379 + up++;
  5380 + } else if (up) {
  5381 + if (i === 0) unshift = true;
  5382 + path.splice(i, 1);
  5383 + up--;
  5384 + }
  5385 + }
  5386 +
  5387 + if (unshift) path.unshift('');
  5388 + if (last === '.' || last === '..') path.push('');
  5389 +
  5390 + return path.join('/');
  5391 +}
  5392 +
  5393 +/**
  5394 + * The actual URL instance. Instead of returning an object we've opted-in to
  5395 + * create an actual constructor as it's much more memory efficient and
  5396 + * faster and it pleases my OCD.
  5397 + *
  5398 + * @constructor
  5399 + * @param {String} address URL we want to parse.
  5400 + * @param {Object|String} location Location defaults for relative paths.
  5401 + * @param {Boolean|Function} parser Parser for the query string.
  5402 + * @api public
  5403 + */
  5404 +function URL(address, location, parser) {
  5405 + if (!(this instanceof URL)) {
  5406 + return new URL(address, location, parser);
  5407 + }
  5408 +
  5409 + var relative, extracted, parse, instruction, index, key
  5410 + , instructions = rules.slice()
  5411 + , type = typeof location
  5412 + , url = this
  5413 + , i = 0;
  5414 +
  5415 + //
  5416 + // The following if statements allows this module two have compatibility with
  5417 + // 2 different API:
  5418 + //
  5419 + // 1. Node.js's `url.parse` api which accepts a URL, boolean as arguments
  5420 + // where the boolean indicates that the query string should also be parsed.
  5421 + //
  5422 + // 2. The `URL` interface of the browser which accepts a URL, object as
  5423 + // arguments. The supplied object will be used as default values / fall-back
  5424 + // for relative paths.
  5425 + //
  5426 + if ('object' !== type && 'string' !== type) {
  5427 + parser = location;
  5428 + location = null;
  5429 + }
  5430 +
  5431 + if (parser && 'function' !== typeof parser) parser = qs.parse;
  5432 +
  5433 + location = lolcation(location);
  5434 +
  5435 + //
  5436 + // Extract protocol information before running the instructions.
  5437 + //
  5438 + extracted = extractProtocol(address || '');
  5439 + relative = !extracted.protocol && !extracted.slashes;
  5440 + url.slashes = extracted.slashes || relative && location.slashes;
  5441 + url.protocol = extracted.protocol || location.protocol || '';
  5442 + address = extracted.rest;
  5443 +
  5444 + //
  5445 + // When the authority component is absent the URL starts with a path
  5446 + // component.
  5447 + //
  5448 + if (!extracted.slashes) instructions[2] = [/(.*)/, 'pathname'];
  5449 +
  5450 + for (; i < instructions.length; i++) {
  5451 + instruction = instructions[i];
  5452 + parse = instruction[0];
  5453 + key = instruction[1];
  5454 +
  5455 + if (parse !== parse) {
  5456 + url[key] = address;
  5457 + } else if ('string' === typeof parse) {
  5458 + if (~(index = address.indexOf(parse))) {
  5459 + if ('number' === typeof instruction[2]) {
  5460 + url[key] = address.slice(0, index);
  5461 + address = address.slice(index + instruction[2]);
  5462 + } else {
  5463 + url[key] = address.slice(index);
  5464 + address = address.slice(0, index);
  5465 + }
  5466 + }
  5467 + } else if (index = parse.exec(address)) {
  5468 + url[key] = index[1];
  5469 + address = address.slice(0, index.index);
  5470 + }
  5471 +
  5472 + url[key] = url[key] || (
  5473 + relative && instruction[3] ? location[key] || '' : ''
  5474 + );
  5475 +
  5476 + //
  5477 + // Hostname, host and protocol should be lowercased so they can be used to
  5478 + // create a proper `origin`.
  5479 + //
  5480 + if (instruction[4]) url[key] = url[key].toLowerCase();
  5481 + }
  5482 +
  5483 + //
  5484 + // Also parse the supplied query string in to an object. If we're supplied
  5485 + // with a custom parser as function use that instead of the default build-in
  5486 + // parser.
  5487 + //
  5488 + if (parser) url.query = parser(url.query);
  5489 +
  5490 + //
  5491 + // If the URL is relative, resolve the pathname against the base URL.
  5492 + //
  5493 + if (
  5494 + relative
  5495 + && location.slashes
  5496 + && url.pathname.charAt(0) !== '/'
  5497 + && (url.pathname !== '' || location.pathname !== '')
  5498 + ) {
  5499 + url.pathname = resolve(url.pathname, location.pathname);
  5500 + }
  5501 +
  5502 + //
  5503 + // We should not add port numbers if they are already the default port number
  5504 + // for a given protocol. As the host also contains the port number we're going
  5505 + // override it with the hostname which contains no port number.
  5506 + //
  5507 + if (!required(url.port, url.protocol)) {
  5508 + url.host = url.hostname;
  5509 + url.port = '';
  5510 + }
  5511 +
  5512 + //
  5513 + // Parse down the `auth` for the username and password.
  5514 + //
  5515 + url.username = url.password = '';
  5516 + if (url.auth) {
  5517 + instruction = url.auth.split(':');
  5518 + url.username = instruction[0] || '';
  5519 + url.password = instruction[1] || '';
  5520 + }
  5521 +
  5522 + url.origin = url.protocol && url.host && url.protocol !== 'file:'
  5523 + ? url.protocol +'//'+ url.host
  5524 + : 'null';
  5525 +
  5526 + //
  5527 + // The href is just the compiled result.
  5528 + //
  5529 + url.href = url.toString();
  5530 +}
  5531 +
  5532 +/**
  5533 + * This is convenience method for changing properties in the URL instance to
  5534 + * insure that they all propagate correctly.
  5535 + *
  5536 + * @param {String} part Property we need to adjust.
  5537 + * @param {Mixed} value The newly assigned value.
  5538 + * @param {Boolean|Function} fn When setting the query, it will be the function
  5539 + * used to parse the query.
  5540 + * When setting the protocol, double slash will be
  5541 + * removed from the final url if it is true.
  5542 + * @returns {URL}
  5543 + * @api public
  5544 + */
  5545 +URL.prototype.set = function set(part, value, fn) {
  5546 + var url = this;
  5547 +
  5548 + switch (part) {
  5549 + case 'query':
  5550 + if ('string' === typeof value && value.length) {
  5551 + value = (fn || qs.parse)(value);
  5552 + }
  5553 +
  5554 + url[part] = value;
  5555 + break;
  5556 +
  5557 + case 'port':
  5558 + url[part] = value;
  5559 +
  5560 + if (!required(value, url.protocol)) {
  5561 + url.host = url.hostname;
  5562 + url[part] = '';
  5563 + } else if (value) {
  5564 + url.host = url.hostname +':'+ value;
  5565 + }
  5566 +
  5567 + break;
  5568 +
  5569 + case 'hostname':
  5570 + url[part] = value;
  5571 +
  5572 + if (url.port) value += ':'+ url.port;
  5573 + url.host = value;
  5574 + break;
  5575 +
  5576 + case 'host':
  5577 + url[part] = value;
  5578 +
  5579 + if (/:\d+$/.test(value)) {
  5580 + value = value.split(':');
  5581 + url.port = value.pop();
  5582 + url.hostname = value.join(':');
  5583 + } else {
  5584 + url.hostname = value;
  5585 + url.port = '';
  5586 + }
  5587 +
  5588 + break;
  5589 +
  5590 + case 'protocol':
  5591 + url.protocol = value.toLowerCase();
  5592 + url.slashes = !fn;
  5593 + break;
  5594 +
  5595 + case 'pathname':
  5596 + url.pathname = value.length && value.charAt(0) !== '/' ? '/' + value : value;
  5597 +
  5598 + break;
  5599 +
  5600 + default:
  5601 + url[part] = value;
  5602 + }
  5603 +
  5604 + for (var i = 0; i < rules.length; i++) {
  5605 + var ins = rules[i];
  5606 +
  5607 + if (ins[4]) url[ins[1]] = url[ins[1]].toLowerCase();
  5608 + }
  5609 +
  5610 + url.origin = url.protocol && url.host && url.protocol !== 'file:'
  5611 + ? url.protocol +'//'+ url.host
  5612 + : 'null';
  5613 +
  5614 + url.href = url.toString();
  5615 +
  5616 + return url;
  5617 +};
  5618 +
  5619 +/**
  5620 + * Transform the properties back in to a valid and full URL string.
  5621 + *
  5622 + * @param {Function} stringify Optional query stringify function.
  5623 + * @returns {String}
  5624 + * @api public
  5625 + */
  5626 +URL.prototype.toString = function toString(stringify) {
  5627 + if (!stringify || 'function' !== typeof stringify) stringify = qs.stringify;
  5628 +
  5629 + var query
  5630 + , url = this
  5631 + , protocol = url.protocol;
  5632 +
  5633 + if (protocol && protocol.charAt(protocol.length - 1) !== ':') protocol += ':';
  5634 +
  5635 + var result = protocol + (url.slashes ? '//' : '');
  5636 +
  5637 + if (url.username) {
  5638 + result += url.username;
  5639 + if (url.password) result += ':'+ url.password;
  5640 + result += '@';
  5641 + }
  5642 +
  5643 + result += url.host + url.pathname;
  5644 +
  5645 + query = 'object' === typeof url.query ? stringify(url.query) : url.query;
  5646 + if (query) result += '?' !== query.charAt(0) ? '?'+ query : query;
  5647 +
  5648 + if (url.hash) result += url.hash;
  5649 +
  5650 + return result;
  5651 +};
  5652 +
  5653 +//
  5654 +// Expose the URL parser and some additional properties that might be useful for
  5655 +// others or testing.
  5656 +//
  5657 +URL.extractProtocol = extractProtocol;
  5658 +URL.location = lolcation;
  5659 +URL.qs = qs;
  5660 +
  5661 +module.exports = URL;
  5662 +
  5663 +},{"./lolcation":62,"querystringify":59,"requires-port":60}],62:[function(require,module,exports){
  5664 +(function (global){
  5665 +'use strict';
  5666 +
  5667 +var slashes = /^[A-Za-z][A-Za-z0-9+-.]*:\/\//;
  5668 +
  5669 +/**
  5670 + * These properties should not be copied or inherited from. This is only needed
  5671 + * for all non blob URL's as a blob URL does not include a hash, only the
  5672 + * origin.
  5673 + *
  5674 + * @type {Object}
  5675 + * @private
  5676 + */
  5677 +var ignore = { hash: 1, query: 1 }
  5678 + , URL;
  5679 +
  5680 +/**
  5681 + * The location object differs when your code is loaded through a normal page,
  5682 + * Worker or through a worker using a blob. And with the blobble begins the
  5683 + * trouble as the location object will contain the URL of the blob, not the
  5684 + * location of the page where our code is loaded in. The actual origin is
  5685 + * encoded in the `pathname` so we can thankfully generate a good "default"
  5686 + * location from it so we can generate proper relative URL's again.
  5687 + *
  5688 + * @param {Object|String} loc Optional default location object.
  5689 + * @returns {Object} lolcation object.
  5690 + * @api public
  5691 + */
  5692 +module.exports = function lolcation(loc) {
  5693 + loc = loc || global.location || {};
  5694 + URL = URL || require('./');
  5695 +
  5696 + var finaldestination = {}
  5697 + , type = typeof loc
  5698 + , key;
  5699 +
  5700 + if ('blob:' === loc.protocol) {
  5701 + finaldestination = new URL(unescape(loc.pathname), {});
  5702 + } else if ('string' === type) {
  5703 + finaldestination = new URL(loc, {});
  5704 + for (key in ignore) delete finaldestination[key];
  5705 + } else if ('object' === type) {
  5706 + for (key in loc) {
  5707 + if (key in ignore) continue;
  5708 + finaldestination[key] = loc[key];
  5709 + }
  5710 +
  5711 + if (finaldestination.slashes === undefined) {
  5712 + finaldestination.slashes = slashes.test(loc.href);
  5713 + }
  5714 + }
  5715 +
  5716 + return finaldestination;
  5717 +};
  5718 +
  5719 +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  5720 +
  5721 +},{"./":61}]},{},[1])(1)
  5722 +});
  5723 +
  5724 +
  5725 +//# sourceMappingURL=sockjs.js.map
src/main/resources/static/assets/plugins/sockjs-client/sockjs.min.js 0 → 100644
  1 +/* sockjs-client v1.1.2 | http://sockjs.org | MIT license */
  2 +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.SockJS=t()}}(function(){var t;return function t(e,n,r){function i(s,a){if(!n[s]){if(!e[s]){var l="function"==typeof require&&require;if(!a&&l)return l(s,!0);if(o)return o(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var c=n[s]={exports:{}};e[s][0].call(c.exports,function(t){var n=e[s][1][t];return i(n?n:t)},c,c.exports,t,e,n,r)}return n[s].exports}for(var o="function"==typeof require&&require,s=0;s<r.length;s++)i(r[s]);return i}({1:[function(t,e,n){(function(n){"use strict";var r=t("./transport-list");e.exports=t("./main")(r),"_sockjs_onload"in n&&setTimeout(n._sockjs_onload,1)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./main":14,"./transport-list":16}],2:[function(t,e,n){"use strict";function r(){o.call(this),this.initEvent("close",!1,!1),this.wasClean=!1,this.code=0,this.reason=""}var i=t("inherits"),o=t("./event");i(r,o),e.exports=r},{"./event":4,inherits:54}],3:[function(t,e,n){"use strict";function r(){o.call(this)}var i=t("inherits"),o=t("./eventtarget");i(r,o),r.prototype.removeAllListeners=function(t){t?delete this._listeners[t]:this._listeners={}},r.prototype.once=function(t,e){function n(){r.removeListener(t,n),i||(i=!0,e.apply(this,arguments))}var r=this,i=!1;this.on(t,n)},r.prototype.emit=function(){var t=arguments[0],e=this._listeners[t];if(e){for(var n=arguments.length,r=new Array(n-1),i=1;i<n;i++)r[i-1]=arguments[i];for(var o=0;o<e.length;o++)e[o].apply(this,r)}},r.prototype.on=r.prototype.addListener=o.prototype.addEventListener,r.prototype.removeListener=o.prototype.removeEventListener,e.exports.EventEmitter=r},{"./eventtarget":5,inherits:54}],4:[function(t,e,n){"use strict";function r(t){this.type=t}r.prototype.initEvent=function(t,e,n){return this.type=t,this.bubbles=e,this.cancelable=n,this.timeStamp=+new Date,this},r.prototype.stopPropagation=function(){},r.prototype.preventDefault=function(){},r.CAPTURING_PHASE=1,r.AT_TARGET=2,r.BUBBLING_PHASE=3,e.exports=r},{}],5:[function(t,e,n){"use strict";function r(){this._listeners={}}r.prototype.addEventListener=function(t,e){t in this._listeners||(this._listeners[t]=[]);var n=this._listeners[t];n.indexOf(e)===-1&&(n=n.concat([e])),this._listeners[t]=n},r.prototype.removeEventListener=function(t,e){var n=this._listeners[t];if(n){var r=n.indexOf(e);return r!==-1?void(n.length>1?this._listeners[t]=n.slice(0,r).concat(n.slice(r+1)):delete this._listeners[t]):void 0}},r.prototype.dispatchEvent=function(){var t=arguments[0],e=t.type,n=1===arguments.length?[t]:Array.apply(null,arguments);if(this["on"+e]&&this["on"+e].apply(this,n),e in this._listeners)for(var r=this._listeners[e],i=0;i<r.length;i++)r[i].apply(this,n)},e.exports=r},{}],6:[function(t,e,n){"use strict";function r(t){o.call(this),this.initEvent("message",!1,!1),this.data=t}var i=t("inherits"),o=t("./event");i(r,o),e.exports=r},{"./event":4,inherits:54}],7:[function(t,e,n){"use strict";function r(t){this._transport=t,t.on("message",this._transportMessage.bind(this)),t.on("close",this._transportClose.bind(this))}var i=t("json3"),o=t("./utils/iframe");r.prototype._transportClose=function(t,e){o.postMessage("c",i.stringify([t,e]))},r.prototype._transportMessage=function(t){o.postMessage("t",t)},r.prototype._send=function(t){this._transport.send(t)},r.prototype._close=function(){this._transport.close(),this._transport.removeAllListeners()},e.exports=r},{"./utils/iframe":47,json3:55}],8:[function(t,e,n){"use strict";var r=t("./utils/url"),i=t("./utils/event"),o=t("json3"),s=t("./facade"),a=t("./info-iframe-receiver"),l=t("./utils/iframe"),u=t("./location");e.exports=function(t,e){var n={};e.forEach(function(t){t.facadeTransport&&(n[t.facadeTransport.transportName]=t.facadeTransport)}),n[a.transportName]=a;var c;t.bootstrap_iframe=function(){var e;l.currentWindowId=u.hash.slice(1);var a=function(i){if(i.source===parent&&("undefined"==typeof c&&(c=i.origin),i.origin===c)){var a;try{a=o.parse(i.data)}catch(t){return}if(a.windowId===l.currentWindowId)switch(a.type){case"s":var f;try{f=o.parse(a.data)}catch(t){break}var h=f[0],d=f[1],p=f[2],v=f[3];if(h!==t.version)throw new Error('Incompatible SockJS! Main site uses: "'+h+'", the iframe: "'+t.version+'".');if(!r.isOriginEqual(p,u.href)||!r.isOriginEqual(v,u.href))throw new Error("Can't connect to different domain from within an iframe. ("+u.href+", "+p+", "+v+")");e=new s(new n[d](p,v));break;case"m":e._send(a.data);break;case"c":e&&e._close(),e=null}}};i.attachEvent("message",a),l.postMessage("s")}}},{"./facade":7,"./info-iframe-receiver":10,"./location":13,"./utils/event":46,"./utils/iframe":47,"./utils/url":52,debug:void 0,json3:55}],9:[function(t,e,n){"use strict";function r(t,e){i.call(this);var n=this,r=+new Date;this.xo=new e("GET",t),this.xo.once("finish",function(t,e){var i,o;if(200===t){if(o=+new Date-r,e)try{i=s.parse(e)}catch(t){}a.isObject(i)||(i={})}n.emit("finish",i,o),n.removeAllListeners()})}var i=t("events").EventEmitter,o=t("inherits"),s=t("json3"),a=t("./utils/object");o(r,i),r.prototype.close=function(){this.removeAllListeners(),this.xo.close()},e.exports=r},{"./utils/object":49,debug:void 0,events:3,inherits:54,json3:55}],10:[function(t,e,n){"use strict";function r(t){var e=this;o.call(this),this.ir=new l(t,a),this.ir.once("finish",function(t,n){e.ir=null,e.emit("message",s.stringify([t,n]))})}var i=t("inherits"),o=t("events").EventEmitter,s=t("json3"),a=t("./transport/sender/xhr-local"),l=t("./info-ajax");i(r,o),r.transportName="iframe-info-receiver",r.prototype.close=function(){this.ir&&(this.ir.close(),this.ir=null),this.removeAllListeners()},e.exports=r},{"./info-ajax":9,"./transport/sender/xhr-local":37,events:3,inherits:54,json3:55}],11:[function(t,e,n){(function(n){"use strict";function r(t,e){var r=this;i.call(this);var o=function(){var n=r.ifr=new l(u.transportName,e,t);n.once("message",function(t){if(t){var e;try{e=s.parse(t)}catch(t){return r.emit("finish"),void r.close()}var n=e[0],i=e[1];r.emit("finish",n,i)}r.close()}),n.once("close",function(){r.emit("finish"),r.close()})};n.document.body?o():a.attachEvent("load",o)}var i=t("events").EventEmitter,o=t("inherits"),s=t("json3"),a=t("./utils/event"),l=t("./transport/iframe"),u=t("./info-iframe-receiver");o(r,i),r.enabled=function(){return l.enabled()},r.prototype.close=function(){this.ifr&&this.ifr.close(),this.removeAllListeners(),this.ifr=null},e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./info-iframe-receiver":10,"./transport/iframe":22,"./utils/event":46,debug:void 0,events:3,inherits:54,json3:55}],12:[function(t,e,n){"use strict";function r(t,e){var n=this;i.call(this),setTimeout(function(){n.doXhr(t,e)},0)}var i=t("events").EventEmitter,o=t("inherits"),s=t("./utils/url"),a=t("./transport/sender/xdr"),l=t("./transport/sender/xhr-cors"),u=t("./transport/sender/xhr-local"),c=t("./transport/sender/xhr-fake"),f=t("./info-iframe"),h=t("./info-ajax");o(r,i),r._getReceiver=function(t,e,n){return n.sameOrigin?new h(e,u):l.enabled?new h(e,l):a.enabled&&n.sameScheme?new h(e,a):f.enabled()?new f(t,e):new h(e,c)},r.prototype.doXhr=function(t,e){var n=this,i=s.addPath(t,"/info");this.xo=r._getReceiver(t,i,e),this.timeoutRef=setTimeout(function(){n._cleanup(!1),n.emit("finish")},r.timeout),this.xo.once("finish",function(t,e){n._cleanup(!0),n.emit("finish",t,e)})},r.prototype._cleanup=function(t){clearTimeout(this.timeoutRef),this.timeoutRef=null,!t&&this.xo&&this.xo.close(),this.xo=null},r.prototype.close=function(){this.removeAllListeners(),this._cleanup(!1)},r.timeout=8e3,e.exports=r},{"./info-ajax":9,"./info-iframe":11,"./transport/sender/xdr":34,"./transport/sender/xhr-cors":35,"./transport/sender/xhr-fake":36,"./transport/sender/xhr-local":37,"./utils/url":52,debug:void 0,events:3,inherits:54}],13:[function(t,e,n){(function(t){"use strict";e.exports=t.location||{origin:"http://localhost:80",protocol:"http",host:"localhost",port:80,href:"http://localhost/",hash:""}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],14:[function(t,e,n){(function(n){"use strict";function r(t,e,n){if(!(this instanceof r))return new r(t,e,n);if(arguments.length<1)throw new TypeError("Failed to construct 'SockJS: 1 argument required, but only 0 present");y.call(this),this.readyState=r.CONNECTING,this.extensions="",this.protocol="",n=n||{},n.protocols_whitelist&&m.warn("'protocols_whitelist' is DEPRECATED. Use 'transports' instead."),this._transportsWhitelist=n.transports,this._transportOptions=n.transportOptions||{};var i=n.sessionId||8;if("function"==typeof i)this._generateSessionId=i;else{if("number"!=typeof i)throw new TypeError("If sessionId is used in the options, it needs to be a number or a function.");this._generateSessionId=function(){return u.string(i)}}this._server=n.server||u.numberString(1e3);var o=new s(t);if(!o.host||!o.protocol)throw new SyntaxError("The URL '"+t+"' is invalid");if(o.hash)throw new SyntaxError("The URL must not contain a fragment");if("http:"!==o.protocol&&"https:"!==o.protocol)throw new SyntaxError("The URL's scheme must be either 'http:' or 'https:'. '"+o.protocol+"' is not allowed.");var a="https:"===o.protocol;if("https"===g.protocol&&!a)throw new Error("SecurityError: An insecure SockJS connection may not be initiated from a page loaded over HTTPS");e?Array.isArray(e)||(e=[e]):e=[];var l=e.sort();l.forEach(function(t,e){if(!t)throw new SyntaxError("The protocols entry '"+t+"' is invalid.");if(e<l.length-1&&t===l[e+1])throw new SyntaxError("The protocols entry '"+t+"' is duplicated.")});var c=f.getOrigin(g.href);this._origin=c?c.toLowerCase():null,o.set("pathname",o.pathname.replace(/\/+$/,"")),this.url=o.href,this._urlInfo={nullOrigin:!v.hasDomain(),sameOrigin:f.isOriginEqual(this.url,g.href),sameScheme:f.isSchemeEqual(this.url,g.href)},this._ir=new _(this.url,this._urlInfo),this._ir.once("finish",this._receiveInfo.bind(this))}function i(t){return 1e3===t||t>=3e3&&t<=4999}t("./shims");var o,s=t("url-parse"),a=t("inherits"),l=t("json3"),u=t("./utils/random"),c=t("./utils/escape"),f=t("./utils/url"),h=t("./utils/event"),d=t("./utils/transport"),p=t("./utils/object"),v=t("./utils/browser"),m=t("./utils/log"),b=t("./event/event"),y=t("./event/eventtarget"),g=t("./location"),w=t("./event/close"),x=t("./event/trans-message"),_=t("./info-receiver");a(r,y),r.prototype.close=function(t,e){if(t&&!i(t))throw new Error("InvalidAccessError: Invalid code");if(e&&e.length>123)throw new SyntaxError("reason argument has an invalid length");if(this.readyState!==r.CLOSING&&this.readyState!==r.CLOSED){var n=!0;this._close(t||1e3,e||"Normal closure",n)}},r.prototype.send=function(t){if("string"!=typeof t&&(t=""+t),this.readyState===r.CONNECTING)throw new Error("InvalidStateError: The connection has not been established yet");this.readyState===r.OPEN&&this._transport.send(c.quote(t))},r.version=t("./version"),r.CONNECTING=0,r.OPEN=1,r.CLOSING=2,r.CLOSED=3,r.prototype._receiveInfo=function(t,e){if(this._ir=null,!t)return void this._close(1002,"Cannot connect to server");this._rto=this.countRTO(e),this._transUrl=t.base_url?t.base_url:this.url,t=p.extend(t,this._urlInfo);var n=o.filterToEnabled(this._transportsWhitelist,t);this._transports=n.main,this._connect()},r.prototype._connect=function(){for(var t=this._transports.shift();t;t=this._transports.shift()){if(t.needBody&&(!n.document.body||"undefined"!=typeof n.document.readyState&&"complete"!==n.document.readyState&&"interactive"!==n.document.readyState))return this._transports.unshift(t),void h.attachEvent("load",this._connect.bind(this));var e=this._rto*t.roundTrips||5e3;this._transportTimeoutId=setTimeout(this._transportTimeout.bind(this),e);var r=f.addPath(this._transUrl,"/"+this._server+"/"+this._generateSessionId()),i=this._transportOptions[t.transportName],o=new t(r,this._transUrl,i);return o.on("message",this._transportMessage.bind(this)),o.once("close",this._transportClose.bind(this)),o.transportName=t.transportName,void(this._transport=o)}this._close(2e3,"All transports failed",!1)},r.prototype._transportTimeout=function(){this.readyState===r.CONNECTING&&this._transportClose(2007,"Transport timed out")},r.prototype._transportMessage=function(t){var e,n=this,r=t.slice(0,1),i=t.slice(1);switch(r){case"o":return void this._open();case"h":return void this.dispatchEvent(new b("heartbeat"))}if(i)try{e=l.parse(i)}catch(t){}if("undefined"!=typeof e)switch(r){case"a":Array.isArray(e)&&e.forEach(function(t){n.dispatchEvent(new x(t))});break;case"m":this.dispatchEvent(new x(e));break;case"c":Array.isArray(e)&&2===e.length&&this._close(e[0],e[1],!0)}},r.prototype._transportClose=function(t,e){return this._transport&&(this._transport.removeAllListeners(),this._transport=null,this.transport=null),i(t)||2e3===t||this.readyState!==r.CONNECTING?void this._close(t,e):void this._connect()},r.prototype._open=function(){this.readyState===r.CONNECTING?(this._transportTimeoutId&&(clearTimeout(this._transportTimeoutId),this._transportTimeoutId=null),this.readyState=r.OPEN,this.transport=this._transport.transportName,this.dispatchEvent(new b("open"))):this._close(1006,"Server lost session")},r.prototype._close=function(t,e,n){var i=!1;if(this._ir&&(i=!0,this._ir.close(),this._ir=null),this._transport&&(this._transport.close(),this._transport=null,this.transport=null),this.readyState===r.CLOSED)throw new Error("InvalidStateError: SockJS has already been closed");this.readyState=r.CLOSING,setTimeout(function(){this.readyState=r.CLOSED,i&&this.dispatchEvent(new b("error"));var o=new w("close");o.wasClean=n||!1,o.code=t||1e3,o.reason=e,this.dispatchEvent(o),this.onmessage=this.onclose=this.onerror=null}.bind(this),0)},r.prototype.countRTO=function(t){return t>100?4*t:300+t},e.exports=function(e){return o=d(e),t("./iframe-bootstrap")(r,e),r}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./event/close":2,"./event/event":4,"./event/eventtarget":5,"./event/trans-message":6,"./iframe-bootstrap":8,"./info-receiver":12,"./location":13,"./shims":15,"./utils/browser":44,"./utils/escape":45,"./utils/event":46,"./utils/log":48,"./utils/object":49,"./utils/random":50,"./utils/transport":51,"./utils/url":52,"./version":53,debug:void 0,inherits:54,json3:55,"url-parse":58}],15:[function(t,e,n){"use strict";function r(t){var e=+t;return e!==e?e=0:0!==e&&e!==1/0&&e!==-(1/0)&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}function i(t){return t>>>0}function o(){}var s,a=Array.prototype,l=Object.prototype,u=Function.prototype,c=String.prototype,f=a.slice,h=l.toString,d=function(t){return"[object Function]"===l.toString.call(t)},p=function(t){return"[object Array]"===h.call(t)},v=function(t){return"[object String]"===h.call(t)},m=Object.defineProperty&&function(){try{return Object.defineProperty({},"x",{}),!0}catch(t){return!1}}();s=m?function(t,e,n,r){!r&&e in t||Object.defineProperty(t,e,{configurable:!0,enumerable:!1,writable:!0,value:n})}:function(t,e,n,r){!r&&e in t||(t[e]=n)};var b=function(t,e,n){for(var r in e)l.hasOwnProperty.call(e,r)&&s(t,r,e[r],n)},y=function(t){if(null==t)throw new TypeError("can't convert "+t+" to object");return Object(t)};b(u,{bind:function(t){var e=this;if(!d(e))throw new TypeError("Function.prototype.bind called on incompatible "+e);for(var n=f.call(arguments,1),r=function(){if(this instanceof l){var r=e.apply(this,n.concat(f.call(arguments)));return Object(r)===r?r:this}return e.apply(t,n.concat(f.call(arguments)))},i=Math.max(0,e.length-n.length),s=[],a=0;a<i;a++)s.push("$"+a);var l=Function("binder","return function ("+s.join(",")+"){ return binder.apply(this, arguments); }")(r);return e.prototype&&(o.prototype=e.prototype,l.prototype=new o,o.prototype=null),l}}),b(Array,{isArray:p});var g=Object("a"),w="a"!==g[0]||!(0 in g),x=function(t){var e=!0,n=!0;return t&&(t.call("foo",function(t,n,r){"object"!=typeof r&&(e=!1)}),t.call([1],function(){n="string"==typeof this},"x")),!!t&&e&&n};b(a,{forEach:function(t){var e=y(this),n=w&&v(this)?this.split(""):e,r=arguments[1],i=-1,o=n.length>>>0;if(!d(t))throw new TypeError;for(;++i<o;)i in n&&t.call(r,n[i],i,e)}},!x(a.forEach));var _=Array.prototype.indexOf&&[0,1].indexOf(1,2)!==-1;b(a,{indexOf:function(t){var e=w&&v(this)?this.split(""):y(this),n=e.length>>>0;if(!n)return-1;var i=0;for(arguments.length>1&&(i=r(arguments[1])),i=i>=0?i:Math.max(0,n+i);i<n;i++)if(i in e&&e[i]===t)return i;return-1}},_);var E=c.split;2!=="ab".split(/(?:ab)*/).length||4!==".".split(/(.?)(.?)/).length||"t"==="tesst".split(/(s)*/)[1]||4!=="test".split(/(?:)/,-1).length||"".split(/.?/).length||".".split(/()()/).length>1?!function(){var t=void 0===/()??/.exec("")[1];c.split=function(e,n){var r=this;if(void 0===e&&0===n)return[];if("[object RegExp]"!==h.call(e))return E.call(this,e,n);var o,s,l,u,c=[],f=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.extended?"x":"")+(e.sticky?"y":""),d=0;for(e=new RegExp(e.source,f+"g"),r+="",t||(o=new RegExp("^"+e.source+"$(?!\\s)",f)),n=void 0===n?-1>>>0:i(n);(s=e.exec(r))&&(l=s.index+s[0].length,!(l>d&&(c.push(r.slice(d,s.index)),!t&&s.length>1&&s[0].replace(o,function(){for(var t=1;t<arguments.length-2;t++)void 0===arguments[t]&&(s[t]=void 0)}),s.length>1&&s.index<r.length&&a.push.apply(c,s.slice(1)),u=s[0].length,d=l,c.length>=n)));)e.lastIndex===s.index&&e.lastIndex++;return d===r.length?!u&&e.test("")||c.push(""):c.push(r.slice(d)),c.length>n?c.slice(0,n):c}}():"0".split(void 0,0).length&&(c.split=function(t,e){return void 0===t&&0===e?[]:E.call(this,t,e)});var j=c.substr,T="".substr&&"b"!=="0b".substr(-1);b(c,{substr:function(t,e){return j.call(this,t<0&&(t=this.length+t)<0?0:t,e)}},T)},{}],16:[function(t,e,n){"use strict";e.exports=[t("./transport/websocket"),t("./transport/xhr-streaming"),t("./transport/xdr-streaming"),t("./transport/eventsource"),t("./transport/lib/iframe-wrap")(t("./transport/eventsource")),t("./transport/htmlfile"),t("./transport/lib/iframe-wrap")(t("./transport/htmlfile")),t("./transport/xhr-polling"),t("./transport/xdr-polling"),t("./transport/lib/iframe-wrap")(t("./transport/xhr-polling")),t("./transport/jsonp-polling")]},{"./transport/eventsource":20,"./transport/htmlfile":21,"./transport/jsonp-polling":23,"./transport/lib/iframe-wrap":26,"./transport/websocket":38,"./transport/xdr-polling":39,"./transport/xdr-streaming":40,"./transport/xhr-polling":41,"./transport/xhr-streaming":42}],17:[function(t,e,n){(function(n){"use strict";function r(t,e,n,r){var o=this;i.call(this),setTimeout(function(){o._start(t,e,n,r)},0)}var i=t("events").EventEmitter,o=t("inherits"),s=t("../../utils/event"),a=t("../../utils/url"),l=n.XMLHttpRequest;o(r,i),r.prototype._start=function(t,e,n,i){var o=this;try{this.xhr=new l}catch(t){}if(!this.xhr)return this.emit("finish",0,"no xhr support"),void this._cleanup();e=a.addQuery(e,"t="+ +new Date),this.unloadRef=s.unloadAdd(function(){o._cleanup(!0)});try{this.xhr.open(t,e,!0),this.timeout&&"timeout"in this.xhr&&(this.xhr.timeout=this.timeout,this.xhr.ontimeout=function(){o.emit("finish",0,""),o._cleanup(!1)})}catch(t){return this.emit("finish",0,""),void this._cleanup(!1)}if(i&&i.noCredentials||!r.supportsCORS||(this.xhr.withCredentials="true"),i&&i.headers)for(var u in i.headers)this.xhr.setRequestHeader(u,i.headers[u]);this.xhr.onreadystatechange=function(){if(o.xhr){var t,e,n=o.xhr;switch(n.readyState){case 3:try{e=n.status,t=n.responseText}catch(t){}1223===e&&(e=204),200===e&&t&&t.length>0&&o.emit("chunk",e,t);break;case 4:e=n.status,1223===e&&(e=204),12005!==e&&12029!==e||(e=0),o.emit("finish",e,n.responseText),o._cleanup(!1)}}};try{o.xhr.send(n)}catch(t){o.emit("finish",0,""),o._cleanup(!1)}},r.prototype._cleanup=function(t){if(this.xhr){if(this.removeAllListeners(),s.unloadDel(this.unloadRef),this.xhr.onreadystatechange=function(){},this.xhr.ontimeout&&(this.xhr.ontimeout=null),t)try{this.xhr.abort()}catch(t){}this.unloadRef=this.xhr=null}},r.prototype.close=function(){this._cleanup(!0)},r.enabled=!!l;var u=["Active"].concat("Object").join("X");!r.enabled&&u in n&&(l=function(){try{return new n[u]("Microsoft.XMLHTTP")}catch(t){return null}},r.enabled=!!new l);var c=!1;try{c="withCredentials"in new l}catch(t){}r.supportsCORS=c,e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../../utils/event":46,"../../utils/url":52,debug:void 0,events:3,inherits:54}],18:[function(t,e,n){(function(t){e.exports=t.EventSource}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],19:[function(t,e,n){(function(t){"use strict";var n=t.WebSocket||t.MozWebSocket;n?e.exports=function(t){return new n(t)}:e.exports=void 0}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],20:[function(t,e,n){"use strict";function r(t){if(!r.enabled())throw new Error("Transport created when disabled");o.call(this,t,"/eventsource",s,a)}var i=t("inherits"),o=t("./lib/ajax-based"),s=t("./receiver/eventsource"),a=t("./sender/xhr-cors"),l=t("eventsource");i(r,o),r.enabled=function(){return!!l},r.transportName="eventsource",r.roundTrips=2,e.exports=r},{"./lib/ajax-based":24,"./receiver/eventsource":29,"./sender/xhr-cors":35,eventsource:18,inherits:54}],21:[function(t,e,n){"use strict";function r(t){if(!o.enabled)throw new Error("Transport created when disabled");a.call(this,t,"/htmlfile",o,s)}var i=t("inherits"),o=t("./receiver/htmlfile"),s=t("./sender/xhr-local"),a=t("./lib/ajax-based");i(r,a),r.enabled=function(t){return o.enabled&&t.sameOrigin},r.transportName="htmlfile",r.roundTrips=2,e.exports=r},{"./lib/ajax-based":24,"./receiver/htmlfile":30,"./sender/xhr-local":37,inherits:54}],22:[function(t,e,n){"use strict";function r(t,e,n){if(!r.enabled())throw new Error("Transport created when disabled");s.call(this);var i=this;this.origin=l.getOrigin(n),this.baseUrl=n,this.transUrl=e,this.transport=t,this.windowId=f.string(8);var o=l.addPath(n,"/iframe.html")+"#"+this.windowId;this.iframeObj=u.createIframe(o,function(t){i.emit("close",1006,"Unable to load an iframe ("+t+")"),i.close()}),this.onmessageCallback=this._message.bind(this),c.attachEvent("message",this.onmessageCallback)}var i=t("inherits"),o=t("json3"),s=t("events").EventEmitter,a=t("../version"),l=t("../utils/url"),u=t("../utils/iframe"),c=t("../utils/event"),f=t("../utils/random");i(r,s),r.prototype.close=function(){if(this.removeAllListeners(),this.iframeObj){c.detachEvent("message",this.onmessageCallback);try{this.postMessage("c")}catch(t){}this.iframeObj.cleanup(),this.iframeObj=null,this.onmessageCallback=this.iframeObj=null}},r.prototype._message=function(t){if(l.isOriginEqual(t.origin,this.origin)){var e;try{e=o.parse(t.data)}catch(t){return}if(e.windowId===this.windowId)switch(e.type){case"s":this.iframeObj.loaded(),this.postMessage("s",o.stringify([a,this.transport,this.transUrl,this.baseUrl]));break;case"t":this.emit("message",e.data);break;case"c":var n;try{n=o.parse(e.data)}catch(t){return}this.emit("close",n[0],n[1]),this.close()}}},r.prototype.postMessage=function(t,e){this.iframeObj.post(o.stringify({windowId:this.windowId,type:t,data:e||""}),this.origin)},r.prototype.send=function(t){this.postMessage("m",t)},r.enabled=function(){return u.iframeEnabled},r.transportName="iframe",r.roundTrips=2,e.exports=r},{"../utils/event":46,"../utils/iframe":47,"../utils/random":50,"../utils/url":52,"../version":53,debug:void 0,events:3,inherits:54,json3:55}],23:[function(t,e,n){(function(n){"use strict";function r(t){if(!r.enabled())throw new Error("Transport created when disabled");o.call(this,t,"/jsonp",a,s)}var i=t("inherits"),o=t("./lib/sender-receiver"),s=t("./receiver/jsonp"),a=t("./sender/jsonp");i(r,o),r.enabled=function(){return!!n.document},r.transportName="jsonp-polling",r.roundTrips=1,r.needBody=!0,e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./lib/sender-receiver":28,"./receiver/jsonp":31,"./sender/jsonp":33,inherits:54}],24:[function(t,e,n){"use strict";function r(t){return function(e,n,r){var i={};"string"==typeof n&&(i.headers={"Content-type":"text/plain"});var o=s.addPath(e,"/xhr_send"),a=new t("POST",o,n,i);return a.once("finish",function(t){return a=null,200!==t&&204!==t?r(new Error("http status "+t)):void r()}),function(){a.close(),a=null;var t=new Error("Aborted");t.code=1e3,r(t)}}}function i(t,e,n,i){a.call(this,t,e,r(i),n,i)}var o=t("inherits"),s=t("../../utils/url"),a=t("./sender-receiver");o(i,a),e.exports=i},{"../../utils/url":52,"./sender-receiver":28,debug:void 0,inherits:54}],25:[function(t,e,n){"use strict";function r(t,e){o.call(this),this.sendBuffer=[],this.sender=e,this.url=t}var i=t("inherits"),o=t("events").EventEmitter;i(r,o),r.prototype.send=function(t){this.sendBuffer.push(t),this.sendStop||this.sendSchedule()},r.prototype.sendScheduleWait=function(){var t,e=this;this.sendStop=function(){e.sendStop=null,clearTimeout(t)},t=setTimeout(function(){e.sendStop=null,e.sendSchedule()},25)},r.prototype.sendSchedule=function(){var t=this;if(this.sendBuffer.length>0){var e="["+this.sendBuffer.join(",")+"]";this.sendStop=this.sender(this.url,e,function(e){t.sendStop=null,e?(t.emit("close",e.code||1006,"Sending error: "+e),t.close()):t.sendScheduleWait()}),this.sendBuffer=[]}},r.prototype._cleanup=function(){this.removeAllListeners()},r.prototype.close=function(){this._cleanup(),this.sendStop&&(this.sendStop(),this.sendStop=null)},e.exports=r},{debug:void 0,events:3,inherits:54}],26:[function(t,e,n){(function(n){"use strict";var r=t("inherits"),i=t("../iframe"),o=t("../../utils/object");e.exports=function(t){function e(e,n){i.call(this,t.transportName,e,n)}return r(e,i),e.enabled=function(e,r){if(!n.document)return!1;var s=o.extend({},r);return s.sameOrigin=!0,t.enabled(s)&&i.enabled()},e.transportName="iframe-"+t.transportName,e.needBody=!0,e.roundTrips=i.roundTrips+t.roundTrips-1,e.facadeTransport=t,e}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../../utils/object":49,"../iframe":22,inherits:54}],27:[function(t,e,n){"use strict";function r(t,e,n){o.call(this),this.Receiver=t,this.receiveUrl=e,this.AjaxObject=n,this._scheduleReceiver()}var i=t("inherits"),o=t("events").EventEmitter;i(r,o),r.prototype._scheduleReceiver=function(){var t=this,e=this.poll=new this.Receiver(this.receiveUrl,this.AjaxObject);e.on("message",function(e){t.emit("message",e)}),e.once("close",function(n,r){t.poll=e=null,t.pollIsClosing||("network"===r?t._scheduleReceiver():(t.emit("close",n||1006,r),t.removeAllListeners()))})},r.prototype.abort=function(){this.removeAllListeners(),this.pollIsClosing=!0,this.poll&&this.poll.abort()},e.exports=r},{debug:void 0,events:3,inherits:54}],28:[function(t,e,n){"use strict";function r(t,e,n,r,i){var l=o.addPath(t,e),u=this;s.call(this,t,n),this.poll=new a(r,l,i),this.poll.on("message",function(t){u.emit("message",t)}),this.poll.once("close",function(t,e){u.poll=null,u.emit("close",t,e),u.close()})}var i=t("inherits"),o=t("../../utils/url"),s=t("./buffered-sender"),a=t("./polling");i(r,s),r.prototype.close=function(){s.prototype.close.call(this),this.removeAllListeners(),this.poll&&(this.poll.abort(),this.poll=null)},e.exports=r},{"../../utils/url":52,"./buffered-sender":25,"./polling":27,debug:void 0,inherits:54}],29:[function(t,e,n){"use strict";function r(t){o.call(this);var e=this,n=this.es=new s(t);n.onmessage=function(t){e.emit("message",decodeURI(t.data))},n.onerror=function(t){var r=2!==n.readyState?"network":"permanent";e._cleanup(),e._close(r)}}var i=t("inherits"),o=t("events").EventEmitter,s=t("eventsource");i(r,o),r.prototype.abort=function(){this._cleanup(),this._close("user")},r.prototype._cleanup=function(){var t=this.es;t&&(t.onmessage=t.onerror=null,t.close(),this.es=null)},r.prototype._close=function(t){var e=this;setTimeout(function(){e.emit("close",null,t),e.removeAllListeners()},200)},e.exports=r},{debug:void 0,events:3,eventsource:18,inherits:54}],30:[function(t,e,n){(function(n){"use strict";function r(t){a.call(this);var e=this;o.polluteGlobalNamespace(),this.id="a"+l.string(6),t=s.addQuery(t,"c="+decodeURIComponent(o.WPrefix+"."+this.id));var i=r.htmlfileEnabled?o.createHtmlfile:o.createIframe;n[o.WPrefix][this.id]={start:function(){e.iframeObj.loaded()},message:function(t){e.emit("message",t)},stop:function(){e._cleanup(),e._close("network")}},this.iframeObj=i(t,function(){e._cleanup(),e._close("permanent")})}var i=t("inherits"),o=t("../../utils/iframe"),s=t("../../utils/url"),a=t("events").EventEmitter,l=t("../../utils/random");i(r,a),r.prototype.abort=function(){this._cleanup(),this._close("user")},r.prototype._cleanup=function(){this.iframeObj&&(this.iframeObj.cleanup(),this.iframeObj=null),delete n[o.WPrefix][this.id]},r.prototype._close=function(t){this.emit("close",null,t),this.removeAllListeners()},r.htmlfileEnabled=!1;var u=["Active"].concat("Object").join("X");if(u in n)try{r.htmlfileEnabled=!!new n[u]("htmlfile")}catch(t){}r.enabled=r.htmlfileEnabled||o.iframeEnabled,e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../../utils/iframe":47,"../../utils/random":50,"../../utils/url":52,debug:void 0,events:3,inherits:54}],31:[function(t,e,n){(function(n){"use strict";function r(t){var e=this;u.call(this),i.polluteGlobalNamespace(),this.id="a"+o.string(6);var s=a.addQuery(t,"c="+encodeURIComponent(i.WPrefix+"."+this.id));n[i.WPrefix][this.id]=this._callback.bind(this),this._createScript(s),this.timeoutId=setTimeout(function(){e._abort(new Error("JSONP script loaded abnormally (timeout)"))},r.timeout)}var i=t("../../utils/iframe"),o=t("../../utils/random"),s=t("../../utils/browser"),a=t("../../utils/url"),l=t("inherits"),u=t("events").EventEmitter;l(r,u),r.prototype.abort=function(){if(n[i.WPrefix][this.id]){var t=new Error("JSONP user aborted read");t.code=1e3,this._abort(t)}},r.timeout=35e3,r.scriptErrorTimeout=1e3,r.prototype._callback=function(t){this._cleanup(),this.aborting||(t&&this.emit("message",t),this.emit("close",null,"network"),this.removeAllListeners())},r.prototype._abort=function(t){this._cleanup(),this.aborting=!0,this.emit("close",t.code,t.message),this.removeAllListeners()},r.prototype._cleanup=function(){if(clearTimeout(this.timeoutId),this.script2&&(this.script2.parentNode.removeChild(this.script2),this.script2=null),this.script){var t=this.script;t.parentNode.removeChild(t),t.onreadystatechange=t.onerror=t.onload=t.onclick=null,this.script=null}delete n[i.WPrefix][this.id]},r.prototype._scriptError=function(){var t=this;this.errorTimer||(this.errorTimer=setTimeout(function(){t.loadedOkay||t._abort(new Error("JSONP script loaded abnormally (onerror)"))},r.scriptErrorTimeout))},r.prototype._createScript=function(t){var e,r=this,i=this.script=n.document.createElement("script");if(i.id="a"+o.string(8),i.src=t,i.type="text/javascript",i.charset="UTF-8",i.onerror=this._scriptError.bind(this),i.onload=function(){r._abort(new Error("JSONP script loaded abnormally (onload)"))},i.onreadystatechange=function(){if(/loaded|closed/.test(i.readyState)){if(i&&i.htmlFor&&i.onclick){r.loadedOkay=!0;try{i.onclick()}catch(t){}}i&&r._abort(new Error("JSONP script loaded abnormally (onreadystatechange)"))}},"undefined"==typeof i.async&&n.document.attachEvent)if(s.isOpera())e=this.script2=n.document.createElement("script"),e.text="try{var a = document.getElementById('"+i.id+"'); if(a)a.onerror();}catch(x){};",
  3 +i.async=e.async=!1;else{try{i.htmlFor=i.id,i.event="onclick"}catch(t){}i.async=!0}"undefined"!=typeof i.async&&(i.async=!0);var a=n.document.getElementsByTagName("head")[0];a.insertBefore(i,a.firstChild),e&&a.insertBefore(e,a.firstChild)},e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../../utils/browser":44,"../../utils/iframe":47,"../../utils/random":50,"../../utils/url":52,debug:void 0,events:3,inherits:54}],32:[function(t,e,n){"use strict";function r(t,e){o.call(this);var n=this;this.bufferPosition=0,this.xo=new e("POST",t,null),this.xo.on("chunk",this._chunkHandler.bind(this)),this.xo.once("finish",function(t,e){n._chunkHandler(t,e),n.xo=null;var r=200===t?"network":"permanent";n.emit("close",null,r),n._cleanup()})}var i=t("inherits"),o=t("events").EventEmitter;i(r,o),r.prototype._chunkHandler=function(t,e){if(200===t&&e)for(var n=-1;;this.bufferPosition+=n+1){var r=e.slice(this.bufferPosition);if(n=r.indexOf("\n"),n===-1)break;var i=r.slice(0,n);i&&this.emit("message",i)}},r.prototype._cleanup=function(){this.removeAllListeners()},r.prototype.abort=function(){this.xo&&(this.xo.close(),this.emit("close",null,"user"),this.xo=null),this._cleanup()},e.exports=r},{debug:void 0,events:3,inherits:54}],33:[function(t,e,n){(function(n){"use strict";function r(t){try{return n.document.createElement('<iframe name="'+t+'">')}catch(r){var e=n.document.createElement("iframe");return e.name=t,e}}function i(){o=n.document.createElement("form"),o.style.display="none",o.style.position="absolute",o.method="POST",o.enctype="application/x-www-form-urlencoded",o.acceptCharset="UTF-8",s=n.document.createElement("textarea"),s.name="d",o.appendChild(s),n.document.body.appendChild(o)}var o,s,a=t("../../utils/random"),l=t("../../utils/url");e.exports=function(t,e,n){o||i();var u="a"+a.string(8);o.target=u,o.action=l.addQuery(l.addPath(t,"/jsonp_send"),"i="+u);var c=r(u);c.id=u,c.style.display="none",o.appendChild(c);try{s.value=e}catch(t){}o.submit();var f=function(t){c.onerror&&(c.onreadystatechange=c.onerror=c.onload=null,setTimeout(function(){c.parentNode.removeChild(c),c=null},500),s.value="",n(t))};return c.onerror=function(){f()},c.onload=function(){f()},c.onreadystatechange=function(t){"complete"===c.readyState&&f()},function(){f(new Error("Aborted"))}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../../utils/random":50,"../../utils/url":52,debug:void 0}],34:[function(t,e,n){(function(n){"use strict";function r(t,e,n){var r=this;i.call(this),setTimeout(function(){r._start(t,e,n)},0)}var i=t("events").EventEmitter,o=t("inherits"),s=t("../../utils/event"),a=t("../../utils/browser"),l=t("../../utils/url");o(r,i),r.prototype._start=function(t,e,r){var i=this,o=new n.XDomainRequest;e=l.addQuery(e,"t="+ +new Date),o.onerror=function(){i._error()},o.ontimeout=function(){i._error()},o.onprogress=function(){i.emit("chunk",200,o.responseText)},o.onload=function(){i.emit("finish",200,o.responseText),i._cleanup(!1)},this.xdr=o,this.unloadRef=s.unloadAdd(function(){i._cleanup(!0)});try{this.xdr.open(t,e),this.timeout&&(this.xdr.timeout=this.timeout),this.xdr.send(r)}catch(t){this._error()}},r.prototype._error=function(){this.emit("finish",0,""),this._cleanup(!1)},r.prototype._cleanup=function(t){if(this.xdr){if(this.removeAllListeners(),s.unloadDel(this.unloadRef),this.xdr.ontimeout=this.xdr.onerror=this.xdr.onprogress=this.xdr.onload=null,t)try{this.xdr.abort()}catch(t){}this.unloadRef=this.xdr=null}},r.prototype.close=function(){this._cleanup(!0)},r.enabled=!(!n.XDomainRequest||!a.hasDomain()),e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../../utils/browser":44,"../../utils/event":46,"../../utils/url":52,debug:void 0,events:3,inherits:54}],35:[function(t,e,n){"use strict";function r(t,e,n,r){o.call(this,t,e,n,r)}var i=t("inherits"),o=t("../driver/xhr");i(r,o),r.enabled=o.enabled&&o.supportsCORS,e.exports=r},{"../driver/xhr":17,inherits:54}],36:[function(t,e,n){"use strict";function r(){var t=this;i.call(this),this.to=setTimeout(function(){t.emit("finish",200,"{}")},r.timeout)}var i=t("events").EventEmitter,o=t("inherits");o(r,i),r.prototype.close=function(){clearTimeout(this.to)},r.timeout=2e3,e.exports=r},{events:3,inherits:54}],37:[function(t,e,n){"use strict";function r(t,e,n){o.call(this,t,e,n,{noCredentials:!0})}var i=t("inherits"),o=t("../driver/xhr");i(r,o),r.enabled=o.enabled,e.exports=r},{"../driver/xhr":17,inherits:54}],38:[function(t,e,n){"use strict";function r(t,e,n){if(!r.enabled())throw new Error("Transport created when disabled");a.call(this);var s=this,u=o.addPath(t,"/websocket");u="https"===u.slice(0,5)?"wss"+u.slice(5):"ws"+u.slice(4),this.url=u,this.ws=new l(this.url,[],n),this.ws.onmessage=function(t){s.emit("message",t.data)},this.unloadRef=i.unloadAdd(function(){s.ws.close()}),this.ws.onclose=function(t){s.emit("close",t.code,t.reason),s._cleanup()},this.ws.onerror=function(t){s.emit("close",1006,"WebSocket connection broken"),s._cleanup()}}var i=t("../utils/event"),o=t("../utils/url"),s=t("inherits"),a=t("events").EventEmitter,l=t("./driver/websocket");s(r,a),r.prototype.send=function(t){var e="["+t+"]";this.ws.send(e)},r.prototype.close=function(){var t=this.ws;this._cleanup(),t&&t.close()},r.prototype._cleanup=function(){var t=this.ws;t&&(t.onmessage=t.onclose=t.onerror=null),i.unloadDel(this.unloadRef),this.unloadRef=this.ws=null,this.removeAllListeners()},r.enabled=function(){return!!l},r.transportName="websocket",r.roundTrips=2,e.exports=r},{"../utils/event":46,"../utils/url":52,"./driver/websocket":19,debug:void 0,events:3,inherits:54}],39:[function(t,e,n){"use strict";function r(t){if(!l.enabled)throw new Error("Transport created when disabled");o.call(this,t,"/xhr",a,l)}var i=t("inherits"),o=t("./lib/ajax-based"),s=t("./xdr-streaming"),a=t("./receiver/xhr"),l=t("./sender/xdr");i(r,o),r.enabled=s.enabled,r.transportName="xdr-polling",r.roundTrips=2,e.exports=r},{"./lib/ajax-based":24,"./receiver/xhr":32,"./sender/xdr":34,"./xdr-streaming":40,inherits:54}],40:[function(t,e,n){"use strict";function r(t){if(!a.enabled)throw new Error("Transport created when disabled");o.call(this,t,"/xhr_streaming",s,a)}var i=t("inherits"),o=t("./lib/ajax-based"),s=t("./receiver/xhr"),a=t("./sender/xdr");i(r,o),r.enabled=function(t){return!t.cookie_needed&&!t.nullOrigin&&(a.enabled&&t.sameScheme)},r.transportName="xdr-streaming",r.roundTrips=2,e.exports=r},{"./lib/ajax-based":24,"./receiver/xhr":32,"./sender/xdr":34,inherits:54}],41:[function(t,e,n){"use strict";function r(t){if(!l.enabled&&!a.enabled)throw new Error("Transport created when disabled");o.call(this,t,"/xhr",s,a)}var i=t("inherits"),o=t("./lib/ajax-based"),s=t("./receiver/xhr"),a=t("./sender/xhr-cors"),l=t("./sender/xhr-local");i(r,o),r.enabled=function(t){return!t.nullOrigin&&(!(!l.enabled||!t.sameOrigin)||a.enabled)},r.transportName="xhr-polling",r.roundTrips=2,e.exports=r},{"./lib/ajax-based":24,"./receiver/xhr":32,"./sender/xhr-cors":35,"./sender/xhr-local":37,inherits:54}],42:[function(t,e,n){(function(n){"use strict";function r(t){if(!l.enabled&&!a.enabled)throw new Error("Transport created when disabled");o.call(this,t,"/xhr_streaming",s,a)}var i=t("inherits"),o=t("./lib/ajax-based"),s=t("./receiver/xhr"),a=t("./sender/xhr-cors"),l=t("./sender/xhr-local"),u=t("../utils/browser");i(r,o),r.enabled=function(t){return!t.nullOrigin&&(!u.isOpera()&&a.enabled)},r.transportName="xhr-streaming",r.roundTrips=2,r.needBody=!!n.document,e.exports=r}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../utils/browser":44,"./lib/ajax-based":24,"./receiver/xhr":32,"./sender/xhr-cors":35,"./sender/xhr-local":37,inherits:54}],43:[function(t,e,n){(function(t){"use strict";t.crypto&&t.crypto.getRandomValues?e.exports.randomBytes=function(e){var n=new Uint8Array(e);return t.crypto.getRandomValues(n),n}:e.exports.randomBytes=function(t){for(var e=new Array(t),n=0;n<t;n++)e[n]=Math.floor(256*Math.random());return e}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],44:[function(t,e,n){(function(t){"use strict";e.exports={isOpera:function(){return t.navigator&&/opera/i.test(t.navigator.userAgent)},isKonqueror:function(){return t.navigator&&/konqueror/i.test(t.navigator.userAgent)},hasDomain:function(){if(!t.document)return!0;try{return!!t.document.domain}catch(t){return!1}}}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],45:[function(t,e,n){"use strict";var r,i=t("json3"),o=/[\x00-\x1f\ud800-\udfff\ufffe\uffff\u0300-\u0333\u033d-\u0346\u034a-\u034c\u0350-\u0352\u0357-\u0358\u035c-\u0362\u0374\u037e\u0387\u0591-\u05af\u05c4\u0610-\u0617\u0653-\u0654\u0657-\u065b\u065d-\u065e\u06df-\u06e2\u06eb-\u06ec\u0730\u0732-\u0733\u0735-\u0736\u073a\u073d\u073f-\u0741\u0743\u0745\u0747\u07eb-\u07f1\u0951\u0958-\u095f\u09dc-\u09dd\u09df\u0a33\u0a36\u0a59-\u0a5b\u0a5e\u0b5c-\u0b5d\u0e38-\u0e39\u0f43\u0f4d\u0f52\u0f57\u0f5c\u0f69\u0f72-\u0f76\u0f78\u0f80-\u0f83\u0f93\u0f9d\u0fa2\u0fa7\u0fac\u0fb9\u1939-\u193a\u1a17\u1b6b\u1cda-\u1cdb\u1dc0-\u1dcf\u1dfc\u1dfe\u1f71\u1f73\u1f75\u1f77\u1f79\u1f7b\u1f7d\u1fbb\u1fbe\u1fc9\u1fcb\u1fd3\u1fdb\u1fe3\u1feb\u1fee-\u1fef\u1ff9\u1ffb\u1ffd\u2000-\u2001\u20d0-\u20d1\u20d4-\u20d7\u20e7-\u20e9\u2126\u212a-\u212b\u2329-\u232a\u2adc\u302b-\u302c\uaab2-\uaab3\uf900-\ufa0d\ufa10\ufa12\ufa15-\ufa1e\ufa20\ufa22\ufa25-\ufa26\ufa2a-\ufa2d\ufa30-\ufa6d\ufa70-\ufad9\ufb1d\ufb1f\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufb4e\ufff0-\uffff]/g,s=function(t){var e,n={},r=[];for(e=0;e<65536;e++)r.push(String.fromCharCode(e));return t.lastIndex=0,r.join("").replace(t,function(t){return n[t]="\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4),""}),t.lastIndex=0,n};e.exports={quote:function(t){var e=i.stringify(t);return o.lastIndex=0,o.test(e)?(r||(r=s(o)),e.replace(o,function(t){return r[t]})):e}}},{json3:55}],46:[function(t,e,n){(function(n){"use strict";var r=t("./random"),i={},o=!1,s=n.chrome&&n.chrome.app&&n.chrome.app.runtime;e.exports={attachEvent:function(t,e){"undefined"!=typeof n.addEventListener?n.addEventListener(t,e,!1):n.document&&n.attachEvent&&(n.document.attachEvent("on"+t,e),n.attachEvent("on"+t,e))},detachEvent:function(t,e){"undefined"!=typeof n.addEventListener?n.removeEventListener(t,e,!1):n.document&&n.detachEvent&&(n.document.detachEvent("on"+t,e),n.detachEvent("on"+t,e))},unloadAdd:function(t){if(s)return null;var e=r.string(8);return i[e]=t,o&&setTimeout(this.triggerUnloadCallbacks,0),e},unloadDel:function(t){t in i&&delete i[t]},triggerUnloadCallbacks:function(){for(var t in i)i[t](),delete i[t]}};var a=function(){o||(o=!0,e.exports.triggerUnloadCallbacks())};s||e.exports.attachEvent("unload",a)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./random":50}],47:[function(t,e,n){(function(n){"use strict";var r=t("./event"),i=t("json3"),o=t("./browser");e.exports={WPrefix:"_jp",currentWindowId:null,polluteGlobalNamespace:function(){e.exports.WPrefix in n||(n[e.exports.WPrefix]={})},postMessage:function(t,r){n.parent!==n&&n.parent.postMessage(i.stringify({windowId:e.exports.currentWindowId,type:t,data:r||""}),"*")},createIframe:function(t,e){var i,o,s=n.document.createElement("iframe"),a=function(){clearTimeout(i);try{s.onload=null}catch(t){}s.onerror=null},l=function(){s&&(a(),setTimeout(function(){s&&s.parentNode.removeChild(s),s=null},0),r.unloadDel(o))},u=function(t){s&&(l(),e(t))},c=function(t,e){try{setTimeout(function(){s&&s.contentWindow&&s.contentWindow.postMessage(t,e)},0)}catch(t){}};return s.src=t,s.style.display="none",s.style.position="absolute",s.onerror=function(){u("onerror")},s.onload=function(){clearTimeout(i),i=setTimeout(function(){u("onload timeout")},2e3)},n.document.body.appendChild(s),i=setTimeout(function(){u("timeout")},15e3),o=r.unloadAdd(l),{post:c,cleanup:l,loaded:a}},createHtmlfile:function(t,i){var o,s,a,l=["Active"].concat("Object").join("X"),u=new n[l]("htmlfile"),c=function(){clearTimeout(o),a.onerror=null},f=function(){u&&(c(),r.unloadDel(s),a.parentNode.removeChild(a),a=u=null,CollectGarbage())},h=function(t){u&&(f(),i(t))},d=function(t,e){try{setTimeout(function(){a&&a.contentWindow&&a.contentWindow.postMessage(t,e)},0)}catch(t){}};u.open(),u.write('<html><script>document.domain="'+n.document.domain+'";</script></html>'),u.close(),u.parentWindow[e.exports.WPrefix]=n[e.exports.WPrefix];var p=u.createElement("div");return u.body.appendChild(p),a=u.createElement("iframe"),p.appendChild(a),a.src=t,a.onerror=function(){h("onerror")},o=setTimeout(function(){h("timeout")},15e3),s=r.unloadAdd(f),{post:d,cleanup:f,loaded:c}}},e.exports.iframeEnabled=!1,n.document&&(e.exports.iframeEnabled=("function"==typeof n.postMessage||"object"==typeof n.postMessage)&&!o.isKonqueror())}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./browser":44,"./event":46,debug:void 0,json3:55}],48:[function(t,e,n){(function(t){"use strict";var n={};["log","debug","warn"].forEach(function(e){var r;try{r=t.console&&t.console[e]&&t.console[e].apply}catch(t){}n[e]=r?function(){return t.console[e].apply(t.console,arguments)}:"log"===e?function(){}:n.log}),e.exports=n}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],49:[function(t,e,n){"use strict";e.exports={isObject:function(t){var e=typeof t;return"function"===e||"object"===e&&!!t},extend:function(t){if(!this.isObject(t))return t;for(var e,n,r=1,i=arguments.length;r<i;r++){e=arguments[r];for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])}return t}}},{}],50:[function(t,e,n){"use strict";var r=t("crypto"),i="abcdefghijklmnopqrstuvwxyz012345";e.exports={string:function(t){for(var e=i.length,n=r.randomBytes(t),o=[],s=0;s<t;s++)o.push(i.substr(n[s]%e,1));return o.join("")},number:function(t){return Math.floor(Math.random()*t)},numberString:function(t){var e=(""+(t-1)).length,n=new Array(e+1).join("0");return(n+this.number(t)).slice(-e)}}},{crypto:43}],51:[function(t,e,n){"use strict";e.exports=function(t){return{filterToEnabled:function(e,n){var r={main:[],facade:[]};return e?"string"==typeof e&&(e=[e]):e=[],t.forEach(function(t){t&&("websocket"===t.transportName&&n.websocket===!1||e.length&&e.indexOf(t.transportName)===-1||t.enabled(n)&&(r.main.push(t),t.facadeTransport&&r.facade.push(t.facadeTransport)))}),r}}}},{debug:void 0}],52:[function(t,e,n){"use strict";var r=t("url-parse");e.exports={getOrigin:function(t){if(!t)return null;var e=new r(t);if("file:"===e.protocol)return null;var n=e.port;return n||(n="https:"===e.protocol?"443":"80"),e.protocol+"//"+e.hostname+":"+n},isOriginEqual:function(t,e){var n=this.getOrigin(t)===this.getOrigin(e);return n},isSchemeEqual:function(t,e){return t.split(":")[0]===e.split(":")[0]},addPath:function(t,e){var n=t.split("?");return n[0]+e+(n[1]?"?"+n[1]:"")},addQuery:function(t,e){return t+(t.indexOf("?")===-1?"?"+e:"&"+e)}}},{debug:void 0,"url-parse":58}],53:[function(t,e,n){e.exports="1.1.2"},{}],54:[function(t,e,n){"function"==typeof Object.create?e.exports=function(t,e){t.super_=e,t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(t,e){t.super_=e;var n=function(){};n.prototype=e.prototype,t.prototype=new n,t.prototype.constructor=t}},{}],55:[function(e,n,r){(function(e){(function(){function i(t,e){function n(t){if(n[t]!==m)return n[t];var i;if("bug-string-char-index"==t)i="a"!="a"[0];else if("json"==t)i=n("json-stringify")&&n("json-parse");else{var s,a='{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';if("json-stringify"==t){var l=e.stringify,c="function"==typeof l&&g;if(c){(s=function(){return 1}).toJSON=s;try{c="0"===l(0)&&"0"===l(new r)&&'""'==l(new o)&&l(y)===m&&l(m)===m&&l()===m&&"1"===l(s)&&"[1]"==l([s])&&"[null]"==l([m])&&"null"==l(null)&&"[null,null,null]"==l([m,y,null])&&l({a:[s,!0,!1,null,"\0\b\n\f\r\t"]})==a&&"1"===l(null,s)&&"[\n 1,\n 2\n]"==l([1,2],null,1)&&'"-271821-04-20T00:00:00.000Z"'==l(new u((-864e13)))&&'"+275760-09-13T00:00:00.000Z"'==l(new u(864e13))&&'"-000001-01-01T00:00:00.000Z"'==l(new u((-621987552e5)))&&'"1969-12-31T23:59:59.999Z"'==l(new u((-1)))}catch(t){c=!1}}i=c}if("json-parse"==t){var f=e.parse;if("function"==typeof f)try{if(0===f("0")&&!f(!1)){s=f(a);var h=5==s.a.length&&1===s.a[0];if(h){try{h=!f('"\t"')}catch(t){}if(h)try{h=1!==f("01")}catch(t){}if(h)try{h=1!==f("1.")}catch(t){}}}}catch(t){h=!1}i=h}}return n[t]=!!i}t||(t=l.Object()),e||(e=l.Object());var r=t.Number||l.Number,o=t.String||l.String,a=t.Object||l.Object,u=t.Date||l.Date,c=t.SyntaxError||l.SyntaxError,f=t.TypeError||l.TypeError,h=t.Math||l.Math,d=t.JSON||l.JSON;"object"==typeof d&&d&&(e.stringify=d.stringify,e.parse=d.parse);var p,v,m,b=a.prototype,y=b.toString,g=new u((-0xc782b5b800cec));try{g=g.getUTCFullYear()==-109252&&0===g.getUTCMonth()&&1===g.getUTCDate()&&10==g.getUTCHours()&&37==g.getUTCMinutes()&&6==g.getUTCSeconds()&&708==g.getUTCMilliseconds()}catch(t){}if(!n("json")){var w="[object Function]",x="[object Date]",_="[object Number]",E="[object String]",j="[object Array]",T="[object Boolean]",S=n("bug-string-char-index");if(!g)var O=h.floor,C=[0,31,59,90,120,151,181,212,243,273,304,334],A=function(t,e){return C[e]+365*(t-1970)+O((t-1969+(e=+(e>1)))/4)-O((t-1901+e)/100)+O((t-1601+e)/400)};if((p=b.hasOwnProperty)||(p=function(t){var e,n={};return(n.__proto__=null,n.__proto__={toString:1},n).toString!=y?p=function(t){var e=this.__proto__,n=t in(this.__proto__=null,this);return this.__proto__=e,n}:(e=n.constructor,p=function(t){var n=(this.constructor||e).prototype;return t in this&&!(t in n&&this[t]===n[t])}),n=null,p.call(this,t)}),v=function(t,e){var n,r,i,o=0;(n=function(){this.valueOf=0}).prototype.valueOf=0,r=new n;for(i in r)p.call(r,i)&&o++;return n=r=null,o?v=2==o?function(t,e){var n,r={},i=y.call(t)==w;for(n in t)i&&"prototype"==n||p.call(r,n)||!(r[n]=1)||!p.call(t,n)||e(n)}:function(t,e){var n,r,i=y.call(t)==w;for(n in t)i&&"prototype"==n||!p.call(t,n)||(r="constructor"===n)||e(n);(r||p.call(t,n="constructor"))&&e(n)}:(r=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"],v=function(t,e){var n,i,o=y.call(t)==w,a=!o&&"function"!=typeof t.constructor&&s[typeof t.hasOwnProperty]&&t.hasOwnProperty||p;for(n in t)o&&"prototype"==n||!a.call(t,n)||e(n);for(i=r.length;n=r[--i];a.call(t,n)&&e(n));}),v(t,e)},!n("json-stringify")){var N={92:"\\\\",34:'\\"',8:"\\b",12:"\\f",10:"\\n",13:"\\r",9:"\\t"},k="000000",I=function(t,e){return(k+(e||0)).slice(-t)},P="\\u00",L=function(t){for(var e='"',n=0,r=t.length,i=!S||r>10,o=i&&(S?t.split(""):t);n<r;n++){var s=t.charCodeAt(n);switch(s){case 8:case 9:case 10:case 12:case 13:case 34:case 92:e+=N[s];break;default:if(s<32){e+=P+I(2,s.toString(16));break}e+=i?o[n]:t.charAt(n)}}return e+'"'},R=function(t,e,n,r,i,o,s){var a,l,u,c,h,d,b,g,w,S,C,N,k,P,U,M;try{a=e[t]}catch(t){}if("object"==typeof a&&a)if(l=y.call(a),l!=x||p.call(a,"toJSON"))"function"==typeof a.toJSON&&(l!=_&&l!=E&&l!=j||p.call(a,"toJSON"))&&(a=a.toJSON(t));else if(a>-1/0&&a<1/0){if(A){for(h=O(a/864e5),u=O(h/365.2425)+1970-1;A(u+1,0)<=h;u++);for(c=O((h-A(u,0))/30.42);A(u,c+1)<=h;c++);h=1+h-A(u,c),d=(a%864e5+864e5)%864e5,b=O(d/36e5)%24,g=O(d/6e4)%60,w=O(d/1e3)%60,S=d%1e3}else u=a.getUTCFullYear(),c=a.getUTCMonth(),h=a.getUTCDate(),b=a.getUTCHours(),g=a.getUTCMinutes(),w=a.getUTCSeconds(),S=a.getUTCMilliseconds();a=(u<=0||u>=1e4?(u<0?"-":"+")+I(6,u<0?-u:u):I(4,u))+"-"+I(2,c+1)+"-"+I(2,h)+"T"+I(2,b)+":"+I(2,g)+":"+I(2,w)+"."+I(3,S)+"Z"}else a=null;if(n&&(a=n.call(e,t,a)),null===a)return"null";if(l=y.call(a),l==T)return""+a;if(l==_)return a>-1/0&&a<1/0?""+a:"null";if(l==E)return L(""+a);if("object"==typeof a){for(P=s.length;P--;)if(s[P]===a)throw f();if(s.push(a),C=[],U=o,o+=i,l==j){for(k=0,P=a.length;k<P;k++)N=R(k,a,n,r,i,o,s),C.push(N===m?"null":N);M=C.length?i?"[\n"+o+C.join(",\n"+o)+"\n"+U+"]":"["+C.join(",")+"]":"[]"}else v(r||a,function(t){var e=R(t,a,n,r,i,o,s);e!==m&&C.push(L(t)+":"+(i?" ":"")+e)}),M=C.length?i?"{\n"+o+C.join(",\n"+o)+"\n"+U+"}":"{"+C.join(",")+"}":"{}";return s.pop(),M}};e.stringify=function(t,e,n){var r,i,o,a;if(s[typeof e]&&e)if((a=y.call(e))==w)i=e;else if(a==j){o={};for(var l,u=0,c=e.length;u<c;l=e[u++],a=y.call(l),(a==E||a==_)&&(o[l]=1));}if(n)if((a=y.call(n))==_){if((n-=n%1)>0)for(r="",n>10&&(n=10);r.length<n;r+=" ");}else a==E&&(r=n.length<=10?n:n.slice(0,10));return R("",(l={},l[""]=t,l),i,o,r,"",[])}}if(!n("json-parse")){var U,M,q=o.fromCharCode,D={92:"\\",34:'"',47:"/",98:"\b",116:"\t",110:"\n",102:"\f",114:"\r"},W=function(){throw U=M=null,c()},J=function(){for(var t,e,n,r,i,o=M,s=o.length;U<s;)switch(i=o.charCodeAt(U)){case 9:case 10:case 13:case 32:U++;break;case 123:case 125:case 91:case 93:case 58:case 44:return t=S?o.charAt(U):o[U],U++,t;case 34:for(t="@",U++;U<s;)if(i=o.charCodeAt(U),i<32)W();else if(92==i)switch(i=o.charCodeAt(++U)){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:t+=D[i],U++;break;case 117:for(e=++U,n=U+4;U<n;U++)i=o.charCodeAt(U),i>=48&&i<=57||i>=97&&i<=102||i>=65&&i<=70||W();t+=q("0x"+o.slice(e,U));break;default:W()}else{if(34==i)break;for(i=o.charCodeAt(U),e=U;i>=32&&92!=i&&34!=i;)i=o.charCodeAt(++U);t+=o.slice(e,U)}if(34==o.charCodeAt(U))return U++,t;W();default:if(e=U,45==i&&(r=!0,i=o.charCodeAt(++U)),i>=48&&i<=57){for(48==i&&(i=o.charCodeAt(U+1),i>=48&&i<=57)&&W(),r=!1;U<s&&(i=o.charCodeAt(U),i>=48&&i<=57);U++);if(46==o.charCodeAt(U)){for(n=++U;n<s&&(i=o.charCodeAt(n),i>=48&&i<=57);n++);n==U&&W(),U=n}if(i=o.charCodeAt(U),101==i||69==i){for(i=o.charCodeAt(++U),43!=i&&45!=i||U++,n=U;n<s&&(i=o.charCodeAt(n),i>=48&&i<=57);n++);n==U&&W(),U=n}return+o.slice(e,U)}if(r&&W(),"true"==o.slice(U,U+4))return U+=4,!0;if("false"==o.slice(U,U+5))return U+=5,!1;if("null"==o.slice(U,U+4))return U+=4,null;W()}return"$"},B=function(t){var e,n;if("$"==t&&W(),"string"==typeof t){if("@"==(S?t.charAt(0):t[0]))return t.slice(1);if("["==t){for(e=[];t=J(),"]"!=t;n||(n=!0))n&&(","==t?(t=J(),"]"==t&&W()):W()),","==t&&W(),e.push(B(t));return e}if("{"==t){for(e={};t=J(),"}"!=t;n||(n=!0))n&&(","==t?(t=J(),"}"==t&&W()):W()),","!=t&&"string"==typeof t&&"@"==(S?t.charAt(0):t[0])&&":"==J()||W(),e[t.slice(1)]=B(J());return e}W()}return t},G=function(t,e,n){var r=F(t,e,n);r===m?delete t[e]:t[e]=r},F=function(t,e,n){var r,i=t[e];if("object"==typeof i&&i)if(y.call(i)==j)for(r=i.length;r--;)G(i,r,n);else v(i,function(t){G(i,t,n)});return n.call(t,e,i)};e.parse=function(t,e){var n,r;return U=0,M=""+t,n=B(J()),"$"!=J()&&W(),U=M=null,e&&y.call(e)==w?F((r={},r[""]=n,r),"",e):n}}}return e.runInContext=i,e}var o="function"==typeof t&&t.amd,s={function:!0,object:!0},a=s[typeof r]&&r&&!r.nodeType&&r,l=s[typeof window]&&window||this,u=a&&s[typeof n]&&n&&!n.nodeType&&"object"==typeof e&&e;if(!u||u.global!==u&&u.window!==u&&u.self!==u||(l=u),a&&!o)i(l,a);else{var c=l.JSON,f=l.JSON3,h=!1,d=i(l,l.JSON3={noConflict:function(){return h||(h=!0,l.JSON=c,l.JSON3=f,c=f=null),d}});l.JSON={parse:d.parse,stringify:d.stringify}}o&&t(function(){return d})}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],56:[function(t,e,n){"use strict";function r(t){for(var e,n=/([^=?&]+)=?([^&]*)/g,r={};e=n.exec(t);r[decodeURIComponent(e[1])]=decodeURIComponent(e[2]));return r}function i(t,e){e=e||"";var n=[];"string"!=typeof e&&(e="?");for(var r in t)o.call(t,r)&&n.push(encodeURIComponent(r)+"="+encodeURIComponent(t[r]));return n.length?e+n.join("&"):""}var o=Object.prototype.hasOwnProperty;n.stringify=i,n.parse=r},{}],57:[function(t,e,n){"use strict";e.exports=function(t,e){if(e=e.split(":")[0],t=+t,!t)return!1;switch(e){case"http":case"ws":return 80!==t;case"https":case"wss":return 443!==t;case"ftp":return 21!==t;case"gopher":return 70!==t;case"file":return!1}return 0!==t}},{}],58:[function(t,e,n){"use strict";function r(t){var e=u.exec(t);return{protocol:e[1]?e[1].toLowerCase():"",slashes:!!e[2],rest:e[3]}}function i(t,e){for(var n=(e||"/").split("/").slice(0,-1).concat(t.split("/")),r=n.length,i=n[r-1],o=!1,s=0;r--;)"."===n[r]?n.splice(r,1):".."===n[r]?(n.splice(r,1),s++):s&&(0===r&&(o=!0),n.splice(r,1),s--);return o&&n.unshift(""),"."!==i&&".."!==i||n.push(""),n.join("/")}function o(t,e,n){if(!(this instanceof o))return new o(t,e,n);var u,f,h,d,p,v,m=c.slice(),b=typeof e,y=this,g=0;for("object"!==b&&"string"!==b&&(n=e,e=null),n&&"function"!=typeof n&&(n=l.parse),e=a(e),f=r(t||""),u=!f.protocol&&!f.slashes,y.slashes=f.slashes||u&&e.slashes,y.protocol=f.protocol||e.protocol||"",t=f.rest,f.slashes||(m[2]=[/(.*)/,"pathname"]);g<m.length;g++)d=m[g],h=d[0],v=d[1],h!==h?y[v]=t:"string"==typeof h?~(p=t.indexOf(h))&&("number"==typeof d[2]?(y[v]=t.slice(0,p),t=t.slice(p+d[2])):(y[v]=t.slice(p),t=t.slice(0,p))):(p=h.exec(t))&&(y[v]=p[1],t=t.slice(0,p.index)),y[v]=y[v]||(u&&d[3]?e[v]||"":""),d[4]&&(y[v]=y[v].toLowerCase());n&&(y.query=n(y.query)),u&&e.slashes&&"/"!==y.pathname.charAt(0)&&(""!==y.pathname||""!==e.pathname)&&(y.pathname=i(y.pathname,e.pathname)),s(y.port,y.protocol)||(y.host=y.hostname,y.port=""),y.username=y.password="",y.auth&&(d=y.auth.split(":"),y.username=d[0]||"",y.password=d[1]||""),y.origin=y.protocol&&y.host&&"file:"!==y.protocol?y.protocol+"//"+y.host:"null",y.href=y.toString()}var s=t("requires-port"),a=t("./lolcation"),l=t("querystringify"),u=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\S\s]*)/i,c=[["#","hash"],["?","query"],["/","pathname"],["@","auth",1],[NaN,"host",void 0,1,1],[/:(\d+)$/,"port",void 0,1],[NaN,"hostname",void 0,1,1]];o.prototype.set=function(t,e,n){var r=this;switch(t){case"query":"string"==typeof e&&e.length&&(e=(n||l.parse)(e)),r[t]=e;break;case"port":r[t]=e,s(e,r.protocol)?e&&(r.host=r.hostname+":"+e):(r.host=r.hostname,r[t]="");break;case"hostname":r[t]=e,r.port&&(e+=":"+r.port),r.host=e;break;case"host":r[t]=e,/:\d+$/.test(e)?(e=e.split(":"),r.port=e.pop(),r.hostname=e.join(":")):(r.hostname=e,r.port="");break;case"protocol":r.protocol=e.toLowerCase(),r.slashes=!n;break;case"pathname":r.pathname=e.length&&"/"!==e.charAt(0)?"/"+e:e;break;default:r[t]=e}for(var i=0;i<c.length;i++){var o=c[i];o[4]&&(r[o[1]]=r[o[1]].toLowerCase())}return r.origin=r.protocol&&r.host&&"file:"!==r.protocol?r.protocol+"//"+r.host:"null",r.href=r.toString(),r},o.prototype.toString=function(t){t&&"function"==typeof t||(t=l.stringify);var e,n=this,r=n.protocol;r&&":"!==r.charAt(r.length-1)&&(r+=":");var i=r+(n.slashes?"//":"");return n.username&&(i+=n.username,n.password&&(i+=":"+n.password),i+="@"),i+=n.host+n.pathname,e="object"==typeof n.query?t(n.query):n.query,e&&(i+="?"!==e.charAt(0)?"?"+e:e),n.hash&&(i+=n.hash),i},o.extractProtocol=r,o.location=a,o.qs=l,e.exports=o},{"./lolcation":59,querystringify:56,"requires-port":57}],59:[function(t,e,n){(function(n){"use strict";var r,i=/^[A-Za-z][A-Za-z0-9+-.]*:\/\//,o={hash:1,query:1};e.exports=function(e){e=e||n.location||{},r=r||t("./");var s,a={},l=typeof e;if("blob:"===e.protocol)a=new r(unescape(e.pathname),{});else if("string"===l){a=new r(e,{});for(s in o)delete a[s]}else if("object"===l){for(s in e)s in o||(a[s]=e[s]);void 0===a.slashes&&(a.slashes=i.test(e.href))}return a}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./":58}]},{},[1])(1)});
  4 +//# sourceMappingURL=sockjs.min.js.map
src/main/resources/static/assets/plugins/toastr/toastr.min.css 0 → 100644
  1 +/* * Note that this is toastr v2.1.3, the "latest" version in url has no more maintenance, * please go to https://cdnjs.com/libraries/toastr.js and pick a certain version you want to use, * make sure you copy the url from the website since the url may change between versions. * */ .toast-title{font-weight:700}.toast-message{-ms-word-wrap:break-word;word-wrap:break-word}.toast-message a,.toast-message label{color:#FFF}.toast-message a:hover{color:#CCC;text-decoration:none}.toast-close-button{position:relative;right:-.3em;top:-.3em;float:right;font-size:20px;font-weight:700;color:#FFF;-webkit-text-shadow:0 1px 0 #fff;text-shadow:0 1px 0 #fff;opacity:.8;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80);line-height:1}.toast-close-button:focus,.toast-close-button:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=40);filter:alpha(opacity=40)}.rtl .toast-close-button{left:-.3em;float:left;right:.3em}button.toast-close-button{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.toast-top-center{top:0;right:0;width:100%}.toast-bottom-center{bottom:0;right:0;width:100%}.toast-top-full-width{top:0;right:0;width:100%}.toast-bottom-full-width{bottom:0;right:0;width:100%}.toast-top-left{top:12px;left:12px}.toast-top-right{top:12px;right:12px}.toast-bottom-right{right:12px;bottom:12px}.toast-bottom-left{bottom:12px;left:12px}#toast-container{position:fixed;z-index:999999;pointer-events:none}#toast-container *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}#toast-container>div{position:relative;pointer-events:auto;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#FFF;opacity:.8;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80)}#toast-container>div.rtl{direction:rtl;padding:15px 50px 15px 15px;background-position:right 15px center}#toast-container>div:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100);cursor:pointer}#toast-container>.toast-info{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=)!important}#toast-container>.toast-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=)!important}#toast-container>.toast-success{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==)!important}#toast-container>.toast-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=)!important}#toast-container.toast-bottom-center>div,#toast-container.toast-top-center>div{width:300px;margin-left:auto;margin-right:auto}#toast-container.toast-bottom-full-width>div,#toast-container.toast-top-full-width>div{width:96%;margin-left:auto;margin-right:auto}.toast{background-color:#030303}.toast-success{background-color:#51A351}.toast-error{background-color:#BD362F}.toast-info{background-color:#2F96B4}.toast-warning{background-color:#F89406}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=40);filter:alpha(opacity=40)}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:11em}#toast-container>div.rtl{padding:8px 50px 8px 8px}#toast-container .toast-close-button{right:-.2em;top:-.2em}#toast-container .rtl .toast-close-button{left:-.2em;right:.2em}}@media all and (min-width:241px) and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:18em}#toast-container>div.rtl{padding:8px 50px 8px 8px}#toast-container .toast-close-button{right:-.2em;top:-.2em}#toast-container .rtl .toast-close-button{left:-.2em;right:.2em}}@media all and (min-width:481px) and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:25em}#toast-container>div.rtl{padding:15px 50px 15px 15px}}
0 \ No newline at end of file 2 \ No newline at end of file
src/main/resources/static/assets/plugins/toastr/toastr.min.js 0 → 100644
  1 +/*
  2 + * Note that this is toastr v2.1.3, the "latest" version in url has no more maintenance,
  3 + * please go to https://cdnjs.com/libraries/toastr.js and pick a certain version you want to use,
  4 + * make sure you copy the url from the website since the url may change between versions.
  5 + * */
  6 +!function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return g({type:O.error,iconClass:m().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=m()),v=e("#"+t.containerId),v.length?v:(n&&(v=d(t)),v)}function o(e,t,n){return g({type:O.info,iconClass:m().iconClasses.info,message:e,optionsOverride:n,title:t})}function s(e){C=e}function i(e,t,n){return g({type:O.success,iconClass:m().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return g({type:O.warning,iconClass:m().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e,t){var o=m();v||n(o),u(e,o,t)||l(o)}function c(t){var o=m();return v||n(o),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function l(t){for(var n=v.children(),o=n.length-1;o>=0;o--)u(e(n[o]),t)}function u(t,n,o){var s=!(!o||!o.force)&&o.force;return!(!t||!s&&0!==e(":focus",t).length)&&(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0)}function d(t){return v=e("<div/>").attr("id",t.containerId).addClass(t.positionClass),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,closeMethod:!1,closeDuration:!1,closeEasing:!1,closeOnHover:!0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",escapeHtml:!1,target:"body",closeHtml:'<button type="button">&times;</button>',closeClass:"toast-close-button",newestOnTop:!0,preventDuplicates:!1,progressBar:!1,progressClass:"toast-progress",rtl:!1}}function f(e){C&&C(e)}function g(t){function o(e){return null==e&&(e=""),e.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/'/g,"&#39;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function s(){c(),u(),d(),p(),g(),C(),l(),i()}function i(){var e="";switch(t.iconClass){case"toast-success":case"toast-info":e="polite";break;default:e="assertive"}I.attr("aria-live",e)}function a(){E.closeOnHover&&I.hover(H,D),!E.onclick&&E.tapToDismiss&&I.click(b),E.closeButton&&j&&j.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),E.onCloseClick&&E.onCloseClick(e),b(!0)}),E.onclick&&I.click(function(e){E.onclick(e),b()})}function r(){I.hide(),I[E.showMethod]({duration:E.showDuration,easing:E.showEasing,complete:E.onShown}),E.timeOut>0&&(k=setTimeout(b,E.timeOut),F.maxHideTime=parseFloat(E.timeOut),F.hideEta=(new Date).getTime()+F.maxHideTime,E.progressBar&&(F.intervalId=setInterval(x,10)))}function c(){t.iconClass&&I.addClass(E.toastClass).addClass(y)}function l(){E.newestOnTop?v.prepend(I):v.append(I)}function u(){if(t.title){var e=t.title;E.escapeHtml&&(e=o(t.title)),M.append(e).addClass(E.titleClass),I.append(M)}}function d(){if(t.message){var e=t.message;E.escapeHtml&&(e=o(t.message)),B.append(e).addClass(E.messageClass),I.append(B)}}function p(){E.closeButton&&(j.addClass(E.closeClass).attr("role","button"),I.prepend(j))}function g(){E.progressBar&&(q.addClass(E.progressClass),I.prepend(q))}function C(){E.rtl&&I.addClass("rtl")}function O(e,t){if(e.preventDuplicates){if(t.message===w)return!0;w=t.message}return!1}function b(t){var n=t&&E.closeMethod!==!1?E.closeMethod:E.hideMethod,o=t&&E.closeDuration!==!1?E.closeDuration:E.hideDuration,s=t&&E.closeEasing!==!1?E.closeEasing:E.hideEasing;if(!e(":focus",I).length||t)return clearTimeout(F.intervalId),I[n]({duration:o,easing:s,complete:function(){h(I),clearTimeout(k),E.onHidden&&"hidden"!==P.state&&E.onHidden(),P.state="hidden",P.endTime=new Date,f(P)}})}function D(){(E.timeOut>0||E.extendedTimeOut>0)&&(k=setTimeout(b,E.extendedTimeOut),F.maxHideTime=parseFloat(E.extendedTimeOut),F.hideEta=(new Date).getTime()+F.maxHideTime)}function H(){clearTimeout(k),F.hideEta=0,I.stop(!0,!0)[E.showMethod]({duration:E.showDuration,easing:E.showEasing})}function x(){var e=(F.hideEta-(new Date).getTime())/F.maxHideTime*100;q.width(e+"%")}var E=m(),y=t.iconClass||E.iconClass;if("undefined"!=typeof t.optionsOverride&&(E=e.extend(E,t.optionsOverride),y=t.optionsOverride.iconClass||y),!O(E,t)){T++,v=n(E,!0);var k=null,I=e("<div/>"),M=e("<div/>"),B=e("<div/>"),q=e("<div/>"),j=e(E.closeHtml),F={intervalId:null,hideEta:null,maxHideTime:null},P={toastId:T,state:"visible",startTime:new Date,options:E,map:t};return s(),r(),a(),f(P),E.debug&&console&&console.log(P),I}}function m(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&(v.remove(),w=void 0))}var v,C,w,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:c,error:t,getContainer:n,info:o,options:{},subscribe:s,success:i,version:"2.1.3",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)});
  7 +//# sourceMappingURL=toastr.js.map
src/main/resources/static/index.html
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 <link rel="stylesheet" href="/assets/plugins/flatpickr/themes/material_orange.css" > 17 <link rel="stylesheet" href="/assets/plugins/flatpickr/themes/material_orange.css" >
18 <!-- jquery contextMenu style --> 18 <!-- jquery contextMenu style -->
19 <link rel="stylesheet" href="/assets/plugins/contextmenu/jquery.contextMenu.min.css" /> 19 <link rel="stylesheet" href="/assets/plugins/contextmenu/jquery.contextMenu.min.css" />
  20 + <link href="/assets/plugins/toastr/toastr.min.css" rel="stylesheet">
20 21
21 </head> 22 </head>
22 23
@@ -66,6 +67,110 @@ @@ -66,6 +67,110 @@
66 <!-- jquery contextMenu --> 67 <!-- jquery contextMenu -->
67 <script src="/assets/plugins/contextmenu/jquery.contextMenu.min.js" ></script> 68 <script src="/assets/plugins/contextmenu/jquery.contextMenu.min.js" ></script>
68 <script src="/assets/plugins/contextmenu/jquery.ui.position.min.js" ></script> 69 <script src="/assets/plugins/contextmenu/jquery.ui.position.min.js" ></script>
  70 +<script src="/assets/plugins/toastr/toastr.min.js"></script>
  71 +<script src="/assets/js/tts.js"></script>
  72 +
  73 +<!-- websocket -->
  74 +<script src="/assets/plugins/sockjs-client/sockjs.min.js"></script>
  75 +<script>
  76 +
  77 + var gb_inout_websocket = (function () {
  78 +
  79 + var schSock = null;
  80 + var recInterval = null;
  81 + var reConnSpace = 1500;//重连间隔
  82 + var reConnCount; //重连次数
  83 + var maxReConn = 6; //最多重连次数
  84 +
  85 + var new_conn = function () {
  86 + schSock = new SockJS('/sockjs/inout');
  87 + schSock.onopen = function (e) {
  88 + if(reConnCount && reConnCount > 1)
  89 + console.log('重新连接websocket');
  90 + reConnCount = 1;
  91 + clearInterval(recInterval);
  92 + console.log('webSocket[realcontrol] onopen');
  93 + $('.top_tools').removeClass('scok-colse');
  94 + };
  95 +
  96 + //接收消息
  97 + schSock.onmessage = function (e) {
  98 + try {
  99 + var jsonMsg = $.parseJSON(e.data);
  100 + console.log('websocket...', jsonMsg);
  101 + msgHandle[jsonMsg.fn](jsonMsg);
  102 + } catch (e) {
  103 + console.log(e, e.data);
  104 + }
  105 + };
  106 +
  107 + //断开
  108 + schSock.onclose = function (e) {
  109 + console.log('和服务器连接断开....', e);
  110 + $('.top_tools').addClass('scok-colse');
  111 + //1.5秒后重新连接
  112 + recInterval = setTimeout(function () {
  113 + reConnCount++;
  114 + if(reConnCount > maxReConn){
  115 + clearInterval(recInterval);
  116 + return;
  117 + }
  118 + new_conn();
  119 + }, reConnSpace * reConnCount);
  120 + };
  121 + };
  122 +
  123 + //初始化websocket连接
  124 + new_conn();
  125 +
  126 + var msgHandle = {
  127 + carIn: carInFun,
  128 + carOut: carOutFun
  129 + };
  130 +
  131 + //子片段的进出场回调
  132 + var inoutEventCallbacks = [];
  133 +
  134 + function carInFun(msg) {
  135 + var text = msg['dataStr'] + " " +msg.nbbm + "进场" + (msg.berthName?(" 停泊位" + msg.berthName):"");
  136 + toastr.info(text);
  137 + gb_tts.speak(text);
  138 +
  139 + //CCCallFuncN
  140 + $.each(inoutEventCallbacks, function (i, cb) {
  141 + cb(msg);
  142 + });
  143 + }
  144 +
  145 + function carOutFun(msg) {
  146 + var text = msg['dataStr'] + " " + msg.nbbm + " 出场";
  147 + toastr.info(text);
  148 + gb_tts.speak(text);
  149 +
  150 + //CCCallFuncN
  151 + $.each(inoutEventCallbacks, function (i, cb) {
  152 + cb(msg);
  153 + });
  154 + }
  155 +
  156 +
  157 + var registerCallback = function (cb) {
  158 + if (cb)
  159 + inoutEventCallbacks.push(cb);
  160 + };
  161 +
  162 + var cancelCallback = function (cb) {
  163 + if(cb){
  164 + removeByValue(inoutEventCallbacks, cb);
  165 + }
  166 + };
  167 +
  168 + return {
  169 + registerCallback: registerCallback,
  170 + cancelCallback: cancelCallback
  171 + }
  172 + })();
  173 +</script>
69 174
70 <script> 175 <script>
71 var company_json, company_code_name={}; 176 var company_json, company_code_name={};
@@ -150,6 +255,19 @@ @@ -150,6 +255,19 @@
150 $(this.calendarContainer).addClass('showTimeInput'); 255 $(this.calendarContainer).addClass('showTimeInput');
151 } 256 }
152 }; 257 };
  258 +
  259 + toastr.options = {
  260 + "timeOut": "10000"
  261 + };
  262 +
  263 + function removeByValue(arr, val) {
  264 + for(var i=0; i<arr.length; i++) {
  265 + if(arr[i] == val) {
  266 + arr.splice(i, 1);
  267 + break;
  268 + }
  269 + }
  270 + }
153 </script> 271 </script>
154 </body> 272 </body>
155 </html> 273 </html>
156 \ No newline at end of file 274 \ No newline at end of file
src/main/resources/static/pages/b_p_manager/add.html
@@ -164,7 +164,7 @@ @@ -164,7 +164,7 @@
164 164
165 var nbbm = activeRow.data('id'); 165 var nbbm = activeRow.data('id');
166 166
167 - gb_common.$post('/car_park_real/add_car2berth', {berthName: berthName, nbbm: nbbm}, function () { 167 + gb_common.$post('/berth/addCar', {berthName: berthName, nbbm: nbbm}, function () {
168 //刷新泊位 168 //刷新泊位
169 $('#b_p_manager_main_wrap').trigger('refresh'); 169 $('#b_p_manager_main_wrap').trigger('refresh');
170 UIkit.modal(modalId).hide(); 170 UIkit.modal(modalId).hide();
src/main/resources/static/pages/b_p_manager/b_p_main.html
1 -<div class="trash_wrap" ></div> 1 +<div class="trash_wrap"></div>
2 <div id="b_p_manager_main_wrap" style="position: relative;height: 100%;"> 2 <div id="b_p_manager_main_wrap" style="position: relative;height: 100%;">
3 <div class="drag_tip"></div> 3 <div class="drag_tip"></div>
4 - <div class="berth_card_list"></div> 4 + <div class="uk-inline" style="left: 25px;">
  5 + <span uk-icon="icon: cog"></span>
  6 + <div uk-dropdown>
  7 + <ul class="uk-nav uk-dropdown-nav show_modal_ul" >
  8 + <li data-type="0"><a>按充电桩排列</a></li>
  9 + <li data-type="1"><a>按泊位顺序排列</a></li>
  10 + </ul>
  11 + </div>
  12 + </div>
  13 + <div class="berth_card_list">
  14 + </div>
5 15
6 <div class="scroll_up"></div> 16 <div class="scroll_up"></div>
7 <div class="scroll_down"></div> 17 <div class="scroll_down"></div>
8 <script id="b_p_manager_main_list-temp" type="text/html"> 18 <script id="b_p_manager_main_list-temp" type="text/html">
9 - {{each list as b i}}  
10 - <div class="berth_card">  
11 - <div class="car_blank free" data-id="{{b.name}}" name="berth_reg_{{b.name}}"></div>  
12 -  
13 - <div class="berth_info">  
14 - <span class="charge_pile">{{b.chargePile}}</span>  
15 - <span class="name">{{b.name}}</span>  
16 - <div class="scale"></div> 19 + {{each data as obj i}}
  20 + <div class="charge_pile_wrap">
  21 + <span class="charge_pile">{{obj.cp}}</span>
  22 + {{each obj.list as b j}}
  23 + <div class="berth_card">
  24 + <div class="car_blank free {{b.status==-1?'lock':''}}" data-id="{{b.name}}" name="berth_reg_{{b.name}}"></div>
  25 +
  26 + <div class="berth_info">
  27 + <span class="name">{{b.name}}</span>
  28 + <div class="scale"></div>
  29 + </div>
17 </div> 30 </div>
  31 + {{/each}}
18 </div> 32 </div>
19 {{/each}} 33 {{/each}}
20 </script> 34 </script>
21 35
22 <script> 36 <script>
23 (function () { 37 (function () {
  38 + var storage = window.localStorage;
24 var wrap = '#b_p_manager_main_wrap'; 39 var wrap = '#b_p_manager_main_wrap';
25 //滚动条 40 //滚动条
26 $('.berth_card_list', wrap).perfectScrollbar({suppressScrollX: true}); 41 $('.berth_card_list', wrap).perfectScrollbar({suppressScrollX: true});
27 42
28 /** 加载全部泊位信息 */ 43 /** 加载全部泊位信息 */
29 - $.get('/berth/all', function (list) {  
30 - var htmlStr = template('b_p_manager_main_list-temp', {list: list});  
31 - $('.berth_card_list', wrap).html(htmlStr);  
32 -  
33 - //init drag events  
34 - initDragEvents();  
35 - //定时刷新实时车辆信息  
36 - fixedTimeRefresh();  
37 - $('.berth_card_list', wrap).perfectScrollbar('update');  
38 - }); 44 + var init = function (cb) {
  45 + $.get('/berth/all_list', function (list) {
  46 + var data = [];
  47 + if ('0'==storage.getItem('berth_show_modal')) {
  48 + //按充电枪排序
  49 + var cpMaps = gb_common.groupBy(list, 'chargePile');
  50 + for (var cp in cpMaps) {
  51 + data.push({cp: cp, list: cpMaps[cp]});
  52 + }
  53 + }
  54 + else {
  55 + //按泊位顺序排列,合并靠近的相同充电枪
  56 + list.sort(berth_sort_fun);
  57 + var cp, tempList;
  58 + for (var i = 0, b; b = list[i++];) {
  59 + if (cp && cp == b.chargePile) {
  60 + tempList.push(b);
  61 + continue;
  62 + }
  63 + else
  64 + tempList = [];
  65 +
  66 + cp = b.chargePile;
  67 + tempList.push(b);
  68 + data.push({cp: cp, list: tempList});
  69 + }
  70 + }
  71 +
  72 + var htmlStr = template('b_p_manager_main_list-temp', {data: data});
  73 + $('.berth_card_list', wrap).html(htmlStr);
  74 +
  75 + //定时刷新电量信息
  76 + fixedElecRefresh();
  77 + //init drag events
  78 + initDragEvents();
  79 + //注册websocket回调
  80 + gb_inout_websocket.registerCallback(socketInoutHandler);
  81 + //加载泊位信息
  82 + queryRealInfos();
  83 + $('.berth_card_list', wrap).perfectScrollbar('update');
  84 +
  85 + cb && cb();
  86 + });
  87 + };
  88 + init();
  89 +
  90 + /**
  91 + * 车辆进出场
  92 + */
  93 + function socketInoutHandler(msg) {
  94 + console.log('queryRealInfos...');
  95 + queryRealInfos();
  96 + }
39 97
40 - //定时刷新实时车辆信息  
41 - var delay = 1000 * 2, fixedExit, fixedTimer;  
42 - function fixedTimeRefresh() { 98 + //定时刷新实时电量信息
  99 + var delay = 1000 * 15, fixedExit, fixedTimer;
  100 + function fixedElecRefresh() {
43 (function () { 101 (function () {
44 var f = arguments.callee; 102 var f = arguments.callee;
45 - queryRealInfos(function () { 103 + queryElecInfos(function () {
46 if(fixedExit) 104 if(fixedExit)
47 return; 105 return;
48 fixedTimer = setTimeout(f, delay); 106 fixedTimer = setTimeout(f, delay);
49 }); 107 });
50 })(); 108 })();
51 } 109 }
  110 +
  111 + function queryElecInfos(cb) {
  112 + $.get('/berth/elecs', function (map) {
  113 + //渲染页面电量信息
  114 + var $berthReg, clazz,soc;
  115 + for(var nbbm in map){
  116 + soc=map[nbbm];
  117 + $berthReg=$('.berth_card_list .car_blank[data-nbbm='+nbbm+']', wrap);
  118 +
  119 + if($berthReg.length==0)
  120 + continue;
  121 +
  122 + clazz = soc >= 100 ? 'over' : 'charging';
  123 + $berthReg.removeClass('free over charging no_elec').addClass(clazz).find('.elec_perc').text(soc+'%');
  124 +
  125 + $berthReg.next('.berth_info').find('.scale')
  126 + .css('width', soc + '%')
  127 + .removeClass('over charging')
  128 + .addClass(clazz);
  129 + //htmlStr = '<div class="car_name">' + nbbm + '<span class="elec_perc">' + soc + '%</span> </div>';
  130 + }
  131 + cb && cb();
  132 + });
  133 + }
52 134
53 /** 135 /**
54 * 退出事件 136 * 退出事件
@@ -57,19 +139,20 @@ @@ -57,19 +139,20 @@
57 fixedExit = true; 139 fixedExit = true;
58 clearTimeout(fixedTimer); 140 clearTimeout(fixedTimer);
59 fixedTimer = null; 141 fixedTimer = null;
  142 + gb_inout_websocket.cancelCallback(socketInoutHandler);
60 }); 143 });
61 144
62 function queryRealInfos(cb) { 145 function queryRealInfos(cb) {
63 $.ajax({ 146 $.ajax({
64 - url: '/car_park_real/bus', 147 + url: '/berth/findCar2Berths',
65 dataType: 'json', 148 dataType: 'json',
66 success: function (list) { 149 success: function (list) {
67 render_bus(list); 150 render_bus(list);
68 - cb(); 151 + cb && cb();
69 }, 152 },
70 error: function (xr, t) { 153 error: function (xr, t) {
71 - UIkit.notification('获取实时车辆信息失败!!', 'danger');  
72 - cb(); 154 + UIkit.notification('获取实时车辆泊位信息失败!!', 'danger');
  155 + cb && cb();
73 } 156 }
74 }); 157 });
75 } 158 }
@@ -78,147 +161,150 @@ @@ -78,147 +161,150 @@
78 161
79 function render_bus(list) { 162 function render_bus(list) {
80 resetAll(); 163 resetAll();
81 - for(var i=0,bus;bus=list[i++];) {  
82 - if (!bus['berthName'])  
83 - continue;  
84 -  
85 - var $berthReg=$('.berth_card_list .car_blank[name=berth_reg_'+bus['berthName']+']', wrap);  
86 - if(!$berthReg) 164 + var $berthReg, clazz, htmlStr, nbbm, soc;
  165 + for (var i = 0, obj; obj = list[i++];) {
  166 + $berthReg = $('.berth_card_list .car_blank[name=berth_reg_' + obj['berth'] + ']', wrap);
  167 + if (!$berthReg)
87 return; 168 return;
88 169
89 - var clazz = bus.soc>=100?'over':'charging';  
90 - var htmlStr = '<div class="car_name">'+bus.nbbm+'<span class="elec_perc">'+bus.soc+'%</span> </div>';  
91 - if(!bus.soc){ 170 + nbbm = obj['bus'].nbbm;
  171 + var htmlStr = '<div class="car_name">' + nbbm + '<span class="elec_perc"></span> </div>';
  172 +
  173 + $berthReg.attr('data-nbbm', nbbm).html(htmlStr).addClass('no_elec').removeClass('free');
  174 + /*soc = obj['elec'] ? obj['elec']['soc'] : -1;
  175 +
  176 + if (soc == -1) {
92 clazz = 'no_elec'; 177 clazz = 'no_elec';
93 - htmlStr = '<div class="car_name">'+bus.nbbm+ '</div>' 178 + htmlStr = '<div class="car_name">' + nbbm + '</div>'
  179 + }
  180 + else {
  181 + clazz = soc >= 100 ? 'over' : 'charging';
  182 + htmlStr = '<div class="car_name">' + nbbm + '<span class="elec_perc">' + soc + '%</span> </div>';
94 } 183 }
95 184
96 $berthReg.removeClass('free over charging no_elec') 185 $berthReg.removeClass('free over charging no_elec')
97 .addClass(clazz) 186 .addClass(clazz)
98 - .data('nbbm', bus.nbbm) 187 + .data('nbbm', nbbm)
99 .attr('draggable', true) 188 .attr('draggable', true)
100 .html(htmlStr); 189 .html(htmlStr);
101 190
102 - if(bus.soc){ 191 + if (soc != -1) {
103 $berthReg.next('.berth_info').find('.scale') 192 $berthReg.next('.berth_info').find('.scale')
104 - .css('width', bus.soc + '%') 193 + .css('width', soc + '%')
105 .removeClass('over charging') 194 .removeClass('over charging')
106 .addClass(clazz); 195 .addClass(clazz);
107 - } 196 + }*/
108 } 197 }
  198 + //刷新电量信息
  199 + queryElecInfos();
109 } 200 }
110 - 201 +
111 function resetAll() { 202 function resetAll() {
112 - $('.berth_card_list .car_blank', wrap).each(function () {  
113 - $(this).empty()  
114 - .removeClass('over charging no_elec')  
115 - .addClass('free')  
116 - .attr('draggable', false)  
117 - .next('.berth_info').find('.scale').removeClass('over charging');  
118 - }); 203 +
  204 + $('.berth_card_list .car_blank', wrap).empty().removeClass('over charging no_elec')
  205 + .removeAttr('data-nbbm').addClass('free');
  206 +
  207 + $('.berth_card_list .berth_info .scale', wrap).removeClass('over charging');
119 } 208 }
120 209
121 /** 210 /**
122 * ondrop event 211 * ondrop event
123 */ 212 */
124 var initDragEvents = function () { 213 var initDragEvents = function () {
125 - $('.berth_card .car_blank', wrap).each(function () {  
126 - this.addEventListener('dragstart', handleDragStart, false);  
127 - this.addEventListener('dragover', handleDragOver, false);  
128 - this.addEventListener('drop', handleDrop, false);  
129 - this.addEventListener('dragleave', handleDragLeave, false);  
130 - this.addEventListener('dragend', handleDragEnd, false);  
131 - }); 214 + /*$('.berth_card .car_blank', wrap).each(function () {
  215 + this.addEventListener('dragstart', handleDragStart, false);
  216 + this.addEventListener('dragover', handleDragOver, false);
  217 + this.addEventListener('drop', handleDrop, false);
  218 + this.addEventListener('dragleave', handleDragLeave, false);
  219 + this.addEventListener('dragend', handleDragEnd, false);
  220 + });*/
132 }; 221 };
133 222
134 - //垃圾桶  
135 - var trashWrap=$('.trash_wrap');  
136 - trashWrap[0].addEventListener('dragover', function (e) {  
137 - e.preventDefault();  
138 - $(this).addClass('open');  
139 - return true;  
140 - }, false);  
141 - trashWrap[0].addEventListener('dragleave', function () {  
142 - $(this).removeClass('open');  
143 - },false);  
144 - trashWrap[0].addEventListener('drop', function () {  
145 - var s = $(drag_e).data('id');  
146 - gb_common.$post('/car_park_real/clear_berth', {b: s}, function (rs) {  
147 - render_bus(rs.list);  
148 - });  
149 - drag_rest();  
150 - },false); 223 + /* //垃圾桶
  224 + var trashWrap=$('.trash_wrap');
  225 + trashWrap[0].addEventListener('dragover', function (e) {
  226 + e.preventDefault();
  227 + $(this).addClass('open');
  228 + return true;
  229 + }, false);
  230 + trashWrap[0].addEventListener('dragleave', function () {
  231 + $(this).removeClass('open');
  232 + },false);
  233 + trashWrap[0].addEventListener('drop', function () {
  234 + var s = $(drag_e).data('id');
  235 + gb_common.$post('/car_park_real/clear_berth', {b: s}, function (rs) {
  236 + render_bus(rs.list);
  237 + });
  238 + drag_rest();
  239 + },false);
151 240
152 241
153 - //泊位拖拽  
154 - var drag_e;  
155 - var handleDragStart = function (e) {  
156 - drag_e = this;  
157 - trashWrap.addClass('show');  
158 - $(this).addClass('draging');  
159 - $('.scroll_down,.scroll_up', wrap).show();  
160 - }; 242 + //泊位拖拽
  243 + var drag_e;
  244 + var handleDragStart = function (e) {
  245 + drag_e = this;
  246 + trashWrap.addClass('show');
  247 + $(this).addClass('draging');
  248 + $('.scroll_down,.scroll_up', wrap).show();
  249 + };
161 250
162 - var handleDragEnd = function () {  
163 - trashWrap.removeClass('show open');  
164 - }; 251 + var handleDragEnd = function () {
  252 + trashWrap.removeClass('show open');
  253 + };
165 254
166 - //允许落下  
167 - var drag_tip = $('.drag_tip', wrap);  
168 - var handleDragOver = function (e) {  
169 - e.preventDefault(); 255 + //允许落下
  256 + var drag_tip = $('.drag_tip', wrap);
  257 + var handleDragOver = function (e) {
  258 + e.preventDefault();
170 259
171 - var d = $(this).data('id');  
172 - if($(drag_e).data('id') != d){  
173 - e.dataTransfer.dropEffect = 'move'; 260 + var d = $(this).data('id');
  261 + if($(drag_e).data('id') != d){
  262 + e.dataTransfer.dropEffect = 'move';
174 263
175 - //show drap tip  
176 - var x = $(this).position().top;  
177 - var y = $(this).position().left;  
178 - var tips = $(drag_e).data('nbbm') + '移至泊位 ' + d;  
179 - drag_tip.html(tips).show().css('left', y + 22).css('top', x - 25);  
180 - }  
181 - return false;  
182 - };  
183 -  
184 - var handleDragLeave = function (e) {  
185 - drag_tip.hide();  
186 - }; 264 + //show drap tip
  265 + var x = $(this).position().top;
  266 + var y = $(this).position().left;
  267 + var tips = $(drag_e).data('nbbm') + '移至泊位 ' + d;
  268 + drag_tip.html(tips).show().css('left', y + 22).css('top', x - 25);
  269 + }
  270 + return false;
  271 + };
187 272
188 - var handleDrop = function () {  
189 - drag_tip.hide();  
190 - //泊位交换  
191 - var s = $(drag_e).data('id');  
192 - var d = $(this).data('id');  
193 - gb_common.$post('/car_park_real/real_change', {s:s, d:d}, function (rs) {  
194 - render_bus(rs.list);  
195 - });  
196 - drag_rest();  
197 - }; 273 + var handleDragLeave = function (e) {
  274 + drag_tip.hide();
  275 + };
198 276
199 - var drag_rest = function () {  
200 - $(drag_e).removeClass('draging');  
201 - drag_e = null;  
202 - $('.scroll_down,.scroll_up', wrap).hide();  
203 - };  
204 - /** 277 + var handleDrop = function () {
  278 + drag_tip.hide();
  279 + //泊位交换
  280 + var s = $(drag_e).data('id');
  281 + var d = $(this).data('id');
  282 + gb_common.$post('/car_park_real/real_change', {s:s, d:d}, function (rs) {
  283 + render_bus(rs.list);
  284 + });
  285 + drag_rest();
  286 + };
  287 +
  288 + var drag_rest = function () {
  289 + $(drag_e).removeClass('draging');
  290 + drag_e = null;
  291 + $('.scroll_down,.scroll_up', wrap).hide();
  292 + };
  293 + /!**
205 * drag 时滚动条 294 * drag 时滚动条
  295 + *!/
  296 + var cardListWrap = $('.berth_card_list', wrap)[0];
  297 + $('.scroll_down', wrap)[0].addEventListener('dragover', function (e) {
  298 + e.preventDefault();
  299 + cardListWrap.scrollTop = cardListWrap.scrollTop + 10;
  300 + return true;
  301 + }, false);
  302 + $('.scroll_up', wrap)[0].addEventListener('dragover', function (e) {
  303 + e.preventDefault();
  304 + cardListWrap.scrollTop = cardListWrap.scrollTop - 10;
  305 + return true;
  306 + }, false);
206 */ 307 */
207 - var cardListWrap = $('.berth_card_list', wrap)[0];  
208 - $('.scroll_down', wrap)[0].addEventListener('dragover', function (e) {  
209 - e.preventDefault();  
210 - cardListWrap.scrollTop = cardListWrap.scrollTop + 10;  
211 - return true;  
212 - }, false);  
213 - $('.scroll_up', wrap)[0].addEventListener('dragover', function (e) {  
214 - e.preventDefault();  
215 - cardListWrap.scrollTop = cardListWrap.scrollTop - 10;  
216 - return true;  
217 - }, false);  
218 -  
219 - /*$('.scroll_down', wrap)[0].addEventListener('dragleave', function () {  
220 - berthcardListWrap.scrollTop = berthcardListWrap.scrollTop + 20;  
221 - },false)*/  
222 308
223 309
224 /** 310 /**
@@ -226,23 +312,40 @@ @@ -226,23 +312,40 @@
226 */ 312 */
227 var callbackHandler = { 313 var callbackHandler = {
228 add: function (berthName) { 314 add: function (berthName) {
229 - gb_common.open_modal('/pages/b_p_manager/add.html', '泊位 '+berthName+' 添加车辆', {name: berthName}); 315 + gb_common.open_modal('/pages/b_p_manager/add.html', '泊位 ' + berthName + ' 添加车辆', {name: berthName});
230 }, 316 },
231 delete: function (berthName) { 317 delete: function (berthName) {
232 gb_common.alt_confirm('你确定要清除泊位 ' + berthName + ' 上的车辆吗?', '确定删除', function () { 318 gb_common.alt_confirm('你确定要清除泊位 ' + berthName + ' 上的车辆吗?', '确定删除', function () {
233 - gb_common.$post('/car_park_real/clear_berth', {b: berthName}, function (rs) {  
234 - render_bus(rs.list); 319 + gb_common.$post('/berth/removeCar', {b: berthName}, function () {
  320 + queryRealInfos();
235 }); 321 });
236 }); 322 });
237 }, 323 },
238 change: function (berthName) { 324 change: function (berthName) {
239 - gb_common.alt_prompt('请输入要和泊位 '+berthName+' 对换的泊位', '', '确定对换', function (v) {  
240 - if(v){  
241 - gb_common.$post('/car_park_real/real_change', {s: berthName, d:v}, function (rs) {  
242 - render_bus(rs.list); 325 + gb_common.alt_prompt('请输入要和泊位 ' + berthName + ' 对换的泊位', '', '确定对换', function (v) {
  326 + if (v) {
  327 + gb_common.$post('/berth/changeCar2Berth', {s: berthName, d: v}, function () {
  328 + queryRealInfos();
243 }); 329 });
244 } 330 }
245 }); 331 });
  332 + },
  333 + lock: function (berthName) {
  334 + gb_common.alt_confirm('确定要禁用泊位 ' + berthName + ' ?', '确定禁用', function () {
  335 + gb_common.$post('/berth/lockBerth', {berthName: berthName}, function () {
  336 + $('.berth_card_list .car_blank[name=berth_reg_' + berthName + ']', wrap)
  337 + .removeClass('over charging no_elec')
  338 + .addClass('free lock')
  339 + });
  340 + });
  341 + },
  342 + unlock: function (berthName) {
  343 + gb_common.alt_confirm('确定要启用泊位 ' + berthName + ' ?', '确定启用', function () {
  344 + gb_common.$post('/berth/unlockBerth', {berthName: berthName}, function () {
  345 + $('.berth_card_list .car_blank[name=berth_reg_' + berthName + ']', wrap)
  346 + .removeClass('lock');
  347 + });
  348 + });
246 } 349 }
247 }; 350 };
248 $.contextMenu({ 351 $.contextMenu({
@@ -261,9 +364,34 @@ @@ -261,9 +364,34 @@
261 }, 364 },
262 'change': { 365 'change': {
263 name: '泊位对换', icon: "fa-exchange" 366 name: '泊位对换', icon: "fa-exchange"
  367 + },
  368 + 'lock': {
  369 + name: '禁用泊位', icon: "fa-lock"
  370 + },
  371 + 'unlock': {
  372 + name: '启用泊位', icon: "fa-unlock"
264 } 373 }
265 } 374 }
266 }); 375 });
  376 +
  377 + function berth_sort_fun(a, b) {
  378 + return a.orderNo.localeCompare(b.orderNo);
  379 + }
  380 +
  381 + //切换显示模式
  382 + var flag;
  383 + $('.show_modal_ul>li').on('click', function () {
  384 + if(flag)
  385 + return;
  386 + flag = true;
  387 + var type = $(this).data('type');
  388 + storage.setItem('berth_show_modal', type);
  389 + $('.ct-cont-body', cont).trigger('exit');
  390 + //fixedExit = false;
  391 + init(function () {
  392 + flag = false;
  393 + });
  394 + });
267 })(); 395 })();
268 </script> 396 </script>
269 </div> 397 </div>
270 \ No newline at end of file 398 \ No newline at end of file
src/main/resources/static/pages/basic_data/berth/berth_main.html
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 <input type="hidden" name="region.id_eq" id="regionIdInput"> 13 <input type="hidden" name="region.id_eq" id="regionIdInput">
14 <div class="ct_field"> 14 <div class="ct_field">
15 <label>充电桩号: 15 <label>充电桩号:
16 - <input class="uk-input" name="chargPile_eq" > 16 + <input class="uk-input" name="chargePile_eq" >
17 </label> 17 </label>
18 </div> 18 </div>
19 <div class="ct_field"> 19 <div class="ct_field">
@@ -82,7 +82,7 @@ @@ -82,7 +82,7 @@
82 禁用 82 禁用
83 {{/if}} 83 {{/if}}
84 </td> 84 </td>
85 - <td>暂时未知</td> 85 + <td>{{b.car}}</td>
86 <td>{{b.remark}}</td> 86 <td>{{b.remark}}</td>
87 <td> 87 <td>
88 <a class="icon edit_icon" data-code="{{b.id}}" uk-icon="icon: file-edit"></a>&nbsp; 88 <a class="icon edit_icon" data-code="{{b.id}}" uk-icon="icon: file-edit"></a>&nbsp;
src/main/resources/static/pages/basic_data/berth/edit.html
@@ -44,12 +44,13 @@ @@ -44,12 +44,13 @@
44 <textarea class="uk-textarea" rows="5" name="remark" value="{{b.remark}}" data-fv-stringlength="true" data-fv-stringlength-max="50" placeholder="不超过50个字符"></textarea> 44 <textarea class="uk-textarea" rows="5" name="remark" value="{{b.remark}}" data-fv-stringlength="true" data-fv-stringlength-max="50" placeholder="不超过50个字符"></textarea>
45 </div> 45 </div>
46 </div> 46 </div>
47 - <div class="uk-margin"> 47 + <input type="hidden" name="status" value="{{b.status}}">
  48 + <!--<div class="uk-margin">
48 <label class="uk-form-label"></label> 49 <label class="uk-form-label"></label>
49 <div class="uk-form-controls"> 50 <div class="uk-form-controls">
50 - <label><input class="uk-checkbox" type="checkbox" {{if status=="-1"}}checked{{/if}} name="status" value="-1"> 禁用</label> 51 + <label><input class="uk-checkbox" disabled type="checkbox" {{if status=="-1"}}checked{{/if}} name="status" value="-1"> 禁用</label>
51 </div> 52 </div>
52 - </div> 53 + </div>-->
53 </script> 54 </script>
54 55
55 56
src/main/resources/static/pages/basic_data/person_card/list.html
@@ -45,7 +45,7 @@ @@ -45,7 +45,7 @@
45 </div> 45 </div>
46 <div class="ct_field"> 46 <div class="ct_field">
47 <label>卡号: 47 <label>卡号:
48 - <input class="uk-input" name="idRFID" placeholder="卡ID号"> 48 + <input class="uk-input" name="idRfid" placeholder="卡ID号">
49 </label> 49 </label>
50 </div> 50 </div>
51 <div class="ct_field"> 51 <div class="ct_field">