├── Kairos.php
├── LICENSE
├── README.md
├── examples
├── assets
│ ├── css
│ │ ├── bootstrap.css.map
│ │ ├── bootstrap.min.css
│ │ └── styles.css
│ ├── fonts
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.svg
│ │ ├── glyphicons-halflings-regular.ttf
│ │ └── glyphicons-halflings-regular.woff
│ ├── images
│ │ ├── loading.gif
│ │ └── sample.jpg
│ └── js
│ │ ├── bootstrap.js
│ │ ├── bootstrap.min.js
│ │ └── scripts.js
├── controller.php
└── methods_test.php
├── simple-detect
├── form-post.php
└── index.html
└── simple-viewSubjects
├── form-post.php
└── index.html
/Kairos.php:
--------------------------------------------------------------------------------
1 | hostname = 'http://api.kairos.com/';
20 | $this->app_id = $app_id;
21 | $this->app_key = $app_key;
22 | }
23 |
24 |
25 | private function authenticationProvided()
26 | {
27 | if(count($this->app_key) > 0 && count($this->app_id) > 0)
28 | {
29 | return true;
30 | }
31 |
32 | return false;
33 | }
34 |
35 | public function viewGalleries($args = array())
36 | {
37 |
38 | if($this->authenticationProvided() == false)
39 | {
40 | return 'set your app_id and app_key before calling this method';
41 | }
42 |
43 | $request_params = array();
44 |
45 | // build request string
46 | $request = json_encode($request_params);
47 |
48 | try
49 | {
50 |
51 | $ch = curl_init();
52 |
53 | curl_setopt($ch, CURLOPT_URL, $this->hostname . "gallery/list_all" );
54 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
55 | curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
56 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
57 | curl_setopt($ch, CURLOPT_HTTPHEADER,
58 | array(
59 | 'Content-Type: application/json',
60 | 'Content-Length: ' . strlen($request),
61 | 'app_id: ' . $this->app_id,
62 | 'app_key: '. $this->app_key)
63 | );
64 |
65 | $response = curl_exec($ch);
66 |
67 | curl_close($ch);
68 |
69 | }
70 | catch(Exception $ex)
71 | {
72 | return 'there was a problem';
73 | }
74 |
75 | return $response;
76 | }
77 |
78 |
79 | public function enroll($args = array())
80 | {
81 |
82 | // to get base64
83 | // $image_data = base64_encode(file_get_contents($args["image_path"]));
84 |
85 | if($this->authenticationProvided() == false)
86 | {
87 | return 'set your app_id and app_key before calling this method';
88 | }
89 |
90 |
91 | $request_params = array(
92 | "image" => $args["image"],
93 | "gallery_name" => $args["gallery_name"],
94 | "subject_id" => $args["subject_id"] );
95 |
96 | // build request string
97 | $request = json_encode($request_params);
98 |
99 | try
100 | {
101 |
102 | $ch = curl_init();
103 |
104 | curl_setopt($ch, CURLOPT_URL, $this->hostname . "enroll" );
105 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
106 | curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
107 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
108 | curl_setopt($ch, CURLOPT_HTTPHEADER,
109 | array(
110 | 'Content-Type: application/json',
111 | 'Content-Length: ' . strlen($request),
112 | 'app_id: ' . $this->app_id,
113 | 'app_key: '. $this->app_key)
114 | );
115 |
116 | $response = curl_exec($ch);
117 |
118 | curl_close($ch);
119 |
120 | }
121 | catch(Exception $ex)
122 | {
123 | return 'there was a problem';
124 | }
125 |
126 | return $response;
127 | }
128 |
129 |
130 | public function viewSubjectsInGallery($args = array())
131 | {
132 |
133 | if($this->authenticationProvided() == false)
134 | {
135 | return 'set your app_id and app_key before calling this method';
136 | }
137 |
138 | $request_params = array(
139 | "gallery_name" => $args["gallery_name"],
140 | );
141 |
142 | // build request string
143 | $request = json_encode($request_params);
144 |
145 | try
146 | {
147 |
148 | $ch = curl_init();
149 |
150 | curl_setopt($ch, CURLOPT_URL, $this->hostname . "gallery/view" );
151 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
152 | curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
153 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
154 | curl_setopt($ch, CURLOPT_HTTPHEADER,
155 | array(
156 | 'Content-Type: application/json',
157 | 'Content-Length: ' . strlen($request),
158 | 'app_id: ' . $this->app_id,
159 | 'app_key: '. $this->app_key)
160 | );
161 |
162 | $response = curl_exec($ch);
163 |
164 | curl_close($ch);
165 |
166 | }
167 | catch(Exception $ex)
168 | {
169 | return 'there was a problem';
170 | }
171 |
172 | return $response;
173 |
174 | }
175 |
176 |
177 |
178 | public function removeSubjectFromGallery($args = array())
179 | {
180 |
181 | if($this->authenticationProvided() == false)
182 | {
183 | return 'set your app_id and app_key before calling this method';
184 | }
185 |
186 | $request_params = array(
187 | "gallery_name" => $args["gallery_name"],
188 | "subject_id" => $args["subject_id"],
189 | );
190 |
191 | // build request string
192 | $request = json_encode($request_params);
193 |
194 | try
195 | {
196 |
197 | $ch = curl_init();
198 |
199 | curl_setopt($ch, CURLOPT_URL, $this->hostname . "gallery/remove_subject" );
200 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
201 | curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
202 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
203 | curl_setopt($ch, CURLOPT_HTTPHEADER,
204 | array(
205 | 'Content-Type: application/json',
206 | 'Content-Length: ' . strlen($request),
207 | 'app_id: ' . $this->app_id,
208 | 'app_key: '. $this->app_key)
209 | );
210 |
211 | $response = curl_exec($ch);
212 |
213 | curl_close($ch);
214 |
215 | }
216 | catch(Exception $ex)
217 | {
218 | return 'there was a problem';
219 | }
220 |
221 | return $response;
222 | }
223 |
224 | public function removeGallery($args = array())
225 | {
226 |
227 |
228 | if($this->authenticationProvided() == false)
229 | {
230 | return 'set your app_id and app_key before calling this method';
231 | }
232 |
233 | $request_params = array(
234 | "gallery_name" => $args["gallery_name"]
235 | );
236 |
237 |
238 | // build request string
239 | $request = json_encode($request_params);
240 |
241 | try
242 | {
243 |
244 | $ch = curl_init();
245 |
246 | curl_setopt($ch, CURLOPT_URL, $this->hostname . "gallery/remove" );
247 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
248 | curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
249 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
250 | curl_setopt($ch, CURLOPT_HTTPHEADER,
251 | array(
252 | 'Content-Type: application/json',
253 | 'Content-Length: ' . strlen($request),
254 | 'app_id: ' . $this->app_id,
255 | 'app_key: '. $this->app_key)
256 | );
257 |
258 | $response = curl_exec($ch);
259 |
260 | curl_close($ch);
261 |
262 | }
263 | catch(Exception $ex)
264 | {
265 | return 'there was a problem';
266 | }
267 |
268 | return $response;
269 |
270 | }
271 |
272 |
273 | public function recognize($args = array())
274 | {
275 |
276 | if($this->authenticationProvided() == false)
277 | {
278 | return 'set your app_id and app_key before calling this method';
279 | }
280 |
281 | $request_params = array(
282 | "image" => $args["image"],
283 | "gallery_name" => $args["gallery_name"]
284 | );
285 |
286 | // build request string
287 | $request = json_encode($request_params);
288 |
289 | try
290 | {
291 |
292 | $ch = curl_init();
293 |
294 | curl_setopt($ch, CURLOPT_URL, $this->hostname . "recognize" );
295 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
296 | curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
297 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
298 | curl_setopt($ch, CURLOPT_HTTPHEADER,
299 | array(
300 | 'Content-Type: application/json',
301 | 'Content-Length: ' . strlen($request),
302 | 'app_id: ' . $this->app_id,
303 | 'app_key: '. $this->app_key)
304 | );
305 |
306 | $response = curl_exec($ch);
307 |
308 | curl_close($ch);
309 |
310 | }
311 | catch(Exception $ex)
312 | {
313 | return 'there was a problem';
314 | }
315 |
316 | return $response;
317 | }
318 |
319 | public function detect($args = array())
320 | {
321 |
322 | if($this->authenticationProvided() == false)
323 | {
324 | return 'set your app_id and app_key before calling this method';
325 | }
326 |
327 | $request_params = array(
328 | "image" => $args["image"]
329 | );
330 |
331 | // build request string
332 | $request = json_encode($request_params);
333 |
334 | try
335 | {
336 |
337 | $ch = curl_init();
338 |
339 | curl_setopt($ch, CURLOPT_URL, $this->hostname . "detect" );
340 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
341 | curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
342 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
343 | curl_setopt($ch, CURLOPT_HTTPHEADER,
344 | array(
345 | 'Content-Type: application/json',
346 | 'Content-Length: ' . strlen($request),
347 | 'app_id: ' . $this->app_id,
348 | 'app_key: '. $this->app_key)
349 | );
350 |
351 | $response = curl_exec($ch);
352 |
353 | curl_close($ch);
354 |
355 | }
356 | catch(Exception $ex)
357 | {
358 | return 'there was a problem';
359 | }
360 |
361 | return $response;
362 |
363 | }
364 |
365 | public function verify($args = array())
366 | {
367 |
368 | if($this->authenticationProvided() == false)
369 | {
370 | return 'set your app_id and app_key before calling this method';
371 | }
372 |
373 | $request_params = array(
374 | "image" => $args["image"],
375 | "subject_id" => $args["subject_id"],
376 | "gallery_name" => $args["gallery_name"]
377 | );
378 |
379 | // build request string
380 | $request = json_encode($request_params);
381 |
382 | try
383 | {
384 |
385 | $ch = curl_init();
386 |
387 | curl_setopt($ch, CURLOPT_URL, $this->hostname . "verify" );
388 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
389 | curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
390 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
391 | curl_setopt($ch, CURLOPT_HTTPHEADER,
392 | array(
393 | 'Content-Type: application/json',
394 | 'Content-Length: ' . strlen($request),
395 | 'app_id: ' . $this->app_id,
396 | 'app_key: '. $this->app_key)
397 | );
398 |
399 | $response = curl_exec($ch);
400 |
401 | curl_close($ch);
402 |
403 | }
404 | catch(Exception $ex)
405 | {
406 | return 'there was a problem';
407 | }
408 |
409 | return $response;
410 |
411 | }
412 |
413 |
414 |
415 |
416 |
417 | }
418 |
419 | ?>
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Kairos AR, Inc.
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 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Kairos SDK (PHP)
2 | ==============
3 |
4 | Kairos is the easist way add **Face-Recognition** to your web applications. Our API provides a full-featured and robust Face-Recognition backend, right out of the box. This is the PHP wrapper for the [Kairos Face Recognition API](https://www.kairos.com). The package includes a **class** _(Kairos.php)_ you can use as an easy client to the API. Continue reading to learn how to integrate Kairos into your web application.
5 |
6 | _Thanks to contributions by some of our customers, we also have [Ruby](https://github.com/kany/kairos-api) and [.NET](https://github.com/humbywan/Kairos.Net) wrappers available. Also see our [Javascript SDK](https://github.com/kairosinc/Kairos-SDK-Javascript), our [Android SDK](https://github.com/kairosinc/Kairos-SDK-Android) and our [iOS SDK](https://github.com/kairosinc/Kairos-SDK-iOS)._
7 |
8 | ## What You'll Need
9 | * An environment configured to run PHP scripts.
10 |
11 | ---
12 |
13 |
14 | ## How to Do a Quick Demo
15 |
16 | If you just want to do a quick test run, follow these steps:
17 |
18 | 1. [Create your free developer account](https://www.kairos.com/signup)
19 | 2. Log into the Kairos Developer Dashboard
20 | 3. Create an application and copy your **App Id** & **App Key**
21 | 3. Run `methods_test.php` in your browser.
22 | 4. Enter your app_id and app_key, and run the Kairos methods.
23 |
24 |
25 | ---
26 |
27 |
28 | ## How to Install Kairos in Your Own Web App
29 |
30 | 1. [Create your free Kairos developer account](https://www.kairos.com/signup) if you don't already have one.
31 | 2. Log into the [dashboard](https://www.kairos.com/login) and create a new app.
32 | 3. Copy your **App ID** & **App Key** (you'll need them later).
33 | 4. [Download](https://github.com/kairosinc/Kairos-SDK-PHP) the SDK and unzip the package.
34 | 5. Open the folder named **Kairos-SDK-PHP** containing the Kairos.php class.
35 | 6. Place the wrapper class _(Kairos.php)_ somewhere within your application.
36 | 7. Include Kairos.php where needed in your web application project.
37 |
38 |
39 | ```
40 | include("Kairos.php");
41 | ```
42 | ## View Your Galleries
43 |
44 | This method returns a list of all galleries you've created:
45 |
46 | ```
47 | $response = $Kairos->viewGalleries();
48 | ```
49 | ## View Your Subjects
50 |
51 | This method returns a list of all subjects for a given gallery:
52 |
53 | ```
54 | $gallery_name = 'friends1';
55 | $argumentArray = array(
56 | "gallery_name" => $gallery_name
57 | );
58 | $response = $Kairos->viewSubjectsInGallery($argumentArray);
59 | ```
60 |
61 | ## Remove a Subject
62 |
63 | This method removes a subject from given gallery:
64 |
65 | ```
66 | $subject_id = 'dave';
67 | $gallery_name = 'friends1';
68 | $argumentArray = array(
69 | "subject_id" => $subject_id,
70 | "gallery_name" => $gallery_name
71 | );
72 | $response = $Kairos->removeSubjectFromGallery($argumentArray);
73 | ```
74 |
75 | ## Remove a Gallery
76 |
77 | This method removes a given gallery:
78 |
79 | ```
80 | $gallery_name = 'friends1';
81 | $argumentArray = array(
82 | "gallery_name" => $gallery_name
83 | );
84 | $response = $Kairos->removeGallery($argumentArray);
85 | ```
86 | ## Enroll an Image
87 |
88 | The **Enroll** method **registers a face for later recognitions**. Here's an example of enrolling a face (subject) using a method that accepts an absolute path to an image file in your file system **or** base64 image data, and enrolls it as a new subject into your specified gallery:
89 |
90 | ```
91 | $image = '/images/myphotos/myphoto123.png';
92 | (or)
93 | $image = 'iVBORw0KGgoAAA ... ABJRU5ErkJggg==\r\n';
94 | $subject_id = 'elizabeth';
95 | $gallery_name = 'friends1';
96 | $argumentArray = array(
97 | "image" => $image,
98 | "subject_id" => $subject_id,
99 | "gallery_name" => $gallery_name
100 | );
101 | $response = $Kairos->enroll($argumentArray);
102 | ```
103 | `The SDK also includes a file upload field, which converts a local image file to base64 data.`
104 |
105 | ## Recognize an Image
106 |
107 | The **Recognize** method takes an image of a subject and **attempts to match it against a given gallery of previously-enrolled subjects**. Here's an example of recognizing a subject using a method that accepts an absolute path to an image file in your file system **or** base64 image data, sends it to the API, and returns a match and confidence value:
108 |
109 | ```
110 | $image = '/images/myphotos/myphoto123.png';
111 | (or)
112 | $image = 'iVBORw0KGgoAAA ... ABJRU5ErkJggg==\r\n';
113 | $gallery_name = 'friends1';
114 | $argumentArray = array(
115 | "image" => $image,
116 | "gallery_name" => $gallery_name
117 | );
118 | $response = $Kairos->recognize($argumentArray);
119 | ```
120 |
121 | `The SDK also includes a file upload field, which converts a local image file to base64 data.`
122 |
123 | ## Detect Image Attributes
124 |
125 | The **Detect** method takes an image of a subject and **returns various attributes pertaining to the face features**. Here's an example of the detect method which accepts a path to an image file on your system **or** base64 image data, sends it to the API, and returns face attributes:
126 |
127 | ```
128 | $image = '/images/myphotos/myphoto123.png';
129 | (or)
130 | $image = 'iVBORw0KGgoAAA ... ABJRU5ErkJggg==\r\n';
131 | $argumentArray = array(
132 | "image" => $image
133 | );
134 | $response = $Kairos->detect($argumentArray);
135 | ```
136 |
137 | `The SDK also includes a file upload field, which converts a local image file to base64 data.`
138 |
139 | ## Verify image
140 |
141 | The **Verify** method takes an image and verifies that it matches an existing subject in a gallery. Here's an example of using verify via method that accepts a path to an image file, sends it to the API, and returns face attributes:
142 |
143 | ```
144 | $image = '/images/myphotos/myphoto123.png';
145 | (or)
146 | $image = 'iVBORw0KGgoAAA ... ABJRU5ErkJggg==\r\n';
147 | $subject_id = 'elizabeth';
148 | $gallery_name = 'friends1';
149 | $argumentArray = array(
150 | "image" => $image,
151 | "subject_id" => $subject_id,
152 | "gallery_name" => $gallery_name
153 | );
154 | $response = $Kairos->verify($argumentArray);
155 | ```
156 | `The SDK also includes a file upload field, which converts a local image file to base64 data.`
157 |
158 | ##Support
159 | Have an issue? Visit our [Support page](http://www.kairos.com/support) or [create an issue on GitHub](https://github.com/kairosinc/Kairos-SDK-PHP)
160 |
161 | Test on [RapidAPI](https://rapidapi.com/package/KairosAPI/functions?utm_source=KairosGitHub&utm_medium=button)
162 |
--------------------------------------------------------------------------------
/examples/assets/css/styles.css:
--------------------------------------------------------------------------------
1 | /*
2 | styles for methods_test.php
3 | created:; November 2016
4 | author: Steve Rucker
5 | */
6 |
7 | #view_data {
8 | padding: 10px 0;
9 | color: #ff0000;
10 | word-wrap: break-word;
11 | }
12 | .method-test {
13 | margin-left: 30px;
14 | }
15 | .glyphicon {
16 | float: left;
17 | margin-top: 2px;
18 | margin-right: 10px;
19 | }
20 | form {
21 | margin-left: 30px;
22 | }
23 | #loader {
24 | display: none;
25 | width: 250px;
26 | float: left;
27 | }
--------------------------------------------------------------------------------
/examples/assets/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kairosinc/Kairos-SDK-PHP/3c5baf3c825f6357549ace6f8cf754199c51f5c2/examples/assets/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/examples/assets/fonts/glyphicons-halflings-regular.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/examples/assets/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kairosinc/Kairos-SDK-PHP/3c5baf3c825f6357549ace6f8cf754199c51f5c2/examples/assets/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/examples/assets/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kairosinc/Kairos-SDK-PHP/3c5baf3c825f6357549ace6f8cf754199c51f5c2/examples/assets/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/examples/assets/images/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kairosinc/Kairos-SDK-PHP/3c5baf3c825f6357549ace6f8cf754199c51f5c2/examples/assets/images/loading.gif
--------------------------------------------------------------------------------
/examples/assets/images/sample.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kairosinc/Kairos-SDK-PHP/3c5baf3c825f6357549ace6f8cf754199c51f5c2/examples/assets/images/sample.jpg
--------------------------------------------------------------------------------
/examples/assets/js/bootstrap.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.3.1 (http://getbootstrap.com)
3 | * Copyright 2011-2014 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 |
7 | if (typeof jQuery === 'undefined') {
8 | throw new Error('Bootstrap\'s JavaScript requires jQuery')
9 | }
10 |
11 | +function ($) {
12 | var version = $.fn.jquery.split(' ')[0].split('.')
13 | if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
14 | throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
15 | }
16 | }(jQuery);
17 |
18 | /* ========================================================================
19 | * Bootstrap: transition.js v3.3.1
20 | * http://getbootstrap.com/javascript/#transitions
21 | * ========================================================================
22 | * Copyright 2011-2014 Twitter, Inc.
23 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
24 | * ======================================================================== */
25 |
26 |
27 | +function ($) {
28 | 'use strict';
29 |
30 | // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
31 | // ============================================================
32 |
33 | function transitionEnd() {
34 | var el = document.createElement('bootstrap')
35 |
36 | var transEndEventNames = {
37 | WebkitTransition : 'webkitTransitionEnd',
38 | MozTransition : 'transitionend',
39 | OTransition : 'oTransitionEnd otransitionend',
40 | transition : 'transitionend'
41 | }
42 |
43 | for (var name in transEndEventNames) {
44 | if (el.style[name] !== undefined) {
45 | return { end: transEndEventNames[name] }
46 | }
47 | }
48 |
49 | return false // explicit for ie8 ( ._.)
50 | }
51 |
52 | // http://blog.alexmaccaw.com/css-transitions
53 | $.fn.emulateTransitionEnd = function (duration) {
54 | var called = false
55 | var $el = this
56 | $(this).one('bsTransitionEnd', function () { called = true })
57 | var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
58 | setTimeout(callback, duration)
59 | return this
60 | }
61 |
62 | $(function () {
63 | $.support.transition = transitionEnd()
64 |
65 | if (!$.support.transition) return
66 |
67 | $.event.special.bsTransitionEnd = {
68 | bindType: $.support.transition.end,
69 | delegateType: $.support.transition.end,
70 | handle: function (e) {
71 | if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
72 | }
73 | }
74 | })
75 |
76 | }(jQuery);
77 |
78 | /* ========================================================================
79 | * Bootstrap: alert.js v3.3.1
80 | * http://getbootstrap.com/javascript/#alerts
81 | * ========================================================================
82 | * Copyright 2011-2014 Twitter, Inc.
83 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
84 | * ======================================================================== */
85 |
86 |
87 | +function ($) {
88 | 'use strict';
89 |
90 | // ALERT CLASS DEFINITION
91 | // ======================
92 |
93 | var dismiss = '[data-dismiss="alert"]'
94 | var Alert = function (el) {
95 | $(el).on('click', dismiss, this.close)
96 | }
97 |
98 | Alert.VERSION = '3.3.1'
99 |
100 | Alert.TRANSITION_DURATION = 150
101 |
102 | Alert.prototype.close = function (e) {
103 | var $this = $(this)
104 | var selector = $this.attr('data-target')
105 |
106 | if (!selector) {
107 | selector = $this.attr('href')
108 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
109 | }
110 |
111 | var $parent = $(selector)
112 |
113 | if (e) e.preventDefault()
114 |
115 | if (!$parent.length) {
116 | $parent = $this.closest('.alert')
117 | }
118 |
119 | $parent.trigger(e = $.Event('close.bs.alert'))
120 |
121 | if (e.isDefaultPrevented()) return
122 |
123 | $parent.removeClass('in')
124 |
125 | function removeElement() {
126 | // detach from parent, fire event then clean up data
127 | $parent.detach().trigger('closed.bs.alert').remove()
128 | }
129 |
130 | $.support.transition && $parent.hasClass('fade') ?
131 | $parent
132 | .one('bsTransitionEnd', removeElement)
133 | .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
134 | removeElement()
135 | }
136 |
137 |
138 | // ALERT PLUGIN DEFINITION
139 | // =======================
140 |
141 | function Plugin(option) {
142 | return this.each(function () {
143 | var $this = $(this)
144 | var data = $this.data('bs.alert')
145 |
146 | if (!data) $this.data('bs.alert', (data = new Alert(this)))
147 | if (typeof option == 'string') data[option].call($this)
148 | })
149 | }
150 |
151 | var old = $.fn.alert
152 |
153 | $.fn.alert = Plugin
154 | $.fn.alert.Constructor = Alert
155 |
156 |
157 | // ALERT NO CONFLICT
158 | // =================
159 |
160 | $.fn.alert.noConflict = function () {
161 | $.fn.alert = old
162 | return this
163 | }
164 |
165 |
166 | // ALERT DATA-API
167 | // ==============
168 |
169 | $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
170 |
171 | }(jQuery);
172 |
173 | /* ========================================================================
174 | * Bootstrap: button.js v3.3.1
175 | * http://getbootstrap.com/javascript/#buttons
176 | * ========================================================================
177 | * Copyright 2011-2014 Twitter, Inc.
178 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
179 | * ======================================================================== */
180 |
181 |
182 | +function ($) {
183 | 'use strict';
184 |
185 | // BUTTON PUBLIC CLASS DEFINITION
186 | // ==============================
187 |
188 | var Button = function (element, options) {
189 | this.$element = $(element)
190 | this.options = $.extend({}, Button.DEFAULTS, options)
191 | this.isLoading = false
192 | }
193 |
194 | Button.VERSION = '3.3.1'
195 |
196 | Button.DEFAULTS = {
197 | loadingText: 'loading...'
198 | }
199 |
200 | Button.prototype.setState = function (state) {
201 | var d = 'disabled'
202 | var $el = this.$element
203 | var val = $el.is('input') ? 'val' : 'html'
204 | var data = $el.data()
205 |
206 | state = state + 'Text'
207 |
208 | if (data.resetText == null) $el.data('resetText', $el[val]())
209 |
210 | // push to event loop to allow forms to submit
211 | setTimeout($.proxy(function () {
212 | $el[val](data[state] == null ? this.options[state] : data[state])
213 |
214 | if (state == 'loadingText') {
215 | this.isLoading = true
216 | $el.addClass(d).attr(d, d)
217 | } else if (this.isLoading) {
218 | this.isLoading = false
219 | $el.removeClass(d).removeAttr(d)
220 | }
221 | }, this), 0)
222 | }
223 |
224 | Button.prototype.toggle = function () {
225 | var changed = true
226 | var $parent = this.$element.closest('[data-toggle="buttons"]')
227 |
228 | if ($parent.length) {
229 | var $input = this.$element.find('input')
230 | if ($input.prop('type') == 'radio') {
231 | if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
232 | else $parent.find('.active').removeClass('active')
233 | }
234 | if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
235 | } else {
236 | this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
237 | }
238 |
239 | if (changed) this.$element.toggleClass('active')
240 | }
241 |
242 |
243 | // BUTTON PLUGIN DEFINITION
244 | // ========================
245 |
246 | function Plugin(option) {
247 | return this.each(function () {
248 | var $this = $(this)
249 | var data = $this.data('bs.button')
250 | var options = typeof option == 'object' && option
251 |
252 | if (!data) $this.data('bs.button', (data = new Button(this, options)))
253 |
254 | if (option == 'toggle') data.toggle()
255 | else if (option) data.setState(option)
256 | })
257 | }
258 |
259 | var old = $.fn.button
260 |
261 | $.fn.button = Plugin
262 | $.fn.button.Constructor = Button
263 |
264 |
265 | // BUTTON NO CONFLICT
266 | // ==================
267 |
268 | $.fn.button.noConflict = function () {
269 | $.fn.button = old
270 | return this
271 | }
272 |
273 |
274 | // BUTTON DATA-API
275 | // ===============
276 |
277 | $(document)
278 | .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
279 | var $btn = $(e.target)
280 | if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
281 | Plugin.call($btn, 'toggle')
282 | e.preventDefault()
283 | })
284 | .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
285 | $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
286 | })
287 |
288 | }(jQuery);
289 |
290 | /* ========================================================================
291 | * Bootstrap: carousel.js v3.3.1
292 | * http://getbootstrap.com/javascript/#carousel
293 | * ========================================================================
294 | * Copyright 2011-2014 Twitter, Inc.
295 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
296 | * ======================================================================== */
297 |
298 |
299 | +function ($) {
300 | 'use strict';
301 |
302 | // CAROUSEL CLASS DEFINITION
303 | // =========================
304 |
305 | var Carousel = function (element, options) {
306 | this.$element = $(element)
307 | this.$indicators = this.$element.find('.carousel-indicators')
308 | this.options = options
309 | this.paused =
310 | this.sliding =
311 | this.interval =
312 | this.$active =
313 | this.$items = null
314 |
315 | this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
316 |
317 | this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
318 | .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
319 | .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
320 | }
321 |
322 | Carousel.VERSION = '3.3.1'
323 |
324 | Carousel.TRANSITION_DURATION = 600
325 |
326 | Carousel.DEFAULTS = {
327 | interval: 5000,
328 | pause: 'hover',
329 | wrap: true,
330 | keyboard: true
331 | }
332 |
333 | Carousel.prototype.keydown = function (e) {
334 | if (/input|textarea/i.test(e.target.tagName)) return
335 | switch (e.which) {
336 | case 37: this.prev(); break
337 | case 39: this.next(); break
338 | default: return
339 | }
340 |
341 | e.preventDefault()
342 | }
343 |
344 | Carousel.prototype.cycle = function (e) {
345 | e || (this.paused = false)
346 |
347 | this.interval && clearInterval(this.interval)
348 |
349 | this.options.interval
350 | && !this.paused
351 | && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
352 |
353 | return this
354 | }
355 |
356 | Carousel.prototype.getItemIndex = function (item) {
357 | this.$items = item.parent().children('.item')
358 | return this.$items.index(item || this.$active)
359 | }
360 |
361 | Carousel.prototype.getItemForDirection = function (direction, active) {
362 | var delta = direction == 'prev' ? -1 : 1
363 | var activeIndex = this.getItemIndex(active)
364 | var itemIndex = (activeIndex + delta) % this.$items.length
365 | return this.$items.eq(itemIndex)
366 | }
367 |
368 | Carousel.prototype.to = function (pos) {
369 | var that = this
370 | var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
371 |
372 | if (pos > (this.$items.length - 1) || pos < 0) return
373 |
374 | if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
375 | if (activeIndex == pos) return this.pause().cycle()
376 |
377 | return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
378 | }
379 |
380 | Carousel.prototype.pause = function (e) {
381 | e || (this.paused = true)
382 |
383 | if (this.$element.find('.next, .prev').length && $.support.transition) {
384 | this.$element.trigger($.support.transition.end)
385 | this.cycle(true)
386 | }
387 |
388 | this.interval = clearInterval(this.interval)
389 |
390 | return this
391 | }
392 |
393 | Carousel.prototype.next = function () {
394 | if (this.sliding) return
395 | return this.slide('next')
396 | }
397 |
398 | Carousel.prototype.prev = function () {
399 | if (this.sliding) return
400 | return this.slide('prev')
401 | }
402 |
403 | Carousel.prototype.slide = function (type, next) {
404 | var $active = this.$element.find('.item.active')
405 | var $next = next || this.getItemForDirection(type, $active)
406 | var isCycling = this.interval
407 | var direction = type == 'next' ? 'left' : 'right'
408 | var fallback = type == 'next' ? 'first' : 'last'
409 | var that = this
410 |
411 | if (!$next.length) {
412 | if (!this.options.wrap) return
413 | $next = this.$element.find('.item')[fallback]()
414 | }
415 |
416 | if ($next.hasClass('active')) return (this.sliding = false)
417 |
418 | var relatedTarget = $next[0]
419 | var slideEvent = $.Event('slide.bs.carousel', {
420 | relatedTarget: relatedTarget,
421 | direction: direction
422 | })
423 | this.$element.trigger(slideEvent)
424 | if (slideEvent.isDefaultPrevented()) return
425 |
426 | this.sliding = true
427 |
428 | isCycling && this.pause()
429 |
430 | if (this.$indicators.length) {
431 | this.$indicators.find('.active').removeClass('active')
432 | var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
433 | $nextIndicator && $nextIndicator.addClass('active')
434 | }
435 |
436 | var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
437 | if ($.support.transition && this.$element.hasClass('slide')) {
438 | $next.addClass(type)
439 | $next[0].offsetWidth // force reflow
440 | $active.addClass(direction)
441 | $next.addClass(direction)
442 | $active
443 | .one('bsTransitionEnd', function () {
444 | $next.removeClass([type, direction].join(' ')).addClass('active')
445 | $active.removeClass(['active', direction].join(' '))
446 | that.sliding = false
447 | setTimeout(function () {
448 | that.$element.trigger(slidEvent)
449 | }, 0)
450 | })
451 | .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
452 | } else {
453 | $active.removeClass('active')
454 | $next.addClass('active')
455 | this.sliding = false
456 | this.$element.trigger(slidEvent)
457 | }
458 |
459 | isCycling && this.cycle()
460 |
461 | return this
462 | }
463 |
464 |
465 | // CAROUSEL PLUGIN DEFINITION
466 | // ==========================
467 |
468 | function Plugin(option) {
469 | return this.each(function () {
470 | var $this = $(this)
471 | var data = $this.data('bs.carousel')
472 | var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
473 | var action = typeof option == 'string' ? option : options.slide
474 |
475 | if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
476 | if (typeof option == 'number') data.to(option)
477 | else if (action) data[action]()
478 | else if (options.interval) data.pause().cycle()
479 | })
480 | }
481 |
482 | var old = $.fn.carousel
483 |
484 | $.fn.carousel = Plugin
485 | $.fn.carousel.Constructor = Carousel
486 |
487 |
488 | // CAROUSEL NO CONFLICT
489 | // ====================
490 |
491 | $.fn.carousel.noConflict = function () {
492 | $.fn.carousel = old
493 | return this
494 | }
495 |
496 |
497 | // CAROUSEL DATA-API
498 | // =================
499 |
500 | var clickHandler = function (e) {
501 | var href
502 | var $this = $(this)
503 | var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
504 | if (!$target.hasClass('carousel')) return
505 | var options = $.extend({}, $target.data(), $this.data())
506 | var slideIndex = $this.attr('data-slide-to')
507 | if (slideIndex) options.interval = false
508 |
509 | Plugin.call($target, options)
510 |
511 | if (slideIndex) {
512 | $target.data('bs.carousel').to(slideIndex)
513 | }
514 |
515 | e.preventDefault()
516 | }
517 |
518 | $(document)
519 | .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
520 | .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
521 |
522 | $(window).on('load', function () {
523 | $('[data-ride="carousel"]').each(function () {
524 | var $carousel = $(this)
525 | Plugin.call($carousel, $carousel.data())
526 | })
527 | })
528 |
529 | }(jQuery);
530 |
531 | /* ========================================================================
532 | * Bootstrap: collapse.js v3.3.1
533 | * http://getbootstrap.com/javascript/#collapse
534 | * ========================================================================
535 | * Copyright 2011-2014 Twitter, Inc.
536 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
537 | * ======================================================================== */
538 |
539 |
540 | +function ($) {
541 | 'use strict';
542 |
543 | // COLLAPSE PUBLIC CLASS DEFINITION
544 | // ================================
545 |
546 | var Collapse = function (element, options) {
547 | this.$element = $(element)
548 | this.options = $.extend({}, Collapse.DEFAULTS, options)
549 | this.$trigger = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]')
550 | this.transitioning = null
551 |
552 | if (this.options.parent) {
553 | this.$parent = this.getParent()
554 | } else {
555 | this.addAriaAndCollapsedClass(this.$element, this.$trigger)
556 | }
557 |
558 | if (this.options.toggle) this.toggle()
559 | }
560 |
561 | Collapse.VERSION = '3.3.1'
562 |
563 | Collapse.TRANSITION_DURATION = 350
564 |
565 | Collapse.DEFAULTS = {
566 | toggle: true,
567 | trigger: '[data-toggle="collapse"]'
568 | }
569 |
570 | Collapse.prototype.dimension = function () {
571 | var hasWidth = this.$element.hasClass('width')
572 | return hasWidth ? 'width' : 'height'
573 | }
574 |
575 | Collapse.prototype.show = function () {
576 | if (this.transitioning || this.$element.hasClass('in')) return
577 |
578 | var activesData
579 | var actives = this.$parent && this.$parent.find('> .panel').children('.in, .collapsing')
580 |
581 | if (actives && actives.length) {
582 | activesData = actives.data('bs.collapse')
583 | if (activesData && activesData.transitioning) return
584 | }
585 |
586 | var startEvent = $.Event('show.bs.collapse')
587 | this.$element.trigger(startEvent)
588 | if (startEvent.isDefaultPrevented()) return
589 |
590 | if (actives && actives.length) {
591 | Plugin.call(actives, 'hide')
592 | activesData || actives.data('bs.collapse', null)
593 | }
594 |
595 | var dimension = this.dimension()
596 |
597 | this.$element
598 | .removeClass('collapse')
599 | .addClass('collapsing')[dimension](0)
600 | .attr('aria-expanded', true)
601 |
602 | this.$trigger
603 | .removeClass('collapsed')
604 | .attr('aria-expanded', true)
605 |
606 | this.transitioning = 1
607 |
608 | var complete = function () {
609 | this.$element
610 | .removeClass('collapsing')
611 | .addClass('collapse in')[dimension]('')
612 | this.transitioning = 0
613 | this.$element
614 | .trigger('shown.bs.collapse')
615 | }
616 |
617 | if (!$.support.transition) return complete.call(this)
618 |
619 | var scrollSize = $.camelCase(['scroll', dimension].join('-'))
620 |
621 | this.$element
622 | .one('bsTransitionEnd', $.proxy(complete, this))
623 | .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
624 | }
625 |
626 | Collapse.prototype.hide = function () {
627 | if (this.transitioning || !this.$element.hasClass('in')) return
628 |
629 | var startEvent = $.Event('hide.bs.collapse')
630 | this.$element.trigger(startEvent)
631 | if (startEvent.isDefaultPrevented()) return
632 |
633 | var dimension = this.dimension()
634 |
635 | this.$element[dimension](this.$element[dimension]())[0].offsetHeight
636 |
637 | this.$element
638 | .addClass('collapsing')
639 | .removeClass('collapse in')
640 | .attr('aria-expanded', false)
641 |
642 | this.$trigger
643 | .addClass('collapsed')
644 | .attr('aria-expanded', false)
645 |
646 | this.transitioning = 1
647 |
648 | var complete = function () {
649 | this.transitioning = 0
650 | this.$element
651 | .removeClass('collapsing')
652 | .addClass('collapse')
653 | .trigger('hidden.bs.collapse')
654 | }
655 |
656 | if (!$.support.transition) return complete.call(this)
657 |
658 | this.$element
659 | [dimension](0)
660 | .one('bsTransitionEnd', $.proxy(complete, this))
661 | .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
662 | }
663 |
664 | Collapse.prototype.toggle = function () {
665 | this[this.$element.hasClass('in') ? 'hide' : 'show']()
666 | }
667 |
668 | Collapse.prototype.getParent = function () {
669 | return $(this.options.parent)
670 | .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
671 | .each($.proxy(function (i, element) {
672 | var $element = $(element)
673 | this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
674 | }, this))
675 | .end()
676 | }
677 |
678 | Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
679 | var isOpen = $element.hasClass('in')
680 |
681 | $element.attr('aria-expanded', isOpen)
682 | $trigger
683 | .toggleClass('collapsed', !isOpen)
684 | .attr('aria-expanded', isOpen)
685 | }
686 |
687 | function getTargetFromTrigger($trigger) {
688 | var href
689 | var target = $trigger.attr('data-target')
690 | || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
691 |
692 | return $(target)
693 | }
694 |
695 |
696 | // COLLAPSE PLUGIN DEFINITION
697 | // ==========================
698 |
699 | function Plugin(option) {
700 | return this.each(function () {
701 | var $this = $(this)
702 | var data = $this.data('bs.collapse')
703 | var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
704 |
705 | if (!data && options.toggle && option == 'show') options.toggle = false
706 | if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
707 | if (typeof option == 'string') data[option]()
708 | })
709 | }
710 |
711 | var old = $.fn.collapse
712 |
713 | $.fn.collapse = Plugin
714 | $.fn.collapse.Constructor = Collapse
715 |
716 |
717 | // COLLAPSE NO CONFLICT
718 | // ====================
719 |
720 | $.fn.collapse.noConflict = function () {
721 | $.fn.collapse = old
722 | return this
723 | }
724 |
725 |
726 | // COLLAPSE DATA-API
727 | // =================
728 |
729 | $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
730 | var $this = $(this)
731 |
732 | if (!$this.attr('data-target')) e.preventDefault()
733 |
734 | var $target = getTargetFromTrigger($this)
735 | var data = $target.data('bs.collapse')
736 | var option = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this })
737 |
738 | Plugin.call($target, option)
739 | })
740 |
741 | }(jQuery);
742 |
743 | /* ========================================================================
744 | * Bootstrap: dropdown.js v3.3.1
745 | * http://getbootstrap.com/javascript/#dropdowns
746 | * ========================================================================
747 | * Copyright 2011-2014 Twitter, Inc.
748 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
749 | * ======================================================================== */
750 |
751 |
752 | +function ($) {
753 | 'use strict';
754 |
755 | // DROPDOWN CLASS DEFINITION
756 | // =========================
757 |
758 | var backdrop = '.dropdown-backdrop'
759 | var toggle = '[data-toggle="dropdown"]'
760 | var Dropdown = function (element) {
761 | $(element).on('click.bs.dropdown', this.toggle)
762 | }
763 |
764 | Dropdown.VERSION = '3.3.1'
765 |
766 | Dropdown.prototype.toggle = function (e) {
767 | var $this = $(this)
768 |
769 | if ($this.is('.disabled, :disabled')) return
770 |
771 | var $parent = getParent($this)
772 | var isActive = $parent.hasClass('open')
773 |
774 | clearMenus()
775 |
776 | if (!isActive) {
777 | if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
778 | // if mobile we use a backdrop because click events don't delegate
779 | $('
').insertAfter($(this)).on('click', clearMenus)
780 | }
781 |
782 | var relatedTarget = { relatedTarget: this }
783 | $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
784 |
785 | if (e.isDefaultPrevented()) return
786 |
787 | $this
788 | .trigger('focus')
789 | .attr('aria-expanded', 'true')
790 |
791 | $parent
792 | .toggleClass('open')
793 | .trigger('shown.bs.dropdown', relatedTarget)
794 | }
795 |
796 | return false
797 | }
798 |
799 | Dropdown.prototype.keydown = function (e) {
800 | if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
801 |
802 | var $this = $(this)
803 |
804 | e.preventDefault()
805 | e.stopPropagation()
806 |
807 | if ($this.is('.disabled, :disabled')) return
808 |
809 | var $parent = getParent($this)
810 | var isActive = $parent.hasClass('open')
811 |
812 | if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
813 | if (e.which == 27) $parent.find(toggle).trigger('focus')
814 | return $this.trigger('click')
815 | }
816 |
817 | var desc = ' li:not(.divider):visible a'
818 | var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
819 |
820 | if (!$items.length) return
821 |
822 | var index = $items.index(e.target)
823 |
824 | if (e.which == 38 && index > 0) index-- // up
825 | if (e.which == 40 && index < $items.length - 1) index++ // down
826 | if (!~index) index = 0
827 |
828 | $items.eq(index).trigger('focus')
829 | }
830 |
831 | function clearMenus(e) {
832 | if (e && e.which === 3) return
833 | $(backdrop).remove()
834 | $(toggle).each(function () {
835 | var $this = $(this)
836 | var $parent = getParent($this)
837 | var relatedTarget = { relatedTarget: this }
838 |
839 | if (!$parent.hasClass('open')) return
840 |
841 | $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
842 |
843 | if (e.isDefaultPrevented()) return
844 |
845 | $this.attr('aria-expanded', 'false')
846 | $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
847 | })
848 | }
849 |
850 | function getParent($this) {
851 | var selector = $this.attr('data-target')
852 |
853 | if (!selector) {
854 | selector = $this.attr('href')
855 | selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
856 | }
857 |
858 | var $parent = selector && $(selector)
859 |
860 | return $parent && $parent.length ? $parent : $this.parent()
861 | }
862 |
863 |
864 | // DROPDOWN PLUGIN DEFINITION
865 | // ==========================
866 |
867 | function Plugin(option) {
868 | return this.each(function () {
869 | var $this = $(this)
870 | var data = $this.data('bs.dropdown')
871 |
872 | if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
873 | if (typeof option == 'string') data[option].call($this)
874 | })
875 | }
876 |
877 | var old = $.fn.dropdown
878 |
879 | $.fn.dropdown = Plugin
880 | $.fn.dropdown.Constructor = Dropdown
881 |
882 |
883 | // DROPDOWN NO CONFLICT
884 | // ====================
885 |
886 | $.fn.dropdown.noConflict = function () {
887 | $.fn.dropdown = old
888 | return this
889 | }
890 |
891 |
892 | // APPLY TO STANDARD DROPDOWN ELEMENTS
893 | // ===================================
894 |
895 | $(document)
896 | .on('click.bs.dropdown.data-api', clearMenus)
897 | .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
898 | .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
899 | .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
900 | .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
901 | .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
902 |
903 | }(jQuery);
904 |
905 | /* ========================================================================
906 | * Bootstrap: modal.js v3.3.1
907 | * http://getbootstrap.com/javascript/#modals
908 | * ========================================================================
909 | * Copyright 2011-2014 Twitter, Inc.
910 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
911 | * ======================================================================== */
912 |
913 |
914 | +function ($) {
915 | 'use strict';
916 |
917 | // MODAL CLASS DEFINITION
918 | // ======================
919 |
920 | var Modal = function (element, options) {
921 | this.options = options
922 | this.$body = $(document.body)
923 | this.$element = $(element)
924 | this.$backdrop =
925 | this.isShown = null
926 | this.scrollbarWidth = 0
927 |
928 | if (this.options.remote) {
929 | this.$element
930 | .find('.modal-content')
931 | .load(this.options.remote, $.proxy(function () {
932 | this.$element.trigger('loaded.bs.modal')
933 | }, this))
934 | }
935 | }
936 |
937 | Modal.VERSION = '3.3.1'
938 |
939 | Modal.TRANSITION_DURATION = 300
940 | Modal.BACKDROP_TRANSITION_DURATION = 150
941 |
942 | Modal.DEFAULTS = {
943 | backdrop: true,
944 | keyboard: true,
945 | show: true
946 | }
947 |
948 | Modal.prototype.toggle = function (_relatedTarget) {
949 | return this.isShown ? this.hide() : this.show(_relatedTarget)
950 | }
951 |
952 | Modal.prototype.show = function (_relatedTarget) {
953 | var that = this
954 | var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
955 |
956 | this.$element.trigger(e)
957 |
958 | if (this.isShown || e.isDefaultPrevented()) return
959 |
960 | this.isShown = true
961 |
962 | this.checkScrollbar()
963 | this.setScrollbar()
964 | this.$body.addClass('modal-open')
965 |
966 | this.escape()
967 | this.resize()
968 |
969 | this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
970 |
971 | this.backdrop(function () {
972 | var transition = $.support.transition && that.$element.hasClass('fade')
973 |
974 | if (!that.$element.parent().length) {
975 | that.$element.appendTo(that.$body) // don't move modals dom position
976 | }
977 |
978 | that.$element
979 | .show()
980 | .scrollTop(0)
981 |
982 | if (that.options.backdrop) that.adjustBackdrop()
983 | that.adjustDialog()
984 |
985 | if (transition) {
986 | that.$element[0].offsetWidth // force reflow
987 | }
988 |
989 | that.$element
990 | .addClass('in')
991 | .attr('aria-hidden', false)
992 |
993 | that.enforceFocus()
994 |
995 | var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
996 |
997 | transition ?
998 | that.$element.find('.modal-dialog') // wait for modal to slide in
999 | .one('bsTransitionEnd', function () {
1000 | that.$element.trigger('focus').trigger(e)
1001 | })
1002 | .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
1003 | that.$element.trigger('focus').trigger(e)
1004 | })
1005 | }
1006 |
1007 | Modal.prototype.hide = function (e) {
1008 | if (e) e.preventDefault()
1009 |
1010 | e = $.Event('hide.bs.modal')
1011 |
1012 | this.$element.trigger(e)
1013 |
1014 | if (!this.isShown || e.isDefaultPrevented()) return
1015 |
1016 | this.isShown = false
1017 |
1018 | this.escape()
1019 | this.resize()
1020 |
1021 | $(document).off('focusin.bs.modal')
1022 |
1023 | this.$element
1024 | .removeClass('in')
1025 | .attr('aria-hidden', true)
1026 | .off('click.dismiss.bs.modal')
1027 |
1028 | $.support.transition && this.$element.hasClass('fade') ?
1029 | this.$element
1030 | .one('bsTransitionEnd', $.proxy(this.hideModal, this))
1031 | .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
1032 | this.hideModal()
1033 | }
1034 |
1035 | Modal.prototype.enforceFocus = function () {
1036 | $(document)
1037 | .off('focusin.bs.modal') // guard against infinite focus loop
1038 | .on('focusin.bs.modal', $.proxy(function (e) {
1039 | if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
1040 | this.$element.trigger('focus')
1041 | }
1042 | }, this))
1043 | }
1044 |
1045 | Modal.prototype.escape = function () {
1046 | if (this.isShown && this.options.keyboard) {
1047 | this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
1048 | e.which == 27 && this.hide()
1049 | }, this))
1050 | } else if (!this.isShown) {
1051 | this.$element.off('keydown.dismiss.bs.modal')
1052 | }
1053 | }
1054 |
1055 | Modal.prototype.resize = function () {
1056 | if (this.isShown) {
1057 | $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
1058 | } else {
1059 | $(window).off('resize.bs.modal')
1060 | }
1061 | }
1062 |
1063 | Modal.prototype.hideModal = function () {
1064 | var that = this
1065 | this.$element.hide()
1066 | this.backdrop(function () {
1067 | that.$body.removeClass('modal-open')
1068 | that.resetAdjustments()
1069 | that.resetScrollbar()
1070 | that.$element.trigger('hidden.bs.modal')
1071 | })
1072 | }
1073 |
1074 | Modal.prototype.removeBackdrop = function () {
1075 | this.$backdrop && this.$backdrop.remove()
1076 | this.$backdrop = null
1077 | }
1078 |
1079 | Modal.prototype.backdrop = function (callback) {
1080 | var that = this
1081 | var animate = this.$element.hasClass('fade') ? 'fade' : ''
1082 |
1083 | if (this.isShown && this.options.backdrop) {
1084 | var doAnimate = $.support.transition && animate
1085 |
1086 | this.$backdrop = $('')
1087 | .prependTo(this.$element)
1088 | .on('click.dismiss.bs.modal', $.proxy(function (e) {
1089 | if (e.target !== e.currentTarget) return
1090 | this.options.backdrop == 'static'
1091 | ? this.$element[0].focus.call(this.$element[0])
1092 | : this.hide.call(this)
1093 | }, this))
1094 |
1095 | if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
1096 |
1097 | this.$backdrop.addClass('in')
1098 |
1099 | if (!callback) return
1100 |
1101 | doAnimate ?
1102 | this.$backdrop
1103 | .one('bsTransitionEnd', callback)
1104 | .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1105 | callback()
1106 |
1107 | } else if (!this.isShown && this.$backdrop) {
1108 | this.$backdrop.removeClass('in')
1109 |
1110 | var callbackRemove = function () {
1111 | that.removeBackdrop()
1112 | callback && callback()
1113 | }
1114 | $.support.transition && this.$element.hasClass('fade') ?
1115 | this.$backdrop
1116 | .one('bsTransitionEnd', callbackRemove)
1117 | .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1118 | callbackRemove()
1119 |
1120 | } else if (callback) {
1121 | callback()
1122 | }
1123 | }
1124 |
1125 | // these following methods are used to handle overflowing modals
1126 |
1127 | Modal.prototype.handleUpdate = function () {
1128 | if (this.options.backdrop) this.adjustBackdrop()
1129 | this.adjustDialog()
1130 | }
1131 |
1132 | Modal.prototype.adjustBackdrop = function () {
1133 | this.$backdrop
1134 | .css('height', 0)
1135 | .css('height', this.$element[0].scrollHeight)
1136 | }
1137 |
1138 | Modal.prototype.adjustDialog = function () {
1139 | var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
1140 |
1141 | this.$element.css({
1142 | paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
1143 | paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
1144 | })
1145 | }
1146 |
1147 | Modal.prototype.resetAdjustments = function () {
1148 | this.$element.css({
1149 | paddingLeft: '',
1150 | paddingRight: ''
1151 | })
1152 | }
1153 |
1154 | Modal.prototype.checkScrollbar = function () {
1155 | this.bodyIsOverflowing = document.body.scrollHeight > document.documentElement.clientHeight
1156 | this.scrollbarWidth = this.measureScrollbar()
1157 | }
1158 |
1159 | Modal.prototype.setScrollbar = function () {
1160 | var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
1161 | if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
1162 | }
1163 |
1164 | Modal.prototype.resetScrollbar = function () {
1165 | this.$body.css('padding-right', '')
1166 | }
1167 |
1168 | Modal.prototype.measureScrollbar = function () { // thx walsh
1169 | var scrollDiv = document.createElement('div')
1170 | scrollDiv.className = 'modal-scrollbar-measure'
1171 | this.$body.append(scrollDiv)
1172 | var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
1173 | this.$body[0].removeChild(scrollDiv)
1174 | return scrollbarWidth
1175 | }
1176 |
1177 |
1178 | // MODAL PLUGIN DEFINITION
1179 | // =======================
1180 |
1181 | function Plugin(option, _relatedTarget) {
1182 | return this.each(function () {
1183 | var $this = $(this)
1184 | var data = $this.data('bs.modal')
1185 | var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
1186 |
1187 | if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
1188 | if (typeof option == 'string') data[option](_relatedTarget)
1189 | else if (options.show) data.show(_relatedTarget)
1190 | })
1191 | }
1192 |
1193 | var old = $.fn.modal
1194 |
1195 | $.fn.modal = Plugin
1196 | $.fn.modal.Constructor = Modal
1197 |
1198 |
1199 | // MODAL NO CONFLICT
1200 | // =================
1201 |
1202 | $.fn.modal.noConflict = function () {
1203 | $.fn.modal = old
1204 | return this
1205 | }
1206 |
1207 |
1208 | // MODAL DATA-API
1209 | // ==============
1210 |
1211 | $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
1212 | var $this = $(this)
1213 | var href = $this.attr('href')
1214 | var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
1215 | var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
1216 |
1217 | if ($this.is('a')) e.preventDefault()
1218 |
1219 | $target.one('show.bs.modal', function (showEvent) {
1220 | if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
1221 | $target.one('hidden.bs.modal', function () {
1222 | $this.is(':visible') && $this.trigger('focus')
1223 | })
1224 | })
1225 | Plugin.call($target, option, this)
1226 | })
1227 |
1228 | }(jQuery);
1229 |
1230 | /* ========================================================================
1231 | * Bootstrap: tooltip.js v3.3.1
1232 | * http://getbootstrap.com/javascript/#tooltip
1233 | * Inspired by the original jQuery.tipsy by Jason Frame
1234 | * ========================================================================
1235 | * Copyright 2011-2014 Twitter, Inc.
1236 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1237 | * ======================================================================== */
1238 |
1239 |
1240 | +function ($) {
1241 | 'use strict';
1242 |
1243 | // TOOLTIP PUBLIC CLASS DEFINITION
1244 | // ===============================
1245 |
1246 | var Tooltip = function (element, options) {
1247 | this.type =
1248 | this.options =
1249 | this.enabled =
1250 | this.timeout =
1251 | this.hoverState =
1252 | this.$element = null
1253 |
1254 | this.init('tooltip', element, options)
1255 | }
1256 |
1257 | Tooltip.VERSION = '3.3.1'
1258 |
1259 | Tooltip.TRANSITION_DURATION = 150
1260 |
1261 | Tooltip.DEFAULTS = {
1262 | animation: true,
1263 | placement: 'top',
1264 | selector: false,
1265 | template: '',
1266 | trigger: 'hover focus',
1267 | title: '',
1268 | delay: 0,
1269 | html: false,
1270 | container: false,
1271 | viewport: {
1272 | selector: 'body',
1273 | padding: 0
1274 | }
1275 | }
1276 |
1277 | Tooltip.prototype.init = function (type, element, options) {
1278 | this.enabled = true
1279 | this.type = type
1280 | this.$element = $(element)
1281 | this.options = this.getOptions(options)
1282 | this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
1283 |
1284 | var triggers = this.options.trigger.split(' ')
1285 |
1286 | for (var i = triggers.length; i--;) {
1287 | var trigger = triggers[i]
1288 |
1289 | if (trigger == 'click') {
1290 | this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
1291 | } else if (trigger != 'manual') {
1292 | var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
1293 | var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
1294 |
1295 | this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
1296 | this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
1297 | }
1298 | }
1299 |
1300 | this.options.selector ?
1301 | (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
1302 | this.fixTitle()
1303 | }
1304 |
1305 | Tooltip.prototype.getDefaults = function () {
1306 | return Tooltip.DEFAULTS
1307 | }
1308 |
1309 | Tooltip.prototype.getOptions = function (options) {
1310 | options = $.extend({}, this.getDefaults(), this.$element.data(), options)
1311 |
1312 | if (options.delay && typeof options.delay == 'number') {
1313 | options.delay = {
1314 | show: options.delay,
1315 | hide: options.delay
1316 | }
1317 | }
1318 |
1319 | return options
1320 | }
1321 |
1322 | Tooltip.prototype.getDelegateOptions = function () {
1323 | var options = {}
1324 | var defaults = this.getDefaults()
1325 |
1326 | this._options && $.each(this._options, function (key, value) {
1327 | if (defaults[key] != value) options[key] = value
1328 | })
1329 |
1330 | return options
1331 | }
1332 |
1333 | Tooltip.prototype.enter = function (obj) {
1334 | var self = obj instanceof this.constructor ?
1335 | obj : $(obj.currentTarget).data('bs.' + this.type)
1336 |
1337 | if (self && self.$tip && self.$tip.is(':visible')) {
1338 | self.hoverState = 'in'
1339 | return
1340 | }
1341 |
1342 | if (!self) {
1343 | self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1344 | $(obj.currentTarget).data('bs.' + this.type, self)
1345 | }
1346 |
1347 | clearTimeout(self.timeout)
1348 |
1349 | self.hoverState = 'in'
1350 |
1351 | if (!self.options.delay || !self.options.delay.show) return self.show()
1352 |
1353 | self.timeout = setTimeout(function () {
1354 | if (self.hoverState == 'in') self.show()
1355 | }, self.options.delay.show)
1356 | }
1357 |
1358 | Tooltip.prototype.leave = function (obj) {
1359 | var self = obj instanceof this.constructor ?
1360 | obj : $(obj.currentTarget).data('bs.' + this.type)
1361 |
1362 | if (!self) {
1363 | self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1364 | $(obj.currentTarget).data('bs.' + this.type, self)
1365 | }
1366 |
1367 | clearTimeout(self.timeout)
1368 |
1369 | self.hoverState = 'out'
1370 |
1371 | if (!self.options.delay || !self.options.delay.hide) return self.hide()
1372 |
1373 | self.timeout = setTimeout(function () {
1374 | if (self.hoverState == 'out') self.hide()
1375 | }, self.options.delay.hide)
1376 | }
1377 |
1378 | Tooltip.prototype.show = function () {
1379 | var e = $.Event('show.bs.' + this.type)
1380 |
1381 | if (this.hasContent() && this.enabled) {
1382 | this.$element.trigger(e)
1383 |
1384 | var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
1385 | if (e.isDefaultPrevented() || !inDom) return
1386 | var that = this
1387 |
1388 | var $tip = this.tip()
1389 |
1390 | var tipId = this.getUID(this.type)
1391 |
1392 | this.setContent()
1393 | $tip.attr('id', tipId)
1394 | this.$element.attr('aria-describedby', tipId)
1395 |
1396 | if (this.options.animation) $tip.addClass('fade')
1397 |
1398 | var placement = typeof this.options.placement == 'function' ?
1399 | this.options.placement.call(this, $tip[0], this.$element[0]) :
1400 | this.options.placement
1401 |
1402 | var autoToken = /\s?auto?\s?/i
1403 | var autoPlace = autoToken.test(placement)
1404 | if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
1405 |
1406 | $tip
1407 | .detach()
1408 | .css({ top: 0, left: 0, display: 'block' })
1409 | .addClass(placement)
1410 | .data('bs.' + this.type, this)
1411 |
1412 | this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1413 |
1414 | var pos = this.getPosition()
1415 | var actualWidth = $tip[0].offsetWidth
1416 | var actualHeight = $tip[0].offsetHeight
1417 |
1418 | if (autoPlace) {
1419 | var orgPlacement = placement
1420 | var $container = this.options.container ? $(this.options.container) : this.$element.parent()
1421 | var containerDim = this.getPosition($container)
1422 |
1423 | placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
1424 | placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
1425 | placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
1426 | placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
1427 | placement
1428 |
1429 | $tip
1430 | .removeClass(orgPlacement)
1431 | .addClass(placement)
1432 | }
1433 |
1434 | var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
1435 |
1436 | this.applyPlacement(calculatedOffset, placement)
1437 |
1438 | var complete = function () {
1439 | var prevHoverState = that.hoverState
1440 | that.$element.trigger('shown.bs.' + that.type)
1441 | that.hoverState = null
1442 |
1443 | if (prevHoverState == 'out') that.leave(that)
1444 | }
1445 |
1446 | $.support.transition && this.$tip.hasClass('fade') ?
1447 | $tip
1448 | .one('bsTransitionEnd', complete)
1449 | .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1450 | complete()
1451 | }
1452 | }
1453 |
1454 | Tooltip.prototype.applyPlacement = function (offset, placement) {
1455 | var $tip = this.tip()
1456 | var width = $tip[0].offsetWidth
1457 | var height = $tip[0].offsetHeight
1458 |
1459 | // manually read margins because getBoundingClientRect includes difference
1460 | var marginTop = parseInt($tip.css('margin-top'), 10)
1461 | var marginLeft = parseInt($tip.css('margin-left'), 10)
1462 |
1463 | // we must check for NaN for ie 8/9
1464 | if (isNaN(marginTop)) marginTop = 0
1465 | if (isNaN(marginLeft)) marginLeft = 0
1466 |
1467 | offset.top = offset.top + marginTop
1468 | offset.left = offset.left + marginLeft
1469 |
1470 | // $.fn.offset doesn't round pixel values
1471 | // so we use setOffset directly with our own function B-0
1472 | $.offset.setOffset($tip[0], $.extend({
1473 | using: function (props) {
1474 | $tip.css({
1475 | top: Math.round(props.top),
1476 | left: Math.round(props.left)
1477 | })
1478 | }
1479 | }, offset), 0)
1480 |
1481 | $tip.addClass('in')
1482 |
1483 | // check to see if placing tip in new offset caused the tip to resize itself
1484 | var actualWidth = $tip[0].offsetWidth
1485 | var actualHeight = $tip[0].offsetHeight
1486 |
1487 | if (placement == 'top' && actualHeight != height) {
1488 | offset.top = offset.top + height - actualHeight
1489 | }
1490 |
1491 | var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
1492 |
1493 | if (delta.left) offset.left += delta.left
1494 | else offset.top += delta.top
1495 |
1496 | var isVertical = /top|bottom/.test(placement)
1497 | var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
1498 | var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
1499 |
1500 | $tip.offset(offset)
1501 | this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
1502 | }
1503 |
1504 | Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
1505 | this.arrow()
1506 | .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
1507 | .css(isHorizontal ? 'top' : 'left', '')
1508 | }
1509 |
1510 | Tooltip.prototype.setContent = function () {
1511 | var $tip = this.tip()
1512 | var title = this.getTitle()
1513 |
1514 | $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
1515 | $tip.removeClass('fade in top bottom left right')
1516 | }
1517 |
1518 | Tooltip.prototype.hide = function (callback) {
1519 | var that = this
1520 | var $tip = this.tip()
1521 | var e = $.Event('hide.bs.' + this.type)
1522 |
1523 | function complete() {
1524 | if (that.hoverState != 'in') $tip.detach()
1525 | that.$element
1526 | .removeAttr('aria-describedby')
1527 | .trigger('hidden.bs.' + that.type)
1528 | callback && callback()
1529 | }
1530 |
1531 | this.$element.trigger(e)
1532 |
1533 | if (e.isDefaultPrevented()) return
1534 |
1535 | $tip.removeClass('in')
1536 |
1537 | $.support.transition && this.$tip.hasClass('fade') ?
1538 | $tip
1539 | .one('bsTransitionEnd', complete)
1540 | .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1541 | complete()
1542 |
1543 | this.hoverState = null
1544 |
1545 | return this
1546 | }
1547 |
1548 | Tooltip.prototype.fixTitle = function () {
1549 | var $e = this.$element
1550 | if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
1551 | $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
1552 | }
1553 | }
1554 |
1555 | Tooltip.prototype.hasContent = function () {
1556 | return this.getTitle()
1557 | }
1558 |
1559 | Tooltip.prototype.getPosition = function ($element) {
1560 | $element = $element || this.$element
1561 |
1562 | var el = $element[0]
1563 | var isBody = el.tagName == 'BODY'
1564 |
1565 | var elRect = el.getBoundingClientRect()
1566 | if (elRect.width == null) {
1567 | // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
1568 | elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
1569 | }
1570 | var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
1571 | var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
1572 | var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
1573 |
1574 | return $.extend({}, elRect, scroll, outerDims, elOffset)
1575 | }
1576 |
1577 | Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
1578 | return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1579 | placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1580 | placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
1581 | /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
1582 |
1583 | }
1584 |
1585 | Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
1586 | var delta = { top: 0, left: 0 }
1587 | if (!this.$viewport) return delta
1588 |
1589 | var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
1590 | var viewportDimensions = this.getPosition(this.$viewport)
1591 |
1592 | if (/right|left/.test(placement)) {
1593 | var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
1594 | var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
1595 | if (topEdgeOffset < viewportDimensions.top) { // top overflow
1596 | delta.top = viewportDimensions.top - topEdgeOffset
1597 | } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
1598 | delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
1599 | }
1600 | } else {
1601 | var leftEdgeOffset = pos.left - viewportPadding
1602 | var rightEdgeOffset = pos.left + viewportPadding + actualWidth
1603 | if (leftEdgeOffset < viewportDimensions.left) { // left overflow
1604 | delta.left = viewportDimensions.left - leftEdgeOffset
1605 | } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
1606 | delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
1607 | }
1608 | }
1609 |
1610 | return delta
1611 | }
1612 |
1613 | Tooltip.prototype.getTitle = function () {
1614 | var title
1615 | var $e = this.$element
1616 | var o = this.options
1617 |
1618 | title = $e.attr('data-original-title')
1619 | || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
1620 |
1621 | return title
1622 | }
1623 |
1624 | Tooltip.prototype.getUID = function (prefix) {
1625 | do prefix += ~~(Math.random() * 1000000)
1626 | while (document.getElementById(prefix))
1627 | return prefix
1628 | }
1629 |
1630 | Tooltip.prototype.tip = function () {
1631 | return (this.$tip = this.$tip || $(this.options.template))
1632 | }
1633 |
1634 | Tooltip.prototype.arrow = function () {
1635 | return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
1636 | }
1637 |
1638 | Tooltip.prototype.enable = function () {
1639 | this.enabled = true
1640 | }
1641 |
1642 | Tooltip.prototype.disable = function () {
1643 | this.enabled = false
1644 | }
1645 |
1646 | Tooltip.prototype.toggleEnabled = function () {
1647 | this.enabled = !this.enabled
1648 | }
1649 |
1650 | Tooltip.prototype.toggle = function (e) {
1651 | var self = this
1652 | if (e) {
1653 | self = $(e.currentTarget).data('bs.' + this.type)
1654 | if (!self) {
1655 | self = new this.constructor(e.currentTarget, this.getDelegateOptions())
1656 | $(e.currentTarget).data('bs.' + this.type, self)
1657 | }
1658 | }
1659 |
1660 | self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
1661 | }
1662 |
1663 | Tooltip.prototype.destroy = function () {
1664 | var that = this
1665 | clearTimeout(this.timeout)
1666 | this.hide(function () {
1667 | that.$element.off('.' + that.type).removeData('bs.' + that.type)
1668 | })
1669 | }
1670 |
1671 |
1672 | // TOOLTIP PLUGIN DEFINITION
1673 | // =========================
1674 |
1675 | function Plugin(option) {
1676 | return this.each(function () {
1677 | var $this = $(this)
1678 | var data = $this.data('bs.tooltip')
1679 | var options = typeof option == 'object' && option
1680 | var selector = options && options.selector
1681 |
1682 | if (!data && option == 'destroy') return
1683 | if (selector) {
1684 | if (!data) $this.data('bs.tooltip', (data = {}))
1685 | if (!data[selector]) data[selector] = new Tooltip(this, options)
1686 | } else {
1687 | if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
1688 | }
1689 | if (typeof option == 'string') data[option]()
1690 | })
1691 | }
1692 |
1693 | var old = $.fn.tooltip
1694 |
1695 | $.fn.tooltip = Plugin
1696 | $.fn.tooltip.Constructor = Tooltip
1697 |
1698 |
1699 | // TOOLTIP NO CONFLICT
1700 | // ===================
1701 |
1702 | $.fn.tooltip.noConflict = function () {
1703 | $.fn.tooltip = old
1704 | return this
1705 | }
1706 |
1707 | }(jQuery);
1708 |
1709 | /* ========================================================================
1710 | * Bootstrap: popover.js v3.3.1
1711 | * http://getbootstrap.com/javascript/#popovers
1712 | * ========================================================================
1713 | * Copyright 2011-2014 Twitter, Inc.
1714 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1715 | * ======================================================================== */
1716 |
1717 |
1718 | +function ($) {
1719 | 'use strict';
1720 |
1721 | // POPOVER PUBLIC CLASS DEFINITION
1722 | // ===============================
1723 |
1724 | var Popover = function (element, options) {
1725 | this.init('popover', element, options)
1726 | }
1727 |
1728 | if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1729 |
1730 | Popover.VERSION = '3.3.1'
1731 |
1732 | Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
1733 | placement: 'right',
1734 | trigger: 'click',
1735 | content: '',
1736 | template: ''
1737 | })
1738 |
1739 |
1740 | // NOTE: POPOVER EXTENDS tooltip.js
1741 | // ================================
1742 |
1743 | Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
1744 |
1745 | Popover.prototype.constructor = Popover
1746 |
1747 | Popover.prototype.getDefaults = function () {
1748 | return Popover.DEFAULTS
1749 | }
1750 |
1751 | Popover.prototype.setContent = function () {
1752 | var $tip = this.tip()
1753 | var title = this.getTitle()
1754 | var content = this.getContent()
1755 |
1756 | $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1757 | $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
1758 | this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
1759 | ](content)
1760 |
1761 | $tip.removeClass('fade top bottom left right in')
1762 |
1763 | // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
1764 | // this manually by checking the contents.
1765 | if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
1766 | }
1767 |
1768 | Popover.prototype.hasContent = function () {
1769 | return this.getTitle() || this.getContent()
1770 | }
1771 |
1772 | Popover.prototype.getContent = function () {
1773 | var $e = this.$element
1774 | var o = this.options
1775 |
1776 | return $e.attr('data-content')
1777 | || (typeof o.content == 'function' ?
1778 | o.content.call($e[0]) :
1779 | o.content)
1780 | }
1781 |
1782 | Popover.prototype.arrow = function () {
1783 | return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
1784 | }
1785 |
1786 | Popover.prototype.tip = function () {
1787 | if (!this.$tip) this.$tip = $(this.options.template)
1788 | return this.$tip
1789 | }
1790 |
1791 |
1792 | // POPOVER PLUGIN DEFINITION
1793 | // =========================
1794 |
1795 | function Plugin(option) {
1796 | return this.each(function () {
1797 | var $this = $(this)
1798 | var data = $this.data('bs.popover')
1799 | var options = typeof option == 'object' && option
1800 | var selector = options && options.selector
1801 |
1802 | if (!data && option == 'destroy') return
1803 | if (selector) {
1804 | if (!data) $this.data('bs.popover', (data = {}))
1805 | if (!data[selector]) data[selector] = new Popover(this, options)
1806 | } else {
1807 | if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
1808 | }
1809 | if (typeof option == 'string') data[option]()
1810 | })
1811 | }
1812 |
1813 | var old = $.fn.popover
1814 |
1815 | $.fn.popover = Plugin
1816 | $.fn.popover.Constructor = Popover
1817 |
1818 |
1819 | // POPOVER NO CONFLICT
1820 | // ===================
1821 |
1822 | $.fn.popover.noConflict = function () {
1823 | $.fn.popover = old
1824 | return this
1825 | }
1826 |
1827 | }(jQuery);
1828 |
1829 | /* ========================================================================
1830 | * Bootstrap: scrollspy.js v3.3.1
1831 | * http://getbootstrap.com/javascript/#scrollspy
1832 | * ========================================================================
1833 | * Copyright 2011-2014 Twitter, Inc.
1834 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1835 | * ======================================================================== */
1836 |
1837 |
1838 | +function ($) {
1839 | 'use strict';
1840 |
1841 | // SCROLLSPY CLASS DEFINITION
1842 | // ==========================
1843 |
1844 | function ScrollSpy(element, options) {
1845 | var process = $.proxy(this.process, this)
1846 |
1847 | this.$body = $('body')
1848 | this.$scrollElement = $(element).is('body') ? $(window) : $(element)
1849 | this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
1850 | this.selector = (this.options.target || '') + ' .nav li > a'
1851 | this.offsets = []
1852 | this.targets = []
1853 | this.activeTarget = null
1854 | this.scrollHeight = 0
1855 |
1856 | this.$scrollElement.on('scroll.bs.scrollspy', process)
1857 | this.refresh()
1858 | this.process()
1859 | }
1860 |
1861 | ScrollSpy.VERSION = '3.3.1'
1862 |
1863 | ScrollSpy.DEFAULTS = {
1864 | offset: 10
1865 | }
1866 |
1867 | ScrollSpy.prototype.getScrollHeight = function () {
1868 | return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
1869 | }
1870 |
1871 | ScrollSpy.prototype.refresh = function () {
1872 | var offsetMethod = 'offset'
1873 | var offsetBase = 0
1874 |
1875 | if (!$.isWindow(this.$scrollElement[0])) {
1876 | offsetMethod = 'position'
1877 | offsetBase = this.$scrollElement.scrollTop()
1878 | }
1879 |
1880 | this.offsets = []
1881 | this.targets = []
1882 | this.scrollHeight = this.getScrollHeight()
1883 |
1884 | var self = this
1885 |
1886 | this.$body
1887 | .find(this.selector)
1888 | .map(function () {
1889 | var $el = $(this)
1890 | var href = $el.data('target') || $el.attr('href')
1891 | var $href = /^#./.test(href) && $(href)
1892 |
1893 | return ($href
1894 | && $href.length
1895 | && $href.is(':visible')
1896 | && [[$href[offsetMethod]().top + offsetBase, href]]) || null
1897 | })
1898 | .sort(function (a, b) { return a[0] - b[0] })
1899 | .each(function () {
1900 | self.offsets.push(this[0])
1901 | self.targets.push(this[1])
1902 | })
1903 | }
1904 |
1905 | ScrollSpy.prototype.process = function () {
1906 | var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
1907 | var scrollHeight = this.getScrollHeight()
1908 | var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
1909 | var offsets = this.offsets
1910 | var targets = this.targets
1911 | var activeTarget = this.activeTarget
1912 | var i
1913 |
1914 | if (this.scrollHeight != scrollHeight) {
1915 | this.refresh()
1916 | }
1917 |
1918 | if (scrollTop >= maxScroll) {
1919 | return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
1920 | }
1921 |
1922 | if (activeTarget && scrollTop < offsets[0]) {
1923 | this.activeTarget = null
1924 | return this.clear()
1925 | }
1926 |
1927 | for (i = offsets.length; i--;) {
1928 | activeTarget != targets[i]
1929 | && scrollTop >= offsets[i]
1930 | && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
1931 | && this.activate(targets[i])
1932 | }
1933 | }
1934 |
1935 | ScrollSpy.prototype.activate = function (target) {
1936 | this.activeTarget = target
1937 |
1938 | this.clear()
1939 |
1940 | var selector = this.selector +
1941 | '[data-target="' + target + '"],' +
1942 | this.selector + '[href="' + target + '"]'
1943 |
1944 | var active = $(selector)
1945 | .parents('li')
1946 | .addClass('active')
1947 |
1948 | if (active.parent('.dropdown-menu').length) {
1949 | active = active
1950 | .closest('li.dropdown')
1951 | .addClass('active')
1952 | }
1953 |
1954 | active.trigger('activate.bs.scrollspy')
1955 | }
1956 |
1957 | ScrollSpy.prototype.clear = function () {
1958 | $(this.selector)
1959 | .parentsUntil(this.options.target, '.active')
1960 | .removeClass('active')
1961 | }
1962 |
1963 |
1964 | // SCROLLSPY PLUGIN DEFINITION
1965 | // ===========================
1966 |
1967 | function Plugin(option) {
1968 | return this.each(function () {
1969 | var $this = $(this)
1970 | var data = $this.data('bs.scrollspy')
1971 | var options = typeof option == 'object' && option
1972 |
1973 | if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
1974 | if (typeof option == 'string') data[option]()
1975 | })
1976 | }
1977 |
1978 | var old = $.fn.scrollspy
1979 |
1980 | $.fn.scrollspy = Plugin
1981 | $.fn.scrollspy.Constructor = ScrollSpy
1982 |
1983 |
1984 | // SCROLLSPY NO CONFLICT
1985 | // =====================
1986 |
1987 | $.fn.scrollspy.noConflict = function () {
1988 | $.fn.scrollspy = old
1989 | return this
1990 | }
1991 |
1992 |
1993 | // SCROLLSPY DATA-API
1994 | // ==================
1995 |
1996 | $(window).on('load.bs.scrollspy.data-api', function () {
1997 | $('[data-spy="scroll"]').each(function () {
1998 | var $spy = $(this)
1999 | Plugin.call($spy, $spy.data())
2000 | })
2001 | })
2002 |
2003 | }(jQuery);
2004 |
2005 | /* ========================================================================
2006 | * Bootstrap: tab.js v3.3.1
2007 | * http://getbootstrap.com/javascript/#tabs
2008 | * ========================================================================
2009 | * Copyright 2011-2014 Twitter, Inc.
2010 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2011 | * ======================================================================== */
2012 |
2013 |
2014 | +function ($) {
2015 | 'use strict';
2016 |
2017 | // TAB CLASS DEFINITION
2018 | // ====================
2019 |
2020 | var Tab = function (element) {
2021 | this.element = $(element)
2022 | }
2023 |
2024 | Tab.VERSION = '3.3.1'
2025 |
2026 | Tab.TRANSITION_DURATION = 150
2027 |
2028 | Tab.prototype.show = function () {
2029 | var $this = this.element
2030 | var $ul = $this.closest('ul:not(.dropdown-menu)')
2031 | var selector = $this.data('target')
2032 |
2033 | if (!selector) {
2034 | selector = $this.attr('href')
2035 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
2036 | }
2037 |
2038 | if ($this.parent('li').hasClass('active')) return
2039 |
2040 | var $previous = $ul.find('.active:last a')
2041 | var hideEvent = $.Event('hide.bs.tab', {
2042 | relatedTarget: $this[0]
2043 | })
2044 | var showEvent = $.Event('show.bs.tab', {
2045 | relatedTarget: $previous[0]
2046 | })
2047 |
2048 | $previous.trigger(hideEvent)
2049 | $this.trigger(showEvent)
2050 |
2051 | if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
2052 |
2053 | var $target = $(selector)
2054 |
2055 | this.activate($this.closest('li'), $ul)
2056 | this.activate($target, $target.parent(), function () {
2057 | $previous.trigger({
2058 | type: 'hidden.bs.tab',
2059 | relatedTarget: $this[0]
2060 | })
2061 | $this.trigger({
2062 | type: 'shown.bs.tab',
2063 | relatedTarget: $previous[0]
2064 | })
2065 | })
2066 | }
2067 |
2068 | Tab.prototype.activate = function (element, container, callback) {
2069 | var $active = container.find('> .active')
2070 | var transition = callback
2071 | && $.support.transition
2072 | && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
2073 |
2074 | function next() {
2075 | $active
2076 | .removeClass('active')
2077 | .find('> .dropdown-menu > .active')
2078 | .removeClass('active')
2079 | .end()
2080 | .find('[data-toggle="tab"]')
2081 | .attr('aria-expanded', false)
2082 |
2083 | element
2084 | .addClass('active')
2085 | .find('[data-toggle="tab"]')
2086 | .attr('aria-expanded', true)
2087 |
2088 | if (transition) {
2089 | element[0].offsetWidth // reflow for transition
2090 | element.addClass('in')
2091 | } else {
2092 | element.removeClass('fade')
2093 | }
2094 |
2095 | if (element.parent('.dropdown-menu')) {
2096 | element
2097 | .closest('li.dropdown')
2098 | .addClass('active')
2099 | .end()
2100 | .find('[data-toggle="tab"]')
2101 | .attr('aria-expanded', true)
2102 | }
2103 |
2104 | callback && callback()
2105 | }
2106 |
2107 | $active.length && transition ?
2108 | $active
2109 | .one('bsTransitionEnd', next)
2110 | .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
2111 | next()
2112 |
2113 | $active.removeClass('in')
2114 | }
2115 |
2116 |
2117 | // TAB PLUGIN DEFINITION
2118 | // =====================
2119 |
2120 | function Plugin(option) {
2121 | return this.each(function () {
2122 | var $this = $(this)
2123 | var data = $this.data('bs.tab')
2124 |
2125 | if (!data) $this.data('bs.tab', (data = new Tab(this)))
2126 | if (typeof option == 'string') data[option]()
2127 | })
2128 | }
2129 |
2130 | var old = $.fn.tab
2131 |
2132 | $.fn.tab = Plugin
2133 | $.fn.tab.Constructor = Tab
2134 |
2135 |
2136 | // TAB NO CONFLICT
2137 | // ===============
2138 |
2139 | $.fn.tab.noConflict = function () {
2140 | $.fn.tab = old
2141 | return this
2142 | }
2143 |
2144 |
2145 | // TAB DATA-API
2146 | // ============
2147 |
2148 | var clickHandler = function (e) {
2149 | e.preventDefault()
2150 | Plugin.call($(this), 'show')
2151 | }
2152 |
2153 | $(document)
2154 | .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
2155 | .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
2156 |
2157 | }(jQuery);
2158 |
2159 | /* ========================================================================
2160 | * Bootstrap: affix.js v3.3.1
2161 | * http://getbootstrap.com/javascript/#affix
2162 | * ========================================================================
2163 | * Copyright 2011-2014 Twitter, Inc.
2164 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2165 | * ======================================================================== */
2166 |
2167 |
2168 | +function ($) {
2169 | 'use strict';
2170 |
2171 | // AFFIX CLASS DEFINITION
2172 | // ======================
2173 |
2174 | var Affix = function (element, options) {
2175 | this.options = $.extend({}, Affix.DEFAULTS, options)
2176 |
2177 | this.$target = $(this.options.target)
2178 | .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
2179 | .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
2180 |
2181 | this.$element = $(element)
2182 | this.affixed =
2183 | this.unpin =
2184 | this.pinnedOffset = null
2185 |
2186 | this.checkPosition()
2187 | }
2188 |
2189 | Affix.VERSION = '3.3.1'
2190 |
2191 | Affix.RESET = 'affix affix-top affix-bottom'
2192 |
2193 | Affix.DEFAULTS = {
2194 | offset: 0,
2195 | target: window
2196 | }
2197 |
2198 | Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
2199 | var scrollTop = this.$target.scrollTop()
2200 | var position = this.$element.offset()
2201 | var targetHeight = this.$target.height()
2202 |
2203 | if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
2204 |
2205 | if (this.affixed == 'bottom') {
2206 | if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
2207 | return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
2208 | }
2209 |
2210 | var initializing = this.affixed == null
2211 | var colliderTop = initializing ? scrollTop : position.top
2212 | var colliderHeight = initializing ? targetHeight : height
2213 |
2214 | if (offsetTop != null && colliderTop <= offsetTop) return 'top'
2215 | if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
2216 |
2217 | return false
2218 | }
2219 |
2220 | Affix.prototype.getPinnedOffset = function () {
2221 | if (this.pinnedOffset) return this.pinnedOffset
2222 | this.$element.removeClass(Affix.RESET).addClass('affix')
2223 | var scrollTop = this.$target.scrollTop()
2224 | var position = this.$element.offset()
2225 | return (this.pinnedOffset = position.top - scrollTop)
2226 | }
2227 |
2228 | Affix.prototype.checkPositionWithEventLoop = function () {
2229 | setTimeout($.proxy(this.checkPosition, this), 1)
2230 | }
2231 |
2232 | Affix.prototype.checkPosition = function () {
2233 | if (!this.$element.is(':visible')) return
2234 |
2235 | var height = this.$element.height()
2236 | var offset = this.options.offset
2237 | var offsetTop = offset.top
2238 | var offsetBottom = offset.bottom
2239 | var scrollHeight = $('body').height()
2240 |
2241 | if (typeof offset != 'object') offsetBottom = offsetTop = offset
2242 | if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
2243 | if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
2244 |
2245 | var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
2246 |
2247 | if (this.affixed != affix) {
2248 | if (this.unpin != null) this.$element.css('top', '')
2249 |
2250 | var affixType = 'affix' + (affix ? '-' + affix : '')
2251 | var e = $.Event(affixType + '.bs.affix')
2252 |
2253 | this.$element.trigger(e)
2254 |
2255 | if (e.isDefaultPrevented()) return
2256 |
2257 | this.affixed = affix
2258 | this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
2259 |
2260 | this.$element
2261 | .removeClass(Affix.RESET)
2262 | .addClass(affixType)
2263 | .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
2264 | }
2265 |
2266 | if (affix == 'bottom') {
2267 | this.$element.offset({
2268 | top: scrollHeight - height - offsetBottom
2269 | })
2270 | }
2271 | }
2272 |
2273 |
2274 | // AFFIX PLUGIN DEFINITION
2275 | // =======================
2276 |
2277 | function Plugin(option) {
2278 | return this.each(function () {
2279 | var $this = $(this)
2280 | var data = $this.data('bs.affix')
2281 | var options = typeof option == 'object' && option
2282 |
2283 | if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
2284 | if (typeof option == 'string') data[option]()
2285 | })
2286 | }
2287 |
2288 | var old = $.fn.affix
2289 |
2290 | $.fn.affix = Plugin
2291 | $.fn.affix.Constructor = Affix
2292 |
2293 |
2294 | // AFFIX NO CONFLICT
2295 | // =================
2296 |
2297 | $.fn.affix.noConflict = function () {
2298 | $.fn.affix = old
2299 | return this
2300 | }
2301 |
2302 |
2303 | // AFFIX DATA-API
2304 | // ==============
2305 |
2306 | $(window).on('load', function () {
2307 | $('[data-spy="affix"]').each(function () {
2308 | var $spy = $(this)
2309 | var data = $spy.data()
2310 |
2311 | data.offset = data.offset || {}
2312 |
2313 | if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
2314 | if (data.offsetTop != null) data.offset.top = data.offsetTop
2315 |
2316 | Plugin.call($spy, data)
2317 | })
2318 | })
2319 |
2320 | }(jQuery);
2321 |
--------------------------------------------------------------------------------
/examples/assets/js/bootstrap.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.3.1 (http://getbootstrap.com)
3 | * Copyright 2011-2014 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");+function(a){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.1",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.1",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")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&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"),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=this.sliding=this.interval=this.$active=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.1",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="prev"==a?-1:1,d=this.getItemIndex(b),e=(d+c)%this.$items.length;return this.$items.eq(e)},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="next"==b?"first":"last",j=this;if(!f.length){if(!this.options.wrap)return;f=this.$element.find(".item")[i]()}if(f.hasClass("active"))return this.sliding=!1;var k=f[0],l=a.Event("slide.bs.carousel",{relatedTarget:k,direction:h});if(this.$element.trigger(l),!l.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var m=a(this.$indicators.children()[this.getItemIndex(f)]);m&&m.addClass("active")}var n=a.Event("slid.bs.carousel",{relatedTarget:k,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(" ")),j.sliding=!1,setTimeout(function(){j.$element.trigger(n)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(n)),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"==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(this.options.trigger).filter('[href="#'+b.id+'"], [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.1",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0,trigger:'[data-toggle="collapse"]'},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.find("> .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":a.extend({},e.data(),{trigger:this});c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};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)))}))}function c(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 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.1",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('').insertAfter(a(this)).on("click",b);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(b){if(/(38|40|27|32)/.test(b.which)&&!/input|textarea/i.test(b.target.tagName)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var e=c(d),g=e.hasClass("open");if(!g&&27!=b.which||g&&27==b.which)return 27==b.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.divider):visible a",i=e.find('[role="menu"]'+h+', [role="listbox"]'+h);if(i.length){var j=i.index(b.target);38==b.which&&j>0&&j--,40==b.which&&j').prependTo(this.$element).on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;f?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.options.backdrop&&this.adjustBackdrop(),this.adjustDialog()},c.prototype.adjustBackdrop=function(){this.$backdrop.css("height",0).css("height",this.$element[0].scrollHeight)},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.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(){this.bodyIsOverflowing=document.body.scrollHeight>document.documentElement.clientHeight,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.bodyIsOverflowing&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right","")},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b,g=f&&f.selector;(e||"destroy"!=b)&&(g?(e||d.data("bs.tooltip",e={}),e[g]||(e[g]=new c(this,f))):e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};c.VERSION="3.3.1",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport);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.$tip&&c.$tip.is(":visible")?void(c.hoverState="in"):(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),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.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)),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);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.options.container?a(this.options.container):this.$element.parent(),p=this.getPosition(o);h="bottom"==h&&k.bottom+m>p.bottom?"top":"top"==h&&k.top-mp.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.width&&(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(){return this.$tip=this.$tip||a(this.options.template)},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))),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)})};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,g=f&&f.selector;(e||"destroy"!=b)&&(g?(e||d.data("bs.popover",e={}),e[g]||(e[g]=new c(this,f))):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.1",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")},c.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};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){var e=a.proxy(this.process,this);this.$body=a("body"),this.$scrollElement=a(a(c).is("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",e),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.1",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="offset",c=0;a.isWindow(this.$scrollElement[0])||(b="position",c=this.$scrollElement.scrollTop()),this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight();var d=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+c,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){d.offsets.push(this[0]),d.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]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.1",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]})
7 | })}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .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")&&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=this.unpin=this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.1",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>=i?"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=a("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);
--------------------------------------------------------------------------------
/examples/assets/js/scripts.js:
--------------------------------------------------------------------------------
1 | //------------------------------------
2 | // scripts.js
3 | // javascript object which sends data to controller.php via AJAX
4 | // created: November 2016
5 | // author: Steve Rucker
6 | //------------------------------------
7 |
8 | var methods_test = methods_test || {}
9 | methods_test = {
10 | init: function () {
11 | this.setActions();
12 | },
13 | setActions: function () {
14 | var self = this;
15 | $("#validateKeys").click(function () {
16 | $("#loader").show();
17 | $("#view_data").empty();
18 | var auth = {"app_id": $(".app_id").val(), "app_key": $(".app_key").val()};
19 | var args = null;
20 | ajaxValidateKeys(auth, "viewGalleries", args);
21 | });
22 | $("#testViewGalleries").click(function () {
23 | self.startTimer();
24 | $("#loader").show();
25 | $("#view_data").empty();
26 | var auth = {"app_id": $(".app_id").val(), "app_key": $(".app_key").val()};
27 | var args = null;
28 | ajaxCallPhp(auth, "viewGalleries", args);
29 | });
30 | $("#testEnroll").click(function () {
31 | $("#view_data").empty();
32 | if (self.validateMe($("#enrollForm")) == true) {
33 | self.startTimer();
34 | $("#loader").show();
35 | var auth = {"app_id": $(".app_id").val(), "app_key": $(".app_key").val()};
36 | var args = {};
37 | args.gallery_name = $("#enrollForm .gallery_name").val();
38 | args.subject_id = $("#enrollForm .subject_id").val();
39 | if($("#enrollForm .image-upload").val() != "") {
40 | var file = $('#enrollForm .image-upload')[0].files[0];
41 | var reader = new FileReader();
42 | reader.readAsDataURL(file);
43 | reader.onloadend = function () {
44 | var fileData = parseImageData(reader.result);
45 | args.image = fileData;
46 | ajaxCallPhp(auth, "enroll", args);
47 | }
48 | }
49 | else {
50 | args.image = $("#enrollForm .image").val();
51 | ajaxCallPhp(auth, "enroll", args);
52 | }
53 | }
54 | });
55 |
56 | $("#testViewSubjectsInGallery").click(function () {
57 | $("#view_data").empty();
58 | if (self.validateMe($("#viewSubjectsInGalleryForm input")) == true) {
59 | self.startTimer();
60 | $("#loader").show();
61 | var auth = {"app_id": $(".app_id").val(), "app_key": $(".app_key").val()};
62 | var args = {};
63 | args.gallery_name = $("#viewSubjectsInGalleryForm .gallery_name").val();
64 | ajaxCallPhp(auth, "viewSubjectsInGallery", args);
65 | }
66 | });
67 |
68 | $("#testRemoveSubjectFromGallery").click(function () {
69 | $("#view_data").empty();
70 | if (self.validateMe($("#removeSubjectFromGalleryForm input")) == true) {
71 | self.startTimer();
72 | $("#loader").show();
73 | var auth = {"app_id": $(".app_id").val(), "app_key": $(".app_key").val()};
74 | var args = {};
75 | args.gallery_name = $("#removeSubjectFromGalleryForm .gallery_name").val();
76 | args.subject_id = $("#removeSubjectFromGalleryForm .subject_id").val();
77 | ajaxCallPhp(auth, "removeSubjectFromGallery", args);
78 | }
79 | });
80 |
81 | $("#testRemoveGallery").click(function () {
82 | $("#view_data").empty();
83 | if (self.validateMe($("#removeGalleryForm input")) == true) {
84 | self.startTimer();
85 | $("#loader").show();
86 | var auth = {"app_id": $(".app_id").val(), "app_key": $(".app_key").val()};
87 | var args = {};
88 | args.gallery_name = $("#removeGalleryForm .gallery_name").val();
89 | ajaxCallPhp(auth, "removeGallery", args);
90 | }
91 | });
92 |
93 | $("#testRecognize").click(function () {
94 | $("#view_data").empty();
95 | if (self.validateMe($("#recognizeForm")) == true) {
96 | self.startTimer();
97 | $("#loader").show();
98 | var auth = {"app_id": $(".app_id").val(), "app_key": $(".app_key").val()};
99 | var args = {};
100 | args.gallery_name = $("#recognizeForm .gallery_name").val();
101 | if($("#recognizeForm .image-upload").val() != "") {
102 | var file = $('#recognizeForm .image-upload')[0].files[0];
103 | var reader = new FileReader();
104 | reader.readAsDataURL(file);
105 | reader.onloadend = function () {
106 | var fileData = parseImageData(reader.result);
107 | args.image = fileData;
108 | ajaxCallPhp(auth, "recognize", args);
109 | }
110 | }
111 | else {
112 | args.image = $("#recognizeForm .image").val();
113 | ajaxCallPhp(auth, "recognize", args);
114 | }
115 | }
116 | });
117 |
118 | $("#testDetect").click(function () {
119 | $("#view_data").empty();
120 | if (self.validateMe($("#detectForm")) == true) {
121 | self.startTimer();
122 | $("#loader").show();
123 | var auth = {"app_id": $(".app_id").val(), "app_key": $(".app_key").val()};
124 | var args = {};
125 | if($("#detectForm .image-upload").val() != "") {
126 | var file = $('#detectForm .image-upload')[0].files[0];
127 | var reader = new FileReader();
128 | reader.readAsDataURL(file);
129 | var a = new Date();
130 | console.log(a.getTime())
131 | reader.onloadend = function () {
132 | var b = new Date();
133 | console.log(b.getTime())
134 | var fileData = parseImageData(reader.result);
135 | args.image = fileData;
136 | ajaxCallPhp(auth, "detect", args);
137 | }
138 | }
139 | else {
140 | args.image = $("#detectForm .image").val();
141 | ajaxCallPhp(auth, "detect", args);
142 | }
143 | }
144 | });
145 |
146 | $("#testVerify").click(function () {
147 | $("#view_data").empty();
148 | if (self.validateMe($("#verifyForm")) == true) {
149 | self.startTimer();
150 | $("#loader").show();
151 | var auth = {"app_id": $(".app_id").val(), "app_key": $(".app_key").val()};
152 | var args = {};
153 | args.gallery_name = $("#verifyForm .gallery_name").val();
154 | args.subject_id = $("#verifyForm .subject_id").val();
155 | if($("#verifyForm .image-upload").val() != "") {
156 | var file = $('#verifyForm .image-upload')[0].files[0];
157 | var reader = new FileReader();
158 | reader.readAsDataURL(file);
159 | reader.onloadend = function () {
160 | var fileData = parseImageData(reader.result);
161 | args.image = fileData;
162 | ajaxCallPhp(auth, "verify", args);
163 | }
164 | }
165 | else {
166 | args.image = $("#verifyForm .image").val();
167 | ajaxCallPhp(auth, "verify", args);
168 | }
169 | }
170 | });
171 | },
172 | validateMe: function(obj) {
173 | var isValid = true;
174 | errorAlert = "";
175 | var fileUploaded = false;
176 | if(obj.find(".image-upload").val() != "") {
177 | fileUploaded = true;
178 | }
179 | obj.find("input").each(function () {
180 | if($(this).attr("type") == "text" && !$(this).hasClass("image")) {
181 | if($(this).val() == "") {
182 | isValid = false;
183 | errorAlert = errorAlert + "Please enter a value for " + $(this).attr("name") + "\n";
184 | }
185 | }
186 | if($(this).hasClass("image")) {
187 | if($(this).val() == "" && !fileUploaded) {
188 | isValid = false;
189 | errorAlert = errorAlert + "Please either enter an image URL or image base64 data, or upload an image" + "\n";
190 | }
191 | if($(this).val() != "" && fileUploaded) {
192 | isValid = false;
193 | $(this).val("");
194 | $("input:file").val("");
195 | errorAlert = errorAlert + "You cannot enter an image URL or image base64 data AND upload an image. Please do one or the other." + "\n";
196 | }
197 | }
198 | });
199 | if (isValid == false) {
200 | alert(errorAlert)
201 | }
202 | return isValid;
203 | },
204 | startTimer: function() {
205 | $(".timer").html("");
206 | var currTime = 0;
207 | self.timer = setInterval(function(){
208 | currTime ++;
209 | $("#timer").html(currTime + " sec");
210 | },1000);
211 | }
212 | }
213 | var ajaxValidateKeys = function(auth, phpMethod, args) {
214 | var data = {};
215 | data["auth"] = auth;
216 | data["phpMethod"] = phpMethod;
217 | data["args"] = args;
218 | $.ajax({
219 | url : "controller.php",
220 | type : "POST",
221 | data : data,
222 | dataType : 'text'
223 | }).done(function(response) {
224 | if (response == "Authentication failed") {
225 | var msg = "Invalid Keys";
226 | }
227 | else {
228 | var msg = "Keys Validated";
229 | }
230 | $("#view_data").empty();
231 | $("#view_data").html(msg);
232 | $("#loader").hide();
233 | $("input:text").not(".app_id, .app_key").val("");
234 | $("input:file").val("");
235 | });
236 | }
237 | var ajaxCallPhp = function(auth, phpMethod, args) {
238 | var data = {};
239 | data["auth"] = auth;
240 | data["phpMethod"] = phpMethod;
241 | data["args"] = args;
242 | $.ajax({
243 | url : "controller.php",
244 | type : "POST",
245 | data : data,
246 | dataType : 'text'
247 | }).done(function(response) {
248 | clearInterval(self.timer);
249 | $("#view_data").empty();
250 | $("#view_data").html(response);
251 | $("#loader").hide();
252 | $("input:text").not(".app_id, .app_key").val("");
253 | $("input:file").val("");
254 | });
255 | }
256 |
257 | var parseImageData = function(imageData) {
258 | imageData = imageData.replace("data:image/jpeg;base64,", "");
259 | imageData = imageData.replace("data:image/jpg;base64,", "");
260 | imageData = imageData.replace("data:image/png;base64,", "");
261 | imageData = imageData.replace("data:image/gif;base64,", "");
262 | imageData = imageData.replace("data:image/bmp;base64,", "");
263 | return imageData;
264 | }
265 |
266 | $(function () {
267 | methods_test.init()
268 | });
269 |
270 |
271 |
--------------------------------------------------------------------------------
/examples/controller.php:
--------------------------------------------------------------------------------
1 | $phpMethod($args);
17 |
18 | echo $response;
19 |
20 | ?>
--------------------------------------------------------------------------------
/examples/methods_test.php:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
Enter API Keys:
27 |
32 |
33 |
34 |
35 |
Test API Methods
36 |
37 |
38 |
viewGalleries() Method
39 |
42 |
43 |
44 |
45 |
46 |
enroll() Method
47 |
54 |
55 |
56 |
57 |
58 |
viewSubjectsInGallery() Method
59 |
63 |
64 |
65 |
66 |
67 |
removeSubjectFromGallery() Method
68 |
73 |
74 |
75 |
76 |
77 |
removeGallery() Method
78 |
82 |
83 |
84 |
85 |
86 |
recognize() Method
87 |
93 |
94 |
95 |
96 |
97 |
detect() Method
98 |
103 |
104 |
105 |
106 |
107 |
verify() Method
108 |
115 |
116 |
117 |
121 |
122 |
Response:
123 |

124 |
125 |
126 |
127 |
128 |
129 |
--------------------------------------------------------------------------------
/simple-detect/form-post.php:
--------------------------------------------------------------------------------
1 | $_POST["image"]
13 | );
14 | // set curl options
15 | curl_setopt($request, CURLOPT_POST, true);
16 | curl_setopt($request,CURLOPT_POSTFIELDS, json_encode($request_params));
17 | curl_setopt($request, CURLOPT_HTTPHEADER, array(
18 | "Content-type: application/json",
19 | "app_id:" . $APP_ID,
20 | "app_key:" . $APP_KEY
21 | )
22 | );
23 |
24 | curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
25 |
26 | $response = curl_exec($request);
27 |
28 | echo $response;
29 | // // close the session
30 | curl_close($request);
31 |
32 | ?>
33 |
34 |
--------------------------------------------------------------------------------
/simple-detect/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
--------------------------------------------------------------------------------
/simple-viewSubjects/form-post.php:
--------------------------------------------------------------------------------
1 | $_POST["gallery_name"],
13 | );
14 | // set curl options
15 | curl_setopt($request, CURLOPT_POST, true);
16 | curl_setopt($request,CURLOPT_POSTFIELDS, json_encode($request_params));
17 | curl_setopt($request, CURLOPT_HTTPHEADER, array(
18 | "Content-type: application/json",
19 | "app_id:" . $APP_ID,
20 | "app_key:" . $APP_KEY
21 | )
22 | );
23 |
24 | curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
25 |
26 | $response = curl_exec($request);
27 |
28 | echo $response;
29 | // // close the session
30 | curl_close($request);
31 |
32 | ?>
33 |
34 |
--------------------------------------------------------------------------------
/simple-viewSubjects/index.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------