From 933cd7229a5bc15b9c8bf16a89c5823aaa7ec72a Mon Sep 17 00:00:00 2001 From: Kevin Fronczak Date: Sat, 20 Jan 2018 22:53:02 -0500 Subject: [PATCH] Add documentation --- README.rst | 60 +- docs/Makefile | 20 + docs/README.rst | 1 + docs/_build/doctrees/README.doctree | Bin 0 -> 30341 bytes docs/_build/doctrees/api/blinkpy.doctree | Bin 0 -> 49299 bytes docs/_build/doctrees/environment.pickle | Bin 0 -> 28308 bytes .../blinkpy/badge.svg/branch=dev/badge.svg | 1 + .../pypi/v/blinkpy.svg/blinkpy.svg | 1 + .../blinkpy.svg/branch=dev/blinkpy.svg | 1 + docs/_build/doctrees/index.doctree | Bin 0 -> 4815 bytes docs/_build/html/.buildinfo | 4 + docs/_build/html/README.html | 156 + .../_build/html/_modules/blinkpy/blinkpy.html | 535 + docs/_build/html/_modules/index.html | 84 + docs/_build/html/_sources/README.rst.txt | 86 + docs/_build/html/_sources/api/blinkpy.rst.txt | 19 + docs/_build/html/_sources/index.rst.txt | 22 + docs/_build/html/_static/ajax-loader.gif | Bin 0 -> 673 bytes docs/_build/html/_static/alabaster.css | 693 ++ docs/_build/html/_static/basic.css | 643 + docs/_build/html/_static/comment-bright.png | Bin 0 -> 756 bytes docs/_build/html/_static/comment-close.png | Bin 0 -> 829 bytes docs/_build/html/_static/comment.png | Bin 0 -> 641 bytes docs/_build/html/_static/custom.css | 1 + docs/_build/html/_static/doctools.js | 311 + docs/_build/html/_static/down-pressed.png | Bin 0 -> 222 bytes docs/_build/html/_static/down.png | Bin 0 -> 202 bytes docs/_build/html/_static/file.png | Bin 0 -> 286 bytes docs/_build/html/_static/jquery-3.1.0.js | 10074 ++++++++++++++++ docs/_build/html/_static/jquery.js | 4 + docs/_build/html/_static/minus.png | Bin 0 -> 90 bytes docs/_build/html/_static/plus.png | Bin 0 -> 90 bytes docs/_build/html/_static/pygments.css | 69 + docs/_build/html/_static/searchtools.js | 761 ++ docs/_build/html/_static/underscore-1.3.1.js | 999 ++ docs/_build/html/_static/underscore.js | 31 + docs/_build/html/_static/up-pressed.png | Bin 0 -> 214 bytes docs/_build/html/_static/up.png | Bin 0 -> 203 bytes docs/_build/html/_static/websupport.js | 808 ++ docs/_build/html/api/blinkpy.html | 274 + docs/_build/html/genindex.html | 254 + docs/_build/html/index.html | 112 + docs/_build/html/objects.inv | 8 + docs/_build/html/py-modindex.html | 108 + docs/_build/html/search.html | 102 + docs/_build/html/searchindex.js | 1 + docs/api/blinkpy.rst | 19 + docs/conf.py | 172 + docs/index.rst | 22 + docs/make.bat | 36 + setup.py | 2 +- 51 files changed, 16435 insertions(+), 59 deletions(-) create mode 100644 docs/Makefile create mode 120000 docs/README.rst create mode 100644 docs/_build/doctrees/README.doctree create mode 100644 docs/_build/doctrees/api/blinkpy.doctree create mode 100644 docs/_build/doctrees/environment.pickle create mode 100644 docs/_build/doctrees/images/https/coveralls.io/repos/github/fronzbot/blinkpy/badge.svg/branch=dev/badge.svg create mode 100644 docs/_build/doctrees/images/https/img.shields.io/pypi/v/blinkpy.svg/blinkpy.svg create mode 100644 docs/_build/doctrees/images/https/travis-ci.org/fronzbot/blinkpy.svg/branch=dev/blinkpy.svg create mode 100644 docs/_build/doctrees/index.doctree create mode 100644 docs/_build/html/.buildinfo create mode 100644 docs/_build/html/README.html create mode 100644 docs/_build/html/_modules/blinkpy/blinkpy.html create mode 100644 docs/_build/html/_modules/index.html create mode 100644 docs/_build/html/_sources/README.rst.txt create mode 100644 docs/_build/html/_sources/api/blinkpy.rst.txt create mode 100644 docs/_build/html/_sources/index.rst.txt create mode 100644 docs/_build/html/_static/ajax-loader.gif create mode 100644 docs/_build/html/_static/alabaster.css create mode 100644 docs/_build/html/_static/basic.css create mode 100644 docs/_build/html/_static/comment-bright.png create mode 100644 docs/_build/html/_static/comment-close.png create mode 100644 docs/_build/html/_static/comment.png create mode 100644 docs/_build/html/_static/custom.css create mode 100644 docs/_build/html/_static/doctools.js create mode 100644 docs/_build/html/_static/down-pressed.png create mode 100644 docs/_build/html/_static/down.png create mode 100644 docs/_build/html/_static/file.png create mode 100644 docs/_build/html/_static/jquery-3.1.0.js create mode 100644 docs/_build/html/_static/jquery.js create mode 100644 docs/_build/html/_static/minus.png create mode 100644 docs/_build/html/_static/plus.png create mode 100644 docs/_build/html/_static/pygments.css create mode 100644 docs/_build/html/_static/searchtools.js create mode 100644 docs/_build/html/_static/underscore-1.3.1.js create mode 100644 docs/_build/html/_static/underscore.js create mode 100644 docs/_build/html/_static/up-pressed.png create mode 100644 docs/_build/html/_static/up.png create mode 100644 docs/_build/html/_static/websupport.js create mode 100644 docs/_build/html/api/blinkpy.html create mode 100644 docs/_build/html/genindex.html create mode 100644 docs/_build/html/index.html create mode 100644 docs/_build/html/objects.inv create mode 100644 docs/_build/html/py-modindex.html create mode 100644 docs/_build/html/search.html create mode 100644 docs/_build/html/searchindex.js create mode 100644 docs/api/blinkpy.rst create mode 100644 docs/conf.py create mode 100644 docs/index.rst create mode 100644 docs/make.bat diff --git a/README.rst b/README.rst index 2948268..5eb9127 100644 --- a/README.rst +++ b/README.rst @@ -38,13 +38,13 @@ This library was built with the intention of allowing easy communication with Bl Usage ========= -In terms of usage, you just need to instantiate the module with a username and password +In terms of usage, you just need to instantiate the module with a username and password and call the ``setup_system()`` method. .. code:: python import blinkpy blink = blinkpy.Blink(username='YOUR USER NAME', password='YOUR PASSWORD') - + blink.setup_system() If you leave out either of those parameters, you need to call the login function which will prompt for your username and password @@ -75,64 +75,8 @@ The cameras are of a BlinkCamera class, of which the following parameters can be print(camera.battery) # Current battery level... I think the value ranges from 0-3, but not quite sure yet. print(camera.battery_string) # Gives battery level as a string ("OK" or "Low"). Returns "Unknown" if value is... well, unknown print(camera.notifications) # Number of unread notifications (ie. motion alerts that haven't been viewed) - print(camera.motion) # Dictionary containing values for keys ['video', 'image', 'time'] - # which corresponds to last motion recorded, thumbnail of last motion, and timestamp of last motion -Class Descriptions -=================== -.. code:: python - - class Blink() - -* ``Blink.cameras`` Returns a dictionary of ``BlinkCamera`` objects where the key corresponds to the camera name and the value is the actual BlinkCamera object. -* ``Blink.network_id`` Returns the current network id. -* ``Blink.account_id`` Returns the account id. -* ``Blink.events`` Returns a list of events recorded by blink. This information will contain links to any motion caught by an armed camera.. -* ``Blink.online`` Returns online status of sync module (True = online, False = offline). -* ``Blink.last_motion()`` Finds last motion information for each camera and stores it in the ``BlinkCamera.motion`` field. -* ``Blink.arm`` Set to True to arm, False to disarm. Can be used to see the status of the system as well. -* ``Blink.refresh()`` Forces a refresh of all camera information. -* ``Blink.get_summary()`` Returns json formatted summary of the system. -* ``Blink.get_cameras()`` Finds all cameras in the system and creates ``BlinkCamera`` objects to represent them. -* ``Blink.set_links()`` Gives each BlinkCamera object the links needed to find recent images and videos. -* ``Blink.login()`` Prompts user for login information. -* ``Blink.get_auth_token()`` Uses login information to retrieve authorization token from Blink for further communication. -* ``Blink.get_ids()`` Retrieves the network_id and account_id from Blink in order to access video and image pages on their server. -* ``Blink.setup_system()`` A wrapper script that calls: - - -.. code:: python - - Blink.get_auth_token() - Blink.get_ids() - Blink.get_camers() - Blink.set_links() - -.. code:: python - - class BlinkCamera(config, urls) - -The ``BlinkCamera`` class expects to receive: - -* A dictionary ``config`` that contains the camera name, device id, armed status, thumbnail url, camera temperature, camery battery level, number of notifications, and region id -* A ``BlinkURLHandler`` object that contains all the links necessary for communication. - - -Ultimately, this class is just a wrapper for each individual camera in order to make communication with individual cameras less clunky. The following properties/methods are availiable (in addition to the ones mentioned earlier): - -* ``BlinkCamera.snap_picture()`` Takes an image with the camera and saves it as the new thumbnail. The ``Blink.refresh()`` method should be called after this if you want to store the new thumbnail link. -* ``BlinkCamera.set_motion_detect(enable=True/False)`` Sending True to this function will enable motion detection for the camera. Setting to False will disable motion detection. -* ``BlinkCamera.image_to_file(path)`` This will write the current thumbnail to the location indicated in 'path' -* ``BlinkCamera.image_refresh()`` Refreshes the current thumbnail. - - -.. code:: python - - class BlinkURLHandler(region_id) - -The ``BlinkURLHandler`` class expects to be initialized with the region id found in the ``Blink.get_auth_token()`` function. The class will then create the necessary links required for various communication. - .. |Build Status| image:: https://travis-ci.org/fronzbot/blinkpy.svg?branch=dev :target: https://travis-ci.org/fronzbot/blinkpy .. |Coverage Status| image:: https://coveralls.io/repos/github/fronzbot/blinkpy/badge.svg?branch=dev diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..774c386 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SPHINXPROJ = blinkpy +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/README.rst b/docs/README.rst new file mode 120000 index 0000000..89a0106 --- /dev/null +++ b/docs/README.rst @@ -0,0 +1 @@ +../README.rst \ No newline at end of file diff --git a/docs/_build/doctrees/README.doctree b/docs/_build/doctrees/README.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e3fd8cf572801464e54ab1e6353df52aaaf393c1 GIT binary patch literal 30341 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 O2dNS?;&iW5S^PhLaqw0E literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/environment.pickle b/docs/_build/doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..281019f165f0dac4e36ed4c745fb6973d8a31b75 GIT binary patch literal 28308 zcmd5_eT*H~Rre> z?<@1+^(HkG$@#DtNTfcH(jrk1kbcls75z|31C=USEkz(&S|I_JS|U(CB>1EK1B8Iz zIp^M)x$|arpPMM^D)H>hoOABE=bm%!Ip^NF`@yZhd!@UDf8tw%zUy@_R-Ntz&+m0R zPB$FH`;J6jyE&hE^r69l-yB>TRN`Ce7d&UJ(Q7*OPOllYodA#Hy~}N{d%nM3Ro6k~ zm;d(uEnD{AH4_E?%(B;=>92=wuRFfqn!ab+0=m~-J#0nc%JhBoWPD;`VqD=`%j;In zx!`rJ2f$F{G5fqVZOvIns0FKGcO2igPBJyC?JfJZzg`_5cf+tB9G;n3^+GpVt~Pp| znH69^w%iM66y5O?zPIXi?Y7nTdttB9Yg?|}I1fgs#RWSI&pcusE}|swW|)J8Ue^nI z{z*k*{A2|3f$KD_sM~aWD|8)e;rJP_)^NIk1J+MFj`i^Iqw|ZW=dBg5?N}>4-|F;y z$7(vE?X`pI_=I%s5zlv~AMgSH&}r+TUI&z=va2%SzaVR?aNTcK|^ zosR9FAMdSo!3278ywh=-o^2iPHmXxr0BUP%Yceos*#%h=Ps)YY#p8}0dcAIS{J3Rz zEQr3_v)1f&%U%J;o*jbn8YC-&Fon0i(F_mYxYz0Tz+fxDIIG`Rov?2Q!8pdEV+C#$ zdTmR+YV`W+B#z#4OGEq4qmdJY3S8e+gV2u}VdOi3#yx5W&T&Y$8+f62!8ztNLQO*r zcGY#-ea8=~j_>z;NGh=APn|k(N;t^_HG173w7X%_KxN#*&yk0ZFV^a3Pdz+kJ$&N9 zi1b?BDU>4$aSu_Ks)?>)xi zt}q`54l@B*z?^_tVbAiN74+A&2p;$6ovvkfo6xH6`JhV1Lj1W71|OZ9wU|&9(ykLi zoe?Sr7)V|Pc*V%-sqa9bT}?srsYEV(O<9rOo}DDiBE#zSR@ib5$?SJccH&7?^BtabbL}z z=&^qR=B1T_rO|Mm#(B$I!Ba!7R@Z4XoFE|Apk>8S%#SrYYfbihK{zRbCtisW=zs%J z>K3X5Qh^B4J}P-nncbAmn*XwZ=pPvar=4q_B(ibqfcPmJS8|q%Za;7`&DkD$dW6(r z{$j)FljT>~I;yAU-+Olc^cg5F^#@ER!^8rgB)>mN{y__@N&po#Tna}IW!fUW@Y7c3 zpre>)yaroA%EORcE4gOQ2?I-0`S#CEc4)j;oynyG(q(GWfu@;Eq!zP@O&Y8yV}XLQ zf6AH%>qj!$*QqMnK-4uc5gEFT)hrp9+2ps35s^)a9QIrNb&Pa)*lK!#z1((YyS-@= z%(V1sXrNPpscz@SfDuf|<^bVMhFc9HxZ`OLljn4|7fv_qcH3!=H`Rz){mJ|fRGSZnUk>WCD?mAvU zOcOe0gMx+C$1mZ(iK>JmuzS_SR5}T#cFpppKt@w~{L&2F1`Whc-Gm5(=>~Jy&IO1v zgUXcY#k&Ymw)CMO^3|kvVEl?7^nubP-g*P&~G>KK| zi3!7&3O8C2Ud~N6kx(=o=qx4(%Nll1UiSjrKy$hap_ruT37XS{=yoz^`gH`4VMI)6 zDBDL2o(Dr_(pl~z;s@Zwu-9MDK&dBrKuieUii!rZQZ%0Dkvc%?bwT{`OJ+Z1 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 literal 0 HcmV?d00001 diff --git a/docs/_build/doctrees/images/https/coveralls.io/repos/github/fronzbot/blinkpy/badge.svg/branch=dev/badge.svg b/docs/_build/doctrees/images/https/coveralls.io/repos/github/fronzbot/blinkpy/badge.svg/branch=dev/badge.svg new file mode 100644 index 0000000..0d9ba73 --- /dev/null +++ b/docs/_build/doctrees/images/https/coveralls.io/repos/github/fronzbot/blinkpy/badge.svg/branch=dev/badge.svg @@ -0,0 +1 @@ +coveragecoverage84%84% \ No newline at end of file diff --git a/docs/_build/doctrees/images/https/img.shields.io/pypi/v/blinkpy.svg/blinkpy.svg b/docs/_build/doctrees/images/https/img.shields.io/pypi/v/blinkpy.svg/blinkpy.svg new file mode 100644 index 0000000..8e5c930 --- /dev/null +++ b/docs/_build/doctrees/images/https/img.shields.io/pypi/v/blinkpy.svg/blinkpy.svg @@ -0,0 +1 @@ +pypipypiv0.6.0v0.6.0 \ No newline at end of file diff --git a/docs/_build/doctrees/images/https/travis-ci.org/fronzbot/blinkpy.svg/branch=dev/blinkpy.svg b/docs/_build/doctrees/images/https/travis-ci.org/fronzbot/blinkpy.svg/branch=dev/blinkpy.svg new file mode 100644 index 0000000..738e29e --- /dev/null +++ b/docs/_build/doctrees/images/https/travis-ci.org/fronzbot/blinkpy.svg/branch=dev/blinkpy.svg @@ -0,0 +1 @@ +buildbuildpassingpassing \ No newline at end of file diff --git a/docs/_build/doctrees/index.doctree b/docs/_build/doctrees/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..b8b34a0974fd9e145efe918f473d682a8c5422ba GIT binary patch literal 4815 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 literal 0 HcmV?d00001 diff --git a/docs/_build/html/.buildinfo b/docs/_build/html/.buildinfo new file mode 100644 index 0000000..00cb868 --- /dev/null +++ b/docs/_build/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 2ba0a0d873b7729cb2d928f9bdf6a26b +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/_build/html/README.html b/docs/_build/html/README.html new file mode 100644 index 0000000..cbf24b5 --- /dev/null +++ b/docs/_build/html/README.html @@ -0,0 +1,156 @@ + + + + + + + blinkpy — blinkpy 0.7.0 documentation + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +
+

blinkpy Build Status Coverage Status PyPi Version

+

A Python library for the Blink Camera system +Only compatible with Python 3+

+
+

Disclaimer:

+

Published under the MIT license - See LICENSE file for more details.

+

“Blink Wire-Free HS Home Monitoring & Alert Systems” is a trademark owned by Immedia Inc., see www.blinkforhome.com for more information. +I am in no way affiliated with Blink, nor Immedia Inc.

+

Original protocol hacking by MattTW : https://github.com/MattTW/BlinkMonitorProtocol

+

API calls faster than 60 seconds is not recommended as it can overwhelm Blink’s servers. Please use this module responsibly.

+
+
+
+

Installation

+

pip3 install blinkpy

+
+
+

Installing Development Version

+

To install the current development version, perform the following steps. Note that the following will create a blinkpy directory in your home area:

+
$ cd ~
+$ git clone https://github.com/fronzbot/blinkpy.git
+$ cd blinkpy
+$ rm -rf build dist
+$ python3 setup.py bdist_wheel
+$ pip3 install --upgrade dist/*.whl
+
+
+
+
+

Purpose

+

This library was built with the intention of allowing easy communication with Blink camera systems, specifically so I can add a module into homeassistant https://home-assistant.io

+
+
+

Usage

+

In terms of usage, you just need to instantiate the module with a username and password and call the setup_system() method.

+
import blinkpy
+blink = blinkpy.Blink(username='YOUR USER NAME', password='YOUR PASSWORD')
+blink.setup_system()
+
+
+

If you leave out either of those parameters, you need to call the login function which will prompt for your username and password

+
import blinkpy
+blink = blinkpy.Blink()
+blink.login()
+
+
+

Once the login information is entered, you can run the setup_system() function which will attempt to authenticate with Blink servers using your username and password, obtain network ids, and create a list of cameras. +The cameras are of a BlinkCamera class, of which the following parameters can be used (the code below creates a Blink object and iterates through each camera found)

+
import blinkpy
+
+blink = blinkpy.Blink(username='YOUR USER NAME', password='YOUR PASSWORD')
+blink.setup_system()
+
+for name, camera in blink.cameras.items():
+    print(name)                  # Name of the camera
+    print(camera.id)             # Integer id of the camera (assigned by Blink)
+    print(camera.armed)          # Whether the device is armed/disarmed (ie. detecting motion)
+    print(camera.clip)           # Link to last motion clip captured
+    print(camera.thumbnail)      # Link to current camera thumbnail
+    print(camera.temperature)    # Current camera temperature (not super accurate, but might be useful for someone)
+    print(camera.battery)        # Current battery level... I think the value ranges from 0-3, but not quite sure yet.
+    print(camera.battery_string) # Gives battery level as a string ("OK" or "Low").  Returns "Unknown" if value is... well, unknown
+    print(camera.notifications)  # Number of unread notifications (ie. motion alerts that haven't been viewed)
+
+
+
+ + +
+
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_modules/blinkpy/blinkpy.html b/docs/_build/html/_modules/blinkpy/blinkpy.html new file mode 100644 index 0000000..405e8f0 --- /dev/null +++ b/docs/_build/html/_modules/blinkpy/blinkpy.html @@ -0,0 +1,535 @@ + + + + + + + blinkpy.blinkpy — blinkpy 0.7.0 documentation + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

Source code for blinkpy.blinkpy

+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+blinkpy by Kevin Fronczak - A Blink camera Python library.
+
+https://github.com/fronzbot/blinkpy
+Original protocol hacking by MattTW :
+https://github.com/MattTW/BlinkMonitorProtocol
+Published under the MIT license - See LICENSE file for more details.
+"Blink Wire-Free HS Home Monitoring & Alert Systems" is a trademark
+owned by Immedia Inc., see www.blinkforhome.com for more information.
+I am in no way affiliated with Blink, nor Immedia Inc.
+"""
+
+import json
+import getpass
+from shutil import copyfileobj
+import requests
+from requests.structures import CaseInsensitiveDict
+import blinkpy.helpers.errors as ERROR
+from blinkpy.helpers.constants import (
+    BLINK_URL, LOGIN_URL, LOGIN_BACKUP_URL,
+    DEFAULT_URL, ONLINE
+)
+
+
+
[docs]def _attempt_reauthorization(blink): + """Attempt to refresh auth token and links.""" + headers = blink.get_auth_token() + blink.set_links() + return headers
+ + +
[docs]def _request(blink, url='http://google.com', data=None, headers=None, + reqtype='get', stream=False, json_resp=True, is_retry=False): + """Perform server requests and check if reauthorization neccessary.""" + if reqtype == 'post': + response = requests.post(url, headers=headers, + data=data) + elif reqtype == 'get': + response = requests.get(url, headers=headers, + stream=stream) + else: + raise BlinkException(ERROR.REQUEST) + + if json_resp and 'code' in response.json(): + if is_retry: + raise BlinkAuthenticationException( + (response.json()['code'], response.json()['message'])) + else: + headers = _attempt_reauthorization(blink) + return _request(blink, url=url, data=data, headers=headers, + reqtype=reqtype, stream=stream, + json_resp=json_resp, is_retry=True) + # pylint: disable=no-else-return + if json_resp: + return response.json() + else: + return response
+ + +# pylint: disable=super-init-not-called +class BlinkException(Exception): + """Class to throw general blink exception.""" + + def __init__(self, errcode): + """Initialize BlinkException.""" + self.errid = errcode[0] + self.message = errcode[1] + + +class BlinkAuthenticationException(BlinkException): + """Class to throw authentication exception.""" + + pass + + +
[docs]class BlinkURLHandler(object): + """Class that handles Blink URLS.""" + + def __init__(self, region_id): + """Initialize the urls.""" + self.base_url = "https://rest.{}.{}".format(region_id, BLINK_URL) + self.home_url = "{}/homescreen".format(self.base_url) + self.event_url = "{}/events/network".format(self.base_url) + self.network_url = "{}/network".format(self.base_url) + self.networks_url = "{}/networks".format(self.base_url) + self.video_url = "{}/api/v2/videos".format(self.base_url)
+ + +
[docs]class BlinkCamera(object): + """Class to initialize individual camera.""" + + def __init__(self, config, blink): + """Initiailize BlinkCamera.""" + self.blink = blink + self.urls = self.blink.urls + self.id = str(config['device_id']) # pylint: disable=invalid-name + self.name = config['name'] + self._status = config['armed'] + self.thumbnail = "{}{}.jpg".format(self.urls.base_url, + config['thumbnail']) + self.clip = "{}{}".format(self.urls.base_url, config['video']) + self.temperature = config['temp'] + self.battery = config['battery'] + self.notifications = config['notifications'] + self.motion = {} + self.header = None + self.image_link = None + self.arm_link = None + self.region_id = config['region_id'] + + @property + def armed(self): + """Return camera arm status.""" + return self._status + + @property + def battery_string(self): + """Return string indicating battery status.""" + status = "Unknown" + if self.battery > 1 and self.battery <= 3: + status = "OK" + elif self.battery >= 0: + status = "Low" + return status + +
[docs] def snap_picture(self): + """Take a picture with camera to create a new thumbnail.""" + _request(self.blink, url=self.image_link, + headers=self.header, reqtype='post')
+ +
[docs] def set_motion_detect(self, enable): + """Set motion detection.""" + url = self.arm_link + if enable: + _request(self.blink, url=url + 'enable', + headers=self.header, reqtype='post') + else: + _request(self.blink, url=url + 'disable', + headers=self.header, reqtype='post')
+ +
[docs] def update(self, values): + """Update camera information.""" + self.name = values['name'] + self._status = values['armed'] + self.thumbnail = "{}{}.jpg".format( + self.urls.base_url, values['thumbnail']) + self.clip = "{}{}".format( + self.urls.base_url, values['video']) + self.temperature = values['temp'] + self.battery = values['battery'] + self.notifications = values['notifications']
+ +
[docs] def image_refresh(self): + """Refresh current thumbnail.""" + url = self.urls.home_url + response = _request(self.blink, url=url, headers=self.header, + reqtype='get')['devices'] + for element in response: + try: + if str(element['device_id']) == self.id: + self.thumbnail = ( + "{}{}.jpg".format( + self.urls.base_url, element['thumbnail']) + ) + return self.thumbnail + except KeyError: + pass + return None
+ +
[docs] def image_to_file(self, path): + """Write image to file.""" + thumb = self.image_refresh() + response = _request(self.blink, url=thumb, headers=self.header, + reqtype='get', stream=True, json_resp=False) + if response.status_code == 200: + with open(path, 'wb') as imgfile: + copyfileobj(response.raw, imgfile)
+ +
[docs] def video_to_file(self, path): + """Write video to file.""" + response = _request(self.blink, url=self.clip, headers=self.header, + reqtype='get', stream=True, json_resp=False) + with open(path, 'wb') as vidfile: + copyfileobj(response.raw, vidfile)
+ + + +
+ +
+
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_modules/index.html b/docs/_build/html/_modules/index.html new file mode 100644 index 0000000..718969b --- /dev/null +++ b/docs/_build/html/_modules/index.html @@ -0,0 +1,84 @@ + + + + + + + Overview: module code — blinkpy 0.7.0 documentation + + + + + + + + + + + + + + + + + + + +
+
+
+
+ +

All modules for which code is available

+ + +
+
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/_build/html/_sources/README.rst.txt b/docs/_build/html/_sources/README.rst.txt new file mode 100644 index 0000000..5eb9127 --- /dev/null +++ b/docs/_build/html/_sources/README.rst.txt @@ -0,0 +1,86 @@ +blinkpy |Build Status| |Coverage Status| |PyPi Version| +=========================================================== +A Python library for the Blink Camera system +Only compatible with Python 3+ + +Disclaimer: +~~~~~~~~~~~~~~~ +Published under the MIT license - See LICENSE file for more details. + +"Blink Wire-Free HS Home Monitoring & Alert Systems" is a trademark owned by Immedia Inc., see www.blinkforhome.com for more information. +I am in no way affiliated with Blink, nor Immedia Inc. + +Original protocol hacking by MattTW : https://github.com/MattTW/BlinkMonitorProtocol + +API calls faster than 60 seconds is not recommended as it can overwhelm Blink's servers. Please use this module responsibly. + +Installation +================ +``pip3 install blinkpy`` + +Installing Development Version +================================== +To install the current development version, perform the following steps. Note that the following will create a blinkpy directory in your home area: + +.. code:: bash + + $ cd ~ + $ git clone https://github.com/fronzbot/blinkpy.git + $ cd blinkpy + $ rm -rf build dist + $ python3 setup.py bdist_wheel + $ pip3 install --upgrade dist/*.whl + + +Purpose +=========== +This library was built with the intention of allowing easy communication with Blink camera systems, specifically so I can add a module into homeassistant https://home-assistant.io + +Usage +========= +In terms of usage, you just need to instantiate the module with a username and password and call the ``setup_system()`` method. + +.. code:: python + + import blinkpy + blink = blinkpy.Blink(username='YOUR USER NAME', password='YOUR PASSWORD') + blink.setup_system() + +If you leave out either of those parameters, you need to call the login function which will prompt for your username and password + +.. code:: python + + import blinkpy + blink = blinkpy.Blink() + blink.login() + + +Once the login information is entered, you can run the `setup_system()` function which will attempt to authenticate with Blink servers using your username and password, obtain network ids, and create a list of cameras. +The cameras are of a BlinkCamera class, of which the following parameters can be used (the code below creates a Blink object and iterates through each camera found) + +.. code:: python + + import blinkpy + + blink = blinkpy.Blink(username='YOUR USER NAME', password='YOUR PASSWORD') + blink.setup_system() + + for name, camera in blink.cameras.items(): + print(name) # Name of the camera + print(camera.id) # Integer id of the camera (assigned by Blink) + print(camera.armed) # Whether the device is armed/disarmed (ie. detecting motion) + print(camera.clip) # Link to last motion clip captured + print(camera.thumbnail) # Link to current camera thumbnail + print(camera.temperature) # Current camera temperature (not super accurate, but might be useful for someone) + print(camera.battery) # Current battery level... I think the value ranges from 0-3, but not quite sure yet. + print(camera.battery_string) # Gives battery level as a string ("OK" or "Low"). Returns "Unknown" if value is... well, unknown + print(camera.notifications) # Number of unread notifications (ie. motion alerts that haven't been viewed) + + +.. |Build Status| image:: https://travis-ci.org/fronzbot/blinkpy.svg?branch=dev + :target: https://travis-ci.org/fronzbot/blinkpy +.. |Coverage Status| image:: https://coveralls.io/repos/github/fronzbot/blinkpy/badge.svg?branch=dev + :target: https://coveralls.io/github/fronzbot/blinkpy?branch=dev +.. |PyPi Version| image:: https://img.shields.io/pypi/v/blinkpy.svg + :target: https://pypi.python.org/pypi/blinkpy + diff --git a/docs/_build/html/_sources/api/blinkpy.rst.txt b/docs/_build/html/_sources/api/blinkpy.rst.txt new file mode 100644 index 0000000..6793b04 --- /dev/null +++ b/docs/_build/html/_sources/api/blinkpy.rst.txt @@ -0,0 +1,19 @@ +.. _core_module: + +:mod:`blinkpy.blinkpy` +---------------------- + +.. automodule:: blinkpy.blinkpy + +.. autoclass:: Blink + :members: + +.. autoclass:: BlinkCamera + :members: + +.. autoclass:: BlinkURLHandler + :members: + +.. autofunction:: _request + +.. autofunction:: _attempt_reauthorization diff --git a/docs/_build/html/_sources/index.rst.txt b/docs/_build/html/_sources/index.rst.txt new file mode 100644 index 0000000..d31aabe --- /dev/null +++ b/docs/_build/html/_sources/index.rst.txt @@ -0,0 +1,22 @@ +.. blinkpy documentation master file, created by + sphinx-quickstart on Sat Jan 20 22:20:16 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to blinkpy's documentation! +=================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + :glob: + + README + api/* + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/_build/html/_static/ajax-loader.gif b/docs/_build/html/_static/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..61faf8cab23993bd3e1560bff0668bd628642330 GIT binary patch literal 673 zcmZ?wbhEHb6krfw_{6~Q|Nno%(3)e{?)x>&1u}A`t?OF7Z|1gRivOgXi&7IyQd1Pl zGfOfQ60;I3a`F>X^fL3(@);C=vM_KlFfb_o=k{|A33hf2a5d61U}gjg=>Rd%XaNQW zW@Cw{|b%Y*pl8F?4B9 zlo4Fz*0kZGJabY|>}Okf0}CCg{u4`zEPY^pV?j2@h+|igy0+Kz6p;@SpM4s6)XEMg z#3Y4GX>Hjlml5ftdH$4x0JGdn8~MX(U~_^d!Hi)=HU{V%g+mi8#UGbE-*ao8f#h+S z2a0-5+vc7MU$e-NhmBjLIC1v|)9+Im8x1yacJ7{^tLX(ZhYi^rpmXm0`@ku9b53aN zEXH@Y3JaztblgpxbJt{AtE1ad1Ca>{v$rwwvK(>{m~Gf_=-Ro7Fk{#;i~+{{>QtvI yb2P8Zac~?~=sRA>$6{!(^3;ZP0TPFR(G_-UDU(8Jl0?(IXu$~#4A!880|o%~Al1tN literal 0 HcmV?d00001 diff --git a/docs/_build/html/_static/alabaster.css b/docs/_build/html/_static/alabaster.css new file mode 100644 index 0000000..be65b13 --- /dev/null +++ b/docs/_build/html/_static/alabaster.css @@ -0,0 +1,693 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif; + font-size: 17px; + background-color: #fff; + color: #000; + margin: 0; + padding: 0; +} + + +div.document { + width: 940px; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 220px; +} + +div.sphinxsidebar { + width: 220px; + font-size: 14px; + line-height: 1.5; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #fff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +div.body > .section { + text-align: left; +} + +div.footer { + width: 940px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + +div.relations { + display: none; +} + + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: left; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: 'Garamond', 'Georgia', serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif; + font-size: 1em; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: 'Garamond', 'Georgia', serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fafafa; +} + +div.admonition p.admonition-title { + font-family: 'Garamond', 'Georgia', serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: #fff; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +/* Cloned from + * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 + */ +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #EEE; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + + +@media screen and (max-width: 870px) { + + div.sphinxsidebar { + display: none; + } + + div.document { + width: 100%; + + } + + div.documentwrapper { + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.bodywrapper { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 0; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .bodywrapper { + margin: 0; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + + +} + + + +@media screen and (max-width: 875px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + } + + div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + padding: 0; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Make nested-list/multi-paragraph items look better in Releases changelog + * pages. Without this, docutils' magical list fuckery causes inconsistent + * formatting between different release sub-lists. + */ +div#changelog > div.section > ul > li > p:only-child { + margin-bottom: 0; +} + +/* Hide fugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} \ No newline at end of file diff --git a/docs/_build/html/_static/basic.css b/docs/_build/html/_static/basic.css new file mode 100644 index 0000000..6f40830 --- /dev/null +++ b/docs/_build/html/_static/basic.css @@ -0,0 +1,643 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox input[type="text"] { + width: 170px; +} + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dl { + margin-bottom: 15px; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +div.code-block-caption { + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +div.code-block-caption + div > div.highlight > pre { + margin-top: 0; +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + padding: 1em 1em 0; +} + +div.literal-block-wrapper div.highlight { + margin: 0; +} + +code.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +code.descclassname { + background-color: transparent; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: relative; + left: 0px; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs/_build/html/_static/comment-bright.png b/docs/_build/html/_static/comment-bright.png new file mode 100644 index 0000000000000000000000000000000000000000..15e27edb12ac25701ac0ac21b97b52bb4e45415e GIT binary patch literal 756 zcmVgfIX78 z$8Pzv({A~p%??+>KickCb#0FM1rYN=mBmQ&Nwp<#JXUhU;{|)}%&s>suq6lXw*~s{ zvHx}3C%<;wE5CH!BR{p5@ml9ws}y)=QN-kL2?#`S5d*6j zk`h<}j1>tD$b?4D^N9w}-k)bxXxFg>+#kme^xx#qg6FI-%iv2U{0h(Y)cs%5a|m%Pn_K3X_bDJ>EH#(Fb73Z zfUt2Q3B>N+ot3qb*DqbTZpFIn4a!#_R-}{?-~Hs=xSS6p&$sZ-k1zDdtqU`Y@`#qL z&zv-~)Q#JCU(dI)Hf;$CEnK=6CK50}q7~wdbI->?E07bJ0R;!GSQTs5Am`#;*WHjvHRvY?&$Lm-vq1a_BzocI^ULXV!lbMd%|^B#fY;XX)n<&R^L z=84u1e_3ziq;Hz-*k5~zwY3*oDKt0;bM@M@@89;@m*4RFgvvM_4;5LB!@OB@^WbVT zjl{t;a8_>od-~P4 m{5|DvB&z#xT;*OnJqG}gk~_7HcNkCr0000W zanA~u9RIXo;n7c96&U)YLgs-FGlx~*_c{Jgvesu1E5(8YEf&5wF=YFPcRe@1=MJmi zag(L*xc2r0(slpcN!vC5CUju;vHJkHc*&70_n2OZsK%O~A=!+YIw z7zLLl7~Z+~RgWOQ=MI6$#0pvpu$Q43 zP@36QAmu6!_9NPM?o<1_!+stoVRRZbW9#SPe!n;#A_6m8f}|xN1;H{`0RoXQ2LM47 zt(g;iZ6|pCb@h2xk&(}S3=EVBUO0e90m2Lp5CB<(SPIaB;n4))3JB87Or#XPOPcum z?<^(g+m9}VNn4Y&B`g8h{t_$+RB1%HKRY6fjtd-<7&EsU;vs0GM(Lmbhi%Gwcfs0FTF}T zL{_M6Go&E0Eg8FuB*(Yn+Z*RVTBE@10eIOb3El^MhO`GabDll(V0&FlJi2k^;q8af zkENdk2}x2)_KVp`5OAwXZM;dG0?M-S)xE1IKDi6BY@5%Or?#aZ9$gcX)dPZ&wA1a< z$rFXHPn|TBf`e?>Are8sKtKrKcjF$i^lp!zkL?C|y^vlHr1HXeVJd;1I~g&Ob-q)& z(fn7s-KI}G{wnKzg_U5G(V%bX6uk zIa+<@>rdmZYd!9Y=C0cuchrbIjuRB_Wq{-RXlic?flu1*_ux}x%(HDH&nT`k^xCeC ziHi1!ChH*sQ6|UqJpTTzX$aw8e(UfcS^f;6yBWd+(1-70zU(rtxtqR%j z-lsH|CKQJXqD{+F7V0OTv8@{~(wp(`oIP^ZykMWgR>&|RsklFMCnOo&Bd{le} zV5F6424Qzl;o2G%oVvmHgRDP9!=rK8fy^!yV8y*4p=??uIRrrr0?>O!(z*g5AvL2!4z0{sq%vhG*Po}`a<6%kTK5TNhtC8}rXNu&h^QH4A&Sk~Autm*s~45(H7+0bi^MraaRVzr05hQ3iK?j` zR#U@^i0WhkIHTg29u~|ypU?sXCQEQgXfObPW;+0YAF;|5XyaMAEM0sQ@4-xCZe=0e z7r$ofiAxn@O5#RodD8rh5D@nKQ;?lcf@tg4o+Wp44aMl~c47azN_(im0N)7OqdPBC zGw;353_o$DqGRDhuhU$Eaj!@m000000NkvXXu0mjfjZ7Z_ literal 0 HcmV?d00001 diff --git a/docs/_build/html/_static/custom.css b/docs/_build/html/_static/custom.css new file mode 100644 index 0000000..2a924f1 --- /dev/null +++ b/docs/_build/html/_static/custom.css @@ -0,0 +1 @@ +/* This file intentionally left blank. */ diff --git a/docs/_build/html/_static/doctools.js b/docs/_build/html/_static/doctools.js new file mode 100644 index 0000000..0c15c00 --- /dev/null +++ b/docs/_build/html/_static/doctools.js @@ -0,0 +1,311 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + */ +jQuery.urldecode = function(x) { + return decodeURIComponent(x).replace(/\+/g, ' '); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var bbox = span.getBBox(); + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + var parentOfText = node.parentNode.parentNode; + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keyup(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box or textarea + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); \ No newline at end of file diff --git a/docs/_build/html/_static/down-pressed.png b/docs/_build/html/_static/down-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..5756c8cad8854722893dc70b9eb4bb0400343a39 GIT binary patch literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`OFdm2Ln;`PZ^+1>KjR?B@S0W7 z%OS_REiHONoJ6{+Ks@6k3590|7k9F+ddB6!zw3#&!aw#S`x}3V3&=A(a#84O-&F7T z^k3tZB;&iR9siw0|F|E|DAL<8r-F4!1H-;1{e*~yAKZN5f0|Ei6yUmR#Is)EM(Po_ zi`qJR6|P<~+)N+kSDgL7AjdIC_!O7Q?eGb+L+qOjm{~LLinM4NHn7U%HcK%uoMYO5 VJ~8zD2B3o(JYD@<);T3K0RV0%P>BEl literal 0 HcmV?d00001 diff --git a/docs/_build/html/_static/down.png b/docs/_build/html/_static/down.png new file mode 100644 index 0000000000000000000000000000000000000000..1b3bdad2ceffae91cee61b32f3295f9bbe646e48 GIT binary patch literal 202 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6CVIL!hEy=F?b*7pIY7kW{q%Rg zx!yQ<9v8bmJwa`TQk7YSw}WVQ()mRdQ;TC;* literal 0 HcmV?d00001 diff --git a/docs/_build/html/_static/file.png b/docs/_build/html/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/docs/_build/html/_static/jquery-3.1.0.js b/docs/_build/html/_static/jquery-3.1.0.js new file mode 100644 index 0000000..f2fc274 --- /dev/null +++ b/docs/_build/html/_static/jquery-3.1.0.js @@ -0,0 +1,10074 @@ +/*eslint-disable no-unused-vars*/ +/*! + * jQuery JavaScript Library v3.1.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2016-07-07T21:44Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + + + + function DOMEval( code, doc ) { + doc = doc || document; + + var script = doc.createElement( "script" ); + + script.text = code; + doc.head.appendChild( script ).parentNode.removeChild( script ); + } +/* global Symbol */ +// Defining this global in .eslintrc would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.1.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? + + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + + // Return all the elements in a clean array + slice.call( this ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = jQuery.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isFunction: function( obj ) { + return jQuery.type( obj ) === "function"; + }, + + isArray: Array.isArray, + + isWindow: function( obj ) { + return obj != null && obj === obj.window; + }, + + isNumeric: function( obj ) { + + // As of jQuery 3.0, isNumeric is limited to + // strings and numbers (primitives or objects) + // that can be coerced to finite numbers (gh-2662) + var type = jQuery.type( obj ); + return ( type === "number" || type === "string" ) && + + // parseFloat NaNs numeric-cast false positives ("") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + !isNaN( obj - parseFloat( obj ) ); + }, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + // Convert dashed to camelCase; used by the css and data modules + // Support: IE <=9 - 11, Edge 12 - 13 + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: Date.now, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.0 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-01-04 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + // Known :disabled false positives: + // IE: *[disabled]:not(button, input, select, textarea, optgroup, option, menuitem, fieldset) + // not IE: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Check form elements and option elements for explicit disabling + return "label" in elem && elem.disabled === disabled || + "form" in elem && elem.disabled === disabled || + + // Check non-disabled form elements for fieldset[disabled] ancestors + "form" in elem && elem.disabled === false && ( + // Support: IE6-11+ + // Ancestry is covered for us + elem.isDisabled === disabled || + + // Otherwise, assume any non-