From 2cd7509f6d19b9e4ed0c199388596f5b4afad2ef Mon Sep 17 00:00:00 2001 From: fangpeng <591930734@qq.com> Date: Mon, 7 Mar 2022 14:41:24 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0nio=E7=9A=84buffer?= =?UTF-8?q?=E4=BD=BF=E7=94=A8demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nio/.gitignore | 46 +++++++++++++ nio/pom.xml | 16 +++++ .../com/lemon/buffer/CreateBufferDemo.java | 29 +++++++++ .../java/com/lemon/buffer/GetBufferDemo.java | 59 +++++++++++++++++ .../java/com/lemon/buffer/PutBufferDemo.java | 64 +++++++++++++++++++ 5 files changed, 214 insertions(+) create mode 100644 nio/.gitignore create mode 100644 nio/pom.xml create mode 100644 nio/src/main/java/com/lemon/buffer/CreateBufferDemo.java create mode 100644 nio/src/main/java/com/lemon/buffer/GetBufferDemo.java create mode 100644 nio/src/main/java/com/lemon/buffer/PutBufferDemo.java diff --git a/nio/.gitignore b/nio/.gitignore new file mode 100644 index 00000000..efb4aab2 --- /dev/null +++ b/nio/.gitignore @@ -0,0 +1,46 @@ +### Java template +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +### Maven template +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +### Example user template template +### Example user template + +# IntelliJ project files +.idea +*.iml +out +gen diff --git a/nio/pom.xml b/nio/pom.xml new file mode 100644 index 00000000..9f7a56de --- /dev/null +++ b/nio/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + com.lemon + nio + 1.0-SNAPSHOT + + + 8 + 8 + + + \ No newline at end of file diff --git a/nio/src/main/java/com/lemon/buffer/CreateBufferDemo.java b/nio/src/main/java/com/lemon/buffer/CreateBufferDemo.java new file mode 100644 index 00000000..17aa076f --- /dev/null +++ b/nio/src/main/java/com/lemon/buffer/CreateBufferDemo.java @@ -0,0 +1,29 @@ +package com.lemon.buffer; + +import java.nio.ByteBuffer; + +/** + * @Description: Buffer的创建 + * @Author : Lemon-CS + * @Date : 2022年03月07日 2:12 下午 + */ +public class CreateBufferDemo { + + public static void main(String[] args) { + //1.创建指定长度的缓冲区 ByteBuffer为例 + ByteBuffer allocate = ByteBuffer.allocate(5); + for (int i = 0; i < 5; i++) { + System.out.println(allocate.get());//从缓冲区当中拿去数据 + } + System.out.println("============================="); + //会报错. 后续讲解 + //System.out.println(allocate.get());//从缓冲区当中拿去数据 + + //2.创建一个有内容的缓冲区 + ByteBuffer wrap = ByteBuffer.wrap("lagou".getBytes()); + for (int i = 0; i < 5; i++) { + System.out.println(wrap.get()); + } + } + +} diff --git a/nio/src/main/java/com/lemon/buffer/GetBufferDemo.java b/nio/src/main/java/com/lemon/buffer/GetBufferDemo.java new file mode 100644 index 00000000..4fcb62eb --- /dev/null +++ b/nio/src/main/java/com/lemon/buffer/GetBufferDemo.java @@ -0,0 +1,59 @@ +package com.lemon.buffer; + +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +/** + * @Description: 从缓冲区中读取数据 + * @Author : Lemon-CS + * @Date : 2022年03月07日 2:26 下午 + */ +public class GetBufferDemo { + + public static void main(String[] args) { + //1.创建一个指定长度的缓冲区 + ByteBuffer buffer = ByteBuffer.allocate(10); + buffer.put("0123".getBytes()); + System.out.println("position:" + buffer.position());//4 + System.out.println("limit:" + buffer.limit());//10 + System.out.println("capacity:" + buffer.capacity());//10 + System.out.println("remaining:" + buffer.remaining());//6 + + //切换读模式 + System.out.println("-------------读取数据--------------"); + buffer.flip(); + System.out.println("position:" + buffer.position());//0 + System.out.println("limit:" + buffer.limit());//4 + System.out.println("capacity:" + buffer.capacity());//10 + System.out.println("remaining:" + buffer.remaining());//4 + for (int i = 0; i < buffer.limit(); i++) { + System.out.println("读取数据为:" + buffer.get()); + } + + //读取完毕后.继续读取会报错,超过limit值 + //System.out.println(allocate.get()); + //读取指定索引字节 + System.out.println("-------------读取指定索引字节--------------"); + System.out.println("读取指定索引数据为:" + buffer.get(1)); + + System.out.println("-------------读取多个字节--------------"); + // 重复读取 + buffer.rewind(); + byte[] bytes = new byte[4]; + buffer.get(bytes); + System.out.println("读取多个字节数据为:" + new String(bytes)); + + // 将缓冲区转化字节数组返回 + System.out.println("-------------将缓冲区转化字节数组返回--------------"); + byte[] array = buffer.array(); + System.out.println("缓冲区转化字节数组数据为:" + new String(array)); + + // 切换写模式,覆盖之前索引所在位置的值 + System.out.println("------------写模式--------------"); + buffer.clear(); + buffer.put("abc".getBytes()); + System.out.println("写入数据后:" + new String(buffer.array())); + + } + +} diff --git a/nio/src/main/java/com/lemon/buffer/PutBufferDemo.java b/nio/src/main/java/com/lemon/buffer/PutBufferDemo.java new file mode 100644 index 00000000..db17aa2a --- /dev/null +++ b/nio/src/main/java/com/lemon/buffer/PutBufferDemo.java @@ -0,0 +1,64 @@ +package com.lemon.buffer; + +import java.nio.ByteBuffer; + +/** + * @Description: 向缓冲区中添加数据 + * @Author : Lemon-CS + * @Date : 2022年03月07日 2:14 下午 + */ +public class PutBufferDemo { + + public static void main(String[] args) { + //1.创建一个缓冲区 + ByteBuffer buffer = ByteBuffer.allocate(10); + System.out.println(buffer.position());//0 获取当前索引所在位置 + System.out.println(buffer.limit());//10 最多能操作到哪个索引位置 + System.out.println(buffer.capacity());//10 返回缓冲区总长度 + System.out.println(buffer.remaining());//10 还有多少个可以操作的个数 + + System.out.println("----------------"); + // 修改当前索引所在位置 + //buffer.position(1); + // 修改最多能操作到哪个索引的位置 + //buffer.limit(9); + // System.out.println(buffer.position());//1 获取当前索引所在位置 + //System.out.println(buffer.limit());//9 最多能操作到哪个索引位置 + //System.out.println(buffer.capacity());//10 返回缓冲区总长度 + //System.out.println(buffer.remaining());//8 还有多少个可以操作的个数 + + // 添加一个字节 + buffer.put((byte) 97); + System.out.println(buffer.position());//1 获取当前索引所在位置 + System.out.println(buffer.limit());//10 最多能操作到哪个索引位置 + System.out.println(buffer.capacity());//10 返回缓冲区总长度 + System.out.println(buffer.remaining());//9 还有多少个可以操作的个数 + + System.out.println("----------------"); + // 添加一个数组 + buffer.put("abc".getBytes()); + System.out.println(buffer.position());//4 获取当前索引所在位置 + System.out.println(buffer.limit());//10 最多能操作到哪个索引位置 + System.out.println(buffer.capacity());//10 返回缓冲区总长度 + System.out.println(buffer.remaining());//6 还有多少个可以操作的个数 + System.out.println("----------------"); + // 添加一个数组 + buffer.put("123456".getBytes()); + System.out.println(buffer.position());//10 获取当前索引所在位置 + System.out.println(buffer.limit());//10 最多能操作到哪个索引位置 + System.out.println(buffer.capacity());//10 返回缓冲区总长度 + System.out.println(buffer.remaining());//0 还有多少个可以操作的个数 + System.out.println(buffer.hasRemaining());//false 是否还能操作 + System.out.println("----------------"); + //如果缓冲区满了. 可以调整position位置, 就可以重复写. 会覆盖之前存入索引位置的值 + buffer.position(0); + buffer.put("123456".getBytes()); + System.out.println(buffer.position());//6 获取当前索引所在位置 + System.out.println(buffer.limit());//10 最多能操作到哪个索引位置 + System.out.println(buffer.capacity());//10 返回缓冲区总长度 + System.out.println(buffer.remaining());//4 还有多少个可以操作的个数 + System.out.println(buffer.hasRemaining());//true 是否还能操作 + + } + +} From 54b9196a986c3a0ab2600c2105355a6da730ea3b Mon Sep 17 00:00:00 2001 From: fangpeng <591930734@qq.com> Date: Mon, 7 Mar 2022 15:03:47 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0nio=E7=9A=84=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E7=AB=AF=E5=92=8C=E6=9C=8D=E5=8A=A1=E7=AB=AFdemo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 46 +++++++++++++++++ README.md | 0 .../java/com/lemon/channel/NIOClient.java | 32 ++++++++++++ .../java/com/lemon/channel/NIOServer.java | 50 +++++++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 nio/src/main/java/com/lemon/channel/NIOClient.java create mode 100644 nio/src/main/java/com/lemon/channel/NIOServer.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..efb4aab2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +### Java template +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +### Maven template +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +### Example user template template +### Example user template + +# IntelliJ project files +.idea +*.iml +out +gen diff --git a/README.md b/README.md new file mode 100644 index 00000000..e69de29b diff --git a/nio/src/main/java/com/lemon/channel/NIOClient.java b/nio/src/main/java/com/lemon/channel/NIOClient.java new file mode 100644 index 00000000..7c743229 --- /dev/null +++ b/nio/src/main/java/com/lemon/channel/NIOClient.java @@ -0,0 +1,32 @@ +package com.lemon.channel; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.nio.charset.StandardCharsets; + +/** + * @Description: 客户端 + * @Author : Lemon-CS + * @Date : 2022年03月07日 2:54 下午 + */ +public class NIOClient { + + public static void main(String[] args) throws IOException { + //1. 打开通道 + SocketChannel socketChannel = SocketChannel.open(); + //2. 设置连接IP和端口号 + socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999)); + //3. 写出数据 + socketChannel.write(ByteBuffer.wrap("老板,还钱吧!".getBytes(StandardCharsets.UTF_8))); + //4. 读取服务器写回的数据 + ByteBuffer byteBuffer = ByteBuffer.allocate(1024); + int read = socketChannel.read(byteBuffer); + System.out.println("服务端消息:" + + new String(byteBuffer.array(), 0, read, StandardCharsets.UTF_8)); + //5. 释放资源 + socketChannel.close(); + } + +} diff --git a/nio/src/main/java/com/lemon/channel/NIOServer.java b/nio/src/main/java/com/lemon/channel/NIOServer.java new file mode 100644 index 00000000..679986d8 --- /dev/null +++ b/nio/src/main/java/com/lemon/channel/NIOServer.java @@ -0,0 +1,50 @@ +package com.lemon.channel; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.nio.charset.StandardCharsets; + +/** + * @Description: 服务端 + * @Author : Lemon-CS + * @Date : 2022年03月07日 2:46 下午 + */ +public class NIOServer { + + public static void main(String[] args) throws IOException, InterruptedException { + //1. 打开一个服务端通道 + ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); + //2. 绑定对应的端口号 + serverSocketChannel.bind(new InetSocketAddress(9999)); + //3. 通道默认是阻塞的,需要设置为非阻塞 + serverSocketChannel.configureBlocking(false); + System.out.println("服务端启动成功...."); + + while (true) { + //4. 检查是否有客户端连接 有客户端连接会返回对应的通道 + SocketChannel socketChannel = serverSocketChannel.accept(); + if (socketChannel == null) { + System.out.println("没有客户端连接...我去做别的事情"); + Thread.sleep(2000); + continue; + } + //5. 获取客户端传递过来的数据,并把数据放在byteBuffer这个缓冲区中 + ByteBuffer byteBuffer = ByteBuffer.allocate(1024); + //返回值 + //正数: 表示本地读到有效字节数 + //0: 表示本次没有读到数据 + //-1: 表示读到末尾 + int read = socketChannel.read(byteBuffer); + System.out.println("客户端消息:" + new String(byteBuffer.array(), 0, + read, StandardCharsets.UTF_8)); + //6. 给客户端回写数据 + socketChannel.write(ByteBuffer.wrap("没钱".getBytes(StandardCharsets.UTF_8))); + //7. 释放资源 + socketChannel.close(); + } + } + +} From eb43ed21cd6a4160d778a22aed173440b96ccc33 Mon Sep 17 00:00:00 2001 From: fangpeng <591930734@qq.com> Date: Mon, 7 Mar 2022 15:35:00 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0nio=E7=9A=84=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E5=99=A8demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/lemon/selector/NIOClient.java | 32 ++++++++ .../com/lemon/selector/NIOSelectorServer.java | 74 +++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 nio/src/main/java/com/lemon/selector/NIOClient.java create mode 100644 nio/src/main/java/com/lemon/selector/NIOSelectorServer.java diff --git a/nio/src/main/java/com/lemon/selector/NIOClient.java b/nio/src/main/java/com/lemon/selector/NIOClient.java new file mode 100644 index 00000000..7176b0ba --- /dev/null +++ b/nio/src/main/java/com/lemon/selector/NIOClient.java @@ -0,0 +1,32 @@ +package com.lemon.selector; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.nio.charset.StandardCharsets; + +/** + * @Description: 客户端 + * @Author : Lemon-CS + * @Date : 2022年03月07日 2:54 下午 + */ +public class NIOClient { + + public static void main(String[] args) throws IOException { + //1. 打开通道 + SocketChannel socketChannel = SocketChannel.open(); + //2. 设置连接IP和端口号 + socketChannel.connect(new InetSocketAddress("127.0.0.1", 9999)); + //3. 写出数据 + socketChannel.write(ByteBuffer.wrap("老板,还钱吧!".getBytes(StandardCharsets.UTF_8))); + //4. 读取服务器写回的数据 + ByteBuffer byteBuffer = ByteBuffer.allocate(1024); + int read = socketChannel.read(byteBuffer); + System.out.println("服务端消息:" + + new String(byteBuffer.array(), 0, read, StandardCharsets.UTF_8)); + //5. 释放资源 + socketChannel.close(); + } + +} diff --git a/nio/src/main/java/com/lemon/selector/NIOSelectorServer.java b/nio/src/main/java/com/lemon/selector/NIOSelectorServer.java new file mode 100644 index 00000000..5593de0a --- /dev/null +++ b/nio/src/main/java/com/lemon/selector/NIOSelectorServer.java @@ -0,0 +1,74 @@ +package com.lemon.selector; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.nio.charset.StandardCharsets; +import java.util.Iterator; +import java.util.Set; + +/** + * @Description: 服务端-选择器 + * @Author : Lemon-CS + * @Date : 2022年03月07日 3:14 下午 + */ +public class NIOSelectorServer { + + public static void main(String[] args) throws IOException { + //1. 打开一个服务端通道 + ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); + //2. 绑定对应的端口号 + serverSocketChannel.bind(new InetSocketAddress(9999)); + //3. 通道默认是阻塞的,需要设置为非阻塞 + serverSocketChannel.configureBlocking(false); + //4. 创建选择器 + Selector selector = Selector.open(); + //5. 将服务端通道注册到选择器上,并指定注册监听的事件为OP_ACCEPT + serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); + + System.out.println("服务端启动成功....."); + while (true) { + //6. 检查选择器是否有事件 + int select = selector.select(2000); + if (select == 0) { + System.out.println("没有事件发生...."); + continue; + } + //7. 获取事件集合 + Set selectionKeys = selector.selectedKeys(); + Iterator iterator = selectionKeys.iterator(); + while (iterator.hasNext()) { + //8. 判断事件是否是客户端连接事件SelectionKey.isAcceptable() + SelectionKey key = iterator.next(); + if (key.isAcceptable()) { + //9. 得到客户端通道,并将通道注册到选择器上, 并指定监听事件为OP_READ + SocketChannel socketChannel = serverSocketChannel.accept(); + System.out.println("有客户端连接....."); + //将通道必须设置成非阻塞的状态.因为selector选择器需要轮询监听每个通道的事件 + socketChannel.configureBlocking(false); + //指定监听事件为OP_READ 读就绪事件 + socketChannel.register(selector, SelectionKey.OP_READ); + } + + //10. 判断是否是客户端读就绪事件SelectionKey.isReadable() + if (key.isReadable()) { + //11.得到客户端通道,读取数据到缓冲区 + SocketChannel socketChannel = (SocketChannel) key.channel(); + ByteBuffer byteBuffer = ByteBuffer.allocate(1024); + int read = socketChannel.read(byteBuffer); + if (read > 0) { + System.out.println("客户端消息:" + new String(byteBuffer.array(), 0, read + , StandardCharsets.UTF_8)); + //12. 给客户端回写数据 + socketChannel.write(ByteBuffer.wrap("没钱".getBytes(StandardCharsets.UTF_8))); + socketChannel.close(); + } + } + //13. 从集合中删除对应的事件, 因为防止二次处理. + iterator.remove(); + } + } + } + +} From 916c818009bf604b6969700d6464b7fd0871a7c7 Mon Sep 17 00:00:00 2001 From: fangpeng <591930734@qq.com> Date: Mon, 7 Mar 2022 18:56:07 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0netty=E5=92=8C=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E7=AB=AF=E5=92=8C=E6=9C=8D=E5=8A=A1=E7=AB=AF=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E7=BC=96=E8=A7=A3=E7=A0=81=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netty-demo/pom.xml | 24 +++++ .../java/com/lemon/codec/MessageCodec.java | 46 ++++++++ .../java/com/lemon/codec/MessageDecoder.java | 22 ++++ .../java/com/lemon/codec/MessageEncoder.java | 22 ++++ .../java/com/lemon/codec/NettyClient.java | 46 ++++++++ .../com/lemon/codec/NettyClientHandler.java | 99 +++++++++++++++++ .../java/com/lemon/codec/NettyServer.java | 60 +++++++++++ .../com/lemon/codec/NettyServerHandler.java | 98 +++++++++++++++++ .../main/java/com/lemon/demo/NettyClient.java | 40 +++++++ .../com/lemon/demo/NettyClientHandler.java | 101 ++++++++++++++++++ .../main/java/com/lemon/demo/NettyServer.java | 54 ++++++++++ .../com/lemon/demo/NettyServerHandler.java | 99 +++++++++++++++++ 12 files changed, 711 insertions(+) create mode 100644 netty-demo/pom.xml create mode 100644 netty-demo/src/main/java/com/lemon/codec/MessageCodec.java create mode 100644 netty-demo/src/main/java/com/lemon/codec/MessageDecoder.java create mode 100644 netty-demo/src/main/java/com/lemon/codec/MessageEncoder.java create mode 100644 netty-demo/src/main/java/com/lemon/codec/NettyClient.java create mode 100644 netty-demo/src/main/java/com/lemon/codec/NettyClientHandler.java create mode 100644 netty-demo/src/main/java/com/lemon/codec/NettyServer.java create mode 100644 netty-demo/src/main/java/com/lemon/codec/NettyServerHandler.java create mode 100644 netty-demo/src/main/java/com/lemon/demo/NettyClient.java create mode 100644 netty-demo/src/main/java/com/lemon/demo/NettyClientHandler.java create mode 100644 netty-demo/src/main/java/com/lemon/demo/NettyServer.java create mode 100644 netty-demo/src/main/java/com/lemon/demo/NettyServerHandler.java diff --git a/netty-demo/pom.xml b/netty-demo/pom.xml new file mode 100644 index 00000000..d587a598 --- /dev/null +++ b/netty-demo/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + + com.lemon + netty-demo + 1.0-SNAPSHOT + + + 8 + 8 + + + + + io.netty + netty-all + 4.1.56.Final + + + + \ No newline at end of file diff --git a/netty-demo/src/main/java/com/lemon/codec/MessageCodec.java b/netty-demo/src/main/java/com/lemon/codec/MessageCodec.java new file mode 100644 index 00000000..49324518 --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/codec/MessageCodec.java @@ -0,0 +1,46 @@ +package com.lemon.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageCodec; +import io.netty.util.CharsetUtil; + +import java.util.List; + +/** + * @Description: 消息编解码器 + * @Author : Lemon-CS + * @Date : 2022年03月07日 6:54 下午 + */ +public class MessageCodec extends MessageToMessageCodec { + /** + * 编码 + * + * @param ctx + * @param msg + * @param out + * @throws Exception + */ + @Override + protected void encode(ChannelHandlerContext ctx, Object msg, List out) throws Exception { + System.out.println("消息正在进行编码...."); + String str = (String) msg; + out.add(Unpooled.copiedBuffer(str, CharsetUtil.UTF_8)); + } + + /** + * 解码 + * + * @param ctx + * @param msg + * @param out + * @throws Exception + */ + @Override + protected void decode(ChannelHandlerContext ctx, Object msg, List out) throws Exception { + System.out.println("正在进行消息解码...."); + ByteBuf byteBuf = (ByteBuf) msg; + out.add(byteBuf.toString(CharsetUtil.UTF_8));//传递到下一个handler + } +} diff --git a/netty-demo/src/main/java/com/lemon/codec/MessageDecoder.java b/netty-demo/src/main/java/com/lemon/codec/MessageDecoder.java new file mode 100644 index 00000000..077c2454 --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/codec/MessageDecoder.java @@ -0,0 +1,22 @@ +package com.lemon.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; +import io.netty.util.CharsetUtil; + +import java.util.List; + +/** + * @Description: 消息解码器 + * @Author : Lemon-CS + * @Date : 2022年03月07日 6:39 下午 + */ +public class MessageDecoder extends MessageToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext ctx, Object msg, List out) throws Exception { + System.out.println("正在进行消息解码...."); + ByteBuf byteBuf = (ByteBuf) msg; + out.add(byteBuf.toString(CharsetUtil.UTF_8)); //传递到下一个handler + } +} diff --git a/netty-demo/src/main/java/com/lemon/codec/MessageEncoder.java b/netty-demo/src/main/java/com/lemon/codec/MessageEncoder.java new file mode 100644 index 00000000..6630c829 --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/codec/MessageEncoder.java @@ -0,0 +1,22 @@ +package com.lemon.codec; + +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageEncoder; +import io.netty.util.CharsetUtil; + +import java.util.List; + +/** + * @Description: 消息的编码器 + * @Author : Lemon-CS + * @Date : 2022年03月07日 6:46 下午 + */ +public class MessageEncoder extends MessageToMessageEncoder { + @Override + protected void encode(ChannelHandlerContext ctx, Object msg, List out) throws Exception { + System.out.println("消息正在进行编码...."); + String str = (String) msg; + out.add(Unpooled.copiedBuffer(str, CharsetUtil.UTF_8)); + } +} diff --git a/netty-demo/src/main/java/com/lemon/codec/NettyClient.java b/netty-demo/src/main/java/com/lemon/codec/NettyClient.java new file mode 100644 index 00000000..a06b6721 --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/codec/NettyClient.java @@ -0,0 +1,46 @@ +package com.lemon.codec; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; + +/** + * @Description: 客户端 + * @Author : Lemon-CS + * @Date : 2022年03月07日 5:28 下午 + */ +public class NettyClient { + + public static void main(String[] args) throws InterruptedException { + //1. 创建线程组 + EventLoopGroup group = new NioEventLoopGroup(); + //2. 创建客户端启动助手 + Bootstrap bootstrap = new Bootstrap(); + //3. 设置线程组 + bootstrap.group(group) + .channel(NioSocketChannel.class)//4. 设置客户端通道实现为NIO + .handler(new ChannelInitializer() { //5. 创建一个通道初始化对象 + @Override + protected void initChannel(SocketChannel ch) throws Exception { + //添加解码器 + //ch.pipeline().addLast("messageDecoder", new MessageDecoder()); + //添加编码器 + //ch.pipeline().addLast("messageEncoder", new MessageEncoder()); + //添加编解码器 + ch.pipeline().addLast(new MessageCodec()); + //6. 向pipeline中添加自定义业务处理handler + ch.pipeline().addLast(new NettyClientHandler()); + } + }); + //7. 启动客户端,等待连接服务端,同时将异步改为同步 + ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9999).sync(); + //8. 关闭通道和关闭连接池 + channelFuture.channel().closeFuture().sync(); + group.shutdownGracefully(); + } + +} diff --git a/netty-demo/src/main/java/com/lemon/codec/NettyClientHandler.java b/netty-demo/src/main/java/com/lemon/codec/NettyClientHandler.java new file mode 100644 index 00000000..e3603a82 --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/codec/NettyClientHandler.java @@ -0,0 +1,99 @@ +package com.lemon.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandler; +import io.netty.util.CharsetUtil; + +/** + * @Description: 客户端处理类 + * @Author : Lemon-CS + * @Date : 2022年03月07日 5:32 下午 + */ +public class NettyClientHandler implements ChannelInboundHandler { + + /** + * 通道就绪事件 + * + * @param ctx + * @throws Exception + */ + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + ChannelFuture future = ctx.writeAndFlush("你好呀.我是Netty客户端"); + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (future.isSuccess()) { + System.out.println("数据发送成功!"); + } else { + System.out.println("数据发送失败!"); + } + } + }); + } + + /** + * 通道读就绪事件 + * + * @param ctx + * @param msg + * @throws Exception + */ + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + System.out.println("客户端发送过来的消息:" + msg); + } + + + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { + + } + + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + + } + + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + + } + + @Override + public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + + } +} + diff --git a/netty-demo/src/main/java/com/lemon/codec/NettyServer.java b/netty-demo/src/main/java/com/lemon/codec/NettyServer.java new file mode 100644 index 00000000..d4a1d291 --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/codec/NettyServer.java @@ -0,0 +1,60 @@ +package com.lemon.codec; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.*; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; + +/** + * @Description: Netty服务端 + * @Author : Lemon-CS + * @Date : 2022年03月07日 5:12 下午 + */ +public class NettyServer { + + public static void main(String[] args) throws InterruptedException { + //1. 创建bossGroup线程组: 处理网络事件--连接事件 + EventLoopGroup bossGroup = new NioEventLoopGroup(1); + //2. 创建workerGroup线程组: 处理网络事件--读写事件 2*处理器线程数 + EventLoopGroup workerGroup = new NioEventLoopGroup(); + //3. 创建服务端启动助手 + ServerBootstrap serverBootstrap = new ServerBootstrap(); + //4. 设置bossGroup线程组和workerGroup线程组 + serverBootstrap.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) //5. 设置服务端通道实现为NIO + .option(ChannelOption.SO_BACKLOG, 128)//6. 参数设置 + .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)//6. 参数设置 + .childHandler(new ChannelInitializer() { //7. 创建一个通道初始化对象 + @Override + protected void initChannel(SocketChannel ch) throws Exception { + //添加解码器 + //ch.pipeline().addLast("messageDecoder", new MessageDecoder()); + //添加编码器 + //ch.pipeline().addLast("messageEncoder", new MessageEncoder()); + //添加编解码器 + ch.pipeline().addLast(new MessageCodec()); + //8. 向pipeline中添加自定义业务处理handler + ch.pipeline().addLast(new NettyServerHandler()); + } + }); + //9. 启动服务端并绑定端口,同时将异步改为同步 + ChannelFuture future = serverBootstrap.bind(9999); + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (future.isSuccess()) { + System.out.println("端口绑定成功!"); + } else { + System.out.println("端口绑定失败!"); + } + } + }); + System.out.println("服务端启动成功."); + //10. 关闭通道(并不是真正意义上关闭,而是监听通道关闭的状态)和关闭连接池 + future.channel().closeFuture().sync(); + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + +} diff --git a/netty-demo/src/main/java/com/lemon/codec/NettyServerHandler.java b/netty-demo/src/main/java/com/lemon/codec/NettyServerHandler.java new file mode 100644 index 00000000..c3f95138 --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/codec/NettyServerHandler.java @@ -0,0 +1,98 @@ +package com.lemon.codec; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandler; +import io.netty.util.CharsetUtil; + +/** + * @Description: 自定义处理Handler + * @Author : Lemon-CS + * @Date : 2022年03月07日 5:20 下午 + */ + +/** + * 自定义处理Handler + */ +public class NettyServerHandler implements ChannelInboundHandler { + + /** + * 通道读取事件 + * + * @param ctx + * @param msg + * @throws Exception + */ + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + System.out.println("客户端发送过来的消息:" + msg); + } + + + /** + * 通道读取完毕事件 + * + * @param ctx + * @throws Exception + */ + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.writeAndFlush("你好.我是Netty服务端");//消息出站 + } + + /** + * 通道异常事件 + * + * @param ctx + * @param cause + * @throws Exception + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + cause.printStackTrace(); + ctx.close(); + } + + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + + } + + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + + } + + @Override + public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + + } + +} diff --git a/netty-demo/src/main/java/com/lemon/demo/NettyClient.java b/netty-demo/src/main/java/com/lemon/demo/NettyClient.java new file mode 100644 index 00000000..6984424d --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/demo/NettyClient.java @@ -0,0 +1,40 @@ +package com.lemon.demo; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; + +/** + * @Description: 客户端 + * @Author : Lemon-CS + * @Date : 2022年03月07日 5:28 下午 + */ +public class NettyClient { + + public static void main(String[] args) throws InterruptedException { + //1. 创建线程组 + EventLoopGroup group = new NioEventLoopGroup(); + //2. 创建客户端启动助手 + Bootstrap bootstrap = new Bootstrap(); + //3. 设置线程组 + bootstrap.group(group) + .channel(NioSocketChannel.class)//4. 设置客户端通道实现为NIO + .handler(new ChannelInitializer() { //5. 创建一个通道初始化对象 + @Override + protected void initChannel(SocketChannel ch) throws Exception { + //6. 向pipeline中添加自定义业务处理handler + ch.pipeline().addLast(new NettyClientHandler()); + } + }); + //7. 启动客户端,等待连接服务端,同时将异步改为同步 + ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9999).sync(); + //8. 关闭通道和关闭连接池 + channelFuture.channel().closeFuture().sync(); + group.shutdownGracefully(); + } + +} diff --git a/netty-demo/src/main/java/com/lemon/demo/NettyClientHandler.java b/netty-demo/src/main/java/com/lemon/demo/NettyClientHandler.java new file mode 100644 index 00000000..fe8bdd45 --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/demo/NettyClientHandler.java @@ -0,0 +1,101 @@ +package com.lemon.demo; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandler; +import io.netty.util.CharsetUtil; + +/** + * @Description: 客户端处理类 + * @Author : Lemon-CS + * @Date : 2022年03月07日 5:32 下午 + */ +public class NettyClientHandler implements ChannelInboundHandler { + + /** + * 通道就绪事件 + * + * @param ctx + * @throws Exception + */ + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + ChannelFuture future = ctx.writeAndFlush(Unpooled.copiedBuffer("你好呀.我是Netty客户端", + CharsetUtil.UTF_8)); + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (future.isSuccess()) { + System.out.println("数据发送成功!"); + } else { + System.out.println("数据发送失败!"); + } + } + }); + } + + /** + * 通道读就绪事件 + * + * @param ctx + * @param msg + * @throws Exception + */ + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + ByteBuf byteBuf = (ByteBuf) msg; + System.out.println("服务端发送的消息:" + byteBuf.toString(CharsetUtil.UTF_8)); + } + + + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { + + } + + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + + } + + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + + } + + @Override + public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + + } +} + diff --git a/netty-demo/src/main/java/com/lemon/demo/NettyServer.java b/netty-demo/src/main/java/com/lemon/demo/NettyServer.java new file mode 100644 index 00000000..523139ad --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/demo/NettyServer.java @@ -0,0 +1,54 @@ +package com.lemon.demo; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.*; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; + +/** + * @Description: Netty服务端 + * @Author : Lemon-CS + * @Date : 2022年03月07日 5:12 下午 + */ +public class NettyServer { + + public static void main(String[] args) throws InterruptedException { + //1. 创建bossGroup线程组: 处理网络事件--连接事件 + EventLoopGroup bossGroup = new NioEventLoopGroup(1); + //2. 创建workerGroup线程组: 处理网络事件--读写事件 2*处理器线程数 + EventLoopGroup workerGroup = new NioEventLoopGroup(); + //3. 创建服务端启动助手 + ServerBootstrap serverBootstrap = new ServerBootstrap(); + //4. 设置bossGroup线程组和workerGroup线程组 + serverBootstrap.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) //5. 设置服务端通道实现为NIO + .option(ChannelOption.SO_BACKLOG, 128)//6. 参数设置 + .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)//6. 参数设置 + .childHandler(new ChannelInitializer() { //7. 创建一个通道初始化对象 + @Override + protected void initChannel(SocketChannel ch) throws Exception { + //8. 向pipeline中添加自定义业务处理handler + ch.pipeline().addLast(new NettyServerHandler()); + } + }); + //9. 启动服务端并绑定端口,同时将异步改为同步 + ChannelFuture future = serverBootstrap.bind(9999); + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (future.isSuccess()) { + System.out.println("端口绑定成功!"); + } else { + System.out.println("端口绑定失败!"); + } + } + }); + System.out.println("服务端启动成功."); + //10. 关闭通道(并不是真正意义上关闭,而是监听通道关闭的状态)和关闭连接池 + future.channel().closeFuture().sync(); + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + +} diff --git a/netty-demo/src/main/java/com/lemon/demo/NettyServerHandler.java b/netty-demo/src/main/java/com/lemon/demo/NettyServerHandler.java new file mode 100644 index 00000000..ec8d49be --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/demo/NettyServerHandler.java @@ -0,0 +1,99 @@ +package com.lemon.demo; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandler; +import io.netty.util.CharsetUtil; + +/** + * @Description: 自定义处理Handler + * @Author : Lemon-CS + * @Date : 2022年03月07日 5:20 下午 + */ +/** + * 自定义处理Handler + */ +public class NettyServerHandler implements ChannelInboundHandler { + + /** + * 通道读取事件 + * + * @param ctx + * @param msg + * @throws Exception + */ + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + ByteBuf byteBuf = (ByteBuf) msg; + System.out.println("客户端发送过来的消息:" + byteBuf.toString(CharsetUtil.UTF_8)); + } + + + /** + * 通道读取完毕事件 + * + * @param ctx + * @throws Exception + */ + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.writeAndFlush(Unpooled.copiedBuffer("你好.我是Netty服务端", + CharsetUtil.UTF_8));//消息出站 + } + + /** + * 通道异常事件 + * + * @param ctx + * @param cause + * @throws Exception + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + cause.printStackTrace(); + ctx.close(); + } + + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + + } + + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + + } + + @Override + public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + + } + +} From 626e99903d8151c9db1675869cba04e51af97337 Mon Sep 17 00:00:00 2001 From: fangpeng <591930734@qq.com> Date: Mon, 7 Mar 2022 19:37:39 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0netty=E8=81=8A=E5=A4=A9?= =?UTF-8?q?=E5=AE=A4demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/lemon/chat/NettyChatClient.java | 73 ++++++++++++++++ .../lemon/chat/NettyChatClientHandler.java | 23 +++++ .../java/com/lemon/chat/NettyChatServer.java | 81 ++++++++++++++++++ .../lemon/chat/NettyChatServerHandler.java | 85 +++++++++++++++++++ 4 files changed, 262 insertions(+) create mode 100644 netty-demo/src/main/java/com/lemon/chat/NettyChatClient.java create mode 100644 netty-demo/src/main/java/com/lemon/chat/NettyChatClientHandler.java create mode 100644 netty-demo/src/main/java/com/lemon/chat/NettyChatServer.java create mode 100644 netty-demo/src/main/java/com/lemon/chat/NettyChatServerHandler.java diff --git a/netty-demo/src/main/java/com/lemon/chat/NettyChatClient.java b/netty-demo/src/main/java/com/lemon/chat/NettyChatClient.java new file mode 100644 index 00000000..5393062a --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/chat/NettyChatClient.java @@ -0,0 +1,73 @@ +package com.lemon.chat; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; + +import java.util.Scanner; + +/** + * @Description: 聊天室的客户端 + * @Author : Lemon-CS + * @Date : 2022年03月07日 7:24 下午 + */ +public class NettyChatClient { + + private String ip;//服务端IP + private int port;//服务端端口号 + + public NettyChatClient(String ip, int port) { + this.ip = ip; + this.port = port; + } + + public void run() throws InterruptedException { + //1. 创建线程组 + EventLoopGroup group = null; + try { + group = new NioEventLoopGroup(); + //2. 创建客户端启动助手 + Bootstrap bootstrap = new Bootstrap(); + //3. 设置线程组 + bootstrap.group(group) + .channel(NioSocketChannel.class)//4. 设置客户端通道实现为NIO + .handler(new ChannelInitializer() { //5. 创建一个通道初始化对象 + @Override + protected void initChannel(SocketChannel ch) throws Exception { + //6. 向pipeline中添加自定义业务处理handler + //添加编解码器 + ch.pipeline().addLast(new StringDecoder()); + ch.pipeline().addLast(new StringEncoder()); + //添加客户端的处理类 + ch.pipeline().addLast(new NettyChatClientHandler()); + } + }); + //7. 启动客户端,等待连接服务端,同时将异步改为同步 + ChannelFuture channelFuture = bootstrap.connect(ip, port).sync(); + Channel channel = channelFuture.channel(); + System.out.println("-------" + channel.localAddress().toString().substring(1) + "--------"); + Scanner scanner = new Scanner(System.in); + while (scanner.hasNextLine()) { + String msg = scanner.nextLine(); + //向服务端发送消息 + channel.writeAndFlush(msg); + } + //8. 关闭通道和关闭连接池 + channelFuture.channel().closeFuture().sync(); + } finally { + group.shutdownGracefully(); + } + } + + public static void main(String[] args) throws InterruptedException { + new NettyChatClient("127.0.0.1", 9999).run(); + } + +} diff --git a/netty-demo/src/main/java/com/lemon/chat/NettyChatClientHandler.java b/netty-demo/src/main/java/com/lemon/chat/NettyChatClientHandler.java new file mode 100644 index 00000000..2de8e673 --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/chat/NettyChatClientHandler.java @@ -0,0 +1,23 @@ +package com.lemon.chat; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +/** + * @Description: 聊天室处理类 + * @Author : Lemon-CS + * @Date : 2022年03月07日 7:26 下午 + */ +public class NettyChatClientHandler extends SimpleChannelInboundHandler { + /** + * 通道读取就绪事件 + * + * @param ctx + * @param msg + * @throws Exception + */ + @Override + protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { + System.out.println(msg); + } +} diff --git a/netty-demo/src/main/java/com/lemon/chat/NettyChatServer.java b/netty-demo/src/main/java/com/lemon/chat/NettyChatServer.java new file mode 100644 index 00000000..bebc37a4 --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/chat/NettyChatServer.java @@ -0,0 +1,81 @@ +package com.lemon.chat; + +import com.lemon.demo.NettyServerHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.*; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.string.StringDecoder; +import io.netty.handler.codec.string.StringEncoder; +import jdk.nashorn.internal.objects.NativeNumber; + +/** + * @Description: 聊天室服务端 + * @Author : Lemon-CS + * @Date : 2022年03月07日 6:59 下午 + */ +public class NettyChatServer { + + //端口号 + private int port; + + public NettyChatServer(int port) { + this.port = port; + } + + public void run() throws InterruptedException { + + //1. 创建bossGroup线程组: 处理网络事件--连接事件 + EventLoopGroup bossGroup = null; + //2. 创建workerGroup线程组: 处理网络事件--读写事件 2*处理器线程数 + EventLoopGroup workerGroup = null; + + try { + bossGroup = new NioEventLoopGroup(1); + workerGroup = new NioEventLoopGroup(); + + //3. 创建服务端启动助手 + ServerBootstrap serverBootstrap = new ServerBootstrap(); + //4. 设置bossGroup线程组和workerGroup线程组 + serverBootstrap.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) //5. 设置服务端通道实现为NIO + .option(ChannelOption.SO_BACKLOG, 128)//6. 参数设置 + .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)//6. 参数设置 + .childHandler(new ChannelInitializer() { //7. 创建一个通道初始化对象 + @Override + protected void initChannel(SocketChannel ch) throws Exception { + //添加编解码器 + ch.pipeline().addLast(new StringDecoder()); + ch.pipeline().addLast(new StringEncoder()); + //8. 向pipeline中添加自定义业务处理handler + ch.pipeline().addLast(new NettyChatServerHandler()); + } + }); + //9. 启动服务端并绑定端口,同时将异步改为同步 + ChannelFuture future = serverBootstrap.bind(port); + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (future.isSuccess()) { + System.out.println("端口绑定成功!"); + } else { + System.out.println("端口绑定失败!"); + } + } + }); + System.out.println("聊天室服务端启动成功."); + //10. 关闭通道(并不是真正意义上关闭,而是监听通道关闭的状态)和关闭连接池 + future.channel().closeFuture().sync(); + + } finally { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } + + public static void main(String[] args) throws InterruptedException { + new NettyChatServer(9999).run(); + } + +} diff --git a/netty-demo/src/main/java/com/lemon/chat/NettyChatServerHandler.java b/netty-demo/src/main/java/com/lemon/chat/NettyChatServerHandler.java new file mode 100644 index 00000000..30adacb7 --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/chat/NettyChatServerHandler.java @@ -0,0 +1,85 @@ +package com.lemon.chat; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Description: 聊天室业务处理类 + * @Author : Lemon-CS + * @Date : 2022年03月07日 7:05 下午 + */ +public class NettyChatServerHandler extends SimpleChannelInboundHandler { + + public static List channelList = new ArrayList<>(); + + /** + * 通道就绪事件 + * + * @param ctx + * @throws Exception + */ + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + Channel channel = ctx.channel(); + //当有新的客户端连接的时候, 将通道放入集合 + channelList.add(channel); + System.out.println("[Server]:" + + channel.remoteAddress().toString().substring(1) + "在线."); + } + + /** + * 通道未就绪--channel下线 + * + * @param ctx + * @throws Exception + */ + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + Channel channel = ctx.channel(); + //当有客户端断开连接的时候,就移除对应的通道 + channelList.remove(channel); + System.out.println("[Server]:" + + channel.remoteAddress().toString().substring(1) + "下线."); + } + + /** + * 通道读取事件 + * + * @param ctx + * @param msg + * @throws Exception + */ + @Override + protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { + //当前发送消息的通道, 当前发送的客户端连接 + Channel channel = ctx.channel(); + for (Channel channel1 : channelList) { + //排除自身通道 + if (channel != channel1) { + channel1.writeAndFlush("[" + channel.remoteAddress().toString().substring(1) + + "]说:" + msg); + } + } + } + + /** + * 异常处理事件 + * + * @param ctx + * @param cause + * @throws Exception + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + cause.printStackTrace(); + Channel channel = ctx.channel(); + //移除集合 + channelList.remove(channel); + System.out.println("[Server]:" + + channel.remoteAddress().toString().substring(1) + "异常."); + } +} From 423e964d2b196dcc36236421eb68bc4a9174323a Mon Sep 17 00:00:00 2001 From: fangpeng <591930734@qq.com> Date: Mon, 7 Mar 2022 21:10:55 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E6=B7=BB=E5=8A=A0netty=E6=95=B4=E5=90=88we?= =?UTF-8?q?bsocket=E8=81=8A=E5=A4=A9=E5=AE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/lemon/http/NettyHttpServer.java | 74 + .../lemon/http/NettyHttpServerHandler.java | 46 + netty-springboot/.gitignore | 33 + .../.mvn/wrapper/maven-wrapper.jar | Bin 0 -> 58727 bytes .../.mvn/wrapper/maven-wrapper.properties | 2 + netty-springboot/mvnw | 316 + netty-springboot/mvnw.cmd | 188 + netty-springboot/pom.xml | 67 + .../com/lemon/NettySpringbootApplication.java | 23 + .../java/com/lemon/config/NettyConfig.java | 21 + .../com/lemon/controller/ChatController.java | 15 + .../com/lemon/netty/NettyWebSocketServer.java | 67 + .../com/lemon/netty/WebSocketChannelInit.java | 43 + .../com/lemon/netty/WebSocketHandler.java | 89 + .../src/main/resources/application.yaml | 17 + .../src/main/resources/static/css/chat.css | 454 + .../main/resources/static/img/arrow_right.svg | 1 + .../src/main/resources/static/img/bg.jpg | Bin 0 -> 41567 bytes .../src/main/resources/static/img/close.svg | 1 + .../src/main/resources/static/img/hongbao.png | Bin 0 -> 35527 bytes .../src/main/resources/static/img/img.png | Bin 0 -> 51828 bytes .../src/main/resources/static/img/my.jpg | Bin 0 -> 5178 bytes .../src/main/resources/static/img/my.png | Bin 0 -> 51828 bytes .../src/main/resources/static/img/pager.png | Bin 0 -> 23468 bytes .../main/resources/static/img/pager_bgc.png | Bin 0 -> 11827 bytes .../src/main/resources/static/img/paper.svg | 1 + .../src/main/resources/static/img/smile.svg | 1 + .../main/resources/static/img/spelling.svg | 1 + .../src/main/resources/static/img/user.png | Bin 0 -> 20088 bytes .../main/resources/static/js/bootstrap.min.js | 7 + .../src/main/resources/static/js/chat.js | 108 + .../src/main/resources/static/js/common.js | 107 + .../main/resources/static/js/jquery-2.2.0.js | 9831 +++++++++++++++++ .../resources/static/js/jquery.1.7.2.min.js | 4 + .../resources/static/js/jquery.tag-editor.js | 328 + .../src/main/resources/templates/chat.html | 46 + .../NettySpringbootApplicationTests.java | 13 + 37 files changed, 11904 insertions(+) create mode 100644 netty-demo/src/main/java/com/lemon/http/NettyHttpServer.java create mode 100644 netty-demo/src/main/java/com/lemon/http/NettyHttpServerHandler.java create mode 100644 netty-springboot/.gitignore create mode 100644 netty-springboot/.mvn/wrapper/maven-wrapper.jar create mode 100644 netty-springboot/.mvn/wrapper/maven-wrapper.properties create mode 100755 netty-springboot/mvnw create mode 100644 netty-springboot/mvnw.cmd create mode 100644 netty-springboot/pom.xml create mode 100644 netty-springboot/src/main/java/com/lemon/NettySpringbootApplication.java create mode 100644 netty-springboot/src/main/java/com/lemon/config/NettyConfig.java create mode 100755 netty-springboot/src/main/java/com/lemon/controller/ChatController.java create mode 100644 netty-springboot/src/main/java/com/lemon/netty/NettyWebSocketServer.java create mode 100644 netty-springboot/src/main/java/com/lemon/netty/WebSocketChannelInit.java create mode 100644 netty-springboot/src/main/java/com/lemon/netty/WebSocketHandler.java create mode 100755 netty-springboot/src/main/resources/application.yaml create mode 100755 netty-springboot/src/main/resources/static/css/chat.css create mode 100755 netty-springboot/src/main/resources/static/img/arrow_right.svg create mode 100755 netty-springboot/src/main/resources/static/img/bg.jpg create mode 100755 netty-springboot/src/main/resources/static/img/close.svg create mode 100755 netty-springboot/src/main/resources/static/img/hongbao.png create mode 100755 netty-springboot/src/main/resources/static/img/img.png create mode 100755 netty-springboot/src/main/resources/static/img/my.jpg create mode 100755 netty-springboot/src/main/resources/static/img/my.png create mode 100755 netty-springboot/src/main/resources/static/img/pager.png create mode 100755 netty-springboot/src/main/resources/static/img/pager_bgc.png create mode 100755 netty-springboot/src/main/resources/static/img/paper.svg create mode 100755 netty-springboot/src/main/resources/static/img/smile.svg create mode 100755 netty-springboot/src/main/resources/static/img/spelling.svg create mode 100755 netty-springboot/src/main/resources/static/img/user.png create mode 100755 netty-springboot/src/main/resources/static/js/bootstrap.min.js create mode 100755 netty-springboot/src/main/resources/static/js/chat.js create mode 100755 netty-springboot/src/main/resources/static/js/common.js create mode 100755 netty-springboot/src/main/resources/static/js/jquery-2.2.0.js create mode 100755 netty-springboot/src/main/resources/static/js/jquery.1.7.2.min.js create mode 100755 netty-springboot/src/main/resources/static/js/jquery.tag-editor.js create mode 100755 netty-springboot/src/main/resources/templates/chat.html create mode 100644 netty-springboot/src/test/java/com/lemon/nettyspringboot/NettySpringbootApplicationTests.java diff --git a/netty-demo/src/main/java/com/lemon/http/NettyHttpServer.java b/netty-demo/src/main/java/com/lemon/http/NettyHttpServer.java new file mode 100644 index 00000000..d20d9325 --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/http/NettyHttpServer.java @@ -0,0 +1,74 @@ +package com.lemon.http; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.*; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.http.HttpServerCodec; + +/** + * @Description: Http服务端 + * @Author : Lemon-CS + * @Date : 2022年03月07日 7:44 下午 + */ +public class NettyHttpServer { + + //端口号 + private int port; + + public NettyHttpServer(int port) { + this.port = port; + } + + public void run() throws InterruptedException { + //1. 创建bossGroup线程组: 处理网络事件--连接事件 + EventLoopGroup bossGroup = null; + //2. 创建workerGroup线程组: 处理网络事件--读写事件 2*处理器线程数 + EventLoopGroup workerGroup = null; + try { + bossGroup = new NioEventLoopGroup(1); + workerGroup = new NioEventLoopGroup(); + //3. 创建服务端启动助手 + ServerBootstrap serverBootstrap = new ServerBootstrap(); + //4. 设置bossGroup线程组和workerGroup线程组 + serverBootstrap.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) //5. 设置服务端通道实现为NIO + .option(ChannelOption.SO_BACKLOG, 128)//6. 参数设置 + .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE)//6. 参数设置 + .childHandler(new ChannelInitializer() { //7. 创建一个通道初始化对象 + @Override + protected void initChannel(SocketChannel ch) throws Exception { + //8. 向pipeline中添加自定义业务处理handler + //添加编解码器 + ch.pipeline().addLast(new HttpServerCodec()); + // 自定义业务处理类 + ch.pipeline().addLast(new NettyHttpServerHandler()); + } + }); + //9. 启动服务端并绑定端口,同时将异步改为同步 + ChannelFuture future = serverBootstrap.bind(port); + future.addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (future.isSuccess()) { + System.out.println("端口绑定成功!"); + } else { + System.out.println("端口绑定失败!"); + } + } + }); + System.out.println("http服务端启动成功."); + //10. 关闭通道(并不是真正意义上关闭,而是监听通道关闭的状态)和关闭连接池 + future.channel().closeFuture().sync(); + } finally { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } + + public static void main(String[] args) throws InterruptedException { + new NettyHttpServer(8080).run(); + } + +} diff --git a/netty-demo/src/main/java/com/lemon/http/NettyHttpServerHandler.java b/netty-demo/src/main/java/com/lemon/http/NettyHttpServerHandler.java new file mode 100644 index 00000000..c47ceafa --- /dev/null +++ b/netty-demo/src/main/java/com/lemon/http/NettyHttpServerHandler.java @@ -0,0 +1,46 @@ +package com.lemon.http; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.*; +import io.netty.util.CharsetUtil; + +/** + * @Description: http服务器处理类 + * @Author : Lemon-CS + * @Date : 2022年03月07日 7:45 下午 + */ +public class NettyHttpServerHandler extends SimpleChannelInboundHandler { + + /** + * 读取就绪事件 + * + * @param ctx + * @param msg + * @throws Exception + */ + @Override + protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { + //1.判断请求是不是HTTP请求 + if (msg instanceof HttpRequest) { + DefaultHttpRequest request = (DefaultHttpRequest) msg; + System.out.println("浏览器请求路径:" + request.uri()); + if ("/favicon.ico".equals(request.uri())) { + System.out.println("图标不响应"); + return; + } + //2.给浏览器进行响应 + ByteBuf byteBuf = Unpooled.copiedBuffer("Hello! 我是Netty服务器 ", CharsetUtil.UTF_8); + + DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, byteBuf); + //2.1 设置响应头 + response.headers().set(HttpHeaderNames.CONTENT_TYPE, + "text/html;charset=utf-8"); + response.headers().set(HttpHeaderNames.CONTENT_LENGTH, + byteBuf.readableBytes()); + ctx.writeAndFlush(response); + } + } +} diff --git a/netty-springboot/.gitignore b/netty-springboot/.gitignore new file mode 100644 index 00000000..549e00a2 --- /dev/null +++ b/netty-springboot/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/netty-springboot/.mvn/wrapper/maven-wrapper.jar b/netty-springboot/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..c1dd12f17644411d6e840bd5a10c6ecda0175f18 GIT binary patch literal 58727 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%0ANsA|A3-jj|r`KAo%oTajX3>^E` zq{Nq+*dAH{EQyjZw_d4E!54gka%phEHEm}XI5o%$)&Z+*4qj<_EChj#X+kA1t|O3V@_RzoBA(&rgxwAF+zhjMY6+Xi>tw<6k+vgz=?DPJS^! zei4z1%+2HDqt}Ow+|2v^3IZQkTR<&IRxc0IZ_-Di>CErQ+oFQ~G{;lJSzvh9rKkAiSGHlAB$1}ZRdR^v zs2OS)Pca>Ap(RaSs7lM2GfJ#%F`}$!)K4#RaGJ_tY}6PMzY{5uHi}HjU>Qb~wlXQ) zdd(`#gdDgN_cat+Q#1q&iH{`26k}U3UR5(?FXM>Jm{W%IKpM4Jo{`3aEHN)XI&Bwx zs}a_P|M)fwG1Tybl)Rkw#D__n_uM+eDn*}}uN4z)3dq)U)n>pIk&pbWpPt@TXlB?b z8AAgq!2_g-!QL>xdU4~4f6CB06j6@M?60$f;#gpb)X1N0YO*%fw2W`m=M@%ZGWPx; z)r*>C$WLCDX)-_~S%jEx%dBpzU6HNHNQ%gLO~*egm7li)zfi|oMBt1pwzMA$x@ zu{Ht#H}ZBZwaf0Ylus3KCZ*qfyfbTUYGuOQI9>??gLrBPf-0XB84}sCqt5Q(O$M& zoJ+1hx4Wp#z?uex+Q1crm2ai?kci;AE!yriBr}c@tQdCnhs$P-CE8jdP&uriF`WFt>D9wO9fCS0WzaqUKjV_uRWg>^hIC!n-~q=1K87NAECZb^W?R zjbI&9pJ)4SSxiq06Zasv*@ATm7ghLgGw3coL-dn6@_D-UhvwPXC3tLC)q3xA2`^D{ z&=G&aeSCN)6{2W6l@cg&2`cCja~D2N{_>ZQ)(5oSf!ns1i9szOif~I8@;2b)f2yQ5 zCqr{lGy5(^+d!<0g??wFzH^wuv=~0)g55&^7m8Ptk3y$OU|eI7 zIovLvNCoY%N(aW#=_C%GDqEO|hH3O9&iCp+LU=&CJ(=JYDGI;&ag&NKq}d;B`TonC zK+-t8V5KjcmDyMR@jvDs|7lkga4>TQej$5B+>A`@{zE&?j-QbQWk4J*eP2@%RzQ{J z?h`1~zwArwi^D7k9~%xtyf(2&$=GsP*n-fTKneej-y6y(3nNfC7|0{drDx{zz~cSs z<_+d2#ZDst@+`w{mwzmn?dM2aB;E;bS-Opq$%w@WnDwa$hUGL90u9c=as)+_6aO10 zLR|CR8nr<2DQTvkaH0QDsyn@TYCs7Nk3lN}Ix$)JM0*zf=0Ad$w9j723W#%{r8V&`{wx-8kSv#)mZ{FU%UZDIi zvbgLHyJ>z0BZe`GNM$Q;D6D48#zc9s(4^SGr>u-arE}okN62N{zuwX)@FL5>$ib=b z5Wtm~!ojD3X|g59lw%^hE?dL;c^bgVtBOkJxQR{Eb*nR1wVM&fJQ{<))bn9e3bSlu z3E-qpLbAE(S^I4mVn`?lycoV!yO!Qj_4qYgsg7tXR)Gu2%1)5FZu&lY7x>bU`eE}x zSZ5c`z~^&$9V?eEH!^Rp-Fz3WiCvEgf`Tq}CnWRZY+@jZ{2NewmyGUM6|xa3Sh7)v zj6d&NWUVqu9f-&W)tQ>Y%Ea!e76@y!Vm*aQp|wU5u<%knNvHZ!U}`fp*_)mIWba=j z*w9~{f5pD;zCmEWePjM#ERNiNjv!SnM-&rGpB9Nmiv}J+hwB&0f_+x?%*lgJFRHsqfFDPwyvh8<*xLT0u_BeEHw{q+UGj=$4udEx)Vq#sV zKB3+_C!RUKy?ac3-`+}dL2!D_2(5=8&@hBf`-AbU`-<_3>Ilqkg6qSI>9G(@Kx?g<0h0K&31$AR>R%d}{%DyXPss$&c^ja7NR z$0AN7Fl$>VpGxqHW15CjxAa6DUVmCpQNbOwBv8D^Y{bXg28> zEQE9xl?CWh0gS6%Y=G4Cy($Vb>jBb2f_dm#0_B<_Ce`|~Obt_Xp^nkR zK%o_`{h1XkWn}i|5Dp#q8D(;k;2|+{DAG{2gJgPNQ=KZ=FKY@d>QEu6W;oLsE(1}< zpnwSEj(K{Bu^#CXdi7L_$!X`QOx^tA1c{&-XTHo3G?3(H*&VM~*Aud?8%FU=dE&kV zJ$SqZoj^g@(q9x;7B30J$(-qUml{?3e+I^Cf?X0PpLr}m zS}W9`QaCwINRU&D5>j9O*j6S}R1`7{5+{d-xUlI~)U!^4+*b5tkuon-Msz03Z{{Kp zH!GAXoyr#1K;t5o#h#a%Lzj3XQGqM0TRnfu$(fsQe^wb_?W!m!+7r55q>svWN`k~T zS(gk9bi|@+8wg;dR<&0f;MpwQbY27$N{{laPQk3@3uCz$w1&jq)`uW*yn!Pe-V^%Q zR9)cW;UB~ODlwolWFAX?ik#_|v)AtHNwoq72E9Jg#v2e5SErf+7nTleI8&}%tn6hf zuz#5YtRs94Ui&E_1PakHfo+^t-{#ewhO*j5ls-zhm^C{kCARNEB1aORsxE!1SXBRz z6Oc-^#|0W6=7AJ;I|}pH#qby@i^C+Vsu9?zdtkE{0`oO_Hw|N=Lz9Is8j}R zI+8thGK?(KSZ5ZW4nQG1`v(=0Jd*0gIlavVihzo#fPaa=}(Rqdxl3^6O8K+{MqU`;1iTJ$<^k)Nms(A$j?A-wHJKvh9 zUHW3}JkE;x?FETPV8DFTxFLY8eSAd%C8vp?P_EuaMakmyFN_e?Hf|LBctnncUb}zF zIGP4WqtKCydoov~Bi<_I%y%$l+})!;SQVcP?>)9wM3q-GE6t9*LfoePBlo{gx~~e{g_XM5PQ8Y5dsuG%3Xq}I&qcY6 zTCo?<6E%)O$A2torq3-g8j3?GGd){+VHg@gM6Kw|E($M9}3HVIyL1D9321C zu#6~~h<<*=V7*ria%j^d5A;S^E;n!mOnFppfi+4)!BQ@#O2<|WH$RS~)&2Qol|@ff zFR#zmU(|jaqCXPA@q?UhrgbMO7zNXQYA@8$E+;4Bz7g=&zV-)=&08J_noLAz#ngz$ zA)8L8MrbXIDZuFsR_M(DsdX)s$}yH!*bLr{s$YWl5J?alLci=I#p`&MbL4`5bC}=2 z^8-(u4v2hs9*us}hjB!uiiY6vvv&QWJcVLTJ=SFG=lpR+S4Cd91l}oZ+B-*ehY2Ic_85)SRSa% zMEL~a3xrvH8ZnMIC!{9@pfOT7lrhxMf^8N20{CJXg}M35=`50S;6g-JYwjwj!K{^) z5Bohf6_G6z=+0V8&>F8xLbJ4mkCVu^g66#h&?tL z9odv&iW21IAh~y9D-DupKP-NcernF2(*RsFkAsM<$<>@-Cl1?&XAi4+Mh2Zm@2x#u zWH&J^1=8G|`|H2%94bnjUZyI>QACu9FS}^$lbtzzCz4AMspqGYEwFFM<%G!Oc$+;7 z3r_L!H~PR}5n8+3-&4v*fFr$uK{y_VamM0*TKn^))nQsn5U?7Iv?`4|Oy&m6himAG z%=a;2ji3f_RtDPqkwR>ISxhnS0f)E`ITo}TR!zIxPwECZy#jzo%q{BNYtd!<IP_S+=*yDOk1GgwLqe!d9esV@3$iVAm1!8RoE| zqnTz;5a)B(~~KcP)c>?+ysFAlAGF4EBor6)K{K*Kn>B(&QtMAkR^ynG%k%UbJpKM zI$}qQXXP3PISHe_vTFssbcL`irhG2zN7J((3ZFmh*bnPuiK~=#YG=820hXqOON#HI<0bvIT{z&SaqRvqaMG-d5<06zdP?-kIH{%UMR$Xn@S}Hx3 zFjg}6no}vN_512D+RIn-mo9^_Li-)WI5%VigYt{Jd!RyI%d|-LqJU$y3aJ*a$y6$1 zjyTuIF2&t>1rPlw&k5OVLhrYBvk5Vl8T(*Gd?Alqi}> z<@-`X_o@9EOB8Ik&?|;lvKHFU@#O+?T!kEf&oJUaLzN;>!}!!e1WIs(T}V#Irf$AK z42`x`z-9ogxd@%CS;D5S z2M^b;Pu)q)c&_KBO!va-4xnI57L7V@*_I_r4vU)z>xk5z6PDVqg92R7_iZH|VlO_B z#8R`5HZVn?ou>czd>gZ~s;w4ZkzVXJNP8FiezlB5JXe6Z-OLsDw%N7!(135!Vl2Lb zLYI79?U{h#W-_#W6hf`<$BQHJCu5ehv?IF+-uxUqt~j!ZW1cxfiEJal^q7~RMWQ0a z2CEaPa1_p|P6qRmmeKgas*N}@(2tH%U37-<5i(DSnVOFFxg-Sv%7&{hPeRh{U`&ufGz=V|JdYQ2sG5 zk%3JimSwQFP=Yr?u_beSG^B$nnh$4hrxb4lpTTiUFRQEZ3ulr+L3m;>;Io?D;jG6Wjj!b)nsZds<6 zX@cD%+aVr!ra~F7HYr`TB!|y-t)HSb^FQt zbo+_XP44IWJGGxg73JyhBjKMSv`77ngDOw}6Eve6ZIol$Q5s65d(1-sP{BU{1_y)7 zF8sh5A~jxRHk=wq3c5i3*e&otCd9>cstT?IQ&D4slC-&^q!ut1;WAQ}fE}Y+jU}r{ zmpSI%sW?})RAm8}$WUU+V$PmQOF5gSKOGQ2;LF-E(gd<67rYu2K| zom8mOppa%XJ6C(@I7-*opqLn73e9BMFStaBER?suJ{jte1$vA%z?$_`Em=a=(?T-q z*A=VZOQ`P{co!*UUKyV@Rd-c#*wmb7v<%rN=TGFmWmqhbj#&+?X|3bZYAjbNGTv~O zs7SIYi3VgW6@?=PGnbNNZIWaY^*+ChW&a)A$uqH8xxehwx2`<1w6mag?zuHbsVJiO$a)tQ zuBBoR>rLfhpA@)Qf`8BwRMx886%9HP5rOR%YCy9pQ|^Xw!=Mcnwx8j=(ZE)P-tJ&s zON&Nsr%14jS@K+IvrJj720NkCR*C(j&aI$EFCV)w$9M<#LdihyRKdzTjJPI|t9_S} z--#oF#;F?Y1KN%_yE);Bxv}9PWZphz_g5mReOKR`y%9UZ=n}GXWw?E$T1%NAfK1Ad z|0$Lp^;sntA>}=ybW)mkxNv1?hkZ`<8hCemcT5 zYl6$I^bhXDzPlz<>6zOy3Fu*3?>#q$;1fJ>nuxyx#&<&x6Y}j zCU&VmtCJ`;aYN+qP}nwr%s2ZQC|Z**axS^?iGu+x^{{>FIv!k0#HaXtEG=*C7kPe!mMnknbn}TKpp6Xv9 zVvq&%A3nmY^N*XTg&+=wO>(|{uTwm;ZP9@+M)6%T zwXPh-&{+aAfv^ZCzOEb;yj>A=f5Pbu)7T{9PT3u>#w*%?K8jqEF%I>A?q;E%CXn)f z|0ohNa5DMv@HVk^vT(L=HBtH*Vzo81L?)M=g7)>@j*vUx?S zxqZo23n3vn@K-Q@bx3lLT+5=fB_oz8+p?P;@*UU<-u)jb5WFEXzoc+8*EC5P6(HWr zY$mfFr=L&G>(jvl8US2fLQqTzHtAGizfR*;W4-kN2^I>L3KkXgx=e*}+i*N($}{?c zi=Q67G)oEMW{|Gdsm{)|V)5Evo}KLj%}gIe>98FFoNTLrJX z-ACRdewnT1w#Egct%wpGg~q%?!$}>$_UJPC4SP0^)G_$d4jN0jBEx}+rcd*^aDtnx zewG{`m!oSbQ?A~FZ6L{&V0hUE+b$DxjO_;oskFha>@gzy(jDnzGO>z3Tzz|i&Dakg zFid5$;SFxINis^4JzK5XIVabKoP`=ZWp|p|t{hTi8n|#XE=-rINwJ*blo?=%Se(qw zkW7x5Qs(LV5RVGxu2e&4);c73lY#0(iZo1x=MY;7mW`uUQIY+$_PqH`4a`6O#urwU zE6(FrvyExmB{c5z*YAj_P&t??F1t6TN2N!$N#~02u(t(PDVyD)$mL3hqKQ4E91N#GOIngPr&pUb-f_Z4*XV8`p1pq+mzrUlUY=4~i|3RDo;Lo36U}uwm zaOah}mO8c@%J*~~{Up7_7->8|3x<}WemgaMA}h>xD17Fey@V9;LgjQFSBS(A<+2kCP9( zlkD%;oXzWtZ_hgu0IxeTjH`6=vi|t_04Btl32=g8swD1oZguWr4|lx0RuXoDHbh27 z+ks?gkVWYnr~_{h+PzQjQ(#8kaJai4We{F!JuqCzU0t*+H{n6i3;K<>_6XUn1n)}) zJ?}JCUPYhT9S1Hi-M+$(Z**%fz7Z%IiMN6%kD>wh%r4#C?Ge4{>w9o??Vbehy9!3@ zffZs8?LGxyWQr@yB(|%~Aa>fVj3$O=i{K*f;?h-a@-ce{(cY8qByOCA1r0;NC}}gr zcC^fCa$Ot`42n>`ehclOAqBo7L&D6Mi=;M5!pd@jj$H z?U7LQWX_u7bHpBzF7L-s4*`C)`dUrbEIgKy5=QHsi7%#&WYozvQOXrNcG{~HIIM%x zV^eEHrB=(%$-FXVCvH@A@|nvmh`|agsu9s1UhmdPdKflZa7m&1G`3*tdUI5$9Z>*F zYy|l8`o!QqR9?pP4D7|Lqz&~*Rl-kIL8%z?mi`BQh9Pk9a$Z}_#nRe4NIwqEYR(W0 z1lAKVtT#ZTXK2pwfcCP%Apfo#EVU|strP=o4bbt3j zP?k0Bn$A&Xv$GTun3!izxU#IXsK1GQt;F0k`Tglr{z>v2>gCINX!vfs`aqag!S*AG5Z`y-# zUv_u&J4r;|EA`r!-gsoYGn<^nSZLH-nj1SRGc0MRG%LWVL)PckFn9z!ebIJ}eg+ix zIJo7GN;j1s$D6!({bYW)auypcB~eAWN;vhF%(l=|RR})$TOn;ldq^@8ZPi<%Xz~{Z zQQ|KAJ@JHaX!Ka2nhP%Cb^I}V6_C|e1SjOQpcPMMwfNz#U@Az|+rmH*Zn=cYJu-KR z{>f++Z~P=jm)4-7^yc#52U4qeNcBRYb!hhT3Q7Ngu5t@CvY*ygxu^Eh?2l6= zhdqN{QEaP(!p>1p1*toD!TllHH6EH~S%l9`mG62dyAd+?}1(vf@N*x^6vhEFU<-RqS7#12*q-xtU z5d|F^n%WSAQHnm-vL)4L-VvoUVvO0kvhpIg57Wf@9p;lYS5YfrG9jtrr?E<_JL{q% z7uPQ52{)aP{7<_v^&=J)?_|}Ep*`{dH-=cDt*65^%LodzPSH@+Z~;7sAL}ZECxQv+;z*f;(?k)>-Lp@jBh9%J`XotGJO(HcJc!21iZ98g zS-O!L9vpE(xMx1mf9DIcy8J5)hGpT!o|C8H4)o-_$BR!bDb^zNiWIT6UA{5}dYySM zHQT8>e*04zk1)?F99$dp5F^2Htt*jJ=( zH(#XwfEZ`EErdI~k(THhgbwNK9a(()+Ha1EBDWVRLSB?0Q;=5Y(M0?PRJ>2M#uzuD zmf5hDxfxr%P1;dy0k|ogO(?oahcJqGgVJmb=m16RKxNU3!xpt19>sEsWYvwP{J!u& zhdu+RFZ4v8PVYnwc{fM7MuBs+CsdV}`PdHl)2nn0;J!OA&)^P23|uK)87pmdZ@8~F$W)lLA}u#meb zcl7EI?ng$CAA;AN+8y~9?aon#I*BgYxWleUO+W3YsQxAUF@2;Lu-m#U?F(tFRNIYA zvXuKXpMuxLjHEn&4;#P|=^k+?^~TbcB2pzqPMEz1N%;UDcf{z2lSiwvJs(KhoK+3^2 zfrmK%Z-ShDHo^OUl@cfy#(cE=fZvfHxbQ!Chs#(vIsL%hf55_zyx>0|h2JT=|7JWo z+Uth3y@G;48O|plybV_jER4KV{y{$yL5wc#-5H&w(6~)&1NfQe9WP99*Kc+Z^!6u7 zj`vK@fV-8(sZW=(Si)_WUKp0uKT$p8mKTgi$@k}(Ng z#xPo-5i8eZl6VB8Bk%2=&`o=v+G7g|dW47~gh}b3hDtjW%w)47v#X!VYM}Z7hG1GI zj16;ufr@1^yZ*w3R&6pB8PMbuz%kQ%r=|F4+a!Gw2RBX6RD5c!3fU@+QCq#X7W@Q5 zuVQ}Uu0dzN+2mSX5)KV%CsU;2FL%B6YT`10$8JR^#;jOO1x?t()Q_gI zxpQr2HI0_^@ge0hNt&MQAI`yJ1Zhd-fpR{rdNmRkEEDu7SpB)QOP4ajV;UBZZZK<6 zWds;!f+|}iP-kqWAH#1@QisJpjcg`+s80!LhAG@(eMad|zcln~oE8}9l5!K{^zf~( zd=HArZ5+Mryc$uNa`@|GSdOX=y}8GZc-%p8W@OM)uk2DfmhQXCU1E#y3XJ>|+XdW2 z)FQLeK38}u_D(5E{GV|YT^rI4qds2{-r<@@@@SG@u&4LbC z5o|KKqVM{?wk$5>2?t*I?IHdh~gljn_2m2zqZNJEEz4Mb$o&I3_UAg#$B{0u$uF4-q}{ zzs5+k@qOe08!CGLGmy3eRrcuqsgB*B>i8c3>3=T^Hv>nL{{u)jtNc6tLbL7KxfUr; z=Pp14Nz+ggjuwd~*oRJ)xWwGwdge+~b!E%c3Gzw6`vT>CCxE0t6v5Z`tw1oKCcm68A~Dbc zgbhP6bkWwSQ=#5EsX*O9Sm^}EwmQQzt2V2phrqqe2y)w8;|&t6W?lUSOTjeU%PKXC z3Kw$|>1YrfgUf6^)h(|d9SRFO_0&Cvpk<+i83DLS_}jgt~^YFwg0XWQSKW?cnBUVU}$R9F3Uo;N#%+js-gOY@`B4+9DH zYuN|s&@2{9&>eH?p1WVQcdDx&V(%-kz&oSSnvqzcXC3VsggWet1#~bRj5lBJDo#zF zSz))FHQd8>3iSw{63m`Pgy_jkkj9LTmJ&!J(V0E~&}HJ4@nXp<(miz$sb;(I<8s!7 zZyezu!-+X81r03486gAlx@n#aKx_93DREBtNcYln*8oliQ zbh0~SkAgHXX%C6}HwN(TRwaK2k_$Y}PxKId;jYt=S1Bf<8s@(IL?k3u1(f^V%TYO1 zA_jPf*V)SLEZFWS#y>M&p$LoSk+%ubs`)H%WEZf=F)RKh&x;i)uLIGJ94~A4m$(;S z;1rQC{m>--`WHFcaFA&5#7~vz|5S;{fB(7pPnG;@$D~C0pZYNEG?B8X*GB2e4{Qk; za1oop8OvHqs1Lk6B`AuYOv4`y`IgM315iTr{VUVc9WeOG;xE z%eDQgE4rb_B%vuT>N?^K zRvPnQwG%7RjO26+DY!OXWjgBu4^!)W-+ob_G&nX++))pD->QdRCo0spZN?Y*J#@-q z)fk-fJvZYz8)GSxYc^oXYIM;Pw}ftHW+a3dis#dXx^OS^m-~FlwcVr6MXv78fNI!i z51K-2t&!&IZ4(GF=mT@;qIp!&R(I@UiWPPz)%Us&(FdAAGxZ-+6^UZ7em`J-F#_3r zLkHym@VAnZFM$J~?0b@&O`l4YXyvOQ+OqalbZ0{g{qD{neY_xno1ZpXlSJWM=Mv(~ zvK{?O>AcXpbd}+hn{~*>weZwDTURX*M^9RkOO#DUfRW1;comKg1bn+mlsrNY8XDyW zgWg9~AWb_1^D8zsD4bL(1J4oinVy0Fimrh&AC}Itl;IH*p4eU_I;SWkOI!9tAbi3B zO@0=q#LHAc>z?ve8Q&hsF(sR9lgf_99_5Kvuug<^&0}Y&m)YjI?bITGIuh}AJO|>z zc*`Mly$>TA={AIT#d%JuMpXHDt($qkc*3UTf-wS$8^awqDD^|EAeA{FoeyJfWM@QX zk>vJ4L|8DU7jg_fB^3Qvz*V$QmDl*AXdw6@KSckh#qxjLCM8Nba!dTkJgr(S@~Z0a zt8%|W!a~3zG4Y&X6xbLtt^JK5;JT($B`_9bv(BjRTfG_Y`tg3k-}%sQoY@F|=}}${ zwmW%Ub6jPd)$;NA0=b7w!^2dE-qvI4)AVr`yvkabJcGwvuQ2rAoRlTjvCC^-$2BG} ziy0<6nt8;J67rymwm&wVZ8E7Krouv2Ir@-GQ%ui6PR42KHKms3MK&Z$zp{_XAVvrd znK4cbg)Ggh5k(4SlFOM9yyRUlVH1oo%|6Lu9%ZxZW28!c9Z%H5#E?B?7H7ulcUtirB<{s@jnS(-R@we z^R#{Mn$#JXd~5sw9rU&~e3fYTx!T&hY{S<~7hviG-T$<4OPcG6eA0KOHJbTz^(`i~ z_WON4ILDLdi}Ra@cWXKLqyd0nPi06vnrU-)-{)Xp&|2gV>E{Uc>Td`@f@=WYJYZ^- zw&+fjnmyeRoK-unBVvX>g>wO3!ey<+X#z@8GNc9MD}khMO>TV{4`z zx4%!9|H6k|Ue;`M{G6d!p#LL+_@6WMpWgF7jk*%$D_JB3c%D`~YmHRJD1UNDLh;Tf zYbbKcv9R(81c4yK+g+1Ril{5w#?E}+NVz>d@n48C-T-(L?9a9W`JV*{dan-sH*P3_Hnt~iRv)}ye;7$b}^4l%ixphDK`G#b!4R4qoouT@*A zZ)kQa)e94??k7N>tqoRl>h(9DFq&92=z|F!LJrh-97EoFL|Wt2v}>(zG1*#aiYA_^ zM_&%_G^g*O8x650e>m!#MDmwRub!irY>^^|L=!4^%lBr;?}mvgP3y~^mSdKSm^R~WAt7T0_ck0mA`GS)J^SYTo6^vQ|vuM7!92&@$BhtcQ^Z4h2)aN zh~EQthyjn1(eI~$FtuHH!|x(iHU{9k40k5nPBwB)X@8Lo$P6u81EeoNOGRct%a-LM_4y3Ts z7ki0PWAO^Es6c%M*SSRn)2|NAoUsKyL%))uVx7?5lkrk`njxs4q@M~x+8%jr7xV;- z|KC=g3aTZO|y|g~oHXB6b42(|J_&fP2Y`*;L07H2d>{~JP zFNGl$MYUG(Qy3dR?9Bfdg8#peGRiVP8VYn@)6T1bj*v)s6q*7<6P(ZVm4ZnTA;rOHSd>P`_5uT0+azWdV`gIvLaJ1o*DB}&W6LCgX|BycgF5qd z!)}dT#A~4*6{1=Bd5VV(Qa2h4x9m#2X711z(ZN>i&cn`BopG*5P`CD*HfYiQmXNGk zhgqcHPBrJP$Z@PLZ4}d-8^}%X^LtUDHq&;~3}lUyrxxl@|IS={GP&6-qq&Iy5gKW- zC@$}`EEZd}DOSeSD+v_x5r_tpBWfN0gDa21p(@TAIrgWQFo7NO@slI6XOAML_lN;3 zEv~}LlMbGWKu}0s$tO-vR)wD!=olGcA?}vU;lRu4+Zf z?nCD7hBmA5`U9P#W8-*0V1=OT-NI0k&_`UZ87DbpYq_=DBdyNDchZ<|V1f%dbaa7i zf~R+6Xt%G)VXlM@8REfP3u#7UPadWYOBMsQ56fHRv!0p9R6q>Rbx!n|IY0goLb%{+ zzy|5WXk+(d@ChzOWatIV1lc1F!(uEOfEmMd;v`|$Kt3X2Uws;%@OV!E86PN?CeHV& z=4#TX{J8RWaH`)!J<8AUs#Ar{6Am^8M{S( zc%K7y2YbcLUz+*eDTXdthNE)Lm^P&*e^eV zilOS9)TVKgr9_^_M!TJ^44v<YF2NO=h(oOr5jYxVTxWk0XJ8n0{F_SOH%49WMk*Sg7`g6B(=^< z*rLAW;8I5;1?;Fh{N=f;kxjLpj}u^mD|k8lih|G4#}wEG1j`HIG( z8y;BMR3cE01e?(+k8NLR|Z+)#>qR^iMZc=BkcixWSKYmkaHpIFN?s%*74kc&wxwB zrtbYBGz9%pvV6E(uli6j)5ir%#lQkjb3dvlX*rw5tLv#Z>OZm@`Bf2t{r>u^&lRCg z11*w4A;Lyb@q~I(UQMdvrmi=)$OCVYnk+t;^r>c#G8`h!o`YcqH8gU}9po>S=du9c*l_g~>doGE0IcWrED`rvE=z~Ywv@;O-##+DMmBR>lb!~_7 zR`BUxf?+5fruGkiwwu|HbWP^Jzui=9t^Pmg#NmGvp(?!d)5EY<%rIhD=9w5u)G z%IE9*4yz9o$1)VZJQuppnkY)lK!TBiW`sGyfH16#{EV>_Im$y783ui)a;-}3CPRt- zmxO@Yt$vIOrD}k_^|B2lDb2%nl2OWg6Y)59a?)gy#YtpS+gXx?_I|RZ&XPO`M!yl7 z;2IS@aT4!^l`Tped5UGWStOw5PrH#`=se%(ox%gmJUBk18PsN$*-J8S%r51Y$i!4N zQ!rW%cgj44jA~_x%%smSTU2WG_W0c&PB$A5*kl8{$|865+lSIX~uyDT`uI7qnS!BPAg1Wwrc0e)8Usf zv9^E38H&hWSp5!@K8Qinl|)9 zEB?NMaxZK^GB!PUf1TBw+`H&jFSNI=Q@v5$Ryf-y^#IuXO#vsM5R+9@qz#z0fD0GP z9|Hj#E>?<=HTcsF$`xn`je~D&3kF1Qi%dfH{sKh!~(IpgjkDGQn zQx2F9rv{*x2$(@P9v?|JZY)^b9cd+SO6_1#63n-HAY3fE&s(G031g2@Q^a@63@o?I zE_^r%aUvMhsOi=tkW;}Shom;+Nc%cdktxtkh|>BIneNRGIK{m_1`lDB*U=m|M^HGl zWF#z8NRBduQcF-G43k2-5YrD}6~rn2DKdpV0gD%Kl{02J{G3<4zSJ1GFFSXFehumq zyPvyjMp2SLpdE5dG#@%A>+R3%AhLAwyqxjvGd{I7J`Iw{?=KKPRzyrdFeU}Qj{rm{351DoP_;vx zMo*s+!Gwgn;${(LXXO(xyI@$ULPZI|uzYR%`>MmW6Hcr1y2aM5b$grFwW_(9Fzz$Q z$&8dKNdWvBkK=iYWA|0}s1B7>8J$g*Ij_+S9vC1#jy~uA8nr)yY)a+ zoJ=e>Lp`7v3^tQN<&6UpDi{c1b}F~fJ$9r=p=@U^J_7bOck$5}ncVjYB0yEjbWrhe@E`j64yN3X?=k_F3BalH$aN zV=94?wDNv=BKLB<1*xU|65Zl!%51r5sHQ?qCggCw;$2QfCZ$lN40WPL=n^{Prf^QS zjbZ&1MRGgiZ2T)}DpiluFr#q*!AZJ$1v#d10YQ{>wQ5px!y28-1hCZ7lwvQnQYN*U zOg9BpvB0A$WUzFs+KWk1qLiGTrDT-0>DUpFl??l(FqWVz_3_Xzqg9vTpagp- zZcJ!5W?|0G%W|AJVVHJ7`u6@<4yyqMGHj@kpv`P+LV<)%PM__Rz&oq~t-*vV12@NR zoEVPz<2D>O==MlNI`;l8Gmv49&|1`FR!}2`NLRCqA{@`imLz6zrjS4ui0)O;!Pu&?KPAcX)?tDPS26uKvR(ry(p{6kiXPoZbnQ!vx6dLu zZCaj~Ocr$h##KqsD;9;ZiUwhmUd%5lrwczWr1Yn6V>+IK=>51;N7JDkrm1NY-ZBes z;FxeOTb^HAyA+~P2}WvSSu_fzt_K=(m4wUp%c*^hF zEJ+1dP0{0B8bryXR+qApLz43iu?ga<5QQxTa$1gMCBq0W=4|DTv4nY4T*-^Im%>U~ z)98;hc(d7vk0zAML$WnPWsqK>=O-FZSLI3_WQKr*PCK=(i6LelZ$$}XXrD5cb~VXz zT%egX>8e;KZs@jcD>cL9VP(Q}b0r~ST$Mc%mr1cC8mqRUQc|N^9@Weu$Z|KeczK7HhSFeFV0i)MQmwrn7CBL=p`_9n?nh320m}6-MSv3L7I*<*56GR zZ`zI^1zyC7F#*zVL@M)F2+oqxydaiQz?|ODmqs|Ub8%&KXk9P3P7<4tM?X{~!;Ygw zt=h7)AYGDO9F&wV=BhCyD9exr#YM_-<;Fo~iE>IBEXK$%;JCUAEr;lR&3S_DUy_E) z#!oCYdENVE9OaaeaIrPk-odMtvdFG;ocA#`L6AifMu0og^?Oy9F|Et9q6 z8;3_|9+Io@hqYoN;58x1K&OP!9Vd#dzhTRjB2kI?%31ceHb#Q~WqJV5lw;@b>4@Rd z={z1S`d05YdWC*RLc7sR0bVGSytn-a3`JZL3|d8KC?vj_70Vi4ohP9QbU&Q4?Zjd0 zSZA?KbqLBsJg(qj>fycto3`zN-)lDe4{Ij-QfoBn@rT_tTszA+CnM~xWmE(4zfpCQ z;zPJfl3=ctrggYM!KQg;V{J;utMMF9&BfOe!<{wU0ph?-VQ%cv3B%fFiW?6xBPdf0 zD-HhEU?0C`G@7e+b-=8fj=TP3mdz&SIQ}Nd`*G#DTz9Y@b zaoDF}Gx7ZhPzpDhi^fA7WZ)EAEFv;N2*bKp0T za0t<^1|Zc#`A+?s$!$8eO4CK~PUFECC3BwNR4f)!V&-Y>$xg(%T{MtrH|CPcO(Lf> zE_meE1?6S-qlV^p2fh! zT11Ub)hHw!_mpFDMIAFB`%Yal+`1IXV>b?%!q^Ps%8nh8wtjVGlF-!5x*D29WJ4=M zZ7X(QvKe$YZNgM(HibD7+VO5Q29?@HzS?k$c|3B@JI6dlLgu5S&LbU4=4p-Yn||z@ z4p05vq*k*pbOV9QjVTMp8`c$?t@~!$8&5AP_sz@tk%a$nWHMh-Gm{WS5+q)5W6pU# za@YZXJCLTpZ}zb=$HCYbIm->?Hu6XIBz_d7)n1+3eSLzGVoNQCTHcu9qS2@({0sxc zu<-mhx@Xz_*(S1DEL|d0`YV7uNevL*Y6|DAQmvSp{4DzPL@>hqJ?`FjvIU;<&}YEKDmFUGSBYjRmK{Km-1m%-t=fFfI9kV|POH|SxvO=P+><+1JK_lt5F6fTPf8PXU+lYEJz__** z&>`4F2F8EWE+k7ZsZx9%!?A56{lsk1juYw5zN)V+g$d^Q^Gm}fnHKA6L^36=`e;p% zp{;JD$X3%}O7qINR*2<>a422}_hmc=)-A7B-1#2v85jN5K31t0DtmqON-Dim`XIR; zOo`KRv)gtn?stp*`^f>}UDnGYGnJAbl(4srd>(5fo2#oqi>#bus86EHfeItFIu$+% z;lE|3gjQA`BXHEE5JdcjCoethN`@NEc~zm6CYf@LJ|hT^1>l}gRl7oDHMnw!*5*IC z@@Mi=gO=lZSnWln`dX^4Bd{9zYG{HNIX-87A#5OM%xu*%V?7K3j3CHcN*t!zNK4N4 z!U2?a>0`8m8}UQshILC0g6-k>8~;SRIJ?vQKDj z@U{DrstWIT7ufyRYox^&*IyHYb$3wtB}V^0sS|1OyK#sDc%sh+(gy&NT9j4Aa7J0C zPe$02TylMjad&|{_oe3`zx)Cqns?6qThYue6U=~j5+l0Po4`bX*&9V@a<-O;;vCzm z(af&;e<^}?5$7&MRW$eb*P< zX|33QmDvFSDFK-qMz|RF|Eedum@~W zt~8C1@i8@LammTr)rAgKm8X_SczCg@+@LeWpcmx;VL;iLQJ;t%Z*|XbNWUnHX|o=Q z%bsXc%bw=pk~8%3aV-w(7E$co9_cHQ$!}Ep6YcoCb7~GQBWl#4D!T8A5!P*tSl4FK zK2CX0mjmosg6TSK@-E-He{dm0?9h{&v~}OX15xgF<1-w4DCypYo22%@;uRq`ZFld- z{Uqof@a@P5dW@kfF-`1B1(!R>(DHb&$UXY%Gd+6r?w8klhP&ldzG*6#l#VuM&`)ki z)f$+Rp?YYog9u==<#MC%1daG#%3EOX9A{7$`_(s#_4mV`xZaB+6YlX`H4{}vq;)TF zo~fR@do6EZIR?413A$V6o^fq&QV7P(bB(9m1969szOosyhZRYciAWXe4@u-}s(LeJpuIkSx)XvjXmvVEseG zJvWN4s|$6r;s(3F+cgeh4DMEq??h!$eb^5h#`whT5d03qfYpol8dCim)A^NG1-H}} z!b)V8DTL2Q8@R2p`y4@CeSVj9;8B5#O?jfl-j<$Quv?Ztwp*)GvQ~|W8i6?-ZV@Lf z8$04U_1m{2|AIu+rd8KW`Qk|P1w(}d%}cjG6cxsTJ3Y&*J^_@bQgXwILWY7w zx+z)v81rZv-|mi>y#p$4S7AA760X?)P&0e{iKcWq4xvv@KA@EWjPGdt8CKvh4}p}~ zdUVzuzkBlU2Z+*hTK214><61~h~9zQ3k+-{Pv~w`#4|YdjTFKc{===9Ml7EMFmE!f zH}U3O{Z`DuJrBZbz~OjSVlD6uZSEeNK8epja_LanEh8v;_$Eg9?g*9ihMoat$#qd^ z?;x?a*y3-pW#6|kF^<$w;2^~s!fc;3D~#&#WYZfK@3;bO{MvmN?>qy%_%v`BVCgfC zdwL~(H14Gr6w(1CX|R;zhZh%?*Q{hxJH`MV2)@Jg$pbqjZeL+LO7^vwgi!@3yn@NT zU91-{;BWIi8bV-j-YR|A9Qs?M?e7Ru&Onl1(Sz(kxAw?LEbd+Le%Z43rZgb2h2m|e z^rblc;4r+}?@tC(YIBB_qpQL?_kg{;zO#6JD9{;HSUgf@zIZ)}Bh4wFZIs>meSd}f z4iF~nD$KAV6CVEw+{YOPrW~~y~Y=?snG4dE3edN$~SXh`!c_F zUsQ1M;ARz&v0mIbfP}aLWZ&cBPU+DU{l+0}_>9DZGL{@}lF6QCtgAg;EWUu`D$Evm znblG}kC!}Mw)bR~U;+S}T9TVc6lXWR!LNMm)nmxr*ORkv#&UO$_WQpt0WdX{A=bjC zV^lB~(r;y!C4$Rk0fWUR|09O?KBos@aFQjUx{ODABcj}h5~ObwM_cS>5;iI^I- zPVEP9qrox2CFbG`T5r_GwQQpoI0>mVc_|$o>zdY5vbE~B%oK26jZ)m=1nu_uLEvZ< z8QI_G?ejz`;^ap+REYQzBo}7CnlSHE_DI5qrR!yVx3J1Jl;`UaLnKp2G$R__fAe;R(9%n zC)#)tvvo-9WUBL~r_=XlhpWhM=WS6B0DItw{1160xd;M(JxX_-a&i%PXO@}rnu73_ zObHBZrH%R!#~pjEp~P?qIj4MdAx@sv;E96Doi$eO-~)oUz%Z0Tr4K`-jl06Il!9{s zdjF*1r{XU?)C(%XKPm;UnpnDGD%QL3pgo0ust~+sB0pa|v37>E1dp*Odn)n=DY;5j zDzSAkU9B6F$;|##_mrDe#%hd7pC1u`{9ZKeDdtkyl&4>H=e)Fq@}$UffPt1#cjYZg zd%O%xpg4~brEr>AnKT)kF@`cdX4tMlZ#Vk!l1Xz!G970p`Gkv^lk-|>jmt0W5Wu6woGf?hNA zXO2?BG)<{`NsYAY#3|L^x*=rS7uWU~s<*UhTC8AYc#lGP-=Aw1I)@y(<` znQb^nL~$rlDbsdAc4nc#{+$_;Z4iY;Pi0i9Q;>ZB3+IjWLg_r40-Fso^xF<*_s7Tj zujFrMH{vW3PmCndjQIscnQE%`Qj|E2kidi#c&PcWIMyH+e#7!l`<$_)*pDP$!49pY6w!bN)j8~A1wV%gIakf+vA04 zV)_Q=QMPSj6$M2Ar#KhhxsbZUOq3nZHh8m0?Fr}I6N(Fk zkhXM(f57yOa8vn^97J+g9ISPa=-**6^8ZX&g=z+m&6~x<1>)MyM&tpbWhSf8#+Pcd4rVK#)NSw>1eLKHTO z44A@sc_}Ypi#ggFRbDRFV(IhOnRU&XPrQYh9`mVMo-^U$&AwsXooSRUFqJ7)XUXCK zFpt;gJ}9QTN9xy9$=3OnRkjgUuQZ`X)!}LBm~WUIEKuK-Z%}f?2?+MKucWU<3)>9G zxsz~2pHut1AmH<@66;LdCB9+dSpojE4ggrYS?%icv*Rpi?G0Q($^`(g<1&Z){O_5B$@f#;I2-+Qa1P$a@=u-vOY5vqo z|6G67X;*A|V86ZET9OpFB&02twZtc2K}~ASoQpM_p{vJ{-XvA8UmQa4Ed%fS{D@g( zr_aY0gKw*=2SIGznXXKFo$r0x3)@bq8@4od^U(L0-jvTsK@qYOWX?2G_>N+?;r{TU2{M>V0zid zB_Zu?WSnRl@k?oE*gsgv;jH@+ z-}BDGyR-ls7$dz{e( ztv7lI2|OxNkLD4zc3xGA`!d7LiSdOys4H!8aA(_c0Nm*uLjS4TW%Z3v>am1nwQ_lI zIs85Uufd;cv-(4wi(Js;QsL#|qdv)n;r_?puaK*1>zTC@d=#sK+q1YF_Q(5B%%3TtI8&bNs_e8vIb;oc|Rk`F~u?|A?jj{c={?{Env{mW#q@8 z)#WEgt4B6b&X2?o3=b`ilz;)-h$t4;hsxPDo-%5C(7m#c9tZF-U`vcx0HnVtf_X(}4Tg}4wx(=y!@T7{)4;I_p95mBhikg-|U9z35q`|!1+Zz@97 z(PFE5jCv|=t;^=(CLqYp)k90rV4ZSiFDAhD8YOCzv{}1WDuB?epORibW36);q(Aig ze27@D?lN-ZyjuB4GsebA$;+(KGiOtCe6Bfd%GKRty>dBS1GUe}MXgnu61UdgO=m1& zE(eECPF_%J-lU{;R)eQJot;;}Wch$-8Z|lxN*AAdc;bkpbD`W}F=Z}^Cy(SKyfF#+ zQSalA%JDDAu|77$M3E|kv==3vx~pFPw_<+9xgcE#oigh*>#QsA2}sTYO7uY(h@dhR zHJBi^bb-`1?<1cGFZJa8Akzs{H^$N<)5@hlXeKwt9hD5^5K&`pdHOI92p<7XhS?>| z(5h9KYctN|H+W~Xh2N4W+yjMyBm(AdewjX?PBuRU$^J zS#+U($K6rhFFzf z0q*kJ>B6xI1qAti?H@X@dxtB7_vT+Nj@PNxr?CSK#xqE6jh5S{`nH#zzvjOId=i1X zK(Yjl!7KF(73GXYLVkQA5irn|v-ArCqwi)CM8X&m!#@NQ3bqmQlfurU4qT`zl_m^C zhpk?mfVvy9L|)*+bW8&NY4lG$@0_PKfO9+~(zrbn?wECGi7472W{H&dRPZum^Qf z73C-TR6$#q>XJgYnUgV!WkbmRas;`TY#7CxPXIEGwT6VPBDKbyr#|C2M%q|7l#Ql< zuM}j=2{D+?SxT8?ZJn&Z%cRN8Gu@y(`zV(lfj1T%g44(d#-g&@O0FL5;I9=?bW>!M z%c3J&e}GThdean-<||jUh zlLP`UeKBhhrQ?HHjM3}kfO7Z=EKB%+rs*t+nuBoeuD2yk%n32SA?-s)4+DsTV7U&K zyKQO2b2*tQT}#((=#fkb%hkRkt^%tY&VK$hcs91+hld zJ%lgC!ooILC&|(Z9$zzk=Q0*%&l7wwyf%nv=`C=OcPjb|Q%@9*XkPGFrn+bxp?t^D z!_qO=e-;bnT)^0d|Ex9X&svN9S8M&R>5l*5Df2H@r2l)VfBO@LqeVw`Fz6TSwAt^I z5Wu6A>LNnF7hq4Ow=7D7LEDv3A))d5!M=lT3ConlFN`5eTQMexVVs* zH0tx-*R+-B@&Lp`0V4j6Uy=LJmLQRY_6tH4vnV{_am%kkv|{CYkF}4Wn6U+|9Xre$ zJkO;_=dtw`@aEs|^GlO-zvpp-73H;PYk}V5RrH83G4SVkRJ0YSluQa8pKejcqB4u~ z^9^lDR|?7vEo|jITtaIFI6}1;vTI6n(d0kDGQUJuk>>sqdd7#VBF;?_dM5i<+VMEq zc>habJK}_0eEsOkdwv48d43jKMnqYFMnYDU&c?vi#Fp+S)sxo1-oVJ*g!X^^K! z>z!G8?KfU{qOnLHhaEF4QRHgOpfvoo7@=FG(2ZefYJk- zZuA9ubiTTP9jw9Uzpx8FfJBFt+NNE9dTlM!$g$|lTD za4LMNxWhw8!AV(x;U`IV-(bK@iQ%#QSmq8D$YqLgt?V#|~% z;{ST}6aQbOoewMKYzZT@8|Qq z@9SNBu1UErolMjrhJW-Id&7y<0I<+Z-lr`IHMh1;M)n@g|hx_T-maO`s{Tuhax}EjC zS;1kdL*A3BW5YZXgD|0zm)g3_3vMs>5xgHUhQDl19lfQWMcfLTsw$)amgDs>bW*Oe+$UK^`ioL%F0Ua5vb%II+EGS>*I zw)AmqcWBZpWH&Aswk_FJT=J|^Gn=MfnDTIzMdnoRUB91MeW?e>+C)g3_FDN8rN$(? zL+kH!*L}rq`MK`KDt^v4nUJg3Ce-`IW0Ph0?|}Puq5WIS_a7iEO;~mGQqqo=Ey;ND zhBXA^$ZrCc#&0}dMA&@)&TCq5PMzgJPafZCg-6$R zRqJ2+_t+dGUAY@~xPzU3`od7-(8nnuMfM-4#u`Q~`l-CUGC7u*^5VwH`ot;Ck#R1% zRr%?;!NrB$w^}NW=GGR}m!3a9bh#wXrq?fF7j-IS?E_!GaD3KYzcXhCUHhjEl-6b# zCmIF#4y@HN=^#uIz zRFl8D)Ri1<(Kr~Hoi_MtXWP8^AyTKxi1)ew88bV{*Ok8w8YLXBFW0sRJ<(vU{$ym| zz)feLQbz3k;_}2_{-bW`h~t&2$ObtlbS?k2k|5Kbu?FZLDMTVW_Z6p#A)c)`3DD?a*hxHS2Zj zcIiebfsINfWvwY7Z{YOlIQ61b`j=%6{>MPs+`()Q{wq0z0?|jwRN(1IrMQsj40BHx zvBC_Xfcr;55&}MeoP_@#nz$avCh%FJfE5NNAE~fW@L7~f8Y=?Wno31128EYOK8+O! zc4Vaj-DCsB6CPH$?pQQVbb_(tg^x{$STYM_WKLtrh-_-Hq-M%Ubpt6$mCHY!B{ISD zz}grIo^bNVDw4={SA2*nDNq5`e@ZO5r4TbQpHM)~qfD9!s0h(Jf>vYd;I~j<2fD4)_>ctbwNX6S*8>i^*4 zYKI5<4}d;hM!!N|A$@eg09J|HV;!UUVIau_I~dxZp#?a3u0G)pts6GKdCNk>FKxdh_`Xu!>zO3Kv?u+W6cYJPy!@=PuY868>3|Zg} z$7galV~M`d!q(`I{;CJsq6G9>W0}H6gVY`q7S@9s8ak1r{>}*Q0JyH&f!f8(NZxhC zkn|KS64r^A1fniFel2KkxYByk%erCx9UgFLI)`yuA)X z8SU?6kj!numPNCAj}>1ipax(t{%rxU;6`(Nqt$~Z4~76TQ$9d8l`yJ}rniII%HbH= zlS_7o!qB{55at^>N!Voer%)`KMh9Yd@Z?~nc19*hs)NGN954`O9zA&&vJHbm&|D@E za(&z6A=3NfC;>I)hlI@ulP8E@W-ziGe{iCf_mHvWGldxw8{ng-hI({EtOdALnD9zG ze)fU?I(DNt)Bzdd9Cs^>!|+2!xv1SK=I zJ+y_;=Sq-zqD~GKy@{5(my&aPgFfGY&_mayR_)?dF_^Fwc-n!UAG+fQQGfjWE-1MF YM{}PByk10KD_nuQ4E7Du?}+~TKh4V)`~Uy| literal 0 HcmV?d00001 diff --git a/netty-springboot/.mvn/wrapper/maven-wrapper.properties b/netty-springboot/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000..b7cb93e7 --- /dev/null +++ b/netty-springboot/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/netty-springboot/mvnw b/netty-springboot/mvnw new file mode 100755 index 00000000..8a8fb228 --- /dev/null +++ b/netty-springboot/mvnw @@ -0,0 +1,316 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/netty-springboot/mvnw.cmd b/netty-springboot/mvnw.cmd new file mode 100644 index 00000000..1d8ab018 --- /dev/null +++ b/netty-springboot/mvnw.cmd @@ -0,0 +1,188 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/netty-springboot/pom.xml b/netty-springboot/pom.xml new file mode 100644 index 00000000..55b6e0f7 --- /dev/null +++ b/netty-springboot/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.6.3 + + + com.lemon + netty-springboot + 0.0.1-SNAPSHOT + netty-springboot + netty-springboot + + 1.8 + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + org.projectlombok + lombok + + + + + io.netty + netty-all + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/netty-springboot/src/main/java/com/lemon/NettySpringbootApplication.java b/netty-springboot/src/main/java/com/lemon/NettySpringbootApplication.java new file mode 100644 index 00000000..3063d624 --- /dev/null +++ b/netty-springboot/src/main/java/com/lemon/NettySpringbootApplication.java @@ -0,0 +1,23 @@ +package com.lemon; + +import com.lemon.netty.NettyWebSocketServer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class NettySpringbootApplication implements CommandLineRunner { + + @Autowired + private NettyWebSocketServer nettyWebSocketServer; + + public static void main(String[] args) { + SpringApplication.run(NettySpringbootApplication.class, args); + } + + @Override + public void run(String... args) throws Exception { + new Thread(nettyWebSocketServer).start(); + } +} diff --git a/netty-springboot/src/main/java/com/lemon/config/NettyConfig.java b/netty-springboot/src/main/java/com/lemon/config/NettyConfig.java new file mode 100644 index 00000000..d2187734 --- /dev/null +++ b/netty-springboot/src/main/java/com/lemon/config/NettyConfig.java @@ -0,0 +1,21 @@ +package com.lemon.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @Description: TODO + * @Author : Lemon-CS + * @Date : 2022年03月07日 8:38 下午 + */ +@Component +@ConfigurationProperties(prefix = "netty") +@Data +public class NettyConfig { + + private int port;//netty监听的端口 + + private String path;//websocket访问路径 + +} diff --git a/netty-springboot/src/main/java/com/lemon/controller/ChatController.java b/netty-springboot/src/main/java/com/lemon/controller/ChatController.java new file mode 100755 index 00000000..7c3407bd --- /dev/null +++ b/netty-springboot/src/main/java/com/lemon/controller/ChatController.java @@ -0,0 +1,15 @@ +package com.lemon.controller; + + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + + +@Controller +public class ChatController { + + @RequestMapping("/") + public String chat() { + return "chat"; + } +} \ No newline at end of file diff --git a/netty-springboot/src/main/java/com/lemon/netty/NettyWebSocketServer.java b/netty-springboot/src/main/java/com/lemon/netty/NettyWebSocketServer.java new file mode 100644 index 00000000..ff52bd1a --- /dev/null +++ b/netty-springboot/src/main/java/com/lemon/netty/NettyWebSocketServer.java @@ -0,0 +1,67 @@ +package com.lemon.netty; + +import com.lemon.config.NettyConfig; +import com.sun.org.apache.bcel.internal.generic.NEW; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PreDestroy; + +/** + * @Description: Netty服务器 + * @Author : Lemon-CS + * @Date : 2022年03月07日 8:39 下午 + */ +@Component +public class NettyWebSocketServer implements Runnable { + + @Autowired + private NettyConfig nettyConfig; + + @Autowired + private WebSocketChannelInit webSocketChannelInit; + + private EventLoopGroup bossGroup = new NioEventLoopGroup(1); + private EventLoopGroup workerGroup = new NioEventLoopGroup(); + + /** + * 资源关闭--在容器销毁是关闭 + */ + @PreDestroy + public void close() { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + + @Override + public void run() { + try { + //1.创建服务端启动助手 + ServerBootstrap serverBootstrap = new ServerBootstrap(); + //2.设置线程组 + serverBootstrap.group(bossGroup, workerGroup); + //3.设置参数 + serverBootstrap.channel(NioServerSocketChannel.class) + .handler(new LoggingHandler(LogLevel.DEBUG)) + .childHandler(webSocketChannelInit); + ChannelFuture future = serverBootstrap.bind(nettyConfig.getPort()).sync(); + System.out.println("--Netty服务端启动成功---"); + future.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } finally { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } +} diff --git a/netty-springboot/src/main/java/com/lemon/netty/WebSocketChannelInit.java b/netty-springboot/src/main/java/com/lemon/netty/WebSocketChannelInit.java new file mode 100644 index 00000000..5284e314 --- /dev/null +++ b/netty-springboot/src/main/java/com/lemon/netty/WebSocketChannelInit.java @@ -0,0 +1,43 @@ +package com.lemon.netty; + +import com.lemon.config.NettyConfig; +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.stream.ChunkedWriteHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @Description: 通道初始化对象 + * @Author : Lemon-CS + * @Date : 2022年03月07日 8:46 下午 + */ +@Component +public class WebSocketChannelInit extends ChannelInitializer { + + @Autowired + private NettyConfig nettyConfig; + + @Autowired + private WebSocketHandler webSocketHandler; + + @Override + protected void initChannel(Channel channel) throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + //对http协议的支持. + pipeline.addLast(new HttpServerCodec()); + // 对大数据流的支持 + pipeline.addLast(new ChunkedWriteHandler()); + //post请求分三部分. request line / request header / message body + // HttpObjectAggregator将多个信息转化成单一的request或者response对象 + pipeline.addLast(new HttpObjectAggregator(8000)); + // 将http协议升级为ws协议. websocket的支持 + pipeline.addLast(new WebSocketServerProtocolHandler(nettyConfig.getPath())); + // 自定义处理handler + pipeline.addLast(webSocketHandler); + } +} diff --git a/netty-springboot/src/main/java/com/lemon/netty/WebSocketHandler.java b/netty-springboot/src/main/java/com/lemon/netty/WebSocketHandler.java new file mode 100644 index 00000000..718998dd --- /dev/null +++ b/netty-springboot/src/main/java/com/lemon/netty/WebSocketHandler.java @@ -0,0 +1,89 @@ +package com.lemon.netty; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Description: 自定义处理类 + * TextWebSocketFrame: websocket数据是帧的形式处理 + * @Author : Lemon-CS + * @Date : 2022年03月07日 8:52 下午 + */ +@Component +@ChannelHandler.Sharable //设置通道共享 +public class WebSocketHandler extends SimpleChannelInboundHandler { + + public static List channelList = new ArrayList<>(); + + /** + * 通道就绪事件 + * + * @param ctx + * @throws Exception + */ + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + Channel channel = ctx.channel(); + //当有新的客户端连接的时候, 将通道放入集合 + channelList.add(channel); + System.out.println("有新的连接."); + } + + + /** + * 通道未就绪--channel下线 + * + * @param ctx + * @throws Exception + */ + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + Channel channel = ctx.channel(); + //当有客户端断开连接的时候,就移除对应的通道 + channelList.remove(channel); + } + + /** + * 读就绪事件 + * + * @param ctx + * @param textWebSocketFrame + * @throws Exception + */ + @Override + protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame) throws Exception { + String msg = textWebSocketFrame.text(); + System.out.println("msg:" + msg); + //当前发送消息的通道, 当前发送的客户端连接 + Channel currChannel = ctx.channel(); + for (Channel channel : channelList) { + //排除自身通道 + if (channel != currChannel) { + channel.writeAndFlush(new TextWebSocketFrame(msg)); + } + } + } + + + /** + * 异常处理事件 + * + * @param ctx + * @param cause + * @throws Exception + */ + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + cause.printStackTrace(); + Channel channel = ctx.channel(); + //移除集合 + channelList.remove(channel); + } +} diff --git a/netty-springboot/src/main/resources/application.yaml b/netty-springboot/src/main/resources/application.yaml new file mode 100755 index 00000000..1f85ad24 --- /dev/null +++ b/netty-springboot/src/main/resources/application.yaml @@ -0,0 +1,17 @@ +server: + port: 8080 +netty: + port: 8081 + path: /chat +resources: + static-locations: + - classpath:/static/ +spring: + thymeleaf: + cache: false + checktemplatelocation: true + enabled: true + encoding: UTF-8 + mode: HTML5 + prefix: classpath:/templates/ + suffix: .html \ No newline at end of file diff --git a/netty-springboot/src/main/resources/static/css/chat.css b/netty-springboot/src/main/resources/static/css/chat.css new file mode 100755 index 00000000..b522b0f4 --- /dev/null +++ b/netty-springboot/src/main/resources/static/css/chat.css @@ -0,0 +1,454 @@ +*, +*:before, +*:after { + box-sizing: border-box; +} + +body, +html { + height: 100%; + overflow: hidden; +} + +input { + background: none; + outline: none; + border: none; +} + +input:focus { + border: none; +} + +body, +ul { + margin: 0; + padding: 0; +} + +body { + color: #323232; + font: 14px/1.4em 'Helvetica Neue', Helvetica, 'Microsoft Yahei', Arial, sans-serif; + background: #f5f5f5 url('img/bg.jpg') no-repeat center; + background-size: cover; + font-smoothing: antialiased; +} + +ul { + list-style: none; +} + +#chat { + display: flex; + overflow: auto; +} + +#chat .sidebar { + float: left; + color: #f4f4f4; + background-color: #2e3238; +} + +.m-card { + padding: 9pt; + border-bottom: 1px solid #24272c; + height: 65px; +} +.m-card header { + display: flex; + align-items: center; +} +.m-card .avatar { + border-radius: 2px; +} + +.m-card .avatar, +.m-card .name { + vertical-align: middle; +} + +.m-card .name { + display: inline-block; + margin: 0 0 0 15px; + font-size: 1pc; + white-space: nowrap; + text-overflow: ellipsis; + flex: 1; + overflow: hidden; +} + +.m-list { + height: 535px; + overflow: auto; +} + +.m-list li { + padding: 9pt 15px; + border-bottom: 1px solid #292c33; + cursor: pointer; + -webkit-transition: background-color .1s; + transition: background-color .1s; + display: flex; + align-items: center; +} + +.m-list .avatar { + border-radius: 2px; +} + +.m-list .avatar, +.m-list .name { + vertical-align: middle; +} + +.m-list .name { + display: inline-block; + margin: 0 0 0 15px; + white-space: nowrap; + text-overflow: ellipsis; + flex: 1; + overflow: hidden; +} + +.m-list li.active { + background-color: hsla(0, 0%, 100%, .1); +} + +#chat .main { + position: relative; + overflow: hidden; + background-color: #eee; + display: flex; +} + +#chat .main, +#chat .sidebar { + height: 100%; +} + +#chat .m-message { + height: calc(100% - 10pc); + width: 100%; +} + +.m-message { + padding: 10px 15px; + overflow-y: scroll; +} + +.m-message .pager_container { + position: relative; +} + +.m-message .mask { + position: absolute; + display: none; + width: 100%; + height: 100%; + z-index: 1; + left: 0; + top: 0; + background: rgba(255, 255, 255, 0.5); +} + +.m-message .self { + text-align: right; + justify-content: flex-end; +} + +.m-message .self .avatar { + float: right; + margin: 0 0 0 10px; +} + +.m-message .self .text { + background-color: rgb(155, 255, 101); +} + +.m-message li { + margin-bottom: 15px; +} + +.m-message .time { + margin: 7px 0; + text-align: center; +} + +.m-message .time > span { + display: inline-block; + padding: 0 18px; + font-size: 9pt; + color: #fff; + border-radius: 2px; + background-color: #dcdcdc; +} + +.m-message .avatar { + float: left; + margin: 10px 10px 0 0; + border-radius: 3px; + width: 35px; + height: 35px; +} + +.m-message .text { + display: inline-block; + position: relative; + padding: 5px 10px; + min-height: 30px; + line-height: 2; + font-size: 9pt; + text-align: left; + word-break: break-all; + background-color: #fafafa; + border-radius: 4px; + max-width: 500px +} + +.m-message .text:before { + content: " "; + position: absolute; + top: 9px; + right: 100%; + border: 6px solid transparent; + border-right-color: #fafafa; +} + +.m-message .user_name { + height: 15px; + font-size: 12px; + margin-bottom: 5px; + color: #666; +} + +#chat .m-text { + position: absolute; + background-color: #fff; + width: 100%; + bottom: 0; + left: 0; + height: 160px; + border-top: 1px solid #ddd; +} + +.m-message .self .text:before { + right: inherit; + left: 100%; + border-right-color: transparent; + border-left-color: rgb(155, 255, 101); +} + +.m-text .handler { + padding-left: 20px; + height: 30px; + background: #eee; +} + +.m-text .handler img { + height: 20px; + width: 20px; + margin-top: 5px; + margin-bottom: 5px; + cursor: pointer; + vertical-align: middle; +} + +.m-text textarea { + padding: 10px 10px 20px 10px; + height: calc(100% - 70px); + width: 100%; + border: none; + outline: 0; + font-family: Micrsofot Yahei; + resize: none; +} + +.m-text .pager_btn { + position: absolute; + bottom: 10px; + width: 100%; + text-align: right; + padding-right: 20px; +} + +.m-text button { + width: 60px; +} + +.m-text .arrow_box { + font-size: 12px; + line-height: 30px; + padding: 0 5px; + width: 100px; + height: 30px; + position: absolute; + bottom: 50px; + right: 15px; + border: 1px solid #666; + border-radius: 3px; + box-sizing: content-box; + display: none; +} + +.m-text .arrow_box .arrow { + width: 0; + height: 0; + border-left: 10px solid transparent; + border-right: 10px solid transparent; + border-top: 10px solid #666; + position: absolute; + right: 0; + bottom: -10px; +} + + +.receive_list { + height: 180px; + overflow: auto; +} + +#pager_result > div { + padding-left: 10px; + padding-right: 10px; +} + +#pager_result .top img { + width: 100%; + height: 100px; + position: absolute; + left: 0; + top: 0; +} + + + + +#already_receive_top { + border-bottom: 1px solid rgb(233, 230, 230); + line-height: 40px; + font-size: 12px; + color: #666; +} + +.receive_list li { + display: flex; + align-items: center; + justify-content: flex-start; +} + +.receive_list li img { + width: 40px; + height: 40px; + vertical-align: center; + margin-right: 10px; + border-radius: 5px; +} + +.receive_list li div { + flex: 1; + border-bottom: 1px solid rgb(233, 230, 230); + padding-top: 10px; + padding-bottom: 10px; +} + +#receive_time { + color: #666; + font-size: 12px; +} + +.receive_list li div p { + margin: 0; +} + +.text_right { + text-align: right; +} + +.flex_between { + display: flex; + align-items: center; + justify-content: space-between; +} + +@media screen and (min-width: 320px) and (max-width: 640px) { + #chat { + width: 100%; + height: 100%; + min-width: 320px; + } + .m-card .name,.m-list .name { + margin: 0 0 0 5px!important; + + } + #chat .main { + flex: 1; + } + + #chat .sidebar { + width: 100px; + } + .m-card { + padding: 5px; + height: 40px; + } + .m-card .avatar { + width: 30px; + height: 30px; + } + #user_list li .avatar { + width: 20px; + height: 20px; + } + .pager_result #pager_result, .m-pager #pager { + top: 50%; + left: 50%; + margin-left: -150px; + margin-top: -250px; + } + .get_pager #get_pager { + margin-left: -100px; + } +} + +@media screen and (min-width: 640px)and (max-width: 992px) { + #chat { + width: 100%; + height: 100%; + } + + #chat .main { + flex: 1; + } + + #chat .sidebar { + width: 150px; + } + .pager_result #pager_result, .m-pager #pager { + margin-top: -250px; + } + .get_pager #get_pager { + margin-left: -50px; + } +} + +@media screen and (min-width: 992px) { + #chat { + margin: 20px auto; + width: 800px; + height: 600px; + } + + #chat .main { + width: 100%; + } + + #chat .sidebar { + width: 200px; + } + .pager_result #pager_result, .m-pager #pager { + margin-top: -300px; + } + .get_pager #get_pager { + margin-left: -50px; + } +} \ No newline at end of file diff --git a/netty-springboot/src/main/resources/static/img/arrow_right.svg b/netty-springboot/src/main/resources/static/img/arrow_right.svg new file mode 100755 index 00000000..d658da11 --- /dev/null +++ b/netty-springboot/src/main/resources/static/img/arrow_right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/netty-springboot/src/main/resources/static/img/bg.jpg b/netty-springboot/src/main/resources/static/img/bg.jpg new file mode 100755 index 0000000000000000000000000000000000000000..6582e6c808de2485b8a39c2b438b5f618d82d09b GIT binary patch literal 41567 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 \ No newline at end of file diff --git a/netty-springboot/src/main/resources/static/img/hongbao.png b/netty-springboot/src/main/resources/static/img/hongbao.png new file mode 100755 index 0000000000000000000000000000000000000000..2658cff261fcf4b2183d4daedd4e53da44bf0a81 GIT binary patch literal 35527 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 z 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 literal 0 HcmV?d00001 diff --git a/netty-springboot/src/main/resources/static/img/img.png b/netty-springboot/src/main/resources/static/img/img.png new file mode 100755 index 0000000000000000000000000000000000000000..40db557f98605ea868bb84d52cf7304662943d8b GIT binary patch literal 51828 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 literal 0 HcmV?d00001 diff --git a/netty-springboot/src/main/resources/static/img/my.jpg b/netty-springboot/src/main/resources/static/img/my.jpg new file mode 100755 index 0000000000000000000000000000000000000000..55f7c313f031a3ad5504b96dc7646d7bf49ccebb GIT binary patch literal 5178 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 literal 0 HcmV?d00001 diff --git a/netty-springboot/src/main/resources/static/img/pager.png b/netty-springboot/src/main/resources/static/img/pager.png new file mode 100755 index 0000000000000000000000000000000000000000..c969c14fdb8d5340397d6dbc2ffd56d666b91bde GIT binary patch literal 23468 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 literal 0 HcmV?d00001 diff --git a/netty-springboot/src/main/resources/static/img/paper.svg b/netty-springboot/src/main/resources/static/img/paper.svg new file mode 100755 index 00000000..8c87c2b3 --- /dev/null +++ b/netty-springboot/src/main/resources/static/img/paper.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/netty-springboot/src/main/resources/static/img/smile.svg b/netty-springboot/src/main/resources/static/img/smile.svg new file mode 100755 index 00000000..edf758b2 --- /dev/null +++ b/netty-springboot/src/main/resources/static/img/smile.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/netty-springboot/src/main/resources/static/img/spelling.svg b/netty-springboot/src/main/resources/static/img/spelling.svg new file mode 100755 index 00000000..a222cd71 --- /dev/null +++ b/netty-springboot/src/main/resources/static/img/spelling.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/netty-springboot/src/main/resources/static/img/user.png b/netty-springboot/src/main/resources/static/img/user.png new file mode 100755 index 0000000000000000000000000000000000000000..39b25ee733529702d10f4cec67b726e8aca566f6 GIT binary patch literal 20088 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 literal 0 HcmV?d00001 diff --git a/netty-springboot/src/main/resources/static/js/bootstrap.min.js b/netty-springboot/src/main/resources/static/js/bootstrap.min.js new file mode 100755 index 00000000..133aeecb --- /dev/null +++ b/netty-springboot/src/main/resources/static/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.5 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under the MIT license + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.5",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.5",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),a(c.target).is('input[type="radio"]')||a(c.target).is('input[type="checkbox"]')||c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.5",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.5",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.5",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger("shown.bs.dropdown",h)}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.5",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.5",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.5",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/netty-springboot/src/main/resources/static/js/chat.js b/netty-springboot/src/main/resources/static/js/chat.js new file mode 100755 index 00000000..6e7f87b4 --- /dev/null +++ b/netty-springboot/src/main/resources/static/js/chat.js @@ -0,0 +1,108 @@ +$(function () { + //这里需要注意的是,prompt有两个参数,前面是提示的话,后面是当对话框出来后,在对话框里的默认值 + var username = ""; + while (true) { + //弹出一个输入框,输入一段文字,可以提交 + username = prompt("请输入您的名字", ""); //将输入的内容赋给变量 name , + if (username.trim() === "")//如果返回的有内容 + { + alert("名称不能输入空") + } else { + $("#username").text(username); + break; + } + } + + var ws = new WebSocket("ws://localhost:8081/chat"); + ws.onopen = function () { + console.log("连接成功.") + } + ws.onmessage = function (evt) { + showMessage(evt.data); + } + ws.onclose = function (){ + console.log("连接关闭") + } + + ws.onerror = function (){ + console.log("连接异常") + } + + function showMessage(message) { + // 张三:你好 + var str = message.split(":"); + $("#msg_list").append(`
  • +
    + +
    +
    ${str[0]}
    +
    ${str[1]}
    +
    +
    +
  • `); + // 置底 + setBottom(); + } + + $('#my_test').bind({ + focus: function (event) { + event.stopPropagation() + $('#my_test').val(''); + $('.arrow_box').hide() + }, + keydown: function (event) { + event.stopPropagation() + if (event.keyCode === 13) { + if ($('#my_test').val().trim() === '') { + this.blur() + $('.arrow_box').show() + setTimeout(() => { + this.focus() + }, 1000) + } else { + $('.arrow_box').hide() + //发送消息 + sendMsg(); + this.blur() + setTimeout(() => { + this.focus() + }) + } + } + } + }); + $('#send').on('click', function (event) { + event.stopPropagation() + if ($('#my_test').val().trim() === '') { + $('.arrow_box').show() + } else { + sendMsg(); + } + }) + + function sendMsg() { + var message = $("#my_test").val(); + $("#msg_list").append(`
  • +
    +
    ` + message + `
    +
    +
  • `); + $("#my_test").val(''); + + //发送消息 + message = username + ":" + message; + ws.send(message); + // 置底 + setBottom(); + } + + // 置底 + function setBottom() { + // 发送消息后滚动到底部 + const container = $('.m-message') + const scroll = $('#msg_list') + container.animate({ + scrollTop: scroll[0].scrollHeight - container[0].clientHeight + container.scrollTop() + 100 + }); + } +}); \ No newline at end of file diff --git a/netty-springboot/src/main/resources/static/js/common.js b/netty-springboot/src/main/resources/static/js/common.js new file mode 100755 index 00000000..36a14490 --- /dev/null +++ b/netty-springboot/src/main/resources/static/js/common.js @@ -0,0 +1,107 @@ +var ws = new WebSocket("ws://localhost:9875/ws"); + ws.onopen = function() + { + console.log("连接成功"); + }; + ws.onmessage = function(evt) + { + var data = JSON.parse(evt.data); + for(var i in protocol){ + if(protocol[i].code == data.code){ + protocol[i].handler(data); + } + } + }; + ws.onclose = function(evt) + { + console.log("WebSocketClosed!"); + }; + ws.onerror = function(evt) + { + console.log("WebSocketError!"); + }; + +/** 发送消息 */ +function send(code,params){ + var obj = new Object(); + obj.code = code; + obj.params = params; + var json = JSON.stringify(obj); + ws.send(json); +} + +/** 协议封装 */ +function protocolHandler(code,handler){ + var obj = { + code: code, + handler: handler + } + return obj; +} + +var joinRoom = function(data){ + $("#first").hide(); + $("#second").hide(); + $("#room").show(); + $("#roomCode").text(data.params.code); +} + +var protocol = new Object(); +//登录返回 +protocol.login = protocolHandler(100,function(data){ + $("#first").hide(); + $("#second").show(); + $("#room").hide(); + $("#username").text(data.params.name); + $("#user").text(data.params.name); +}) +//发送消息到所有 +protocol.msgAll = protocolHandler(102,function(data){ + $("#allTable").append("" + + "" + data.params.username + ":" + + "" + data.params.msg + ""); +}) +//私聊 +protocol.msgOne = protocolHandler(103,function(data){ + $("#oneTable").append("" + + "" + data.params.username + ":" + + "" + data.params.msg + ""); +}) +//加入房间 +protocol.joinRoomById = protocolHandler(104,joinRoom); +protocol.joinRoomRandom = protocolHandler(105,joinRoom); +protocol.createRoom = protocolHandler(106,joinRoom); +//离开房间 +protocol.leaveRoom = protocolHandler(107,function(data){ + $("#first").hide(); + $("#second").show(); + $("#room").hide(); + $("#allTable").empty(); +}) +//用户加入 +protocol.userJoinRoom = protocolHandler(-101,function(data){ + $("#allTable").append("" + + "系统消息:" + + "<" + data.params.username + ">加入房间"); +}) +//用户离开 +protocol.userLeaveRoom = protocolHandler(-102,function(data){ + $("#allTable").append("" + + "系统消息:" + + "<" + data.params.username + ">离开房间"); +}) +//服务器主动推送 +protocol.serverPush = protocolHandler(-200,function(data){ + +}) +//错误信息 +protocol.errorMsg = protocolHandler(-400,function(data){ + layer.msg(data.msg); +}) + + + + + + + diff --git a/netty-springboot/src/main/resources/static/js/jquery-2.2.0.js b/netty-springboot/src/main/resources/static/js/jquery-2.2.0.js new file mode 100755 index 00000000..1e0ba997 --- /dev/null +++ b/netty-springboot/src/main/resources/static/js/jquery-2.2.0.js @@ -0,0 +1,9831 @@ +/*! + * jQuery JavaScript Library v2.2.0 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-01-08T20:02Z + */ + +(function( global, factory ) { + + if ( typeof module === "object" && typeof module.exports === "object" ) { + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Support: Firefox 18+ +// Can't be in strict mode, several libs including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +//"use strict"; +var arr = []; + +var document = window.document; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var support = {}; + + + +var + version = "2.2.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android<4.1 + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? + + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + + // Return all the elements in a clean array + slice.call( this ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = jQuery.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isFunction: function( obj ) { + return jQuery.type( obj ) === "function"; + }, + + isArray: Array.isArray, + + isWindow: function( obj ) { + return obj != null && obj === obj.window; + }, + + isNumeric: function( obj ) { + + // parseFloat NaNs numeric-cast false positives (null|true|false|"") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + // adding 1 corrects loss of precision from parseFloat (#15100) + var realStringObj = obj && obj.toString(); + return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0; + }, + + isPlainObject: function( obj ) { + + // Not plain objects: + // - Any object or value whose internal [[Class]] property is not "[object Object]" + // - DOM nodes + // - window + if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.constructor && + !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { + return false; + } + + // If the function hasn't returned already, we're confident that + // |obj| is a plain object, created by {} or constructed with new Object + return true; + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android<4.0, iOS<6 (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + var script, + indirect = eval; + + code = jQuery.trim( code ); + + if ( code ) { + + // If the code includes a valid, prologue position + // strict mode pragma, execute code by injecting a + // script tag into the document. + if ( code.indexOf( "use strict" ) === 1 ) { + script = document.createElement( "script" ); + script.text = code; + document.head.appendChild( script ).parentNode.removeChild( script ); + } else { + + // Otherwise, avoid the DOM node creation, insertion + // and removal by using an indirect global eval + + indirect( code ); + } + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Support: IE9-11+ + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android<4.1 + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: Date.now, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +// JSHint would error on this code due to the Symbol not being defined in ES5. +// Defining this global in .jshintrc would create a danger of using the global +// unguarded in another place, it seems safer to just disable JSHint for these +// three lines. +/* jshint ignore: start */ +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} +/* jshint ignore: end */ + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: iOS 8.2 (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.2.1 + * http://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2015-10-17 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // General-purpose constants + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // http://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, nidselect, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']"; + while ( i-- ) { + groups[i] = nidselect + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, parent, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( (parent = document.defaultView) && parent.top !== parent ) { + // Support: IE 11 + if ( parent.addEventListener ) { + parent.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( parent.attachEvent ) { + parent.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( document.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var m = context.getElementById( id ); + return m ? [ m ] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + docElem.appendChild( div ).innerHTML = "
    " + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( div.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibing-combinator selector` fails + if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( div ) { + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( div.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( (oldCache = uniqueCache[ dir ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ dir ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + +var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ ); + + + +var risSimple = /^.[^:#\[\.,]*$/; + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + } ); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + + } + + if ( typeof qualifier === "string" ) { + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, + len = this.length, + ret = [], + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + // Support: Blackberry 4.6 + // gEBID returns nodes no longer in the document (#6963) + if ( elem && elem.parentNode ) { + + // Inject the element directly into the jQuery object + this.length = 1; + this[ 0 ] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( pos ? + pos.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + return elem.contentDocument || jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnotwhite = ( /\S+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( jQuery.isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ], + [ "notify", "progress", jQuery.Callbacks( "memory" ) ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this === promise ? newDefer.promise() : this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( function() { + + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || + ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. + // If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // Add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .progress( updateFunc( i, progressContexts, progressValues ) ) + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ); + } else { + --remaining; + } + } + } + + // If we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +} ); + + +// The deferred used on DOM ready +var readyList; + +jQuery.fn.ready = function( fn ) { + + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + jQuery( document ).off( "ready" ); + } + } +} ); + +/** + * The ready event handler and self cleanup method + */ +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called + // after the browser event has already occurred. + // Support: IE9-10 only + // Older IE sometimes signals "interactive" too soon + if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + + } else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); + } + } + return readyList.promise( obj ); +}; + +// Kick off the DOM ready check even if the user does not +jQuery.ready.promise(); + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + len ? fn( elems[ 0 ], key ) : emptyGet; +}; +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + /* jshint -W018 */ + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + register: function( owner, initial ) { + var value = initial || {}; + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable, non-writable property + // configurability must be true to allow the property to be + // deleted with the delete operator + } else { + Object.defineProperty( owner, this.expando, { + value: value, + writable: true, + configurable: true + } ); + } + return owner[ this.expando ]; + }, + cache: function( owner ) { + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( !acceptData( owner ) ) { + return {}; + } + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + if ( typeof data === "string" ) { + cache[ data ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ prop ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + owner[ this.expando ] && owner[ this.expando ][ key ]; + }, + access: function( owner, key, value ) { + var stored; + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + stored = this.get( owner, key ); + + return stored !== undefined ? + stored : this.get( owner, jQuery.camelCase( key ) ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, name, camel, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key === undefined ) { + this.register( owner ); + + } else { + + // Support array or space separated string of keys + if ( jQuery.isArray( key ) ) { + + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = key.concat( key.map( jQuery.camelCase ) ); + } else { + camel = jQuery.camelCase( key ); + + // Try the string as a key before any manipulation + if ( key in cache ) { + name = [ key, camel ]; + } else { + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + name = camel; + name = name in cache ? + [ name ] : ( name.match( rnotwhite ) || [] ); + } + } + + i = name.length; + + while ( i-- ) { + delete cache[ name[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <= 35-45+ + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://code.google.com/p/chromium/issues/detail?id=378607 + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE11+ + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data, camelKey; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // with the key as-is + data = dataUser.get( elem, key ) || + + // Try to find dashed key if it exists (gh-2779) + // This is for 2.2.x only + dataUser.get( elem, key.replace( rmultiDash, "-$&" ).toLowerCase() ); + + if ( data !== undefined ) { + return data; + } + + camelKey = jQuery.camelCase( key ); + + // Attempt to get data from the cache + // with the key camelized + data = dataUser.get( elem, camelKey ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, camelKey, undefined ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + camelKey = jQuery.camelCase( key ); + this.each( function() { + + // First, attempt to store a copy or reference of any + // data that might've been store with a camelCased key. + var data = dataUser.get( this, camelKey ); + + // For HTML5 data-* attribute interop, we have to + // store property names with dashes in a camelCase form. + // This might not apply to all properties...* + dataUser.set( this, camelKey, value ); + + // *... In the case of properties that might _actually_ + // have dashes, we need to also store a copy of that + // unchanged property. + if ( key.indexOf( "-" ) > -1 && data !== undefined ) { + dataUser.set( this, key, value ); + } + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHidden = function( elem, el ) { + + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || + !jQuery.contains( elem.ownerDocument, elem ); + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, + scale = 1, + maxIterations = 20, + currentValue = tween ? + function() { return tween.cur(); } : + function() { return jQuery.css( elem, prop, "" ); }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + do { + + // If previous iteration zeroed out, double until we get *something*. + // Use string for doubling so we don't accidentally see scale as unchanged below + scale = scale || ".5"; + + // Adjust and apply + initialInUnit = initialInUnit / scale; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Update scale, tolerating zero or NaN from tween.cur() + // Break the loop if scale is unchanged or perfect, or if we've just had enough. + } while ( + scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations + ); + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([\w:-]+)/ ); + +var rscriptType = ( /^$|\/(?:java|ecma)script/i ); + + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE9 + option: [ 1, "" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
    " ], + col: [ 2, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + + _default: [ 0, "", "" ] +}; + +// Support: IE9 +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE9-11+ + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== "undefined" ? + context.querySelectorAll( tag || "*" ) : + []; + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], ret ) : + ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + + // Support: Android<4.1, PhantomJS<2 + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android<4.1, PhantomJS<2 + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0-4.3, Safari<=5.1 + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Safari<=5.1, Android<4.2 + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<=11+ + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +} )(); + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE9 +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, j, ret, matched, handleObj, + handlerQueue = [], + args = slice.call( arguments ), + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, matches, sel, handleObj, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Support (at least): Chrome, IE9 + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // + // Support: Firefox<=42+ + // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343) + if ( delegateCount && cur.nodeType && + ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push( { elem: cur, handlers: matches } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " + + "metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split( " " ), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: ( "button buttons clientX clientY offsetX offsetY pageX pageY " + + "screenX screenY toElement" ).split( " " ), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - + ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - + ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: Cordova 2.5 (WebKit) (#13255) + // All events should have a target; Cordova deviceready doesn't + if ( !event.target ) { + event.target = document; + } + + // Support: Safari 6.0+, Chrome<28 + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android<4.0 + src.returnValue === false ? + returnTrue : + returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://code.google.com/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi, + + // Support: IE 10-11, Edge 10240+ + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +function manipulationTarget( elem, content ) { + if ( jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return elem.getElementsByTagName( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + + if ( match ) { + elem.type = match[ 1 ]; + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( isFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android<4.1, PhantomJS<2 + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <= 35-45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <= 35-45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + + // Keep domManip exposed until 3.0 (gh-2225) + domManip: domManip, + + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: QtWebKit + // .get() because push.apply(_, arraylike) throws + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); + + +var iframe, + elemdisplay = { + + // Support: Firefox + // We have to pre-define these values for FF (#10227) + HTML: "block", + BODY: "block" + }; + +/** + * Retrieve the actual display of a element + * @param {String} name nodeName of the element + * @param {Object} doc Document object + */ + +// Called only from within defaultDisplay +function actualDisplay( name, doc ) { + var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + + display = jQuery.css( elem[ 0 ], "display" ); + + // We don't have any data stored on the element, + // so use "detach" method as fast way to get rid of the element + elem.detach(); + + return display; +} + +/** + * Try to determine the default display value of an element + * @param {String} nodeName + */ +function defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + + // Use the already-created iframe if possible + iframe = ( iframe || jQuery( "