├── LICENSE ├── README.md ├── slides ├── Redis 的高并发实战:抢购系统 .pdf ├── Redis开发实操之春运迁徙页面.pdf ├── Redis架构与介质选择指引.pdf ├── Redis生态.pdf ├── Redis的开发规范和常见问题.pdf └── Redis的运维实战.pdf └── spring-boot-example-redis ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── HELP.md ├── README.md ├── demo ├── css │ ├── bootstrap.min.css │ └── index.css ├── index.html └── js │ ├── bootstrap.min.js │ ├── index.js │ └── jquery.min.js ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── aliyun │ │ └── tair │ │ └── springbootexample │ │ ├── SpringBootExampleApplication.java │ │ ├── config │ │ └── BeanConfig.java │ │ ├── controller │ │ ├── HotAreaController.java │ │ ├── InsertDataController.java │ │ ├── NewsController.java │ │ ├── PositionController.java │ │ ├── RankController.java │ │ └── UserController.java │ │ ├── model │ │ ├── HotArea.java │ │ ├── News.java │ │ ├── Position.java │ │ ├── Rank.java │ │ └── User.java │ │ └── repo │ │ ├── HotAreaRepository.java │ │ ├── NewsRepository.java │ │ ├── PositionRepository.java │ │ ├── RankRepository.java │ │ └── UserRepository.java └── resources │ └── application.properties └── test └── java └── com └── aliyun └── tair └── springbootexample ├── JedisTest.java └── SpringBootExampleApplicationTests.java /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Alibaba Cloud 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### 2021 阿里云开发者社区 [Redis训练营](https://developer.aliyun.com/learning/trainingcamp/redis/1) 演示资料 2 | 3 | 视频地址:https://developer.aliyun.com/learning/course/777 4 | 学习流程:登录阿里云账号-加入学习-课时列表 5 | 6 | | 课程 | 介绍 | 演示资料及代码 | 7 | | ---------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | 8 | | 走进 Redis | Redis 的整体架构,主要数据结构,以及支撑其高性能、高可扩展的关键技术机制。 | 暂无 | 9 | | Redis 开发实操之春运迁徙页面 | Redis 启动到连接,使用 Redis Hash,Sorted Set,Stream,TairGis 等结构实现一个春运迁徙页面。 | [ppt](https://github.com/aliyun/alibabacloud-redis-training-demo/blob/master/slides/Redis%E5%BC%80%E5%8F%91%E5%AE%9E%E6%93%8D%E4%B9%8B%E6%98%A5%E8%BF%90%E8%BF%81%E5%BE%99%E9%A1%B5%E9%9D%A2.pdf), [demo-code](https://github.com/aliyun/alibabacloud-redis-training-demo/tree/master/spring-boot-example-redis) | 10 | | Redis 的运维实战 | Redis 社区及运营方式介绍,云 Redis 特性介绍及运维解法、高级容灾。 | [ppt](https://github.com/aliyun/alibabacloud-redis-training-demo/blob/master/slides/Redis%E7%9A%84%E8%BF%90%E7%BB%B4%E5%AE%9E%E6%88%98.pdf) | 11 | | Redis 的开发规范和常见问题 | 如何定制 Redis 开发规则,阿里内部系统的开发规约介绍及 Redis 的常见问题处理。 | [ppt](https://github.com/aliyun/alibabacloud-redis-training-demo/blob/master/slides/Redis%E7%9A%84%E5%BC%80%E5%8F%91%E8%A7%84%E8%8C%83%E5%92%8C%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98.pdf) | 12 | | Redis 架构及介质选择指引 | 如何进行 Redis 选型,云 Redis 版集群架构及对比,如何使用 Redis 做缓存。 | [ppt](https://github.com/aliyun/alibabacloud-redis-training-demo/blob/master/slides/Redis%E6%9E%B6%E6%9E%84%E4%B8%8E%E4%BB%8B%E8%B4%A8%E9%80%89%E6%8B%A9%E6%8C%87%E5%BC%95.pdf) | 13 | | Redis 的高并发实战:抢购系统 | IO 模型和问题,资源竞争与分布式锁,如何利用 Redis 高并发原理做抢购系统。 | [ppt](https://github.com/aliyun/alibabacloud-redis-training-demo/blob/master/slides/Redis%20%E7%9A%84%E9%AB%98%E5%B9%B6%E5%8F%91%E5%AE%9E%E6%88%98%EF%BC%9A%E6%8A%A2%E8%B4%AD%E7%B3%BB%E7%BB%9F%20.pdf) | 14 | | Redis 的生态 | DMS/DTS/Redis-shake工具使用,Redis和数据库/大数据的联动应用场景等。 | [ppt](https://github.com/aliyun/alibabacloud-redis-training-demo/blob/master/slides/Redis%E7%94%9F%E6%80%81.pdf) | 15 | 16 | 更多资料,Redis 最佳实践获取,请访问[阿里云数据库Redis文档](https://help.aliyun.com/product/26340.html)。 17 | -------------------------------------------------------------------------------- /slides/Redis 的高并发实战:抢购系统 .pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyun/alibabacloud-redis-training-demo/50d321bc3ec304c0300eff70a937047eebcc92b6/slides/Redis 的高并发实战:抢购系统 .pdf -------------------------------------------------------------------------------- /slides/Redis开发实操之春运迁徙页面.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyun/alibabacloud-redis-training-demo/50d321bc3ec304c0300eff70a937047eebcc92b6/slides/Redis开发实操之春运迁徙页面.pdf -------------------------------------------------------------------------------- /slides/Redis架构与介质选择指引.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyun/alibabacloud-redis-training-demo/50d321bc3ec304c0300eff70a937047eebcc92b6/slides/Redis架构与介质选择指引.pdf -------------------------------------------------------------------------------- /slides/Redis生态.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyun/alibabacloud-redis-training-demo/50d321bc3ec304c0300eff70a937047eebcc92b6/slides/Redis生态.pdf -------------------------------------------------------------------------------- /slides/Redis的开发规范和常见问题.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyun/alibabacloud-redis-training-demo/50d321bc3ec304c0300eff70a937047eebcc92b6/slides/Redis的开发规范和常见问题.pdf -------------------------------------------------------------------------------- /slides/Redis的运维实战.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyun/alibabacloud-redis-training-demo/50d321bc3ec304c0300eff70a937047eebcc92b6/slides/Redis的运维实战.pdf -------------------------------------------------------------------------------- /spring-boot-example-redis/.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import java.net.*; 18 | import java.io.*; 19 | import java.nio.channels.*; 20 | import java.util.Properties; 21 | 22 | public class MavenWrapperDownloader { 23 | 24 | private static final String WRAPPER_VERSION = "0.5.6"; 25 | /** 26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 27 | */ 28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 30 | 31 | /** 32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 33 | * use instead of the default one. 34 | */ 35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 36 | ".mvn/wrapper/maven-wrapper.properties"; 37 | 38 | /** 39 | * Path where the maven-wrapper.jar will be saved to. 40 | */ 41 | private static final String MAVEN_WRAPPER_JAR_PATH = 42 | ".mvn/wrapper/maven-wrapper.jar"; 43 | 44 | /** 45 | * Name of the property which should be used to override the default download url for the wrapper. 46 | */ 47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 48 | 49 | public static void main(String args[]) { 50 | System.out.println("- Downloader started"); 51 | File baseDirectory = new File(args[0]); 52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 53 | 54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 55 | // wrapperUrl parameter. 56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 57 | String url = DEFAULT_DOWNLOAD_URL; 58 | if (mavenWrapperPropertyFile.exists()) { 59 | FileInputStream mavenWrapperPropertyFileInputStream = null; 60 | try { 61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 62 | Properties mavenWrapperProperties = new Properties(); 63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 65 | } catch (IOException e) { 66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 67 | } finally { 68 | try { 69 | if (mavenWrapperPropertyFileInputStream != null) { 70 | mavenWrapperPropertyFileInputStream.close(); 71 | } 72 | } catch (IOException e) { 73 | // Ignore ... 74 | } 75 | } 76 | } 77 | System.out.println("- Downloading from: " + url); 78 | 79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 80 | if (!outputFile.getParentFile().exists()) { 81 | if (!outputFile.getParentFile().mkdirs()) { 82 | System.out.println( 83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 84 | } 85 | } 86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 87 | try { 88 | downloadFileFromURL(url, outputFile); 89 | System.out.println("Done"); 90 | System.exit(0); 91 | } catch (Throwable e) { 92 | System.out.println("- Error downloading"); 93 | e.printStackTrace(); 94 | System.exit(1); 95 | } 96 | } 97 | 98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 100 | String username = System.getenv("MVNW_USERNAME"); 101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 102 | Authenticator.setDefault(new Authenticator() { 103 | @Override 104 | protected PasswordAuthentication getPasswordAuthentication() { 105 | return new PasswordAuthentication(username, password); 106 | } 107 | }); 108 | } 109 | URL website = new URL(urlString); 110 | ReadableByteChannel rbc; 111 | rbc = Channels.newChannel(website.openStream()); 112 | FileOutputStream fos = new FileOutputStream(destination); 113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 114 | fos.close(); 115 | rbc.close(); 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /spring-boot-example-redis/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyun/alibabacloud-redis-training-demo/50d321bc3ec304c0300eff70a937047eebcc92b6/spring-boot-example-redis/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /spring-boot-example-redis/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /spring-boot-example-redis/HELP.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | ### Reference Documentation 4 | 5 | For further reference, please consider the following sections: 6 | 7 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html) 8 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.4.2/maven-plugin/reference/html/) 9 | * [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.4.2/maven-plugin/reference/html/#build-image) 10 | * [Spring Web](https://docs.spring.io/spring-boot/docs/2.4.2/reference/htmlsingle/#boot-features-developing-web-applications) 11 | 12 | ### Guides 13 | 14 | The following guides illustrate how to use some features concretely: 15 | 16 | * [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/) 17 | * [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/) 18 | * [Building REST services with Spring](https://spring.io/guides/tutorials/bookmarks/) 19 | 20 | -------------------------------------------------------------------------------- /spring-boot-example-redis/README.md: -------------------------------------------------------------------------------- 1 | # spring-boot-example 2 | 3 | 1,start redis at 127.0.0.1:6379 4 | 5 | 2,start spring-boot-example at 8080 6 | 7 | 3,insert data 8 | ```shell 9 | curl -v -X PUT http://127.0.0.1:8080/insert 10 | ``` 11 | 12 | 4,open `demo/index.html` at browser. -------------------------------------------------------------------------------- /spring-boot-example-redis/demo/css/index.css: -------------------------------------------------------------------------------- 1 | #content { 2 | border: 1px solid #191919; 3 | width: 300px; 4 | padding: 30px; 5 | box-sizing: border-box; 6 | border-radius: 10px; 7 | color: #666666; 8 | } 9 | 10 | .demo-date { 11 | margin-bottom: 10px; 12 | } 13 | 14 | .demo-item { 15 | margin-top: 10px; 16 | margin-bottom: 8px; 17 | } 18 | -------------------------------------------------------------------------------- /spring-boot-example-redis/demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /spring-boot-example-redis/demo/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.4 (http://getbootstrap.com) 3 | * Copyright 2011-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | if ("undefined" == typeof jQuery) throw new Error("Bootstrap's JavaScript requires jQuery"); 7 | +function (a) { 8 | "use strict"; 9 | var b = a.fn.jquery.split(" ")[0].split("."); 10 | 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") 11 | }(jQuery), +function (a) { 12 | "use strict"; 13 | 14 | function b() { 15 | var a = document.createElement("bootstrap"), 16 | b = { 17 | WebkitTransition: "webkitTransitionEnd", 18 | MozTransition: "transitionend", 19 | OTransition: "oTransitionEnd otransitionend", 20 | transition: "transitionend" 21 | }; 22 | for (var c in b) 23 | if (void 0 !== a.style[c]) return {end: b[c]}; 24 | return !1 25 | } 26 | 27 | a.fn.emulateTransitionEnd = function (b) { 28 | var c = !1, 29 | d = this; 30 | a(this).one("bsTransitionEnd", function () { 31 | c = !0 32 | }); 33 | var e = function () { 34 | c || a(d).trigger(a.support.transition.end) 35 | }; 36 | return setTimeout(e, b), this 37 | }, a(function () { 38 | a.support.transition = b(), a.support.transition && (a.event.special.bsTransitionEnd = { 39 | bindType: a.support.transition.end, 40 | delegateType: a.support.transition.end, 41 | handle: function (b) { 42 | return a(b.target).is(this) ? b.handleObj.handler.apply(this, arguments) : void 0 43 | } 44 | }) 45 | }) 46 | }(jQuery), +function (a) { 47 | "use strict"; 48 | 49 | function b(b) { 50 | return this.each(function () { 51 | var c = a(this), 52 | e = c.data("bs.alert"); 53 | e || c.data("bs.alert", e = new d(this)), "string" == typeof b && e[b].call(c) 54 | }) 55 | } 56 | 57 | var c = '[data-dismiss="alert"]', 58 | d = function (b) { 59 | a(b).on("click", c, this.close) 60 | }; 61 | d.VERSION = "3.3.4", d.TRANSITION_DURATION = 150, d.prototype.close = function (b) { 62 | function c() { 63 | g.detach().trigger("closed.bs.alert").remove() 64 | } 65 | 66 | var e = a(this), 67 | f = e.attr("data-target"); 68 | f || (f = e.attr("href"), f = f && f.replace(/.*(?=#[^\s]*$)/, "")); 69 | var g = a(f); 70 | 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()) 71 | }; 72 | var e = a.fn.alert; 73 | a.fn.alert = b, a.fn.alert.Constructor = d, a.fn.alert.noConflict = function () { 74 | return a.fn.alert = e, this 75 | }, a(document).on("click.bs.alert.data-api", c, d.prototype.close) 76 | }(jQuery), +function (a) { 77 | "use strict"; 78 | 79 | function b(b) { 80 | return this.each(function () { 81 | var d = a(this), 82 | e = d.data("bs.button"), 83 | f = "object" == typeof b && b; 84 | e || d.data("bs.button", e = new c(this, f)), "toggle" == b ? e.toggle() : b && e.setState(b) 85 | }) 86 | } 87 | 88 | var c = function (b, d) { 89 | this.$element = a(b), this.options = a.extend({}, c.DEFAULTS, d), this.isLoading = !1 90 | }; 91 | c.VERSION = "3.3.4", c.DEFAULTS = {loadingText: "loading..."}, c.prototype.setState = function (b) { 92 | var c = "disabled", 93 | d = this.$element, 94 | e = d.is("input") ? "val" : "html", 95 | f = d.data(); 96 | b += "Text", null == f.resetText && d.data("resetText", d[e]()), setTimeout(a.proxy(function () { 97 | 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)) 98 | }, this), 0) 99 | }, c.prototype.toggle = function () { 100 | var a = !0, 101 | b = this.$element.closest('[data-toggle="buttons"]'); 102 | if (b.length) { 103 | var c = this.$element.find("input"); 104 | "radio" == c.prop("type") && (c.prop("checked") && this.$element.hasClass("active") ? a = !1 : b.find(".active").removeClass("active")), a && c.prop("checked", !this.$element.hasClass("active")).trigger("change") 105 | } else this.$element.attr("aria-pressed", !this.$element.hasClass("active")); 106 | a && this.$element.toggleClass("active") 107 | }; 108 | var d = a.fn.button; 109 | a.fn.button = b, a.fn.button.Constructor = c, a.fn.button.noConflict = function () { 110 | return a.fn.button = d, this 111 | }, a(document).on("click.bs.button.data-api", '[data-toggle^="button"]', function (c) { 112 | var d = a(c.target); 113 | d.hasClass("btn") || (d = d.closest(".btn")), b.call(d, "toggle"), c.preventDefault() 114 | }).on("focus.bs.button.data-api blur.bs.button.data-api", '[data-toggle^="button"]', function (b) { 115 | a(b.target).closest(".btn").toggleClass("focus", /^focus(in)?$/.test(b.type)) 116 | }) 117 | }(jQuery), +function (a) { 118 | "use strict"; 119 | 120 | function b(b) { 121 | return this.each(function () { 122 | var d = a(this), 123 | e = d.data("bs.carousel"), 124 | f = a.extend({}, c.DEFAULTS, d.data(), "object" == typeof b && b), 125 | g = "string" == typeof b ? b : f.slide; 126 | e || d.data("bs.carousel", e = new c(this, f)), "number" == typeof b ? e.to(b) : g ? e[g]() : f.interval && e.pause().cycle() 127 | }) 128 | } 129 | 130 | var c = function (b, c) { 131 | 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)) 132 | }; 133 | c.VERSION = "3.3.4", c.TRANSITION_DURATION = 600, c.DEFAULTS = { 134 | interval: 5e3, 135 | pause: "hover", 136 | wrap: !0, 137 | keyboard: !0 138 | }, c.prototype.keydown = function (a) { 139 | if (!/input|textarea/i.test(a.target.tagName)) { 140 | switch (a.which) { 141 | case 37: 142 | this.prev(); 143 | break; 144 | case 39: 145 | this.next(); 146 | break; 147 | default: 148 | return 149 | } 150 | a.preventDefault() 151 | } 152 | }, c.prototype.cycle = function (b) { 153 | 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 154 | }, c.prototype.getItemIndex = function (a) { 155 | return this.$items = a.parent().children(".item"), this.$items.index(a || this.$active) 156 | }, c.prototype.getItemForDirection = function (a, b) { 157 | var c = this.getItemIndex(b), 158 | d = "prev" == a && 0 === c || "next" == a && c == this.$items.length - 1; 159 | if (d && !this.options.wrap) return b; 160 | var e = "prev" == a ? -1 : 1, 161 | f = (c + e) % this.$items.length; 162 | return this.$items.eq(f) 163 | }, c.prototype.to = function (a) { 164 | var b = this, 165 | c = this.getItemIndex(this.$active = this.$element.find(".item.active")); 166 | return a > this.$items.length - 1 || 0 > a ? void 0 : this.sliding ? this.$element.one("slid.bs.carousel", function () { 167 | b.to(a) 168 | }) : c == a ? this.pause().cycle() : this.slide(a > c ? "next" : "prev", this.$items.eq(a)) 169 | }, c.prototype.pause = function (b) { 170 | 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 171 | }, c.prototype.next = function () { 172 | return this.sliding ? void 0 : this.slide("next") 173 | }, c.prototype.prev = function () { 174 | return this.sliding ? void 0 : this.slide("prev") 175 | }, c.prototype.slide = function (b, d) { 176 | var e = this.$element.find(".item.active"), 177 | f = d || this.getItemForDirection(b, e), 178 | g = this.interval, 179 | h = "next" == b ? "left" : "right", 180 | i = this; 181 | if (f.hasClass("active")) return this.sliding = !1; 182 | var j = f[0], 183 | k = a.Event("slide.bs.carousel", {relatedTarget: j, direction: h}); 184 | if (this.$element.trigger(k), !k.isDefaultPrevented()) { 185 | if (this.sliding = !0, g && this.pause(), this.$indicators.length) { 186 | this.$indicators.find(".active").removeClass("active"); 187 | var l = a(this.$indicators.children()[this.getItemIndex(f)]); 188 | l && l.addClass("active") 189 | } 190 | var m = a.Event("slid.bs.carousel", {relatedTarget: j, direction: h}); 191 | return a.support.transition && this.$element.hasClass("slide") ? (f.addClass(b), f[0].offsetWidth, e.addClass(h), f.addClass(h), e.one("bsTransitionEnd", function () { 192 | f.removeClass([b, h].join(" ")).addClass("active"), e.removeClass(["active", h].join(" ")), i.sliding = !1, setTimeout(function () { 193 | i.$element.trigger(m) 194 | }, 0) 195 | }).emulateTransitionEnd(c.TRANSITION_DURATION)) : (e.removeClass("active"), f.addClass("active"), this.sliding = !1, this.$element.trigger(m)), g && this.cycle(), this 196 | } 197 | }; 198 | var d = a.fn.carousel; 199 | a.fn.carousel = b, a.fn.carousel.Constructor = c, a.fn.carousel.noConflict = function () { 200 | return a.fn.carousel = d, this 201 | }; 202 | var e = function (c) { 203 | var d, e = a(this), 204 | f = a(e.attr("data-target") || (d = e.attr("href")) && d.replace(/.*(?=#[^\s]+$)/, "")); 205 | if (f.hasClass("carousel")) { 206 | var g = a.extend({}, f.data(), e.data()), 207 | h = e.attr("data-slide-to"); 208 | h && (g.interval = !1), b.call(f, g), h && f.data("bs.carousel").to(h), c.preventDefault() 209 | } 210 | }; 211 | 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 () { 212 | a('[data-ride="carousel"]').each(function () { 213 | var c = a(this); 214 | b.call(c, c.data()) 215 | }) 216 | }) 217 | }(jQuery), +function (a) { 218 | "use strict"; 219 | 220 | function b(b) { 221 | var c, d = b.attr("data-target") || (c = b.attr("href")) && c.replace(/.*(?=#[^\s]+$)/, ""); 222 | return a(d) 223 | } 224 | 225 | function c(b) { 226 | return this.each(function () { 227 | var c = a(this), 228 | e = c.data("bs.collapse"), 229 | f = a.extend({}, d.DEFAULTS, c.data(), "object" == typeof b && b); 230 | !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]() 231 | }) 232 | } 233 | 234 | var d = function (b, c) { 235 | 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() 236 | }; 237 | d.VERSION = "3.3.4", d.TRANSITION_DURATION = 350, d.DEFAULTS = {toggle: !0}, d.prototype.dimension = function () { 238 | var a = this.$element.hasClass("width"); 239 | return a ? "width" : "height" 240 | }, d.prototype.show = function () { 241 | if (!this.transitioning && !this.$element.hasClass("in")) { 242 | var b, e = this.$parent && this.$parent.children(".panel").children(".in, .collapsing"); 243 | if (!(e && e.length && (b = e.data("bs.collapse"), b && b.transitioning))) { 244 | var f = a.Event("show.bs.collapse"); 245 | if (this.$element.trigger(f), !f.isDefaultPrevented()) { 246 | e && e.length && (c.call(e, "hide"), b || e.data("bs.collapse", null)); 247 | var g = this.dimension(); 248 | this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded", !0), this.$trigger.removeClass("collapsed").attr("aria-expanded", !0), this.transitioning = 1; 249 | var h = function () { 250 | this.$element.removeClass("collapsing").addClass("collapse in")[g](""), this.transitioning = 0, this.$element.trigger("shown.bs.collapse") 251 | }; 252 | if (!a.support.transition) return h.call(this); 253 | var i = a.camelCase(["scroll", g].join("-")); 254 | this.$element.one("bsTransitionEnd", a.proxy(h, this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i]) 255 | } 256 | } 257 | } 258 | }, d.prototype.hide = function () { 259 | if (!this.transitioning && this.$element.hasClass("in")) { 260 | var b = a.Event("hide.bs.collapse"); 261 | if (this.$element.trigger(b), !b.isDefaultPrevented()) { 262 | var c = this.dimension(); 263 | 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; 264 | var e = function () { 265 | this.transitioning = 0, this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse") 266 | }; 267 | return a.support.transition ? void this.$element[c](0).one("bsTransitionEnd", a.proxy(e, this)).emulateTransitionEnd(d.TRANSITION_DURATION) : e.call(this) 268 | } 269 | } 270 | }, d.prototype.toggle = function () { 271 | this[this.$element.hasClass("in") ? "hide" : "show"]() 272 | }, d.prototype.getParent = function () { 273 | return a(this.options.parent).find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]').each(a.proxy(function (c, d) { 274 | var e = a(d); 275 | this.addAriaAndCollapsedClass(b(e), e) 276 | }, this)).end() 277 | }, d.prototype.addAriaAndCollapsedClass = function (a, b) { 278 | var c = a.hasClass("in"); 279 | a.attr("aria-expanded", c), b.toggleClass("collapsed", !c).attr("aria-expanded", c) 280 | }; 281 | var e = a.fn.collapse; 282 | a.fn.collapse = c, a.fn.collapse.Constructor = d, a.fn.collapse.noConflict = function () { 283 | return a.fn.collapse = e, this 284 | }, a(document).on("click.bs.collapse.data-api", '[data-toggle="collapse"]', function (d) { 285 | var e = a(this); 286 | e.attr("data-target") || d.preventDefault(); 287 | var f = b(e), 288 | g = f.data("bs.collapse"), 289 | h = g ? "toggle" : e.data(); 290 | c.call(f, h) 291 | }) 292 | }(jQuery), +function (a) { 293 | "use strict"; 294 | 295 | function b(b) { 296 | b && 3 === b.which || (a(e).remove(), a(f).each(function () { 297 | var d = a(this), 298 | e = c(d), 299 | f = {relatedTarget: this}; 300 | e.hasClass("open") && (e.trigger(b = a.Event("hide.bs.dropdown", f)), b.isDefaultPrevented() || (d.attr("aria-expanded", "false"), e.removeClass("open").trigger("hidden.bs.dropdown", f))) 301 | })) 302 | } 303 | 304 | function c(b) { 305 | var c = b.attr("data-target"); 306 | c || (c = b.attr("href"), c = c && /#[A-Za-z]/.test(c) && c.replace(/.*(?=#[^\s]*$)/, "")); 307 | var d = c && a(c); 308 | return d && d.length ? d : b.parent() 309 | } 310 | 311 | function d(b) { 312 | return this.each(function () { 313 | var c = a(this), 314 | d = c.data("bs.dropdown"); 315 | d || c.data("bs.dropdown", d = new g(this)), "string" == typeof b && d[b].call(c) 316 | }) 317 | } 318 | 319 | var e = ".dropdown-backdrop", 320 | f = '[data-toggle="dropdown"]', 321 | g = function (b) { 322 | a(b).on("click.bs.dropdown", this.toggle) 323 | }; 324 | g.VERSION = "3.3.4", g.prototype.toggle = function (d) { 325 | var e = a(this); 326 | if (!e.is(".disabled, :disabled")) { 327 | var f = c(e), 328 | g = f.hasClass("open"); 329 | if (b(), !g) { 330 | "ontouchstart" in document.documentElement && !f.closest(".navbar-nav").length && a('