From f443c6434176a08f9255944412628abf5d95b044 Mon Sep 17 00:00:00 2001
From: Marko Mikulicic <mkm@cesanta.com>
Date: Wed, 11 May 2016 20:35:52 +0300
Subject: [PATCH] Temporarily disable appdash from docker-compose

Until I read the doc and find how to limit the retention,
otherwise it just eats all my ram and cpu and things start to fall
apart.

PUBLISHED_FROM=eb33fb44736f07b992270689217aca4af70513ff
---
 docs/build-options/disabling-flags.md         |    12 -
 docs/build-options/enabling-flags.md          |    11 -
 docs/build-options/intro.md                   |    17 -
 docs/build-options/items.json                 |     9 -
 docs/build-options/platform-spec.md           |    10 -
 docs/build-options/tunables.md                |    11 -
 docs/build_opts.adoc                          |    54 +
 docs/c-api/coap.h/intro.md                    |    16 -
 docs/c-api/coap.h/items.json                  |    44 -
 docs/c-api/coap.h/mg_coap_add_option.md       |    13 -
 docs/c-api/coap.h/mg_coap_compose.md          |    12 -
 docs/c-api/coap.h/mg_coap_free_options.md     |    11 -
 docs/c-api/coap.h/mg_coap_parse.md            |    22 -
 docs/c-api/coap.h/mg_coap_send_ack.md         |    12 -
 docs/c-api/coap.h/mg_coap_send_message.md     |    19 -
 docs/c-api/coap.h/mg_set_protocol_coap.md     |    10 -
 docs/c-api/coap.h/struct_mg_coap_message.md   |    20 -
 docs/c-api/coap.h/struct_mg_coap_option.md    |    16 -
 docs/c-api/dns-server.h/intro.md              |     8 -
 docs/c-api/dns-server.h/items.json            |    20 -
 .../c-api/dns-server.h/mg_dns_create_reply.md |    36 -
 .../c-api/dns-server.h/mg_dns_reply_record.md |    18 -
 docs/c-api/dns-server.h/mg_dns_send_reply.md  |    19 -
 docs/c-api/dns.h/intro.md                     |     8 -
 docs/c-api/dns.h/items.json                   |    48 -
 docs/c-api/dns.h/mg_dns_copy_questions.md     |    15 -
 docs/c-api/dns.h/mg_dns_encode_record.md      |    25 -
 docs/c-api/dns.h/mg_dns_insert_header.md      |    13 -
 docs/c-api/dns.h/mg_dns_parse_record_data.md  |    20 -
 docs/c-api/dns.h/mg_dns_uncompress_name.md    |    21 -
 docs/c-api/dns.h/mg_parse_dns.md              |    10 -
 docs/c-api/dns.h/mg_send_dns_query.md         |    11 -
 docs/c-api/dns.h/mg_set_protocol_dns.md       |    19 -
 docs/c-api/dns.h/struct_mg_dns_message.md     |    18 -
 .../dns.h/struct_mg_dns_resource_record.md    |    17 -
 docs/c-api/http.h/intro.md                    |     8 -
 docs/c-api/http.h/items.json                  |   128 -
 docs/c-api/http.h/mg_connect_http.md          |    35 -
 docs/c-api/http.h/mg_connect_http_opt.md      |    18 -
 docs/c-api/http.h/mg_connect_ws.md            |    30 -
 docs/c-api/http.h/mg_connect_ws_opt.md        |    17 -
 docs/c-api/http.h/mg_file_upload_handler.md   |    39 -
 docs/c-api/http.h/mg_fu_fname_fn.md           |    11 -
 docs/c-api/http.h/mg_get_http_header.md       |    13 -
 docs/c-api/http.h/mg_get_http_var.md          |    16 -
 .../mg_http_create_digest_auth_header.md      |    13 -
 docs/c-api/http.h/mg_http_parse_header.md     |    23 -
 docs/c-api/http.h/mg_parse_http.md            |    15 -
 docs/c-api/http.h/mg_parse_multipart.md       |    46 -
 docs/c-api/http.h/mg_printf_html_escape.md    |    10 -
 docs/c-api/http.h/mg_printf_http_chunk.md     |    11 -
 .../c-api/http.h/mg_printf_websocket_frame.md |    14 -
 .../c-api/http.h/mg_register_http_endpoint.md |    35 -
 docs/c-api/http.h/mg_send_head.md             |    21 -
 docs/c-api/http.h/mg_send_http_chunk.md       |    25 -
 docs/c-api/http.h/mg_send_response_line.md    |    21 -
 docs/c-api/http.h/mg_send_websocket_frame.md  |    26 -
 docs/c-api/http.h/mg_send_websocket_framev.md |    13 -
 .../http.h/mg_send_websocket_handshake.md     |    22 -
 .../http.h/mg_send_websocket_handshake2.md    |    19 -
 docs/c-api/http.h/mg_serve_http.md            |    28 -
 .../http.h/mg_set_protocol_http_websocket.md  |    50 -
 docs/c-api/http.h/mg_url_decode.md            |    18 -
 docs/c-api/http.h/struct_http_message.md      |    38 -
 .../http.h/struct_mg_http_multipart_part.md   |    16 -
 .../c-api/http.h/struct_mg_serve_http_opts.md |   104 -
 docs/c-api/http.h/struct_websocket_message.md |    14 -
 docs/c-api/items.json                         |    44 -
 docs/c-api/json-rpc.h/intro.md                |     8 -
 docs/c-api/json-rpc.h/items.json              |    44 -
 docs/c-api/json-rpc.h/mg_rpc_create_error.md  |    16 -
 docs/c-api/json-rpc.h/mg_rpc_create_reply.md  |    16 -
 .../c-api/json-rpc.h/mg_rpc_create_request.md |    16 -
 .../json-rpc.h/mg_rpc_create_std_error.md     |    22 -
 docs/c-api/json-rpc.h/mg_rpc_dispatch.md      |    20 -
 docs/c-api/json-rpc.h/mg_rpc_parse_reply.md   |    24 -
 docs/c-api/json-rpc.h/struct_mg_rpc_error.md  |    16 -
 docs/c-api/json-rpc.h/struct_mg_rpc_reply.md  |    14 -
 .../c-api/json-rpc.h/struct_mg_rpc_request.md |    15 -
 docs/c-api/mbuf.h/intro.md                    |    11 -
 docs/c-api/mbuf.h/items.json                  |    40 -
 docs/c-api/mbuf.h/mbuf_append.md              |    12 -
 docs/c-api/mbuf.h/mbuf_free.md                |    10 -
 docs/c-api/mbuf.h/mbuf_init.md                |    11 -
 docs/c-api/mbuf.h/mbuf_insert.md              |    14 -
 docs/c-api/mbuf.h/mbuf_remove.md              |    10 -
 docs/c-api/mbuf.h/mbuf_resize.md              |    13 -
 docs/c-api/mbuf.h/mbuf_trim.md                |    10 -
 docs/c-api/mbuf.h/struct_mbuf.md              |    14 -
 docs/c-api/mqtt-broker.h/intro.md             |     8 -
 docs/c-api/mqtt-broker.h/items.json           |    28 -
 docs/c-api/mqtt-broker.h/mg_mqtt_broker.md    |    32 -
 .../mqtt-broker.h/mg_mqtt_broker_init.md      |    10 -
 docs/c-api/mqtt-broker.h/mg_mqtt_next.md      |    18 -
 .../mqtt-broker.h/struct_mg_mqtt_broker.md    |    13 -
 .../mqtt-broker.h/struct_mg_mqtt_session.md   |    17 -
 docs/c-api/mqtt.h/intro.md                    |     8 -
 docs/c-api/mqtt.h/items.json                  |    80 -
 docs/c-api/mqtt.h/mg_mqtt_connack.md          |    10 -
 docs/c-api/mqtt.h/mg_mqtt_disconnect.md       |    10 -
 .../mqtt.h/mg_mqtt_next_subscribe_topic.md    |    15 -
 docs/c-api/mqtt.h/mg_mqtt_ping.md             |    10 -
 docs/c-api/mqtt.h/mg_mqtt_pong.md             |    10 -
 docs/c-api/mqtt.h/mg_mqtt_puback.md           |    10 -
 docs/c-api/mqtt.h/mg_mqtt_pubcomp.md          |    10 -
 docs/c-api/mqtt.h/mg_mqtt_publish.md          |    12 -
 docs/c-api/mqtt.h/mg_mqtt_pubrec.md           |    10 -
 docs/c-api/mqtt.h/mg_mqtt_pubrel.md           |    10 -
 docs/c-api/mqtt.h/mg_mqtt_suback.md           |    12 -
 docs/c-api/mqtt.h/mg_mqtt_subscribe.md        |    12 -
 docs/c-api/mqtt.h/mg_mqtt_unsuback.md         |    10 -
 docs/c-api/mqtt.h/mg_mqtt_unsubscribe.md      |    11 -
 docs/c-api/mqtt.h/mg_send_mqtt_handshake.md   |    10 -
 .../mqtt.h/mg_send_mqtt_handshake_opt.md      |    11 -
 docs/c-api/mqtt.h/mg_set_protocol_mqtt.md     |    20 -
 .../mqtt.h/struct_mg_mqtt_topic_expression.md |    13 -
 docs/c-api/net.h/intro.md                     |    12 -
 docs/c-api/net.h/items.json                   |   120 -
 docs/c-api/net.h/mg_add_sock.md               |    13 -
 docs/c-api/net.h/mg_add_sock_opt.md           |    15 -
 docs/c-api/net.h/mg_bind.md                   |    13 -
 docs/c-api/net.h/mg_bind_opt.md               |    26 -
 docs/c-api/net.h/mg_broadcast.md              |    19 -
 docs/c-api/net.h/mg_check_ip_acl.md           |    27 -
 docs/c-api/net.h/mg_connect.md                |    13 -
 docs/c-api/net.h/mg_connect_opt.md            |    57 -
 docs/c-api/net.h/mg_enable_javascript.md      |    14 -
 docs/c-api/net.h/mg_enable_multithreading.md  |    14 -
 docs/c-api/net.h/mg_event_handler_t.md        |    11 -
 docs/c-api/net.h/mg_mgr_free.md               |    12 -
 docs/c-api/net.h/mg_mgr_init.md               |    15 -
 docs/c-api/net.h/mg_mgr_poll.md               |    15 -
 docs/c-api/net.h/mg_next.md                   |    20 -
 docs/c-api/net.h/mg_printf.md                 |    12 -
 docs/c-api/net.h/mg_send.md                   |    14 -
 docs/c-api/net.h/mg_set_ssl.md                |    19 -
 docs/c-api/net.h/mg_set_timer.md              |    31 -
 docs/c-api/net.h/mg_socketpair.md             |    12 -
 docs/c-api/net.h/mg_time.md                   |    10 -
 docs/c-api/net.h/mg_vprintf.md                |    10 -
 docs/c-api/net.h/struct_mg_add_sock_opts.md   |    17 -
 docs/c-api/net.h/struct_mg_bind_opts.md       |    22 -
 docs/c-api/net.h/struct_mg_connect_opts.md    |    28 -
 docs/c-api/net.h/struct_mg_connection.md      |    63 -
 docs/c-api/net.h/struct_mg_mgr.md             |    21 -
 docs/c-api/net.h/struct_mg_str.md             |    13 -
 docs/c-api/util.h/MG_MK_STR.md                |    10 -
 docs/c-api/util.h/intro.md                    |     8 -
 docs/c-api/util.h/items.json                  |    96 -
 docs/c-api/util.h/mg_avprintf.md              |    22 -
 docs/c-api/util.h/mg_base64_decode.md         |    16 -
 docs/c-api/util.h/mg_base64_encode.md         |    12 -
 docs/c-api/util.h/mg_casecmp.md               |    10 -
 docs/c-api/util.h/mg_conn_addr_to_str.md      |    21 -
 docs/c-api/util.h/mg_fopen.md                 |    14 -
 docs/c-api/util.h/mg_hexdump.md               |    15 -
 docs/c-api/util.h/mg_hexdump_connection.md    |    15 -
 docs/c-api/util.h/mg_is_big_endian.md         |    10 -
 docs/c-api/util.h/mg_match_prefix.md          |    12 -
 docs/c-api/util.h/mg_mk_str.md                |    10 -
 docs/c-api/util.h/mg_ncasecmp.md              |    10 -
 docs/c-api/util.h/mg_next_comma_list_entry.md |    21 -
 docs/c-api/util.h/mg_open.md                  |    14 -
 docs/c-api/util.h/mg_skip.md                  |    17 -
 docs/c-api/util.h/mg_sock_addr_to_str.md      |    13 -
 docs/c-api/util.h/mg_sock_to_str.md           |    10 -
 docs/c-api/util.h/mg_start_thread.md          |    13 -
 docs/c-api/util.h/mg_stat.md                  |    14 -
 docs/c-api/util.h/mg_vcasecmp.md              |    11 -
 docs/c-api/util.h/mg_vcmp.md                  |    11 -
 docs/coap.adoc                                |   129 +
 docs/common.adoc                              |     2 +
 docs/concept.adoc                             |   167 +
 docs/design-concept/conn-flags.md             |    32 -
 docs/design-concept/event-handler.md          |    31 -
 docs/design-concept/events.md                 |    52 -
 docs/design-concept/intro.md                  |    24 -
 docs/design-concept/items.json                |     9 -
 docs/design-concept/memory-buffers.md         |    15 -
 docs/dns-server.adoc                          |    71 +
 docs/dns.adoc                                 |   151 +
 docs/http.adoc                                |   694 +
 docs/img/mbuf.png                             |   Bin 73349 -> 0 bytes
 docs/index-docinfo.html                       | 10396 ++++++++++++
 docs/index.adoc                               |    23 +
 docs/index.html                               | 14093 ++++++++++++++++
 docs/internal.adoc                            |    36 +
 docs/items.json                               |     8 -
 docs/json-rpc.adoc                            |   143 +
 docs/mbuf.adoc                                |    85 +
 docs/mqtt-broker.adoc                         |    82 +
 docs/mqtt.adoc                                |   161 +
 docs/net.adoc                                 |   499 +
 docs/net_if.adoc                              |   127 +
 docs/resolv.adoc                              |    64 +
 .../{usage-example/intro.md => tutorial.adoc} |    33 +-
 docs/uri.adoc                                 |    33 +
 docs/usage-example/items.json                 |     5 -
 docs/util.adoc                                |   260 +
 199 files changed, 27289 insertions(+), 3591 deletions(-)
 delete mode 100644 docs/build-options/disabling-flags.md
 delete mode 100644 docs/build-options/enabling-flags.md
 delete mode 100644 docs/build-options/intro.md
 delete mode 100644 docs/build-options/items.json
 delete mode 100644 docs/build-options/platform-spec.md
 delete mode 100644 docs/build-options/tunables.md
 create mode 100644 docs/build_opts.adoc
 delete mode 100644 docs/c-api/coap.h/intro.md
 delete mode 100644 docs/c-api/coap.h/items.json
 delete mode 100644 docs/c-api/coap.h/mg_coap_add_option.md
 delete mode 100644 docs/c-api/coap.h/mg_coap_compose.md
 delete mode 100644 docs/c-api/coap.h/mg_coap_free_options.md
 delete mode 100644 docs/c-api/coap.h/mg_coap_parse.md
 delete mode 100644 docs/c-api/coap.h/mg_coap_send_ack.md
 delete mode 100644 docs/c-api/coap.h/mg_coap_send_message.md
 delete mode 100644 docs/c-api/coap.h/mg_set_protocol_coap.md
 delete mode 100644 docs/c-api/coap.h/struct_mg_coap_message.md
 delete mode 100644 docs/c-api/coap.h/struct_mg_coap_option.md
 delete mode 100644 docs/c-api/dns-server.h/intro.md
 delete mode 100644 docs/c-api/dns-server.h/items.json
 delete mode 100644 docs/c-api/dns-server.h/mg_dns_create_reply.md
 delete mode 100644 docs/c-api/dns-server.h/mg_dns_reply_record.md
 delete mode 100644 docs/c-api/dns-server.h/mg_dns_send_reply.md
 delete mode 100644 docs/c-api/dns.h/intro.md
 delete mode 100644 docs/c-api/dns.h/items.json
 delete mode 100644 docs/c-api/dns.h/mg_dns_copy_questions.md
 delete mode 100644 docs/c-api/dns.h/mg_dns_encode_record.md
 delete mode 100644 docs/c-api/dns.h/mg_dns_insert_header.md
 delete mode 100644 docs/c-api/dns.h/mg_dns_parse_record_data.md
 delete mode 100644 docs/c-api/dns.h/mg_dns_uncompress_name.md
 delete mode 100644 docs/c-api/dns.h/mg_parse_dns.md
 delete mode 100644 docs/c-api/dns.h/mg_send_dns_query.md
 delete mode 100644 docs/c-api/dns.h/mg_set_protocol_dns.md
 delete mode 100644 docs/c-api/dns.h/struct_mg_dns_message.md
 delete mode 100644 docs/c-api/dns.h/struct_mg_dns_resource_record.md
 delete mode 100644 docs/c-api/http.h/intro.md
 delete mode 100644 docs/c-api/http.h/items.json
 delete mode 100644 docs/c-api/http.h/mg_connect_http.md
 delete mode 100644 docs/c-api/http.h/mg_connect_http_opt.md
 delete mode 100644 docs/c-api/http.h/mg_connect_ws.md
 delete mode 100644 docs/c-api/http.h/mg_connect_ws_opt.md
 delete mode 100644 docs/c-api/http.h/mg_file_upload_handler.md
 delete mode 100644 docs/c-api/http.h/mg_fu_fname_fn.md
 delete mode 100644 docs/c-api/http.h/mg_get_http_header.md
 delete mode 100644 docs/c-api/http.h/mg_get_http_var.md
 delete mode 100644 docs/c-api/http.h/mg_http_create_digest_auth_header.md
 delete mode 100644 docs/c-api/http.h/mg_http_parse_header.md
 delete mode 100644 docs/c-api/http.h/mg_parse_http.md
 delete mode 100644 docs/c-api/http.h/mg_parse_multipart.md
 delete mode 100644 docs/c-api/http.h/mg_printf_html_escape.md
 delete mode 100644 docs/c-api/http.h/mg_printf_http_chunk.md
 delete mode 100644 docs/c-api/http.h/mg_printf_websocket_frame.md
 delete mode 100644 docs/c-api/http.h/mg_register_http_endpoint.md
 delete mode 100644 docs/c-api/http.h/mg_send_head.md
 delete mode 100644 docs/c-api/http.h/mg_send_http_chunk.md
 delete mode 100644 docs/c-api/http.h/mg_send_response_line.md
 delete mode 100644 docs/c-api/http.h/mg_send_websocket_frame.md
 delete mode 100644 docs/c-api/http.h/mg_send_websocket_framev.md
 delete mode 100644 docs/c-api/http.h/mg_send_websocket_handshake.md
 delete mode 100644 docs/c-api/http.h/mg_send_websocket_handshake2.md
 delete mode 100644 docs/c-api/http.h/mg_serve_http.md
 delete mode 100644 docs/c-api/http.h/mg_set_protocol_http_websocket.md
 delete mode 100644 docs/c-api/http.h/mg_url_decode.md
 delete mode 100644 docs/c-api/http.h/struct_http_message.md
 delete mode 100644 docs/c-api/http.h/struct_mg_http_multipart_part.md
 delete mode 100644 docs/c-api/http.h/struct_mg_serve_http_opts.md
 delete mode 100644 docs/c-api/http.h/struct_websocket_message.md
 delete mode 100644 docs/c-api/items.json
 delete mode 100644 docs/c-api/json-rpc.h/intro.md
 delete mode 100644 docs/c-api/json-rpc.h/items.json
 delete mode 100644 docs/c-api/json-rpc.h/mg_rpc_create_error.md
 delete mode 100644 docs/c-api/json-rpc.h/mg_rpc_create_reply.md
 delete mode 100644 docs/c-api/json-rpc.h/mg_rpc_create_request.md
 delete mode 100644 docs/c-api/json-rpc.h/mg_rpc_create_std_error.md
 delete mode 100644 docs/c-api/json-rpc.h/mg_rpc_dispatch.md
 delete mode 100644 docs/c-api/json-rpc.h/mg_rpc_parse_reply.md
 delete mode 100644 docs/c-api/json-rpc.h/struct_mg_rpc_error.md
 delete mode 100644 docs/c-api/json-rpc.h/struct_mg_rpc_reply.md
 delete mode 100644 docs/c-api/json-rpc.h/struct_mg_rpc_request.md
 delete mode 100644 docs/c-api/mbuf.h/intro.md
 delete mode 100644 docs/c-api/mbuf.h/items.json
 delete mode 100644 docs/c-api/mbuf.h/mbuf_append.md
 delete mode 100644 docs/c-api/mbuf.h/mbuf_free.md
 delete mode 100644 docs/c-api/mbuf.h/mbuf_init.md
 delete mode 100644 docs/c-api/mbuf.h/mbuf_insert.md
 delete mode 100644 docs/c-api/mbuf.h/mbuf_remove.md
 delete mode 100644 docs/c-api/mbuf.h/mbuf_resize.md
 delete mode 100644 docs/c-api/mbuf.h/mbuf_trim.md
 delete mode 100644 docs/c-api/mbuf.h/struct_mbuf.md
 delete mode 100644 docs/c-api/mqtt-broker.h/intro.md
 delete mode 100644 docs/c-api/mqtt-broker.h/items.json
 delete mode 100644 docs/c-api/mqtt-broker.h/mg_mqtt_broker.md
 delete mode 100644 docs/c-api/mqtt-broker.h/mg_mqtt_broker_init.md
 delete mode 100644 docs/c-api/mqtt-broker.h/mg_mqtt_next.md
 delete mode 100644 docs/c-api/mqtt-broker.h/struct_mg_mqtt_broker.md
 delete mode 100644 docs/c-api/mqtt-broker.h/struct_mg_mqtt_session.md
 delete mode 100644 docs/c-api/mqtt.h/intro.md
 delete mode 100644 docs/c-api/mqtt.h/items.json
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_connack.md
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_disconnect.md
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_next_subscribe_topic.md
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_ping.md
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_pong.md
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_puback.md
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_pubcomp.md
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_publish.md
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_pubrec.md
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_pubrel.md
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_suback.md
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_subscribe.md
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_unsuback.md
 delete mode 100644 docs/c-api/mqtt.h/mg_mqtt_unsubscribe.md
 delete mode 100644 docs/c-api/mqtt.h/mg_send_mqtt_handshake.md
 delete mode 100644 docs/c-api/mqtt.h/mg_send_mqtt_handshake_opt.md
 delete mode 100644 docs/c-api/mqtt.h/mg_set_protocol_mqtt.md
 delete mode 100644 docs/c-api/mqtt.h/struct_mg_mqtt_topic_expression.md
 delete mode 100644 docs/c-api/net.h/intro.md
 delete mode 100644 docs/c-api/net.h/items.json
 delete mode 100644 docs/c-api/net.h/mg_add_sock.md
 delete mode 100644 docs/c-api/net.h/mg_add_sock_opt.md
 delete mode 100644 docs/c-api/net.h/mg_bind.md
 delete mode 100644 docs/c-api/net.h/mg_bind_opt.md
 delete mode 100644 docs/c-api/net.h/mg_broadcast.md
 delete mode 100644 docs/c-api/net.h/mg_check_ip_acl.md
 delete mode 100644 docs/c-api/net.h/mg_connect.md
 delete mode 100644 docs/c-api/net.h/mg_connect_opt.md
 delete mode 100644 docs/c-api/net.h/mg_enable_javascript.md
 delete mode 100644 docs/c-api/net.h/mg_enable_multithreading.md
 delete mode 100644 docs/c-api/net.h/mg_event_handler_t.md
 delete mode 100644 docs/c-api/net.h/mg_mgr_free.md
 delete mode 100644 docs/c-api/net.h/mg_mgr_init.md
 delete mode 100644 docs/c-api/net.h/mg_mgr_poll.md
 delete mode 100644 docs/c-api/net.h/mg_next.md
 delete mode 100644 docs/c-api/net.h/mg_printf.md
 delete mode 100644 docs/c-api/net.h/mg_send.md
 delete mode 100644 docs/c-api/net.h/mg_set_ssl.md
 delete mode 100644 docs/c-api/net.h/mg_set_timer.md
 delete mode 100644 docs/c-api/net.h/mg_socketpair.md
 delete mode 100644 docs/c-api/net.h/mg_time.md
 delete mode 100644 docs/c-api/net.h/mg_vprintf.md
 delete mode 100644 docs/c-api/net.h/struct_mg_add_sock_opts.md
 delete mode 100644 docs/c-api/net.h/struct_mg_bind_opts.md
 delete mode 100644 docs/c-api/net.h/struct_mg_connect_opts.md
 delete mode 100644 docs/c-api/net.h/struct_mg_connection.md
 delete mode 100644 docs/c-api/net.h/struct_mg_mgr.md
 delete mode 100644 docs/c-api/net.h/struct_mg_str.md
 delete mode 100644 docs/c-api/util.h/MG_MK_STR.md
 delete mode 100644 docs/c-api/util.h/intro.md
 delete mode 100644 docs/c-api/util.h/items.json
 delete mode 100644 docs/c-api/util.h/mg_avprintf.md
 delete mode 100644 docs/c-api/util.h/mg_base64_decode.md
 delete mode 100644 docs/c-api/util.h/mg_base64_encode.md
 delete mode 100644 docs/c-api/util.h/mg_casecmp.md
 delete mode 100644 docs/c-api/util.h/mg_conn_addr_to_str.md
 delete mode 100644 docs/c-api/util.h/mg_fopen.md
 delete mode 100644 docs/c-api/util.h/mg_hexdump.md
 delete mode 100644 docs/c-api/util.h/mg_hexdump_connection.md
 delete mode 100644 docs/c-api/util.h/mg_is_big_endian.md
 delete mode 100644 docs/c-api/util.h/mg_match_prefix.md
 delete mode 100644 docs/c-api/util.h/mg_mk_str.md
 delete mode 100644 docs/c-api/util.h/mg_ncasecmp.md
 delete mode 100644 docs/c-api/util.h/mg_next_comma_list_entry.md
 delete mode 100644 docs/c-api/util.h/mg_open.md
 delete mode 100644 docs/c-api/util.h/mg_skip.md
 delete mode 100644 docs/c-api/util.h/mg_sock_addr_to_str.md
 delete mode 100644 docs/c-api/util.h/mg_sock_to_str.md
 delete mode 100644 docs/c-api/util.h/mg_start_thread.md
 delete mode 100644 docs/c-api/util.h/mg_stat.md
 delete mode 100644 docs/c-api/util.h/mg_vcasecmp.md
 delete mode 100644 docs/c-api/util.h/mg_vcmp.md
 create mode 100644 docs/coap.adoc
 create mode 100644 docs/common.adoc
 create mode 100644 docs/concept.adoc
 delete mode 100644 docs/design-concept/conn-flags.md
 delete mode 100644 docs/design-concept/event-handler.md
 delete mode 100644 docs/design-concept/events.md
 delete mode 100644 docs/design-concept/intro.md
 delete mode 100644 docs/design-concept/items.json
 delete mode 100644 docs/design-concept/memory-buffers.md
 create mode 100644 docs/dns-server.adoc
 create mode 100644 docs/dns.adoc
 create mode 100644 docs/http.adoc
 delete mode 100644 docs/img/mbuf.png
 create mode 100644 docs/index-docinfo.html
 create mode 100644 docs/index.adoc
 create mode 100644 docs/index.html
 create mode 100644 docs/internal.adoc
 delete mode 100644 docs/items.json
 create mode 100644 docs/json-rpc.adoc
 create mode 100644 docs/mbuf.adoc
 create mode 100644 docs/mqtt-broker.adoc
 create mode 100644 docs/mqtt.adoc
 create mode 100644 docs/net.adoc
 create mode 100644 docs/net_if.adoc
 create mode 100644 docs/resolv.adoc
 rename docs/{usage-example/intro.md => tutorial.adoc} (53%)
 create mode 100644 docs/uri.adoc
 delete mode 100644 docs/usage-example/items.json
 create mode 100644 docs/util.adoc

diff --git a/docs/build-options/disabling-flags.md b/docs/build-options/disabling-flags.md
deleted file mode 100644
index c88e25b86..000000000
--- a/docs/build-options/disabling-flags.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: Disabling flags
----
-
-- `MG_DISABLE_HTTP_WEBSOCKET` disable HTTP + Websocket protocol support
-- `MG_DISABLE_HTTP_DIGEST_AUTH` disable HTTP Digest (MD5) authorization support
-- `MG_DISABLE_MQTT` disable MQTT support
-- `MG_DISABLE_SHA1` disable SHA1 support (used by Websocket)
-- `MG_DISABLE_MD5` disable MD5 support (used by HTTP auth)
-- `MG_DISABLE_JSON_RPC` disable JSON-RPC support
-- `MG_DISABLE_SOCKETPAIR` disable `mg_broadcast()` API
-- `MG_DISABLE_HTTP_KEEP_ALIVE` useful for embedded systems to save resources
diff --git a/docs/build-options/enabling-flags.md b/docs/build-options/enabling-flags.md
deleted file mode 100644
index 5dfd64595..000000000
--- a/docs/build-options/enabling-flags.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: Enabling flags
----
-
-- `MG_ENABLE_SSL` Enable OpenSSL support
-- `MG_ENABLE_IPV6` Enable IPV6 support
-- `MG_ENABLE_THREADS` enable `mg_start_thread()` API
-- `MG_ENABLE_MQTT_BROKER` enable MQTT broker
-- `MG_ENABLE_DNS_SERVER` enable DNS server
-- `MG_ENABLE_COAP` enable CoAP protocol
-- `MG_ENABLE_GETADDRINFO` enable `getaddrinfo()` in `mg_resolve2()`
diff --git a/docs/build-options/intro.md b/docs/build-options/intro.md
deleted file mode 100644
index f418a963c..000000000
--- a/docs/build-options/intro.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-title: Build Options
----
-
-Mongoose source code ships in a single .c file that contains functionality
-for all supported protocols (modules). Modules can be disabled at compile
-time which reduces executable size. That can be done by setting preprocessor
-flags. Also, some preprocessor flags can be used to tune internal Mongoose
-parameters.
-
-To set a preprocessor flag during compile time, use `-D <PREPROCESSOR_FLAG>`
-compiler option. For example, to disable both MQTT and JSON-RPC,
-compile the application `my_app.c` like this (assumed UNIX system):
-
-```
-  $ cc my_app.c mongoose.c -D MG_DISABLE_MQTT -D MG_DISABLE_JSON_RPC
-```
diff --git a/docs/build-options/items.json b/docs/build-options/items.json
deleted file mode 100644
index 2d8c57bdc..000000000
--- a/docs/build-options/items.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "items": [
-    { "type": "markdown", "name": "intro.md" },
-    { "type": "markdown", "name": "enabling-flags.md" },
-    { "type": "markdown", "name": "disabling-flags.md" },
-    { "type": "markdown", "name": "platform-spec.md" },
-    { "type": "markdown", "name": "tunables.md" }
-  ]
-}
diff --git a/docs/build-options/platform-spec.md b/docs/build-options/platform-spec.md
deleted file mode 100644
index 408045a89..000000000
--- a/docs/build-options/platform-spec.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: Platform specific
----
-
-Mongoose tries to detect the target platform whenever possible, but in some cases you have
-to explicitly declare some peculiarities of your target, such as:
-
-- `MG_LWIP`: use LWIP networking stack
-- `MG_CC3200`: enable workarounds for the TI CC3200 target.
-- `MG_ESP8266`: enable workarounds for the ESP8266 target, add `RTOS_SDK` to specify the RTOS SDK flavour.
diff --git a/docs/build-options/tunables.md b/docs/build-options/tunables.md
deleted file mode 100644
index 1eeefe427..000000000
--- a/docs/build-options/tunables.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: Tunables
----
-
-- `MG_MALLOC`, `MG_CALLOC`, `MG_REALLOC`, `MG_FREE` allow to use custom
-  memory allocator, e.g. `-DMG_MALLOC=my_malloc`
-- `MG_USE_READ_WRITE` when set replaces calls to `recv` with `read` and `send` with `write`,
-  thus enabling to add any kind of file descriptor (files, serial devices) to an event manager.
-- `MG_SSL_CRYPTO_MODERN`, `MG_SSL_CRYPTO_OLD` - choose either "Modern" or "Old" ciphers
-  instead of the default "Intermediate" setting.
-  See [this article](https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations) for details.
diff --git a/docs/build_opts.adoc b/docs/build_opts.adoc
new file mode 100644
index 000000000..ee6d44a56
--- /dev/null
+++ b/docs/build_opts.adoc
@@ -0,0 +1,54 @@
+
+== Build Options
+
+Mongoose source code ships in a single .c file that contains functionality
+for all supported protocols (modules). Modules can be disabled at compile
+time which reduces executable size. That can be done by setting preprocessor
+flags. Also, some preprocessor flags can be used to tune internal Mongoose
+parameters.
+
+To set a preprocessor flag during compile time, use `-D <PREPROCESSOR_FLAG>`
+compiler option. For example, to disable both MQTT and JSON-RPC,
+compile the application `my_app.c` like this (assumed UNIX system):
+
+```
+  $ cc my_app.c mongoose.c -D MG_DISABLE_MQTT -D MG_DISABLE_JSON_RPC
+```
+
+=== Enabling flags
+- `MG_ENABLE_SSL` Enable OpenSSL support
+- `MG_ENABLE_IPV6` Enable IPV6 support
+- `MG_ENABLE_THREADS` enable `mg_start_thread()` API
+- `MG_ENABLE_MQTT_BROKER` enable MQTT broker
+- `MG_ENABLE_DNS_SERVER` enable DNS server
+- `MG_ENABLE_COAP` enable CoAP protocol
+- `MG_ENABLE_GETADDRINFO` enable `getaddrinfo()` in `mg_resolve2()`
+
+=== Disabling flags
+
+- `MG_DISABLE_HTTP_WEBSOCKET` disable HTTP + Websocket protocol support
+- `MG_DISABLE_HTTP_DIGEST_AUTH` disable HTTP Digest (MD5) authorization support
+- `MG_DISABLE_MQTT` disable MQTT support
+- `MG_DISABLE_SHA1` disable SHA1 support (used by Websocket)
+- `MG_DISABLE_MD5` disable MD5 support (used by HTTP auth)
+- `MG_DISABLE_JSON_RPC` disable JSON-RPC support
+- `MG_DISABLE_SOCKETPAIR` disable `mg_broadcast()` API
+- `MG_DISABLE_HTTP_KEEP_ALIVE` useful for embedded systems to save resources
+
+=== Platform specific
+
+Mongoose tries to detect the target platform whenever possible, but in some cases you have
+to explicitly declare some peculiarities of your target, such as:
+
+- `MG_LWIP`: use LWIP networking stack
+- `MG_CC3200`: enable workarounds for the TI CC3200 target.
+- `MG_ESP8266`: enable workarounds for the ESP8266 target, add `RTOS_SDK` to specify the RTOS SDK flavour.
+
+=== Tunables
+- `MG_MALLOC`, `MG_CALLOC`, `MG_REALLOC`, `MG_FREE` allow to use custom
+  memory allocator, e.g. `-DMG_MALLOC=my_malloc`
+- `MG_USE_READ_WRITE` when set replaces calls to `recv` with `read` and `send` with `write`,
+  thus enabling to add any kind of file descriptor (files, serial devices) to an event manager.
+- `MG_SSL_CRYPTO_MODERN`, `MG_SSL_CRYPTO_OLD` - choose either "Modern" or "Old" ciphers
+  instead of the default "Intermediate" setting.
+  See [this article](https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations) for details.
diff --git a/docs/c-api/coap.h/intro.md b/docs/c-api/coap.h/intro.md
deleted file mode 100644
index 764f07775..000000000
--- a/docs/c-api/coap.h/intro.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: "CoAP"
-symbol_kind: "intro"
-decl_name: "coap.h"
----
-
-CoAP message format:
-
-```
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
-|Ver| T | TKL | Code | Message ID | Token (if any, TKL bytes) ...
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
-| Options (if any) ...            |1 1 1 1 1 1 1 1| Payload (if any) ...
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
-```
-
diff --git a/docs/c-api/coap.h/items.json b/docs/c-api/coap.h/items.json
deleted file mode 100644
index de1889c40..000000000
--- a/docs/c-api/coap.h/items.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
-    "items": [
-        {
-            "type": "markdown",
-            "name": "intro.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_set_protocol_coap.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_coap_add_option.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_coap_free_options.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_coap_send_message.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_coap_send_ack.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_coap_parse.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_coap_compose.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_coap_option.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_coap_message.md"
-        }
-    ]
-}
diff --git a/docs/c-api/coap.h/mg_coap_add_option.md b/docs/c-api/coap.h/mg_coap_add_option.md
deleted file mode 100644
index f56887e5d..000000000
--- a/docs/c-api/coap.h/mg_coap_add_option.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "mg_coap_add_option()"
-decl_name: "mg_coap_add_option"
-symbol_kind: "func"
-signature: |
-  struct mg_coap_option *mg_coap_add_option(struct mg_coap_message *cm,
-                                            uint32_t number, char *value,
-                                            size_t len);
----
-
-Add new option to mg_coap_message structure.
-Returns pointer to the newly created option. 
-
diff --git a/docs/c-api/coap.h/mg_coap_compose.md b/docs/c-api/coap.h/mg_coap_compose.md
deleted file mode 100644
index 844c1b61b..000000000
--- a/docs/c-api/coap.h/mg_coap_compose.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "mg_coap_compose()"
-decl_name: "mg_coap_compose"
-symbol_kind: "func"
-signature: |
-  uint32_t mg_coap_compose(struct mg_coap_message *cm, struct mbuf *io);
----
-
-Composes CoAP message from mg_coap_message structure.
-This is a helper function.
-Return value: see `mg_coap_send_message()` 
-
diff --git a/docs/c-api/coap.h/mg_coap_free_options.md b/docs/c-api/coap.h/mg_coap_free_options.md
deleted file mode 100644
index 39d07d443..000000000
--- a/docs/c-api/coap.h/mg_coap_free_options.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: "mg_coap_free_options()"
-decl_name: "mg_coap_free_options"
-symbol_kind: "func"
-signature: |
-  void mg_coap_free_options(struct mg_coap_message *cm);
----
-
-Free the memory allocated for options,
-if cm paramater doesn't contain any option does nothing. 
-
diff --git a/docs/c-api/coap.h/mg_coap_parse.md b/docs/c-api/coap.h/mg_coap_parse.md
deleted file mode 100644
index 2f3bc0c65..000000000
--- a/docs/c-api/coap.h/mg_coap_parse.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-title: "mg_coap_parse()"
-decl_name: "mg_coap_parse"
-symbol_kind: "func"
-signature: |
-  uint32_t mg_coap_parse(struct mbuf *io, struct mg_coap_message *cm);
----
-
-Parse COAP message and fills mg_coap_message and returns cm->flags.
-This is a helper function.
-
-NOTE: usually CoAP work over UDP, so lack of data means format error,
-but in theory it is possible to use CoAP over TCP (according to RFC)
-
-The caller have to check results and treat COAP_NOT_ENOUGH_DATA according to
-underlying protocol:
-
-- in case of UDP COAP_NOT_ENOUGH_DATA means COAP_FORMAT_ERROR,
-- in case of TCP client can try to receive more data
-
-Return value: see `mg_coap_send_message()` 
-
diff --git a/docs/c-api/coap.h/mg_coap_send_ack.md b/docs/c-api/coap.h/mg_coap_send_ack.md
deleted file mode 100644
index 5cdd0c1d1..000000000
--- a/docs/c-api/coap.h/mg_coap_send_ack.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "mg_coap_send_ack()"
-decl_name: "mg_coap_send_ack"
-symbol_kind: "func"
-signature: |
-  uint32_t mg_coap_send_ack(struct mg_connection *nc, uint16_t msg_id);
----
-
-Compose CoAP acknowledgement from `mg_coap_message`
-and send it into `nc` connection.
-Return value: see `mg_coap_send_message()` 
-
diff --git a/docs/c-api/coap.h/mg_coap_send_message.md b/docs/c-api/coap.h/mg_coap_send_message.md
deleted file mode 100644
index 34bf3c87c..000000000
--- a/docs/c-api/coap.h/mg_coap_send_message.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-title: "mg_coap_send_message()"
-decl_name: "mg_coap_send_message"
-symbol_kind: "func"
-signature: |
-  uint32_t mg_coap_send_message(struct mg_connection *nc,
-                                struct mg_coap_message *cm);
----
-
-Compose CoAP message from `mg_coap_message`
-and send it into `nc` connection.
-Return 0 on success. On error, it is a bitmask:
-
-- `#define MG_COAP_ERROR 0x10000`
-- `#define MG_COAP_FORMAT_ERROR (MG_COAP_ERROR | 0x20000)`
-- `#define MG_COAP_IGNORE (MG_COAP_ERROR | 0x40000)`
-- `#define MG_COAP_NOT_ENOUGH_DATA (MG_COAP_ERROR | 0x80000)`
-- `#define MG_COAP_NETWORK_ERROR (MG_COAP_ERROR | 0x100000)` 
-
diff --git a/docs/c-api/coap.h/mg_set_protocol_coap.md b/docs/c-api/coap.h/mg_set_protocol_coap.md
deleted file mode 100644
index 60981fb6b..000000000
--- a/docs/c-api/coap.h/mg_set_protocol_coap.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_set_protocol_coap()"
-decl_name: "mg_set_protocol_coap"
-symbol_kind: "func"
-signature: |
-  int mg_set_protocol_coap(struct mg_connection *nc);
----
-
-Set CoAP protocol handler - trigger CoAP specific events 
-
diff --git a/docs/c-api/coap.h/struct_mg_coap_message.md b/docs/c-api/coap.h/struct_mg_coap_message.md
deleted file mode 100644
index 0ea618a90..000000000
--- a/docs/c-api/coap.h/struct_mg_coap_message.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-title: "struct mg_coap_message"
-decl_name: "struct mg_coap_message"
-symbol_kind: "struct"
-signature: |
-  struct mg_coap_message {
-    uint32_t flags;
-    uint8_t msg_type;
-    uint8_t code_class;
-    uint8_t code_detail;
-    uint16_t msg_id;
-    struct mg_str token;
-    struct mg_coap_option *options;
-    struct mg_str payload;
-    struct mg_coap_option *optiomg_tail;
-  };
----
-
-CoAP message. See RFC 7252 for details. 
-
diff --git a/docs/c-api/coap.h/struct_mg_coap_option.md b/docs/c-api/coap.h/struct_mg_coap_option.md
deleted file mode 100644
index b5eeb15fa..000000000
--- a/docs/c-api/coap.h/struct_mg_coap_option.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: "struct mg_coap_option"
-decl_name: "struct mg_coap_option"
-symbol_kind: "struct"
-signature: |
-  struct mg_coap_option {
-    struct mg_coap_option *next;
-    uint32_t number;
-    struct mg_str value;
-  };
----
-
-CoAP options.
-Use mg_coap_add_option and mg_coap_free_options
-for creation and destruction. 
-
diff --git a/docs/c-api/dns-server.h/intro.md b/docs/c-api/dns-server.h/intro.md
deleted file mode 100644
index 8ac224dd1..000000000
--- a/docs/c-api/dns-server.h/intro.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-title: "DNS server"
-symbol_kind: "intro"
-decl_name: "dns-server.h"
----
-
-Disabled by default; enable with `-DMG_ENABLE_DNS_SERVER`.
-
diff --git a/docs/c-api/dns-server.h/items.json b/docs/c-api/dns-server.h/items.json
deleted file mode 100644
index feea0c960..000000000
--- a/docs/c-api/dns-server.h/items.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-    "items": [
-        {
-            "type": "markdown",
-            "name": "intro.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_dns_create_reply.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_dns_reply_record.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_dns_send_reply.md"
-        }
-    ]
-}
diff --git a/docs/c-api/dns-server.h/mg_dns_create_reply.md b/docs/c-api/dns-server.h/mg_dns_create_reply.md
deleted file mode 100644
index b616c925d..000000000
--- a/docs/c-api/dns-server.h/mg_dns_create_reply.md
+++ /dev/null
@@ -1,36 +0,0 @@
----
-title: "mg_dns_create_reply()"
-decl_name: "mg_dns_create_reply"
-symbol_kind: "func"
-signature: |
-  struct mg_dns_reply mg_dns_create_reply(struct mbuf *io,
-                                          struct mg_dns_message *msg);
----
-
-Create a DNS reply.
-
-The reply will be based on an existing query message `msg`.
-The query body will be appended to the output buffer.
-"reply + recursion allowed" will be added to the message flags and
-message's num_answers will be set to 0.
-
-Answer records can be appended with `mg_dns_send_reply` or by lower
-level function defined in the DNS API.
-
-In order to send the reply use `mg_dns_send_reply`.
-It's possible to use a connection's send buffer as reply buffers,
-and it will work for both UDP and TCP connections.
-
-Example:
-
-```c
-reply = mg_dns_create_reply(&nc->send_mbuf, msg);
-for (i = 0; i < msg->num_questions; i++) {
-  rr = &msg->questions[i];
-  if (rr->rtype == MG_DNS_A_RECORD) {
-    mg_dns_reply_record(&reply, rr, 3600, &dummy_ip_addr, 4);
-  }
-}
-mg_dns_send_reply(nc, &reply);
-``` 
-
diff --git a/docs/c-api/dns-server.h/mg_dns_reply_record.md b/docs/c-api/dns-server.h/mg_dns_reply_record.md
deleted file mode 100644
index a247c8eca..000000000
--- a/docs/c-api/dns-server.h/mg_dns_reply_record.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: "mg_dns_reply_record()"
-decl_name: "mg_dns_reply_record"
-symbol_kind: "func"
-signature: |
-  int mg_dns_reply_record(struct mg_dns_reply *reply,
-                          struct mg_dns_resource_record *question,
-                          const char *name, int rtype, int ttl, const void *rdata,
-                          size_t rdata_len);
----
-
-Append a DNS reply record to the IO buffer and to the DNS message.
-
-The message num_answers field will be incremented. It's caller's duty
-to ensure num_answers is propertly initialized.
-
-Returns -1 on error. 
-
diff --git a/docs/c-api/dns-server.h/mg_dns_send_reply.md b/docs/c-api/dns-server.h/mg_dns_send_reply.md
deleted file mode 100644
index d5b15de49..000000000
--- a/docs/c-api/dns-server.h/mg_dns_send_reply.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-title: "mg_dns_send_reply()"
-decl_name: "mg_dns_send_reply"
-symbol_kind: "func"
-signature: |
-  void mg_dns_send_reply(struct mg_connection *nc, struct mg_dns_reply *r);
----
-
-Send a DNS reply through a connection.
-
-The DNS data is stored in an IO buffer pointed by reply structure in `r`.
-This function mutates the content of that buffer in order to ensure that
-the DNS header reflects size and flags of the mssage, that might have been
-updated either with `mg_dns_reply_record` or by direct manipulation of
-`r->message`.
-
-Once sent, the IO buffer will be trimmed unless the reply IO buffer
-is the connection's send buffer and the connection is not in UDP mode. 
-
diff --git a/docs/c-api/dns.h/intro.md b/docs/c-api/dns.h/intro.md
deleted file mode 100644
index d9522b18e..000000000
--- a/docs/c-api/dns.h/intro.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-title: "DNS"
-symbol_kind: "intro"
-decl_name: "dns.h"
----
-
-
-
diff --git a/docs/c-api/dns.h/items.json b/docs/c-api/dns.h/items.json
deleted file mode 100644
index 8d21dd80d..000000000
--- a/docs/c-api/dns.h/items.json
+++ /dev/null
@@ -1,48 +0,0 @@
-{
-    "items": [
-        {
-            "type": "markdown",
-            "name": "intro.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_dns_parse_record_data.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_send_dns_query.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_dns_insert_header.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_dns_copy_questions.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_dns_encode_record.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_parse_dns.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_dns_uncompress_name.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_set_protocol_dns.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_dns_resource_record.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_dns_message.md"
-        }
-    ]
-}
diff --git a/docs/c-api/dns.h/mg_dns_copy_questions.md b/docs/c-api/dns.h/mg_dns_copy_questions.md
deleted file mode 100644
index 9fc2091fb..000000000
--- a/docs/c-api/dns.h/mg_dns_copy_questions.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: "mg_dns_copy_questions()"
-decl_name: "mg_dns_copy_questions"
-symbol_kind: "func"
-signature: |
-  int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg);
----
-
-Append already encoded questions from an existing message.
-
-This is useful when generating a DNS reply message which includes
-all question records.
-
-Return number of appened bytes. 
-
diff --git a/docs/c-api/dns.h/mg_dns_encode_record.md b/docs/c-api/dns.h/mg_dns_encode_record.md
deleted file mode 100644
index 4b8a98504..000000000
--- a/docs/c-api/dns.h/mg_dns_encode_record.md
+++ /dev/null
@@ -1,25 +0,0 @@
----
-title: "mg_dns_encode_record()"
-decl_name: "mg_dns_encode_record"
-symbol_kind: "func"
-signature: |
-  int mg_dns_encode_record(struct mbuf *io, struct mg_dns_resource_record *rr,
-                           const char *name, size_t nlen, const void *rdata,
-                           size_t rlen);
----
-
-Encode and append a DNS resource record to an IO buffer.
-
-The record metadata is taken from the `rr` parameter, while the name and data
-are taken from the parameters, encoded in the appropriate format depending on
-record type, and stored in the IO buffer. The encoded values might contain
-offsets within the IO buffer. It's thus important that the IO buffer doesn't
-get trimmed while a sequence of records are encoded while preparing a DNS
-*reply.
-
-This function doesn't update the `name` and `rdata` pointers in the `rr`
-*struct
-because they might be invalidated as soon as the IO buffer grows again.
-
-Return the number of bytes appened or -1 in case of error. 
-
diff --git a/docs/c-api/dns.h/mg_dns_insert_header.md b/docs/c-api/dns.h/mg_dns_insert_header.md
deleted file mode 100644
index 0a9d7dae4..000000000
--- a/docs/c-api/dns.h/mg_dns_insert_header.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "mg_dns_insert_header()"
-decl_name: "mg_dns_insert_header"
-symbol_kind: "func"
-signature: |
-  int mg_dns_insert_header(struct mbuf *io, size_t pos,
-                           struct mg_dns_message *msg);
----
-
-Insert a DNS header to an IO buffer.
-
-Return number of bytes inserted. 
-
diff --git a/docs/c-api/dns.h/mg_dns_parse_record_data.md b/docs/c-api/dns.h/mg_dns_parse_record_data.md
deleted file mode 100644
index d8239befe..000000000
--- a/docs/c-api/dns.h/mg_dns_parse_record_data.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-title: "mg_dns_parse_record_data()"
-decl_name: "mg_dns_parse_record_data"
-symbol_kind: "func"
-signature: |
-  int mg_dns_parse_record_data(struct mg_dns_message *msg,
-                               struct mg_dns_resource_record *rr, void *data,
-                               size_t data_len);
----
-
-Parse the record data from a DNS resource record.
-
- - A:     struct in_addr *ina
- - AAAA:  struct in6_addr *ina
- - CNAME: char buffer
-
-Returns -1 on error.
-
-TODO(mkm): MX 
-
diff --git a/docs/c-api/dns.h/mg_dns_uncompress_name.md b/docs/c-api/dns.h/mg_dns_uncompress_name.md
deleted file mode 100644
index 3db03df89..000000000
--- a/docs/c-api/dns.h/mg_dns_uncompress_name.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-title: "mg_dns_uncompress_name()"
-decl_name: "mg_dns_uncompress_name"
-symbol_kind: "func"
-signature: |
-  size_t mg_dns_uncompress_name(struct mg_dns_message *msg, struct mg_str *name,
-                                char *dst, int dst_len);
----
-
-Uncompress a DNS compressed name.
-
-The containing dns message is required because the compressed encoding
-and reference suffixes present elsewhere in the packet.
-
-If name is less than `dst_len` characters long, the remainder
-of `dst` is terminated with `\0' characters. Otherwise, `dst` is not
-*terminated.
-
-If `dst_len` is 0 `dst` can be NULL.
-Return the uncompressed name length. 
-
diff --git a/docs/c-api/dns.h/mg_parse_dns.md b/docs/c-api/dns.h/mg_parse_dns.md
deleted file mode 100644
index 3e28efeed..000000000
--- a/docs/c-api/dns.h/mg_parse_dns.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_parse_dns()"
-decl_name: "mg_parse_dns"
-symbol_kind: "func"
-signature: |
-  int mg_parse_dns(const char *buf, int len, struct mg_dns_message *msg);
----
-
-Low-level: parses a DNS response. 
-
diff --git a/docs/c-api/dns.h/mg_send_dns_query.md b/docs/c-api/dns.h/mg_send_dns_query.md
deleted file mode 100644
index 5dd22c368..000000000
--- a/docs/c-api/dns.h/mg_send_dns_query.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: "mg_send_dns_query()"
-decl_name: "mg_send_dns_query"
-symbol_kind: "func"
-signature: |
-  void mg_send_dns_query(struct mg_connection *nc, const char *name,
-                         int query_type);
----
-
-Send a DNS query to the remote end. 
-
diff --git a/docs/c-api/dns.h/mg_set_protocol_dns.md b/docs/c-api/dns.h/mg_set_protocol_dns.md
deleted file mode 100644
index 7d7d0dc4f..000000000
--- a/docs/c-api/dns.h/mg_set_protocol_dns.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-title: "mg_set_protocol_dns()"
-decl_name: "mg_set_protocol_dns"
-symbol_kind: "func"
-signature: |
-  void mg_set_protocol_dns(struct mg_connection *nc);
----
-
-Attach built-in DNS event handler to the given listening connection.
-
-DNS event handler parses incoming UDP packets, treating them as DNS
-requests. If incoming packet gets successfully parsed by the DNS event
-handler, a user event handler will receive `MG_DNS_REQUEST` event, with
-`ev_data` pointing to the parsed `struct mg_dns_message`.
-
-See
-[captive_dns_server](https://github.com/cesanta/mongoose/tree/master/examples/captive_dns_server)
-example on how to handle DNS request and send DNS reply. 
-
diff --git a/docs/c-api/dns.h/struct_mg_dns_message.md b/docs/c-api/dns.h/struct_mg_dns_message.md
deleted file mode 100644
index 9838bec9c..000000000
--- a/docs/c-api/dns.h/struct_mg_dns_message.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: "struct mg_dns_message"
-decl_name: "struct mg_dns_message"
-symbol_kind: "struct"
-signature: |
-  struct mg_dns_message {
-    struct mg_str pkt; /* packet body */
-    uint16_t flags;
-    uint16_t transaction_id;
-    int num_questions;
-    int num_answers;
-    struct mg_dns_resource_record questions[MG_MAX_DNS_QUESTIONS];
-    struct mg_dns_resource_record answers[MG_MAX_DNS_ANSWERS];
-  };
----
-
-DNS message (request and response). 
-
diff --git a/docs/c-api/dns.h/struct_mg_dns_resource_record.md b/docs/c-api/dns.h/struct_mg_dns_resource_record.md
deleted file mode 100644
index 8ff7af403..000000000
--- a/docs/c-api/dns.h/struct_mg_dns_resource_record.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-title: "struct mg_dns_resource_record"
-decl_name: "struct mg_dns_resource_record"
-symbol_kind: "struct"
-signature: |
-  struct mg_dns_resource_record {
-    struct mg_str name; /* buffer with compressed name */
-    int rtype;
-    int rclass;
-    int ttl;
-    enum mg_dns_resource_record_kind kind;
-    struct mg_str rdata; /* protocol data (can be a compressed name) */
-  };
----
-
-DNS resource record. 
-
diff --git a/docs/c-api/http.h/intro.md b/docs/c-api/http.h/intro.md
deleted file mode 100644
index 730204713..000000000
--- a/docs/c-api/http.h/intro.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-title: "HTTP + Websocket"
-symbol_kind: "intro"
-decl_name: "http.h"
----
-
-
-
diff --git a/docs/c-api/http.h/items.json b/docs/c-api/http.h/items.json
deleted file mode 100644
index a8bd24e0b..000000000
--- a/docs/c-api/http.h/items.json
+++ /dev/null
@@ -1,128 +0,0 @@
-{
-    "items": [
-        {
-            "type": "markdown",
-            "name": "intro.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_set_protocol_http_websocket.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_send_websocket_handshake.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_send_websocket_handshake2.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_connect_ws.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_connect_ws_opt.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_send_websocket_frame.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_send_websocket_framev.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_printf_websocket_frame.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_send_http_chunk.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_printf_http_chunk.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_send_response_line.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_send_head.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_printf_html_escape.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_parse_http.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_get_http_header.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_http_parse_header.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_parse_multipart.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_get_http_var.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_url_decode.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_http_create_digest_auth_header.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_connect_http.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_connect_http_opt.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_serve_http.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_register_http_endpoint.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_file_upload_handler.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_fu_fname_fn.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_http_message.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_websocket_message.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_http_multipart_part.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_serve_http_opts.md"
-        }
-    ]
-}
diff --git a/docs/c-api/http.h/mg_connect_http.md b/docs/c-api/http.h/mg_connect_http.md
deleted file mode 100644
index b897be0ce..000000000
--- a/docs/c-api/http.h/mg_connect_http.md
+++ /dev/null
@@ -1,35 +0,0 @@
----
-title: "mg_connect_http()"
-decl_name: "mg_connect_http"
-symbol_kind: "func"
-signature: |
-  struct mg_connection *mg_connect_http(struct mg_mgr *mgr,
-                                        mg_event_handler_t event_handler,
-                                        const char *url,
-                                        const char *extra_headers,
-                                        const char *post_data);
----
-
-Helper function that creates outbound HTTP connection.
-
-`url` is a URL to fetch. It must be properly URL-encoded, e.g. have
-no spaces, etc. By default, `mg_connect_http()` sends Connection and
-Host headers. `extra_headers` is an extra HTTP headers to send, e.g.
-`"User-Agent: my-app\r\n"`.
-If `post_data` is NULL, then GET request is created. Otherwise, POST request
-is created with the specified POST data. Note that if the data being posted
-is a form submission, the `Content-Type` header should be set accordingly
-(see example below).
-
-Examples:
-
-```c
-  nc1 = mg_connect_http(mgr, ev_handler_1, "http://www.google.com", NULL,
-                        NULL);
-  nc2 = mg_connect_http(mgr, ev_handler_1, "https://github.com", NULL, NULL);
-  nc3 = mg_connect_http(
-      mgr, ev_handler_1, "my_server:8000/form_submit/",
-      "Content-Type: application/x-www-form-urlencoded\r\n",
-      "var_1=value_1&var_2=value_2");
-``` 
-
diff --git a/docs/c-api/http.h/mg_connect_http_opt.md b/docs/c-api/http.h/mg_connect_http_opt.md
deleted file mode 100644
index be68a67f0..000000000
--- a/docs/c-api/http.h/mg_connect_http_opt.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: "mg_connect_http_opt()"
-decl_name: "mg_connect_http_opt"
-symbol_kind: "func"
-signature: |
-  struct mg_connection *mg_connect_http_opt(struct mg_mgr *mgr,
-                                            mg_event_handler_t ev_handler,
-                                            struct mg_connect_opts opts,
-                                            const char *url,
-                                            const char *extra_headers,
-                                            const char *post_data);
----
-
-Helper function that creates outbound HTTP connection.
-
-Mostly identical to mg_connect_http, but allows to provide extra parameters
-(for example, SSL parameters 
-
diff --git a/docs/c-api/http.h/mg_connect_ws.md b/docs/c-api/http.h/mg_connect_ws.md
deleted file mode 100644
index 417279c86..000000000
--- a/docs/c-api/http.h/mg_connect_ws.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-title: "mg_connect_ws()"
-decl_name: "mg_connect_ws"
-symbol_kind: "func"
-signature: |
-  struct mg_connection *mg_connect_ws(struct mg_mgr *mgr,
-                                      mg_event_handler_t event_handler,
-                                      const char *url, const char *protocol,
-                                      const char *extra_headers);
----
-
-Helper function that creates an outbound WebSocket connection.
-
-`url` is a URL to connect to. It must be properly URL-encoded, e.g. have
-no spaces, etc. By default, `mg_connect_ws()` sends Connection and
-Host headers. `extra_headers` is an extra HTTP headers to send, e.g.
-`"User-Agent: my-app\r\n"`.
-If `protocol` is not NULL, then a `Sec-WebSocket-Protocol` header is sent.
-
-Examples:
-
-```c
-  nc1 = mg_connect_ws(mgr, ev_handler_1, "ws://echo.websocket.org", NULL,
-                      NULL);
-  nc2 = mg_connect_ws(mgr, ev_handler_1, "wss://echo.websocket.org", NULL,
-                      NULL);
-  nc3 = mg_connect_ws(mgr, ev_handler_1, "ws://api.cesanta.com",
-                      "clubby.cesanta.com", NULL);
-``` 
-
diff --git a/docs/c-api/http.h/mg_connect_ws_opt.md b/docs/c-api/http.h/mg_connect_ws_opt.md
deleted file mode 100644
index 3ab91083d..000000000
--- a/docs/c-api/http.h/mg_connect_ws_opt.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-title: "mg_connect_ws_opt()"
-decl_name: "mg_connect_ws_opt"
-symbol_kind: "func"
-signature: |
-  struct mg_connection *mg_connect_ws_opt(struct mg_mgr *mgr,
-                                          mg_event_handler_t ev_handler,
-                                          struct mg_connect_opts opts,
-                                          const char *url, const char *protocol,
-                                          const char *extra_headers);
----
-
-Helper function that creates an outbound WebSocket connection
-
-Mostly identical to mg_connect_ws, but allows to provide extra parameters
-(for example, SSL parameters 
-
diff --git a/docs/c-api/http.h/mg_file_upload_handler.md b/docs/c-api/http.h/mg_file_upload_handler.md
deleted file mode 100644
index b0459676f..000000000
--- a/docs/c-api/http.h/mg_file_upload_handler.md
+++ /dev/null
@@ -1,39 +0,0 @@
----
-title: "mg_file_upload_handler()"
-decl_name: "mg_file_upload_handler"
-symbol_kind: "func"
-signature: |
-  void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
-                              mg_fu_fname_fn local_name_fn);
----
-
-File upload handler.
-This handler can be used to implement file uploads with minimum code.
-This handler will process MG_EV_HTTP_PART_* events and store file data into
-a local file.
-`local_name_fn` will be invoked with whatever name was provided by the client
-and will expect the name of the local file to open. Return value of NULL will
-abort file upload (client will get a "403 Forbidden" response). If non-null,
-the returned string must be heap-allocated and will be freed by the caller.
-Exception: it is ok to return the same string verbatim.
-
-Example:
-
-```c
-struct mg_str upload_fname(struct mg_connection *nc, struct mg_str fname) {
-  // Just return the same filename. Do not actually do this except in test!
-  // fname is user-controlled and needs to be sanitized.
-  return fname;
-}
-void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
-  switch (ev) {
-    ...
-    case MG_EV_HTTP_PART_BEGIN:
-    case MG_EV_HTTP_PART_DATA:
-    case MG_EV_HTTP_PART_END:
-      mg_file_upload_handler(nc, ev, ev_data, upload_fname);
-      break;
-  }
-}
-``` 
-
diff --git a/docs/c-api/http.h/mg_fu_fname_fn.md b/docs/c-api/http.h/mg_fu_fname_fn.md
deleted file mode 100644
index 78aa7c8bd..000000000
--- a/docs/c-api/http.h/mg_fu_fname_fn.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: "mg_fu_fname_fn"
-decl_name: "mg_fu_fname_fn"
-symbol_kind: "typedef"
-signature: |
-  typedef struct mg_str (*mg_fu_fname_fn)(struct mg_connection *nc,
-                                          struct mg_str fname);
----
-
-Callback prototype for `mg_file_upload_handler()`. 
-
diff --git a/docs/c-api/http.h/mg_get_http_header.md b/docs/c-api/http.h/mg_get_http_header.md
deleted file mode 100644
index 5c6d85ba1..000000000
--- a/docs/c-api/http.h/mg_get_http_header.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "mg_get_http_header()"
-decl_name: "mg_get_http_header"
-symbol_kind: "func"
-signature: |
-  struct mg_str *mg_get_http_header(struct http_message *hm, const char *name);
----
-
-Search and return header `name` in parsed HTTP message `hm`.
-If header is not found, NULL is returned. Example:
-
-    struct mg_str *host_hdr = mg_get_http_header(hm, "Host"); 
-
diff --git a/docs/c-api/http.h/mg_get_http_var.md b/docs/c-api/http.h/mg_get_http_var.md
deleted file mode 100644
index cc54c2ebe..000000000
--- a/docs/c-api/http.h/mg_get_http_var.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: "mg_get_http_var()"
-decl_name: "mg_get_http_var"
-symbol_kind: "func"
-signature: |
-  int mg_get_http_var(const struct mg_str *buf, const char *name, char *dst,
-                      size_t dst_len);
----
-
-Fetch an HTTP form variable.
-
-Fetch a variable `name` from a `buf` into a buffer specified by
-`dst`, `dst_len`. Destination is always zero-terminated. Return length
-of a fetched variable. If not found, 0 is returned. `buf` must be
-valid url-encoded buffer. If destination is too small, `-1` is returned. 
-
diff --git a/docs/c-api/http.h/mg_http_create_digest_auth_header.md b/docs/c-api/http.h/mg_http_create_digest_auth_header.md
deleted file mode 100644
index dd98fdc1d..000000000
--- a/docs/c-api/http.h/mg_http_create_digest_auth_header.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "mg_http_create_digest_auth_header()"
-decl_name: "mg_http_create_digest_auth_header"
-symbol_kind: "func"
-signature: |
-  int mg_http_create_digest_auth_header(char *buf, size_t buf_len,
-                                        const char *method, const char *uri,
-                                        const char *auth_domain, const char *user,
-                                        const char *passwd);
----
-
-Create Digest authentication header for client request. 
-
diff --git a/docs/c-api/http.h/mg_http_parse_header.md b/docs/c-api/http.h/mg_http_parse_header.md
deleted file mode 100644
index cd7beb6e0..000000000
--- a/docs/c-api/http.h/mg_http_parse_header.md
+++ /dev/null
@@ -1,23 +0,0 @@
----
-title: "mg_http_parse_header()"
-decl_name: "mg_http_parse_header"
-symbol_kind: "func"
-signature: |
-  int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf,
-                           size_t buf_size);
----
-
-Parse HTTP header `hdr`. Find variable `var_name` and store it's value
-in the buffer `buf`, `buf_size`. Return 0 if variable not found, non-zero
-otherwise.
-
-This function is supposed to parse
-cookies, authentication headers, etcetera. Example (error handling omitted):
-
-    char user[20];
-    struct mg_str *hdr = mg_get_http_header(hm, "Authorization");
-    mg_http_parse_header(hdr, "username", user, sizeof(user));
-
-Return length of the variable's value. If buffer is not large enough,
-or variable not found, 0 is returned. 
-
diff --git a/docs/c-api/http.h/mg_parse_http.md b/docs/c-api/http.h/mg_parse_http.md
deleted file mode 100644
index 068ddc16d..000000000
--- a/docs/c-api/http.h/mg_parse_http.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: "mg_parse_http()"
-decl_name: "mg_parse_http"
-symbol_kind: "func"
-signature: |
-  int mg_parse_http(const char *s, int n, struct http_message *hm, int is_req);
----
-
-Parse a HTTP message.
-
-`is_req` should be set to 1 if parsing request, 0 if reply.
-
-Return number of bytes parsed. If HTTP message is
-incomplete, `0` is returned. On parse error, negative number is returned. 
-
diff --git a/docs/c-api/http.h/mg_parse_multipart.md b/docs/c-api/http.h/mg_parse_multipart.md
deleted file mode 100644
index 3eb82cdb7..000000000
--- a/docs/c-api/http.h/mg_parse_multipart.md
+++ /dev/null
@@ -1,46 +0,0 @@
----
-title: "mg_parse_multipart()"
-decl_name: "mg_parse_multipart"
-symbol_kind: "func"
-signature: |
-  size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name,
-                            size_t var_name_len, char *file_name,
-                            size_t file_name_len, const char **chunk,
-                            size_t *chunk_len);
----
-
-Parse buffer `buf`, `buf_len` that contains multipart form data chunks.
-Store chunk name in a `var_name`, `var_name_len` buffer.
-If a chunk is an uploaded file, then `file_name`, `file_name_len` is
-filled with an uploaded file name. `chunk`, `chunk_len`
-points to the chunk data.
-
-Return: number of bytes to skip to the next chunk, or 0 if there are
-        no more chunks.
-
-Usage example:
-
-```c
-   static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
-     switch(ev) {
-       case MG_EV_HTTP_REQUEST: {
-         struct http_message *hm = (struct http_message *) ev_data;
-         char var_name[100], file_name[100];
-         const char *chunk;
-         size_t chunk_len, n1, n2;
-
-         n1 = n2 = 0;
-         while ((n2 = mg_parse_multipart(hm->body.p + n1,
-                                         hm->body.len - n1,
-                                         var_name, sizeof(var_name),
-                                         file_name, sizeof(file_name),
-                                         &chunk, &chunk_len)) > 0) {
-           printf("var: %s, file_name: %s, size: %d, chunk: [%.*s]\n",
-                  var_name, file_name, (int) chunk_len,
-                  (int) chunk_len, chunk);
-           n1 += n2;
-         }
-       }
-       break;
-``` 
-
diff --git a/docs/c-api/http.h/mg_printf_html_escape.md b/docs/c-api/http.h/mg_printf_html_escape.md
deleted file mode 100644
index fd1ff3e0a..000000000
--- a/docs/c-api/http.h/mg_printf_html_escape.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_printf_html_escape()"
-decl_name: "mg_printf_html_escape"
-symbol_kind: "func"
-signature: |
-  void mg_printf_html_escape(struct mg_connection *nc, const char *fmt, ...);
----
-
-Send printf-formatted HTTP chunk, escaping HTML tags. 
-
diff --git a/docs/c-api/http.h/mg_printf_http_chunk.md b/docs/c-api/http.h/mg_printf_http_chunk.md
deleted file mode 100644
index a8e6d1427..000000000
--- a/docs/c-api/http.h/mg_printf_http_chunk.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: "mg_printf_http_chunk()"
-decl_name: "mg_printf_http_chunk"
-symbol_kind: "func"
-signature: |
-  void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt, ...);
----
-
-Send printf-formatted HTTP chunk.
-Functionality is similar to `mg_send_http_chunk()`. 
-
diff --git a/docs/c-api/http.h/mg_printf_websocket_frame.md b/docs/c-api/http.h/mg_printf_websocket_frame.md
deleted file mode 100644
index a65612999..000000000
--- a/docs/c-api/http.h/mg_printf_websocket_frame.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "mg_printf_websocket_frame()"
-decl_name: "mg_printf_websocket_frame"
-symbol_kind: "func"
-signature: |
-  void mg_printf_websocket_frame(struct mg_connection *nc, int op_and_flags,
-                                 const char *fmt, ...);
----
-
-Send websocket frame to the remote end.
-
-Like `mg_send_websocket_frame()`, but allows to create formatted message
-with `printf()`-like semantics. 
-
diff --git a/docs/c-api/http.h/mg_register_http_endpoint.md b/docs/c-api/http.h/mg_register_http_endpoint.md
deleted file mode 100644
index eefbe99e0..000000000
--- a/docs/c-api/http.h/mg_register_http_endpoint.md
+++ /dev/null
@@ -1,35 +0,0 @@
----
-title: "mg_register_http_endpoint()"
-decl_name: "mg_register_http_endpoint"
-symbol_kind: "func"
-signature: |
-  void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
-                                 mg_event_handler_t handler);
----
-
-Register callback for specified http endpoint
-Note: if callback is registered it is called instead of
-callback provided in mg_bind
-
-Example code snippet:
-
-```c
-static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
-  (void) ev; (void) ev_data;
-  mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello1]");
- nc->flags |= MG_F_SEND_AND_CLOSE;
-}
-
-static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
- (void) ev; (void) ev_data;
-  mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello2]");
- nc->flags |= MG_F_SEND_AND_CLOSE;
-}
-
-void init() {
-  nc = mg_bind(&mgr, local_addr, cb1);
-  mg_register_http_endpoint(nc, "/hello1", handle_hello1);
-  mg_register_http_endpoint(nc, "/hello1/hello2", handle_hello2);
-}
-``` 
-
diff --git a/docs/c-api/http.h/mg_send_head.md b/docs/c-api/http.h/mg_send_head.md
deleted file mode 100644
index cd18d36c9..000000000
--- a/docs/c-api/http.h/mg_send_head.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-title: "mg_send_head()"
-decl_name: "mg_send_head"
-symbol_kind: "func"
-signature: |
-  void mg_send_head(struct mg_connection *n, int status_code,
-                    int64_t content_length, const char *extra_headers);
----
-
-Send response line and headers.
-This function sends response line with the `status_code`, and automatically
-sends one header: either "Content-Length", or "Transfer-Encoding".
-If `content_length` is negative, then "Transfer-Encoding: chunked" header
-is sent, otherwise, "Content-Length" header is sent.
-
-NOTE: If `Transfer-Encoding` is `chunked`, then message body must be sent
-using `mg_send_http_chunk()` or `mg_printf_http_chunk()` functions.
-Otherwise, `mg_send()` or `mg_printf()` must be used.
-Extra headers could be set through `extra_headers` - and note `extra_headers`
-must NOT be terminated by a new line. 
-
diff --git a/docs/c-api/http.h/mg_send_http_chunk.md b/docs/c-api/http.h/mg_send_http_chunk.md
deleted file mode 100644
index 6d017fbbe..000000000
--- a/docs/c-api/http.h/mg_send_http_chunk.md
+++ /dev/null
@@ -1,25 +0,0 @@
----
-title: "mg_send_http_chunk()"
-decl_name: "mg_send_http_chunk"
-symbol_kind: "func"
-signature: |
-  void mg_send_http_chunk(struct mg_connection *nc, const char *buf, size_t len);
----
-
-Send buffer `buf` of size `len` to the client using chunked HTTP encoding.
-This function first sends buffer size as hex number + newline, then
-buffer itself, then newline. For example,
-  `mg_send_http_chunk(nc, "foo", 3)` whill append `3\r\nfoo\r\n` string to
-the `nc->send_mbuf` output IO buffer.
-
-NOTE: HTTP header "Transfer-Encoding: chunked" should be sent prior to
-using this function.
-
-NOTE: do not forget to send empty chunk at the end of the response,
-to tell the client that everything was sent. Example:
-
-```
-  mg_printf_http_chunk(nc, "%s", "my response!");
-  mg_send_http_chunk(nc, "", 0); // Tell the client we're finished
-``` 
-
diff --git a/docs/c-api/http.h/mg_send_response_line.md b/docs/c-api/http.h/mg_send_response_line.md
deleted file mode 100644
index 8f62d717f..000000000
--- a/docs/c-api/http.h/mg_send_response_line.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-title: "mg_send_response_line()"
-decl_name: "mg_send_response_line"
-symbol_kind: "func"
-signature: |
-  void mg_send_response_line(struct mg_connection *c, int status_code,
-                             const char *extra_headers);
----
-
-Send response status line.
-If `extra_headers` is not NULL, then `extra_headers` are also sent
-after the reponse line. `extra_headers` must NOT end end with new line.
-Example:
-
-     mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
-
-Will result in:
-
-     HTTP/1.1 200 OK\r\n
-     Access-Control-Allow-Origin: *\r\n 
-
diff --git a/docs/c-api/http.h/mg_send_websocket_frame.md b/docs/c-api/http.h/mg_send_websocket_frame.md
deleted file mode 100644
index bcc5d0c57..000000000
--- a/docs/c-api/http.h/mg_send_websocket_frame.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-title: "mg_send_websocket_frame()"
-decl_name: "mg_send_websocket_frame"
-symbol_kind: "func"
-signature: |
-  void mg_send_websocket_frame(struct mg_connection *nc, int op_and_flags,
-                               const void *data, size_t data_len);
----
-
-Send websocket frame to the remote end.
-
-`op_and_flags` specifies frame's type, one of:
-
-- WEBSOCKET_OP_CONTINUE
-- WEBSOCKET_OP_TEXT
-- WEBSOCKET_OP_BINARY
-- WEBSOCKET_OP_CLOSE
-- WEBSOCKET_OP_PING
-- WEBSOCKET_OP_PONG
-
-Orred with one of the flags:
-
-- WEBSOCKET_DONT_FIN: Don't set the FIN flag on the frame to be sent.
-
-`data` and `data_len` contain frame data. 
-
diff --git a/docs/c-api/http.h/mg_send_websocket_framev.md b/docs/c-api/http.h/mg_send_websocket_framev.md
deleted file mode 100644
index 4eb3709f9..000000000
--- a/docs/c-api/http.h/mg_send_websocket_framev.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "mg_send_websocket_framev()"
-decl_name: "mg_send_websocket_framev"
-symbol_kind: "func"
-signature: |
-  void mg_send_websocket_framev(struct mg_connection *nc, int op_and_flags,
-                                const struct mg_str *strings, int num_strings);
----
-
-Send multiple websocket frames.
-
-Like `mg_send_websocket_frame()`, but composes a frame from multiple buffers. 
-
diff --git a/docs/c-api/http.h/mg_send_websocket_handshake.md b/docs/c-api/http.h/mg_send_websocket_handshake.md
deleted file mode 100644
index 20ee7017b..000000000
--- a/docs/c-api/http.h/mg_send_websocket_handshake.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-title: "mg_send_websocket_handshake()"
-decl_name: "mg_send_websocket_handshake"
-symbol_kind: "func"
-signature: |
-  void mg_send_websocket_handshake(struct mg_connection *nc, const char *uri,
-                                   const char *extra_headers);
----
-
-Send websocket handshake to the server.
-
-`nc` must be a valid connection, connected to a server. `uri` is an URI
-to fetch, extra_headers` is extra HTTP headers to send or `NULL`.
-
-This function is intended to be used by websocket client.
-
-Note that the Host header is mandatory in HTTP/1.1 and must be
-included in `extra_headers`. `mg_send_websocket_handshake2` offers
-a better API for that.
-
-Deprecated in favour of `mg_send_websocket_handshake2` 
-
diff --git a/docs/c-api/http.h/mg_send_websocket_handshake2.md b/docs/c-api/http.h/mg_send_websocket_handshake2.md
deleted file mode 100644
index 27c5c3b82..000000000
--- a/docs/c-api/http.h/mg_send_websocket_handshake2.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-title: "mg_send_websocket_handshake2()"
-decl_name: "mg_send_websocket_handshake2"
-symbol_kind: "func"
-signature: |
-  void mg_send_websocket_handshake2(struct mg_connection *nc, const char *path,
-                                    const char *host, const char *protocol,
-                                    const char *extra_headers);
----
-
-Send websocket handshake to the server.
-
-`nc` must be a valid connection, connected to a server. `uri` is an URI
-to fetch, `host` goes into the `Host` header, `protocol` goes into the
-`Sec-WebSocket-Proto` header (NULL to omit), extra_headers` is extra HTTP
-headers to send or `NULL`.
-
-This function is intended to be used by websocket client. 
-
diff --git a/docs/c-api/http.h/mg_serve_http.md b/docs/c-api/http.h/mg_serve_http.md
deleted file mode 100644
index 22b326887..000000000
--- a/docs/c-api/http.h/mg_serve_http.md
+++ /dev/null
@@ -1,28 +0,0 @@
----
-title: "mg_serve_http()"
-decl_name: "mg_serve_http"
-symbol_kind: "func"
-signature: |
-  void mg_serve_http(struct mg_connection *nc, struct http_message *hm,
-                     struct mg_serve_http_opts opts);
----
-
-Serve given HTTP request according to the `options`.
-
-Example code snippet:
-
-```c
-static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
-  struct http_message *hm = (struct http_message *) ev_data;
-  struct mg_serve_http_opts opts = { .document_root = "/var/www" };  // C99
-
-  switch (ev) {
-    case MG_EV_HTTP_REQUEST:
-      mg_serve_http(nc, hm, opts);
-      break;
-    default:
-      break;
-  }
-}
-``` 
-
diff --git a/docs/c-api/http.h/mg_set_protocol_http_websocket.md b/docs/c-api/http.h/mg_set_protocol_http_websocket.md
deleted file mode 100644
index 9dcefcba3..000000000
--- a/docs/c-api/http.h/mg_set_protocol_http_websocket.md
+++ /dev/null
@@ -1,50 +0,0 @@
----
-title: "mg_set_protocol_http_websocket()"
-decl_name: "mg_set_protocol_http_websocket"
-symbol_kind: "func"
-signature: |
-  void mg_set_protocol_http_websocket(struct mg_connection *nc);
----
-
-Attach built-in HTTP event handler to the given connection.
-User-defined event handler will receive following extra events:
-
-- MG_EV_HTTP_REQUEST: HTTP request has arrived. Parsed HTTP request
- is passed as
-  `struct http_message` through the handler's `void *ev_data` pointer.
-- MG_EV_HTTP_MULTIPART_REQUEST: A multipart POST request has received.
-  This event is sent before body is parsed. After this user
-  should expect a sequence of MG_EV_HTTP_PART_BEGIN/DATA/END requests.
-  This is also the last time when headers and other request fields are
-  accessible.
-- MG_EV_HTTP_REPLY: HTTP reply has arrived. Parsed HTTP reply is passed as
-  `struct http_message` through the handler's `void *ev_data` pointer.
-- MG_EV_HTTP_CHUNK: HTTP chunked-encoding chunk has arrived.
-  Parsed HTTP reply is passed as `struct http_message` through the
-  handler's `void *ev_data` pointer. `http_message::body` would contain
-  incomplete, reassembled HTTP body.
-  It will grow with every new chunk arrived, and
-  potentially can consume a lot of memory. An event handler may process
-  the body as chunks are coming, and signal Mongoose to delete processed
-  body by setting `MG_F_DELETE_CHUNK` in `mg_connection::flags`. When
-  the last zero chunk is received,
-  Mongoose sends `MG_EV_HTTP_REPLY` event with
-  full reassembled body (if handler did not signal to delete chunks) or
-  with empty body (if handler did signal to delete chunks).
-- MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received websocket handshake
-  request. `ev_data` contains parsed HTTP request.
-- MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed Websocket handshake.
-  `ev_data` is `NULL`.
-- MG_EV_WEBSOCKET_FRAME: new websocket frame has arrived. `ev_data` is
-  `struct websocket_message *`
-- MG_EV_HTTP_PART_BEGIN: new part of multipart message is started,
-  extra parameters are passed in mg_http_multipart_part
-- MG_EV_HTTP_PART_DATA: new portion of data from multiparted message
-  no additional headers are available, only data and data size
-- MG_EV_HTTP_PART_END: final boundary received, analogue to maybe used to
-  find the end of packet
-  Note: Mongoose should be compiled with MG_ENABLE_HTTP_STREAMING_MULTIPART
-  to enable MG_EV_HTTP_MULTIPART_REQUEST, MG_EV_HTTP_REQUEST_END,
-  MG_EV_HTTP_REQUEST_CANCEL, MG_EV_HTTP_PART_BEGIN, MG_EV_HTTP_PART_DATA,
-  MG_EV_HTTP_PART_END constants 
-
diff --git a/docs/c-api/http.h/mg_url_decode.md b/docs/c-api/http.h/mg_url_decode.md
deleted file mode 100644
index 9e2f7e783..000000000
--- a/docs/c-api/http.h/mg_url_decode.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: "mg_url_decode()"
-decl_name: "mg_url_decode"
-symbol_kind: "func"
-signature: |
-  int mg_url_decode(const char *src, int src_len, char *dst, int dst_len,
-                    int is_form_url_encoded);
----
-
-Decode URL-encoded string.
-
-Source string is specified by (`src`, `src_len`), and destination is
-(`dst`, `dst_len`). If `is_form_url_encoded` is non-zero, then
-`+` character is decoded as a blank space character. This function
-guarantees to `\0`-terminate the destination. If destination is too small,
-then source string is partially decoded and `-1` is returned. Otherwise,
-a length of decoded string is returned, not counting final `\0`. 
-
diff --git a/docs/c-api/http.h/struct_http_message.md b/docs/c-api/http.h/struct_http_message.md
deleted file mode 100644
index 60eae685f..000000000
--- a/docs/c-api/http.h/struct_http_message.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-title: "struct http_message"
-decl_name: "struct http_message"
-symbol_kind: "struct"
-signature: |
-  struct http_message {
-    struct mg_str message; /* Whole message: request line + headers + body */
-  
-    /* HTTP Request line (or HTTP response line) */
-    struct mg_str method; /* "GET" */
-    struct mg_str uri;    /* "/my_file.html" */
-    struct mg_str proto;  /* "HTTP/1.1" -- for both request and response */
-  
-    /* For responses, code and response status message are set */
-    int resp_code;
-    struct mg_str resp_status_msg;
-  
-    /*
-     * Query-string part of the URI. For example, for HTTP request
-     *    GET /foo/bar?param1=val1&param2=val2
-     *    |    uri    |     query_string     |
-     *
-     * Note that question mark character doesn't belong neither to the uri,
-     * nor to the query_string
-     */
-    struct mg_str query_string;
-  
-    /* Headers */
-    struct mg_str header_names[MG_MAX_HTTP_HEADERS];
-    struct mg_str header_values[MG_MAX_HTTP_HEADERS];
-  
-    /* Message body */
-    struct mg_str body; /* Zero-length for requests with no body */
-  };
----
-
-HTTP message 
-
diff --git a/docs/c-api/http.h/struct_mg_http_multipart_part.md b/docs/c-api/http.h/struct_mg_http_multipart_part.md
deleted file mode 100644
index cd2d0c2e4..000000000
--- a/docs/c-api/http.h/struct_mg_http_multipart_part.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: "struct mg_http_multipart_part"
-decl_name: "struct mg_http_multipart_part"
-symbol_kind: "struct"
-signature: |
-  struct mg_http_multipart_part {
-    const char *file_name;
-    const char *var_name;
-    struct mg_str data;
-    int status; /* <0 on error */
-    void *user_data;
-  };
----
-
-HTTP multipart part 
-
diff --git a/docs/c-api/http.h/struct_mg_serve_http_opts.md b/docs/c-api/http.h/struct_mg_serve_http_opts.md
deleted file mode 100644
index c0fafeed7..000000000
--- a/docs/c-api/http.h/struct_mg_serve_http_opts.md
+++ /dev/null
@@ -1,104 +0,0 @@
----
-title: "struct mg_serve_http_opts"
-decl_name: "struct mg_serve_http_opts"
-symbol_kind: "struct"
-signature: |
-  struct mg_serve_http_opts {
-    /* Path to web root directory */
-    const char *document_root;
-  
-    /* List of index files. Default is "" */
-    const char *index_files;
-  
-    /*
-     * Leave as NULL to disable authentication.
-     * To enable directory protection with authentication, set this to ".htpasswd"
-     * Then, creating ".htpasswd" file in any directory automatically protects
-     * it with digest authentication.
-     * Use `mongoose` web server binary, or `htdigest` Apache utility to
-     * create/manipulate passwords file.
-     * Make sure `auth_domain` is set to a valid domain name.
-     */
-    const char *per_directory_auth_file;
-  
-    /* Authorization domain (domain name of this web server) */
-    const char *auth_domain;
-  
-    /*
-     * Leave as NULL to disable authentication.
-     * Normally, only selected directories in the document root are protected.
-     * If absolutely every access to the web server needs to be authenticated,
-     * regardless of the URI, set this option to the path to the passwords file.
-     * Format of that file is the same as ".htpasswd" file. Make sure that file
-     * is located outside document root to prevent people fetching it.
-     */
-    const char *global_auth_file;
-  
-    /* Set to "no" to disable directory listing. Enabled by default. */
-    const char *enable_directory_listing;
-  
-    /* SSI files pattern. If not set, "**.shtml$|**.shtm$" is used. */
-    const char *ssi_pattern;
-  
-    /* IP ACL. By default, NULL, meaning all IPs are allowed to connect */
-    const char *ip_acl;
-  
-    /* URL rewrites.
-     *
-     * Comma-separated list of `uri_pattern=file_or_directory_path` rewrites.
-     * When HTTP request is received, Mongoose constructs a file name from the
-     * requested URI by combining `document_root` and the URI. However, if the
-     * rewrite option is used and `uri_pattern` matches requested URI, then
-     * `document_root` is ignored. Instead, `file_or_directory_path` is used,
-     * which should be a full path name or a path relative to the web server's
-     * current working directory. Note that `uri_pattern`, as all Mongoose
-     * patterns, is a prefix pattern.
-     *
-     * If uri_pattern starts with `@` symbol, then Mongoose compares it with the
-     * HOST header of the request. If they are equal, Mongoose sets document root
-     * to `file_or_directory_path`, implementing virtual hosts support.
-     * Example: `@foo.com=/document/root/for/foo.com`
-     *
-     * If `uri_pattern` starts with `%` symbol, then Mongoose compares it with
-     * the listening port. If they match, then Mongoose issues a 301 redirect.
-     * For example, to redirect all HTTP requests to the
-     * HTTPS port, do `%80=https://my.site.com`. Note that the request URI is
-     * automatically appended to the redirect location.
-     */
-    const char *url_rewrites;
-  
-    /* DAV document root. If NULL, DAV requests are going to fail. */
-    const char *dav_document_root;
-  
-    /*
-     * DAV passwords file. If NULL, DAV requests are going to fail.
-     * If passwords file is set to "-", then DAV auth is disabled.
-     */
-    const char *dav_auth_file;
-  
-    /* Glob pattern for the files to hide. */
-    const char *hidden_file_pattern;
-  
-    /* Set to non-NULL to enable CGI, e.g. **.cgi$|**.php$" */
-    const char *cgi_file_pattern;
-  
-    /* If not NULL, ignore CGI script hashbang and use this interpreter */
-    const char *cgi_interpreter;
-  
-    /*
-     * Comma-separated list of Content-Type overrides for path suffixes, e.g.
-     * ".txt=text/plain; charset=utf-8,.c=text/plain"
-     */
-    const char *custom_mime_types;
-  
-    /*
-     * Extra HTTP headers to add to each server response.
-     * Example: to enable CORS, set this to "Access-Control-Allow-Origin: *".
-     */
-    const char *extra_headers;
-  };
----
-
-This structure defines how `mg_serve_http()` works.
-Best practice is to set only required settings, and leave the rest as NULL. 
-
diff --git a/docs/c-api/http.h/struct_websocket_message.md b/docs/c-api/http.h/struct_websocket_message.md
deleted file mode 100644
index 37b7912a5..000000000
--- a/docs/c-api/http.h/struct_websocket_message.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "struct websocket_message"
-decl_name: "struct websocket_message"
-symbol_kind: "struct"
-signature: |
-  struct websocket_message {
-    unsigned char *data;
-    size_t size;
-    unsigned char flags;
-  };
----
-
-WebSocket message 
-
diff --git a/docs/c-api/items.json b/docs/c-api/items.json
deleted file mode 100644
index 1133954a5..000000000
--- a/docs/c-api/items.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
-    "items": [
-        {
-            "type": "section",
-            "name": "mbuf.h"
-        },
-        {
-            "type": "section",
-            "name": "net.h"
-        },
-        {
-            "type": "section",
-            "name": "http.h"
-        },
-        {
-            "type": "section",
-            "name": "json-rpc.h"
-        },
-        {
-            "type": "section",
-            "name": "dns.h"
-        },
-        {
-            "type": "section",
-            "name": "dns-server.h"
-        },
-        {
-            "type": "section",
-            "name": "mqtt.h"
-        },
-        {
-            "type": "section",
-            "name": "mqtt-broker.h"
-        },
-        {
-            "type": "section",
-            "name": "coap.h"
-        },
-        {
-            "type": "section",
-            "name": "util.h"
-        }
-    ]
-}
diff --git a/docs/c-api/json-rpc.h/intro.md b/docs/c-api/json-rpc.h/intro.md
deleted file mode 100644
index 8d04b6232..000000000
--- a/docs/c-api/json-rpc.h/intro.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-title: "JSON-RPC"
-symbol_kind: "intro"
-decl_name: "json-rpc.h"
----
-
-
-
diff --git a/docs/c-api/json-rpc.h/items.json b/docs/c-api/json-rpc.h/items.json
deleted file mode 100644
index 6fc301768..000000000
--- a/docs/c-api/json-rpc.h/items.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
-    "items": [
-        {
-            "type": "markdown",
-            "name": "intro.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_rpc_parse_reply.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_rpc_create_request.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_rpc_create_reply.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_rpc_create_error.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_rpc_create_std_error.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_rpc_dispatch.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_rpc_request.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_rpc_reply.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_rpc_error.md"
-        }
-    ]
-}
diff --git a/docs/c-api/json-rpc.h/mg_rpc_create_error.md b/docs/c-api/json-rpc.h/mg_rpc_create_error.md
deleted file mode 100644
index b6910e02b..000000000
--- a/docs/c-api/json-rpc.h/mg_rpc_create_error.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: "mg_rpc_create_error()"
-decl_name: "mg_rpc_create_error"
-symbol_kind: "func"
-signature: |
-  int mg_rpc_create_error(char *buf, int len, struct mg_rpc_request *req,
-                          int code, const char *message, const char *fmt, ...);
----
-
-Create JSON-RPC error reply in a given buffer.
-
-Return length of the error, which
-can be larger then `len` that indicates an overflow.
-`fmt` format string should conform to `json_emit()` API,
-see https://github.com/cesanta/frozen 
-
diff --git a/docs/c-api/json-rpc.h/mg_rpc_create_reply.md b/docs/c-api/json-rpc.h/mg_rpc_create_reply.md
deleted file mode 100644
index 58a373653..000000000
--- a/docs/c-api/json-rpc.h/mg_rpc_create_reply.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: "mg_rpc_create_reply()"
-decl_name: "mg_rpc_create_reply"
-symbol_kind: "func"
-signature: |
-  int mg_rpc_create_reply(char *buf, int len, const struct mg_rpc_request *req,
-                          const char *result_fmt, ...);
----
-
-Create JSON-RPC reply in a given buffer.
-
-Return length of the reply, which
-can be larger then `len` that indicates an overflow.
-`result_fmt` format string should conform to `json_emit()` API,
-see https://github.com/cesanta/frozen 
-
diff --git a/docs/c-api/json-rpc.h/mg_rpc_create_request.md b/docs/c-api/json-rpc.h/mg_rpc_create_request.md
deleted file mode 100644
index 28c83e404..000000000
--- a/docs/c-api/json-rpc.h/mg_rpc_create_request.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: "mg_rpc_create_request()"
-decl_name: "mg_rpc_create_request"
-symbol_kind: "func"
-signature: |
-  int mg_rpc_create_request(char *buf, int len, const char *method,
-                            const char *id, const char *params_fmt, ...);
----
-
-Create JSON-RPC request in a given buffer.
-
-Return length of the request, which
-can be larger then `len` that indicates an overflow.
-`params_fmt` format string should conform to `json_emit()` API,
-see https://github.com/cesanta/frozen 
-
diff --git a/docs/c-api/json-rpc.h/mg_rpc_create_std_error.md b/docs/c-api/json-rpc.h/mg_rpc_create_std_error.md
deleted file mode 100644
index b682431c3..000000000
--- a/docs/c-api/json-rpc.h/mg_rpc_create_std_error.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-title: "mg_rpc_create_std_error()"
-decl_name: "mg_rpc_create_std_error"
-symbol_kind: "func"
-signature: |
-  int mg_rpc_create_std_error(char *buf, int len, struct mg_rpc_request *req,
-                              int code);
----
-
-Create JSON-RPC error in a given buffer.
-
-Return length of the error, which
-can be larger then `len` that indicates an overflow. See
-JSON_RPC_*_ERROR definitions for standard error values:
-
-- `#define JSON_RPC_PARSE_ERROR (-32700)`
-- `#define JSON_RPC_INVALID_REQUEST_ERROR (-32600)`
-- `#define JSON_RPC_METHOD_NOT_FOUND_ERROR (-32601)`
-- `#define JSON_RPC_INVALID_PARAMS_ERROR (-32602)`
-- `#define JSON_RPC_INTERNAL_ERROR (-32603)`
-- `#define JSON_RPC_SERVER_ERROR (-32000)` 
-
diff --git a/docs/c-api/json-rpc.h/mg_rpc_dispatch.md b/docs/c-api/json-rpc.h/mg_rpc_dispatch.md
deleted file mode 100644
index d58f5026a..000000000
--- a/docs/c-api/json-rpc.h/mg_rpc_dispatch.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-title: "mg_rpc_dispatch()"
-decl_name: "mg_rpc_dispatch"
-symbol_kind: "func"
-signature: |
-  int mg_rpc_dispatch(const char *buf, int, char *dst, int dst_len,
-                      const char **methods, mg_rpc_handler_t *handlers);
----
-
-Dispatches a JSON-RPC request.
-
-Parses JSON-RPC request contained in `buf`, `len`.
-Then, dispatches the request to the correct handler method.
-Valid method names should be specified in NULL
-terminated array `methods`, and corresponding handlers in `handlers`.
-Result is put in `dst`, `dst_len`. Return: length of the result, which
-can be larger then `dst_len` that indicates an overflow.
-Overflown bytes are not written to the buffer.
-If method is not found, an error is automatically generated. 
-
diff --git a/docs/c-api/json-rpc.h/mg_rpc_parse_reply.md b/docs/c-api/json-rpc.h/mg_rpc_parse_reply.md
deleted file mode 100644
index 36fad9202..000000000
--- a/docs/c-api/json-rpc.h/mg_rpc_parse_reply.md
+++ /dev/null
@@ -1,24 +0,0 @@
----
-title: "mg_rpc_parse_reply()"
-decl_name: "mg_rpc_parse_reply"
-symbol_kind: "func"
-signature: |
-  int mg_rpc_parse_reply(const char *buf, int len, struct json_token *toks,
-                         int max_toks, struct mg_rpc_reply *,
-                         struct mg_rpc_error *);
----
-
-Parse JSON-RPC reply contained in `buf`, `len` into JSON tokens array
-`toks`, `max_toks`. If buffer contains valid reply, `reply` structure is
-populated. The result of RPC call is located in `reply.result`. On error,
-`error` structure is populated. Returns: the result of calling
-`parse_json(buf, len, toks, max_toks)`:
-
-On success, an offset inside `json_string` is returned
-where parsing has finished. On failure, a negative number is
-returned, one of:
-
-- `#define JSON_STRING_INVALID           -1`
-- `#define JSON_STRING_INCOMPLETE        -2`
-- `#define JSON_TOKEN_ARRAY_TOO_SMALL    -3` 
-
diff --git a/docs/c-api/json-rpc.h/struct_mg_rpc_error.md b/docs/c-api/json-rpc.h/struct_mg_rpc_error.md
deleted file mode 100644
index b2bff13b4..000000000
--- a/docs/c-api/json-rpc.h/struct_mg_rpc_error.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: "struct mg_rpc_error"
-decl_name: "struct mg_rpc_error"
-symbol_kind: "struct"
-signature: |
-  struct mg_rpc_error {
-    struct json_token *message;       /* Whole RPC message */
-    struct json_token *id;            /* Message ID */
-    struct json_token *error_code;    /* error.code */
-    struct json_token *error_message; /* error.message */
-    struct json_token *error_data;    /* error.data, can be NULL */
-  };
----
-
-JSON-RPC error 
-
diff --git a/docs/c-api/json-rpc.h/struct_mg_rpc_reply.md b/docs/c-api/json-rpc.h/struct_mg_rpc_reply.md
deleted file mode 100644
index fd6060267..000000000
--- a/docs/c-api/json-rpc.h/struct_mg_rpc_reply.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "struct mg_rpc_reply"
-decl_name: "struct mg_rpc_reply"
-symbol_kind: "struct"
-signature: |
-  struct mg_rpc_reply {
-    struct json_token *message; /* Whole RPC message */
-    struct json_token *id;      /* Message ID */
-    struct json_token *result;  /* Remote call result */
-  };
----
-
-JSON-RPC response 
-
diff --git a/docs/c-api/json-rpc.h/struct_mg_rpc_request.md b/docs/c-api/json-rpc.h/struct_mg_rpc_request.md
deleted file mode 100644
index fc0bb8ae8..000000000
--- a/docs/c-api/json-rpc.h/struct_mg_rpc_request.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: "struct mg_rpc_request"
-decl_name: "struct mg_rpc_request"
-symbol_kind: "struct"
-signature: |
-  struct mg_rpc_request {
-    struct json_token *message; /* Whole RPC message */
-    struct json_token *id;      /* Message ID */
-    struct json_token *method;  /* Method name */
-    struct json_token *params;  /* Method params */
-  };
----
-
-JSON-RPC request 
-
diff --git a/docs/c-api/mbuf.h/intro.md b/docs/c-api/mbuf.h/intro.md
deleted file mode 100644
index 49c6b7fc8..000000000
--- a/docs/c-api/mbuf.h/intro.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: "Memory Buffers"
-symbol_kind: "intro"
-decl_name: "mbuf.h"
----
-
-Mbufs are mutable/growing memory buffers, like C++ strings.
-Mbuf can append data to the end of a buffer, or insert data into arbitrary
-position in the middle of a buffer. The buffer grows automatically when
-needed.
-
diff --git a/docs/c-api/mbuf.h/items.json b/docs/c-api/mbuf.h/items.json
deleted file mode 100644
index 9f5f2123a..000000000
--- a/docs/c-api/mbuf.h/items.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
-    "items": [
-        {
-            "type": "markdown",
-            "name": "intro.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mbuf_init.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mbuf_free.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mbuf_append.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mbuf_insert.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mbuf_remove.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mbuf_resize.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mbuf_trim.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mbuf.md"
-        }
-    ]
-}
diff --git a/docs/c-api/mbuf.h/mbuf_append.md b/docs/c-api/mbuf.h/mbuf_append.md
deleted file mode 100644
index ea803926e..000000000
--- a/docs/c-api/mbuf.h/mbuf_append.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "mbuf_append()"
-decl_name: "mbuf_append"
-symbol_kind: "func"
-signature: |
-  size_t mbuf_append(struct mbuf *, const void *data, size_t data_size);
----
-
-Appends data to the Mbuf.
-
-Return the number of bytes appended, or 0 if out of memory. 
-
diff --git a/docs/c-api/mbuf.h/mbuf_free.md b/docs/c-api/mbuf.h/mbuf_free.md
deleted file mode 100644
index 273d24b9f..000000000
--- a/docs/c-api/mbuf.h/mbuf_free.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mbuf_free()"
-decl_name: "mbuf_free"
-symbol_kind: "func"
-signature: |
-  void mbuf_free(struct mbuf *);
----
-
-Free the space allocated for the mbuffer and resets the mbuf structure. 
-
diff --git a/docs/c-api/mbuf.h/mbuf_init.md b/docs/c-api/mbuf.h/mbuf_init.md
deleted file mode 100644
index 960f92b81..000000000
--- a/docs/c-api/mbuf.h/mbuf_init.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: "mbuf_init()"
-decl_name: "mbuf_init"
-symbol_kind: "func"
-signature: |
-  void mbuf_init(struct mbuf *, size_t initial_capacity);
----
-
-Initialize an Mbuf.
-`initial_capacity` specifies the initial capacity of the mbuf. 
-
diff --git a/docs/c-api/mbuf.h/mbuf_insert.md b/docs/c-api/mbuf.h/mbuf_insert.md
deleted file mode 100644
index b9e84a711..000000000
--- a/docs/c-api/mbuf.h/mbuf_insert.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "mbuf_insert()"
-decl_name: "mbuf_insert"
-symbol_kind: "func"
-signature: |
-  size_t mbuf_insert(struct mbuf *, size_t, const void *, size_t);
----
-
-Insert data at a specified offset in the Mbuf.
-
-Existing data will be shifted forwards and the buffer will
-be grown if necessary.
-Return the number of bytes inserted. 
-
diff --git a/docs/c-api/mbuf.h/mbuf_remove.md b/docs/c-api/mbuf.h/mbuf_remove.md
deleted file mode 100644
index b4ce18c9d..000000000
--- a/docs/c-api/mbuf.h/mbuf_remove.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mbuf_remove()"
-decl_name: "mbuf_remove"
-symbol_kind: "func"
-signature: |
-  void mbuf_remove(struct mbuf *, size_t data_size);
----
-
-Remove `data_size` bytes from the beginning of the buffer. 
-
diff --git a/docs/c-api/mbuf.h/mbuf_resize.md b/docs/c-api/mbuf.h/mbuf_resize.md
deleted file mode 100644
index 92f8b302e..000000000
--- a/docs/c-api/mbuf.h/mbuf_resize.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "mbuf_resize()"
-decl_name: "mbuf_resize"
-symbol_kind: "func"
-signature: |
-  void mbuf_resize(struct mbuf *, size_t new_size);
----
-
-Resize an Mbuf.
-
-If `new_size` is smaller than buffer's `len`, the
-resize is not performed. 
-
diff --git a/docs/c-api/mbuf.h/mbuf_trim.md b/docs/c-api/mbuf.h/mbuf_trim.md
deleted file mode 100644
index d1878b03f..000000000
--- a/docs/c-api/mbuf.h/mbuf_trim.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mbuf_trim()"
-decl_name: "mbuf_trim"
-symbol_kind: "func"
-signature: |
-  void mbuf_trim(struct mbuf *);
----
-
-Shrink an Mbuf by resizing its `size` to `len`. 
-
diff --git a/docs/c-api/mbuf.h/struct_mbuf.md b/docs/c-api/mbuf.h/struct_mbuf.md
deleted file mode 100644
index 98dcdc33b..000000000
--- a/docs/c-api/mbuf.h/struct_mbuf.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "struct mbuf"
-decl_name: "struct mbuf"
-symbol_kind: "struct"
-signature: |
-  struct mbuf {
-    char *buf;   /* Buffer pointer */
-    size_t len;  /* Data length. Data is located between offset 0 and len. */
-    size_t size; /* Buffer size allocated by realloc(1). Must be >= len */
-  };
----
-
-Memory buffer descriptor 
-
diff --git a/docs/c-api/mqtt-broker.h/intro.md b/docs/c-api/mqtt-broker.h/intro.md
deleted file mode 100644
index 592ccbc4b..000000000
--- a/docs/c-api/mqtt-broker.h/intro.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-title: "MQTT Broker"
-symbol_kind: "intro"
-decl_name: "mqtt-broker.h"
----
-
-
-
diff --git a/docs/c-api/mqtt-broker.h/items.json b/docs/c-api/mqtt-broker.h/items.json
deleted file mode 100644
index 2908ffbb4..000000000
--- a/docs/c-api/mqtt-broker.h/items.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-    "items": [
-        {
-            "type": "markdown",
-            "name": "intro.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_broker_init.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_broker.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_next.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_mqtt_session.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_mqtt_broker.md"
-        }
-    ]
-}
diff --git a/docs/c-api/mqtt-broker.h/mg_mqtt_broker.md b/docs/c-api/mqtt-broker.h/mg_mqtt_broker.md
deleted file mode 100644
index 2532bc6fd..000000000
--- a/docs/c-api/mqtt-broker.h/mg_mqtt_broker.md
+++ /dev/null
@@ -1,32 +0,0 @@
----
-title: "mg_mqtt_broker()"
-decl_name: "mg_mqtt_broker"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_broker(struct mg_connection *brk, int ev, void *data);
----
-
-Process a MQTT broker message.
-
-Listening connection expects a pointer to an initialized `mg_mqtt_broker`
-structure in the `user_data` field.
-
-Basic usage:
-
-```c
-mg_mqtt_broker_init(&brk, NULL);
-
-if ((nc = mg_bind(&mgr, address, mg_mqtt_broker)) == NULL) {
-  // fail;
-}
-nc->user_data = &brk;
-```
-
-New incoming connections will receive a `mg_mqtt_session` structure
-in the connection `user_data`. The original `user_data` will be stored
-in the `user_data` field of the session structure. This allows the user
-handler to store user data before `mg_mqtt_broker` creates the session.
-
-Since only the MG_EV_ACCEPT message is processed by the listening socket,
-for most events the `user_data` will thus point to a `mg_mqtt_session`. 
-
diff --git a/docs/c-api/mqtt-broker.h/mg_mqtt_broker_init.md b/docs/c-api/mqtt-broker.h/mg_mqtt_broker_init.md
deleted file mode 100644
index 74b7e5db7..000000000
--- a/docs/c-api/mqtt-broker.h/mg_mqtt_broker_init.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_mqtt_broker_init()"
-decl_name: "mg_mqtt_broker_init"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_broker_init(struct mg_mqtt_broker *brk, void *user_data);
----
-
-Initialize a MQTT broker. 
-
diff --git a/docs/c-api/mqtt-broker.h/mg_mqtt_next.md b/docs/c-api/mqtt-broker.h/mg_mqtt_next.md
deleted file mode 100644
index 5c4eab9d4..000000000
--- a/docs/c-api/mqtt-broker.h/mg_mqtt_next.md
+++ /dev/null
@@ -1,18 +0,0 @@
----
-title: "mg_mqtt_next()"
-decl_name: "mg_mqtt_next"
-symbol_kind: "func"
-signature: |
-  struct mg_mqtt_session *mg_mqtt_next(struct mg_mqtt_broker *brk,
-                                       struct mg_mqtt_session *s);
----
-
-Iterate over all mqtt sessions connections. Example:
-
-```c
-struct mg_mqtt_session *s;
-for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) {
-  // Do something
-}
-``` 
-
diff --git a/docs/c-api/mqtt-broker.h/struct_mg_mqtt_broker.md b/docs/c-api/mqtt-broker.h/struct_mg_mqtt_broker.md
deleted file mode 100644
index d78e620e4..000000000
--- a/docs/c-api/mqtt-broker.h/struct_mg_mqtt_broker.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "struct mg_mqtt_broker"
-decl_name: "struct mg_mqtt_broker"
-symbol_kind: "struct"
-signature: |
-  struct mg_mqtt_broker {
-    struct mg_mqtt_session *sessions; /* Session list */
-    void *user_data;                  /* User data */
-  };
----
-
-MQTT broker. 
-
diff --git a/docs/c-api/mqtt-broker.h/struct_mg_mqtt_session.md b/docs/c-api/mqtt-broker.h/struct_mg_mqtt_session.md
deleted file mode 100644
index 4ce850145..000000000
--- a/docs/c-api/mqtt-broker.h/struct_mg_mqtt_session.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-title: "struct mg_mqtt_session"
-decl_name: "struct mg_mqtt_session"
-symbol_kind: "struct"
-signature: |
-  struct mg_mqtt_session {
-    struct mg_mqtt_broker *brk;          /* Broker */
-    struct mg_mqtt_session *next, *prev; /* mg_mqtt_broker::sessions linkage */
-    struct mg_connection *nc;            /* Connection with the client */
-    size_t num_subscriptions;            /* Size of `subscriptions` array */
-    struct mg_mqtt_topic_expression *subscriptions;
-    void *user_data; /* User data */
-  };
----
-
-MQTT session (Broker side). 
-
diff --git a/docs/c-api/mqtt.h/intro.md b/docs/c-api/mqtt.h/intro.md
deleted file mode 100644
index 55117eee2..000000000
--- a/docs/c-api/mqtt.h/intro.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-title: "MQTT"
-symbol_kind: "intro"
-decl_name: "mqtt.h"
----
-
-
-
diff --git a/docs/c-api/mqtt.h/items.json b/docs/c-api/mqtt.h/items.json
deleted file mode 100644
index b77926f70..000000000
--- a/docs/c-api/mqtt.h/items.json
+++ /dev/null
@@ -1,80 +0,0 @@
-{
-    "items": [
-        {
-            "type": "markdown",
-            "name": "intro.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_set_protocol_mqtt.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_send_mqtt_handshake.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_send_mqtt_handshake_opt.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_publish.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_subscribe.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_unsubscribe.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_disconnect.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_connack.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_puback.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_pubrec.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_pubrel.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_pubcomp.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_suback.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_unsuback.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_ping.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_pong.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mqtt_next_subscribe_topic.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_mqtt_topic_expression.md"
-        }
-    ]
-}
diff --git a/docs/c-api/mqtt.h/mg_mqtt_connack.md b/docs/c-api/mqtt.h/mg_mqtt_connack.md
deleted file mode 100644
index 3b22d0a0f..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_connack.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_mqtt_connack()"
-decl_name: "mg_mqtt_connack"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_connack(struct mg_connection *nc, uint8_t return_code);
----
-
-Send a CONNACK command with a given `return_code`. 
-
diff --git a/docs/c-api/mqtt.h/mg_mqtt_disconnect.md b/docs/c-api/mqtt.h/mg_mqtt_disconnect.md
deleted file mode 100644
index 2437c21d4..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_disconnect.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_mqtt_disconnect()"
-decl_name: "mg_mqtt_disconnect"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_disconnect(struct mg_connection *nc);
----
-
-Send a DISCONNECT command. 
-
diff --git a/docs/c-api/mqtt.h/mg_mqtt_next_subscribe_topic.md b/docs/c-api/mqtt.h/mg_mqtt_next_subscribe_topic.md
deleted file mode 100644
index 3e7eeab52..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_next_subscribe_topic.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: "mg_mqtt_next_subscribe_topic()"
-decl_name: "mg_mqtt_next_subscribe_topic"
-symbol_kind: "func"
-signature: |
-  int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg,
-                                   struct mg_str *topic, uint8_t *qos, int pos);
----
-
-Extract the next topic expression from a SUBSCRIBE command payload.
-
-Topic expression name will point to a string in the payload buffer.
-Return the pos of the next topic expression or -1 when the list
-of topics is exhausted. 
-
diff --git a/docs/c-api/mqtt.h/mg_mqtt_ping.md b/docs/c-api/mqtt.h/mg_mqtt_ping.md
deleted file mode 100644
index acaa11ac5..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_ping.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_mqtt_ping()"
-decl_name: "mg_mqtt_ping"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_ping(struct mg_connection *nc);
----
-
-Send a PINGREQ command. 
-
diff --git a/docs/c-api/mqtt.h/mg_mqtt_pong.md b/docs/c-api/mqtt.h/mg_mqtt_pong.md
deleted file mode 100644
index da353b572..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_pong.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_mqtt_pong()"
-decl_name: "mg_mqtt_pong"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_pong(struct mg_connection *nc);
----
-
-Send a PINGRESP command. 
-
diff --git a/docs/c-api/mqtt.h/mg_mqtt_puback.md b/docs/c-api/mqtt.h/mg_mqtt_puback.md
deleted file mode 100644
index aad96f669..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_puback.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_mqtt_puback()"
-decl_name: "mg_mqtt_puback"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_puback(struct mg_connection *nc, uint16_t message_id);
----
-
-Send a PUBACK command with a given `message_id`. 
-
diff --git a/docs/c-api/mqtt.h/mg_mqtt_pubcomp.md b/docs/c-api/mqtt.h/mg_mqtt_pubcomp.md
deleted file mode 100644
index aab320f61..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_pubcomp.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_mqtt_pubcomp()"
-decl_name: "mg_mqtt_pubcomp"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_pubcomp(struct mg_connection *nc, uint16_t message_id);
----
-
-Send a PUBCOMP command with a given `message_id`. 
-
diff --git a/docs/c-api/mqtt.h/mg_mqtt_publish.md b/docs/c-api/mqtt.h/mg_mqtt_publish.md
deleted file mode 100644
index 8b28c57ba..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_publish.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "mg_mqtt_publish()"
-decl_name: "mg_mqtt_publish"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_publish(struct mg_connection *nc, const char *topic,
-                       uint16_t message_id, int flags, const void *data,
-                       size_t len);
----
-
-Publish a message to a given topic. 
-
diff --git a/docs/c-api/mqtt.h/mg_mqtt_pubrec.md b/docs/c-api/mqtt.h/mg_mqtt_pubrec.md
deleted file mode 100644
index e5173f771..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_pubrec.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_mqtt_pubrec()"
-decl_name: "mg_mqtt_pubrec"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_pubrec(struct mg_connection *nc, uint16_t message_id);
----
-
-Send a PUBREC command with a given `message_id`. 
-
diff --git a/docs/c-api/mqtt.h/mg_mqtt_pubrel.md b/docs/c-api/mqtt.h/mg_mqtt_pubrel.md
deleted file mode 100644
index 899e8b9db..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_pubrel.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_mqtt_pubrel()"
-decl_name: "mg_mqtt_pubrel"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_pubrel(struct mg_connection *nc, uint16_t message_id);
----
-
-Send a PUBREL command with a given `message_id`. 
-
diff --git a/docs/c-api/mqtt.h/mg_mqtt_suback.md b/docs/c-api/mqtt.h/mg_mqtt_suback.md
deleted file mode 100644
index 943fd65e3..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_suback.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "mg_mqtt_suback()"
-decl_name: "mg_mqtt_suback"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_suback(struct mg_connection *nc, uint8_t *qoss, size_t qoss_len,
-                      uint16_t message_id);
----
-
-Send a SUBACK command with a given `message_id`
-and a sequence of granted QoSs. 
-
diff --git a/docs/c-api/mqtt.h/mg_mqtt_subscribe.md b/docs/c-api/mqtt.h/mg_mqtt_subscribe.md
deleted file mode 100644
index 0978b071a..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_subscribe.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "mg_mqtt_subscribe()"
-decl_name: "mg_mqtt_subscribe"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_subscribe(struct mg_connection *nc,
-                         const struct mg_mqtt_topic_expression *topics,
-                         size_t topics_len, uint16_t message_id);
----
-
-Subscribe to a bunch of topics. 
-
diff --git a/docs/c-api/mqtt.h/mg_mqtt_unsuback.md b/docs/c-api/mqtt.h/mg_mqtt_unsuback.md
deleted file mode 100644
index e3f6e6ea4..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_unsuback.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_mqtt_unsuback()"
-decl_name: "mg_mqtt_unsuback"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_unsuback(struct mg_connection *nc, uint16_t message_id);
----
-
-Send a UNSUBACK command with a given `message_id`. 
-
diff --git a/docs/c-api/mqtt.h/mg_mqtt_unsubscribe.md b/docs/c-api/mqtt.h/mg_mqtt_unsubscribe.md
deleted file mode 100644
index 73a283e3e..000000000
--- a/docs/c-api/mqtt.h/mg_mqtt_unsubscribe.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: "mg_mqtt_unsubscribe()"
-decl_name: "mg_mqtt_unsubscribe"
-symbol_kind: "func"
-signature: |
-  void mg_mqtt_unsubscribe(struct mg_connection *nc, char **topics,
-                           size_t topics_len, uint16_t message_id);
----
-
-Unsubscribe from a bunch of topics. 
-
diff --git a/docs/c-api/mqtt.h/mg_send_mqtt_handshake.md b/docs/c-api/mqtt.h/mg_send_mqtt_handshake.md
deleted file mode 100644
index 1e903f90c..000000000
--- a/docs/c-api/mqtt.h/mg_send_mqtt_handshake.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_send_mqtt_handshake()"
-decl_name: "mg_send_mqtt_handshake"
-symbol_kind: "func"
-signature: |
-  void mg_send_mqtt_handshake(struct mg_connection *nc, const char *client_id);
----
-
-Send MQTT handshake. 
-
diff --git a/docs/c-api/mqtt.h/mg_send_mqtt_handshake_opt.md b/docs/c-api/mqtt.h/mg_send_mqtt_handshake_opt.md
deleted file mode 100644
index c1d3fd4c2..000000000
--- a/docs/c-api/mqtt.h/mg_send_mqtt_handshake_opt.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: "mg_send_mqtt_handshake_opt()"
-decl_name: "mg_send_mqtt_handshake_opt"
-symbol_kind: "func"
-signature: |
-  void mg_send_mqtt_handshake_opt(struct mg_connection *nc, const char *client_id,
-                                  struct mg_send_mqtt_handshake_opts);
----
-
-Send MQTT handshake with optional parameters. 
-
diff --git a/docs/c-api/mqtt.h/mg_set_protocol_mqtt.md b/docs/c-api/mqtt.h/mg_set_protocol_mqtt.md
deleted file mode 100644
index a559eae82..000000000
--- a/docs/c-api/mqtt.h/mg_set_protocol_mqtt.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-title: "mg_set_protocol_mqtt()"
-decl_name: "mg_set_protocol_mqtt"
-symbol_kind: "func"
-signature: |
-  void mg_set_protocol_mqtt(struct mg_connection *nc);
----
-
-Attach built-in MQTT event handler to the given connection.
-
-The user-defined event handler will receive following extra events:
-
-- MG_EV_MQTT_CONNACK
-- MG_EV_MQTT_PUBLISH
-- MG_EV_MQTT_PUBACK
-- MG_EV_MQTT_PUBREC
-- MG_EV_MQTT_PUBREL
-- MG_EV_MQTT_PUBCOMP
-- MG_EV_MQTT_SUBACK 
-
diff --git a/docs/c-api/mqtt.h/struct_mg_mqtt_topic_expression.md b/docs/c-api/mqtt.h/struct_mg_mqtt_topic_expression.md
deleted file mode 100644
index 8ae14b2d1..000000000
--- a/docs/c-api/mqtt.h/struct_mg_mqtt_topic_expression.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "struct mg_mqtt_topic_expression"
-decl_name: "struct mg_mqtt_topic_expression"
-symbol_kind: "struct"
-signature: |
-  struct mg_mqtt_topic_expression {
-    const char *topic;
-    uint8_t qos;
-  };
----
-
-puback 
-
diff --git a/docs/c-api/net.h/intro.md b/docs/c-api/net.h/intro.md
deleted file mode 100644
index bb03baccc..000000000
--- a/docs/c-api/net.h/intro.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "Core: TCP/UDP/SSL"
-symbol_kind: "intro"
-decl_name: "net.h"
----
-
-NOTE: Mongoose manager is single threaded. It does not protect
-its data structures by mutexes, therefore all functions that are dealing
-with particular event manager should be called from the same thread,
-with exception of `mg_broadcast()` function. It is fine to have different
-event managers handled by different threads.
-
diff --git a/docs/c-api/net.h/items.json b/docs/c-api/net.h/items.json
deleted file mode 100644
index 8a8e54689..000000000
--- a/docs/c-api/net.h/items.json
+++ /dev/null
@@ -1,120 +0,0 @@
-{
-    "items": [
-        {
-            "type": "markdown",
-            "name": "intro.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mgr_init.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mgr_free.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mgr_poll.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_broadcast.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_next.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_add_sock.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_add_sock_opt.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_bind.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_bind_opt.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_connect.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_connect_opt.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_set_ssl.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_send.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_printf.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_vprintf.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_socketpair.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_check_ip_acl.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_enable_multithreading.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_enable_javascript.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_set_timer.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_time.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_event_handler_t.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_str.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_mgr.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_connection.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_add_sock_opts.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_bind_opts.md"
-        },
-        {
-            "type": "markdown",
-            "name": "struct_mg_connect_opts.md"
-        }
-    ]
-}
diff --git a/docs/c-api/net.h/mg_add_sock.md b/docs/c-api/net.h/mg_add_sock.md
deleted file mode 100644
index 268dc3344..000000000
--- a/docs/c-api/net.h/mg_add_sock.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "mg_add_sock()"
-decl_name: "mg_add_sock"
-symbol_kind: "func"
-signature: |
-  struct mg_connection *mg_add_sock(struct mg_mgr *, sock_t, mg_event_handler_t);
----
-
-Create a connection, associate it with the given socket and event handler,
-and add it to the manager.
-
-For more options see the `mg_add_sock_opt` variant. 
-
diff --git a/docs/c-api/net.h/mg_add_sock_opt.md b/docs/c-api/net.h/mg_add_sock_opt.md
deleted file mode 100644
index 9a94aee7f..000000000
--- a/docs/c-api/net.h/mg_add_sock_opt.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: "mg_add_sock_opt()"
-decl_name: "mg_add_sock_opt"
-symbol_kind: "func"
-signature: |
-  struct mg_connection *mg_add_sock_opt(struct mg_mgr *, sock_t,
-                                        mg_event_handler_t,
-                                        struct mg_add_sock_opts);
----
-
-Create a connection, associate it with the given socket and event handler,
-and add to the manager.
-
-See the `mg_add_sock_opts` structure for a description of the options. 
-
diff --git a/docs/c-api/net.h/mg_bind.md b/docs/c-api/net.h/mg_bind.md
deleted file mode 100644
index b6106219b..000000000
--- a/docs/c-api/net.h/mg_bind.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "mg_bind()"
-decl_name: "mg_bind"
-symbol_kind: "func"
-signature: |
-  struct mg_connection *mg_bind(struct mg_mgr *, const char *,
-                                mg_event_handler_t);
----
-
-Create listening connection.
-
-See `mg_bind_opt` for full documentation. 
-
diff --git a/docs/c-api/net.h/mg_bind_opt.md b/docs/c-api/net.h/mg_bind_opt.md
deleted file mode 100644
index 4fb514bf7..000000000
--- a/docs/c-api/net.h/mg_bind_opt.md
+++ /dev/null
@@ -1,26 +0,0 @@
----
-title: "mg_bind_opt()"
-decl_name: "mg_bind_opt"
-symbol_kind: "func"
-signature: |
-  struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address,
-                                    mg_event_handler_t handler,
-                                    struct mg_bind_opts opts);
----
-
-Create listening connection.
-
-`address` parameter tells which address to bind to. It's format is the same
-as for the `mg_connect()` call, where `HOST` part is optional. `address`
-can be just a port number, e.g. `:8000`. To bind to a specific interface,
-an IP address can be specified, e.g. `1.2.3.4:8000`. By default, a TCP
-connection is created. To create UDP connection, prepend `udp://` prefix,
-e.g. `udp://:8000`. To summarize, `address` paramer has following format:
-`[PROTO://][IP_ADDRESS]:PORT`, where `PROTO` could be `tcp` or `udp`.
-
-See the `mg_bind_opts` structure for a description of the optional
-parameters.
-
-Return a new listening connection, or `NULL` on error.
-NOTE: Connection remains owned by the manager, do not free(). 
-
diff --git a/docs/c-api/net.h/mg_broadcast.md b/docs/c-api/net.h/mg_broadcast.md
deleted file mode 100644
index 94fceb8f0..000000000
--- a/docs/c-api/net.h/mg_broadcast.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-title: "mg_broadcast()"
-decl_name: "mg_broadcast"
-symbol_kind: "func"
-signature: |
-  void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t);
----
-
-Pass a message of a given length to all connections.
-
-Must be called from a thread that does NOT call `mg_mgr_poll()`.
-Note that `mg_broadcast()` is the only function
-that can be, and must be, called from a different (non-IO) thread.
-
-`func` callback function will be called by the IO thread for each
-connection. When called, event would be `MG_EV_POLL`, and message will
-be passed as `ev_data` pointer. Maximum message size is capped
-by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes. 
-
diff --git a/docs/c-api/net.h/mg_check_ip_acl.md b/docs/c-api/net.h/mg_check_ip_acl.md
deleted file mode 100644
index 957a684fb..000000000
--- a/docs/c-api/net.h/mg_check_ip_acl.md
+++ /dev/null
@@ -1,27 +0,0 @@
----
-title: "mg_check_ip_acl()"
-decl_name: "mg_check_ip_acl"
-symbol_kind: "func"
-signature: |
-  int mg_check_ip_acl(const char *acl, uint32_t remote_ip);
----
-
-Verify given IP address against the ACL.
-
-`remote_ip` - an IPv4 address to check, in host byte order
-`acl` - a comma separated list of IP subnets: `x.x.x.x/x` or `x.x.x.x`.
-Each subnet is
-prepended by either a - or a + sign. A plus sign means allow, where a
-minus sign means deny. If a subnet mask is omitted, such as `-1.2.3.4`,
-this means to deny only that single IP address.
-Subnet masks may vary from 0 to 32, inclusive. The default setting
-is to allow all accesses. On each request the full list is traversed,
-and the last match wins. Example:
-
-`-0.0.0.0/0,+192.168/16` - deny all acccesses, only allow 192.168/16 subnet
-
-To learn more about subnet masks, see the
-link:https://en.wikipedia.org/wiki/Subnetwork[Wikipedia page on Subnetwork]
-
-Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed. 
-
diff --git a/docs/c-api/net.h/mg_connect.md b/docs/c-api/net.h/mg_connect.md
deleted file mode 100644
index 388196e31..000000000
--- a/docs/c-api/net.h/mg_connect.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "mg_connect()"
-decl_name: "mg_connect"
-symbol_kind: "func"
-signature: |
-  struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address,
-                                   mg_event_handler_t handler);
----
-
-Connect to a remote host.
-
-See `mg_connect_opt()` for full documentation. 
-
diff --git a/docs/c-api/net.h/mg_connect_opt.md b/docs/c-api/net.h/mg_connect_opt.md
deleted file mode 100644
index d169ded10..000000000
--- a/docs/c-api/net.h/mg_connect_opt.md
+++ /dev/null
@@ -1,57 +0,0 @@
----
-title: "mg_connect_opt()"
-decl_name: "mg_connect_opt"
-symbol_kind: "func"
-signature: |
-  struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address,
-                                       mg_event_handler_t handler,
-                                       struct mg_connect_opts opts);
----
-
-Connect to a remote host.
-
-`address` format is `[PROTO://]HOST:PORT`. `PROTO` could be `tcp` or `udp`.
-`HOST` could be an IP address,
-IPv6 address (if Mongoose is compiled with `-DMG_ENABLE_IPV6`), or a host
-name. If `HOST` is a name, Mongoose will resolve it asynchronously. Examples
-of valid addresses: `google.com:80`, `udp://1.2.3.4:53`, `10.0.0.1:443`,
-`[::1]:80`
-
-See the `mg_connect_opts` structure for a description of the optional
-parameters.
-
-Returns a new outbound connection, or `NULL` on error.
-
-NOTE: Connection remains owned by the manager, do not free().
-
-NOTE: To enable IPv6 addresses, `-DMG_ENABLE_IPV6` should be specified
-in the compilation flags.
-
-NOTE: New connection will receive `MG_EV_CONNECT` as it's first event
-which will report connect success status.
-If asynchronous resolution fail, or `connect()` syscall fail for whatever
-reason (e.g. with `ECONNREFUSED` or `ENETUNREACH`), then `MG_EV_CONNECT`
-event report failure. Code example below:
-
-```c
-static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
-  int connect_status;
-
-  switch (ev) {
-    case MG_EV_CONNECT:
-      connect_status = * (int *) ev_data;
-      if (connect_status == 0) {
-        // Success
-      } else  {
-        // Error
-        printf("connect() error: %s\n", strerror(connect_status));
-      }
-      break;
-    ...
-  }
-}
-
-  ...
-  mg_connect(mgr, "my_site.com:80", ev_handler);
-``` 
-
diff --git a/docs/c-api/net.h/mg_enable_javascript.md b/docs/c-api/net.h/mg_enable_javascript.md
deleted file mode 100644
index cb2753866..000000000
--- a/docs/c-api/net.h/mg_enable_javascript.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "mg_enable_javascript()"
-decl_name: "mg_enable_javascript"
-symbol_kind: "func"
-signature: |
-  enum v7_err mg_enable_javascript(struct mg_mgr *m, struct v7 *v7,
-                                   const char *init_js_file_name);
----
-
-Enable server-side JavaScript scripting.
-Requires `-DMG_ENABLE_JAVASCRIPT` compilation flag, and V7 engine sources.
-v7 instance must not be destroyed during manager's lifetime.
-Return V7 error. 
-
diff --git a/docs/c-api/net.h/mg_enable_multithreading.md b/docs/c-api/net.h/mg_enable_multithreading.md
deleted file mode 100644
index 3498e4de3..000000000
--- a/docs/c-api/net.h/mg_enable_multithreading.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "mg_enable_multithreading()"
-decl_name: "mg_enable_multithreading"
-symbol_kind: "func"
-signature: |
-  void mg_enable_multithreading(struct mg_connection *nc);
----
-
-Enable multi-threaded handling for the given listening connection `nc`.
-For each accepted connection, Mongoose will create a separate thread
-and run event handler in that thread. Thus, if an event hanler is doing
-a blocking call or some long computation, that will not slow down
-other connections. 
-
diff --git a/docs/c-api/net.h/mg_event_handler_t.md b/docs/c-api/net.h/mg_event_handler_t.md
deleted file mode 100644
index 79a5ffd9f..000000000
--- a/docs/c-api/net.h/mg_event_handler_t.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: "mg_event_handler_t"
-decl_name: "mg_event_handler_t"
-symbol_kind: "typedef"
-signature: |
-  typedef void (*mg_event_handler_t)(struct mg_connection *, int ev, void *);
----
-
-Callback function (event handler) prototype, must be defined by user.
-Mongoose calls event handler, passing events defined below. 
-
diff --git a/docs/c-api/net.h/mg_mgr_free.md b/docs/c-api/net.h/mg_mgr_free.md
deleted file mode 100644
index 07ca25d3c..000000000
--- a/docs/c-api/net.h/mg_mgr_free.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "mg_mgr_free()"
-decl_name: "mg_mgr_free"
-symbol_kind: "func"
-signature: |
-  void mg_mgr_free(struct mg_mgr *);
----
-
-De-initializes Mongoose manager.
-
-Close and deallocate all active connections. 
-
diff --git a/docs/c-api/net.h/mg_mgr_init.md b/docs/c-api/net.h/mg_mgr_init.md
deleted file mode 100644
index b59506bdf..000000000
--- a/docs/c-api/net.h/mg_mgr_init.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: "mg_mgr_init()"
-decl_name: "mg_mgr_init"
-symbol_kind: "func"
-signature: |
-  void mg_mgr_init(struct mg_mgr *mgr, void *user_data);
----
-
-Initialize Mongoose manager. Side effect: ignores SIGPIPE signal.
-`mgr->user_data` field will be initialized with `user_data` parameter.
-That is an arbitrary pointer, where user code can associate some data
-with the particular Mongoose manager. For example, a C++ wrapper class
-could be written, in which case `user_data` can hold a pointer to the
-class instance. 
-
diff --git a/docs/c-api/net.h/mg_mgr_poll.md b/docs/c-api/net.h/mg_mgr_poll.md
deleted file mode 100644
index f25c75956..000000000
--- a/docs/c-api/net.h/mg_mgr_poll.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: "mg_mgr_poll()"
-decl_name: "mg_mgr_poll"
-symbol_kind: "func"
-signature: |
-  time_t mg_mgr_poll(struct mg_mgr *, int milli);
----
-
-This function performs the actual IO, and must be called in a loop
-(an event loop). Returns the current timestamp.
-`milli` is the maximum number of milliseconds to sleep.
-`mg_mgr_poll()` checks all connection for IO readiness. If at least one
-of the connections is IO-ready, `mg_mgr_poll()` triggers respective
-event handlers and returns. 
-
diff --git a/docs/c-api/net.h/mg_next.md b/docs/c-api/net.h/mg_next.md
deleted file mode 100644
index fc817262d..000000000
--- a/docs/c-api/net.h/mg_next.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-title: "mg_next()"
-decl_name: "mg_next"
-symbol_kind: "func"
-signature: |
-  struct mg_connection *mg_next(struct mg_mgr *, struct mg_connection *);
----
-
-Iterate over all active connections.
-
-Returns next connection from the list
-of active connections, or `NULL` if there is no more connections. Below
-is the iteration idiom:
-
-```c
-for (c = mg_next(srv, NULL); c != NULL; c = mg_next(srv, c)) {
-  // Do something with connection `c`
-}
-``` 
-
diff --git a/docs/c-api/net.h/mg_printf.md b/docs/c-api/net.h/mg_printf.md
deleted file mode 100644
index 281fb4fd5..000000000
--- a/docs/c-api/net.h/mg_printf.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "mg_printf()"
-decl_name: "mg_printf"
-symbol_kind: "func"
-signature: |
-  int mg_printf(struct mg_connection *, const char *fmt, ...);
----
-
-Send `printf`-style formatted data to the connection.
-
-See `mg_send` for more details on send semantics. 
-
diff --git a/docs/c-api/net.h/mg_send.md b/docs/c-api/net.h/mg_send.md
deleted file mode 100644
index e1aed3e03..000000000
--- a/docs/c-api/net.h/mg_send.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "mg_send()"
-decl_name: "mg_send"
-symbol_kind: "func"
-signature: |
-  void mg_send(struct mg_connection *, const void *buf, int len);
----
-
-Send data to the connection.
-
-Note that sending functions do not actually push data to the socket.
-They just append data to the output buffer. MG_EV_SEND will be delivered when
-the data has actually been pushed out. 
-
diff --git a/docs/c-api/net.h/mg_set_ssl.md b/docs/c-api/net.h/mg_set_ssl.md
deleted file mode 100644
index c2212b870..000000000
--- a/docs/c-api/net.h/mg_set_ssl.md
+++ /dev/null
@@ -1,19 +0,0 @@
----
-title: "mg_set_ssl()"
-decl_name: "mg_set_ssl"
-symbol_kind: "func"
-signature: |
-  const char *mg_set_ssl(struct mg_connection *nc, const char *cert,
-                         const char *ca_cert);
----
-
-Enable SSL for a given connection.
-`cert` is a server certificate file name for a listening connection,
-or a client certificate file name for an outgoing connection.
-Certificate files must be in PEM format. Server certificate file
-must contain a certificate, concatenated with a private key, optionally
-concatenated with parameters.
-`ca_cert` is a CA certificate, or NULL if peer verification is not
-required.
-Return: NULL on success, or error message on error. 
-
diff --git a/docs/c-api/net.h/mg_set_timer.md b/docs/c-api/net.h/mg_set_timer.md
deleted file mode 100644
index e559c26b2..000000000
--- a/docs/c-api/net.h/mg_set_timer.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-title: "mg_set_timer()"
-decl_name: "mg_set_timer"
-symbol_kind: "func"
-signature: |
-  double mg_set_timer(struct mg_connection *c, double timestamp);
----
-
-Schedule MG_EV_TIMER event to be delivered at `timestamp` time.
-`timestamp` is a UNIX time (a number of seconds since Epoch). It is
-`double` instead of `time_t` to allow for sub-second precision.
-Return the old timer value.
-
-Example: set connect timeout to 1.5 seconds:
-
-```
- c = mg_connect(&mgr, "cesanta.com", ev_handler);
- mg_set_timer(c, mg_time() + 1.5);
- ...
-
- void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
- switch (ev) {
-   case MG_EV_CONNECT:
-     mg_set_timer(c, 0);  // Clear connect timer
-     break;
-   case MG_EV_TIMER:
-     log("Connect timeout");
-     c->flags |= MG_F_CLOSE_IMMEDIATELY;
-     break;
-``` 
-
diff --git a/docs/c-api/net.h/mg_socketpair.md b/docs/c-api/net.h/mg_socketpair.md
deleted file mode 100644
index 1509c0f3a..000000000
--- a/docs/c-api/net.h/mg_socketpair.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "mg_socketpair()"
-decl_name: "mg_socketpair"
-symbol_kind: "func"
-signature: |
-  int mg_socketpair(sock_t[2], int sock_type);
----
-
-Create a socket pair.
-`sock_type` can be either `SOCK_STREAM` or `SOCK_DGRAM`.
-Return 0 on failure, 1 on success. 
-
diff --git a/docs/c-api/net.h/mg_time.md b/docs/c-api/net.h/mg_time.md
deleted file mode 100644
index 73b5e3870..000000000
--- a/docs/c-api/net.h/mg_time.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_time()"
-decl_name: "mg_time"
-symbol_kind: "func"
-signature: |
-  double mg_time();
----
-
-A sub-second precision version of time(). 
-
diff --git a/docs/c-api/net.h/mg_vprintf.md b/docs/c-api/net.h/mg_vprintf.md
deleted file mode 100644
index ff66e264f..000000000
--- a/docs/c-api/net.h/mg_vprintf.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_vprintf()"
-decl_name: "mg_vprintf"
-symbol_kind: "func"
-signature: |
-  int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
----
-
-Same as `mg_printf()`, but takes `va_list ap` as an argument. 
-
diff --git a/docs/c-api/net.h/struct_mg_add_sock_opts.md b/docs/c-api/net.h/struct_mg_add_sock_opts.md
deleted file mode 100644
index 1f399874c..000000000
--- a/docs/c-api/net.h/struct_mg_add_sock_opts.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-title: "struct mg_add_sock_opts"
-decl_name: "struct mg_add_sock_opts"
-symbol_kind: "struct"
-signature: |
-  struct mg_add_sock_opts {
-    void *user_data;           /* Initial value for connection's user_data */
-    unsigned int flags;        /* Initial connection flags */
-    const char **error_string; /* Placeholder for the error string */
-  };
----
-
-Optional parameters to `mg_add_sock_opt()`.
-
-`flags` is an initial `struct mg_connection::flags` bitmask to set,
-see `MG_F_*` flags definitions. 
-
diff --git a/docs/c-api/net.h/struct_mg_bind_opts.md b/docs/c-api/net.h/struct_mg_bind_opts.md
deleted file mode 100644
index a72e7a16a..000000000
--- a/docs/c-api/net.h/struct_mg_bind_opts.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-title: "struct mg_bind_opts"
-decl_name: "struct mg_bind_opts"
-symbol_kind: "struct"
-signature: |
-  struct mg_bind_opts {
-    void *user_data;           /* Initial value for connection's user_data */
-    unsigned int flags;        /* Extra connection flags */
-    const char **error_string; /* Placeholder for the error string */
-  #ifdef MG_ENABLE_SSL
-    /* SSL settings. */
-    const char *ssl_cert;    /* Server certificate to present to clients */
-    const char *ssl_ca_cert; /* Verify client certificates with this CA bundle */
-  #endif
-  };
----
-
-Optional parameters to `mg_bind_opt()`.
-
-`flags` is an initial `struct mg_connection::flags` bitmask to set,
-see `MG_F_*` flags definitions. 
-
diff --git a/docs/c-api/net.h/struct_mg_connect_opts.md b/docs/c-api/net.h/struct_mg_connect_opts.md
deleted file mode 100644
index 167035c2d..000000000
--- a/docs/c-api/net.h/struct_mg_connect_opts.md
+++ /dev/null
@@ -1,28 +0,0 @@
----
-title: "struct mg_connect_opts"
-decl_name: "struct mg_connect_opts"
-symbol_kind: "struct"
-signature: |
-  struct mg_connect_opts {
-    void *user_data;           /* Initial value for connection's user_data */
-    unsigned int flags;        /* Extra connection flags */
-    const char **error_string; /* Placeholder for the error string */
-  #ifdef MG_ENABLE_SSL
-    /* SSL settings. */
-    const char *ssl_cert;    /* Client certificate to present to the server */
-    const char *ssl_ca_cert; /* Verify server certificate using this CA bundle */
-  
-    /*
-     * Server name verification. If ssl_ca_cert is set and the certificate has
-     * passed verification, its subject will be verified against this string.
-     * By default (if ssl_server_name is NULL) hostname part of the address will
-     * be used. Wildcard matching is supported. A special value of "*" disables
-     * name verification.
-     */
-    const char *ssl_server_name;
-  #endif
-  };
----
-
-Optional parameters to `mg_connect_opt()` 
-
diff --git a/docs/c-api/net.h/struct_mg_connection.md b/docs/c-api/net.h/struct_mg_connection.md
deleted file mode 100644
index fb72db9ba..000000000
--- a/docs/c-api/net.h/struct_mg_connection.md
+++ /dev/null
@@ -1,63 +0,0 @@
----
-title: "struct mg_connection"
-decl_name: "struct mg_connection"
-symbol_kind: "struct"
-signature: |
-  struct mg_connection {
-    struct mg_connection *next, *prev; /* mg_mgr::active_connections linkage */
-    struct mg_connection *listener;    /* Set only for accept()-ed connections */
-    struct mg_mgr *mgr;                /* Pointer to containing manager */
-  
-    sock_t sock; /* Socket to the remote peer */
-    int err;
-    union socket_address sa; /* Remote peer address */
-    size_t recv_mbuf_limit;  /* Max size of recv buffer */
-    struct mbuf recv_mbuf;   /* Received data */
-    struct mbuf send_mbuf;   /* Data scheduled for sending */
-    SSL *ssl;
-    SSL_CTX *ssl_ctx;
-    time_t last_io_time;              /* Timestamp of the last socket IO */
-    double ev_timer_time;             /* Timestamp of the future MG_EV_TIMER */
-    mg_event_handler_t proto_handler; /* Protocol-specific event handler */
-    void *proto_data;                 /* Protocol-specific data */
-    void (*proto_data_destructor)(void *proto_data);
-    mg_event_handler_t handler; /* Event handler function */
-    void *user_data;            /* User-specific data */
-    union {
-      void *v;
-      /*
-       * the C standard is fussy about fitting function pointers into
-       * void pointers, since some archs might have fat pointers for functions.
-       */
-      mg_event_handler_t f;
-    } priv_1;       /* Used by mg_enable_multithreading() */
-    void *priv_2;   /* Used by mg_enable_multithreading() */
-    void *mgr_data; /* Implementation-specific event manager's data. */
-    unsigned long flags;
-  /* Flags set by Mongoose */
-  #define MG_F_LISTENING (1 << 0)          /* This connection is listening */
-  #define MG_F_UDP (1 << 1)                /* This connection is UDP */
-  #define MG_F_RESOLVING (1 << 2)          /* Waiting for async resolver */
-  #define MG_F_CONNECTING (1 << 3)         /* connect() call in progress */
-  #define MG_F_SSL_HANDSHAKE_DONE (1 << 4) /* SSL specific */
-  #define MG_F_WANT_READ (1 << 5)          /* SSL specific */
-  #define MG_F_WANT_WRITE (1 << 6)         /* SSL specific */
-  #define MG_F_IS_WEBSOCKET (1 << 7)       /* Websocket specific */
-  
-  /* Flags that are settable by user */
-  #define MG_F_SEND_AND_CLOSE (1 << 10)      /* Push remaining data and close  */
-  #define MG_F_CLOSE_IMMEDIATELY (1 << 11)   /* Disconnect */
-  #define MG_F_WEBSOCKET_NO_DEFRAG (1 << 12) /* Websocket specific */
-  #define MG_F_DELETE_CHUNK (1 << 13)        /* HTTP specific */
-  
-  #define MG_F_USER_1 (1 << 20) /* Flags left for application */
-  #define MG_F_USER_2 (1 << 21)
-  #define MG_F_USER_3 (1 << 22)
-  #define MG_F_USER_4 (1 << 23)
-  #define MG_F_USER_5 (1 << 24)
-  #define MG_F_USER_6 (1 << 25)
-  };
----
-
-Mongoose connection. 
-
diff --git a/docs/c-api/net.h/struct_mg_mgr.md b/docs/c-api/net.h/struct_mg_mgr.md
deleted file mode 100644
index f510e1b08..000000000
--- a/docs/c-api/net.h/struct_mg_mgr.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-title: "struct mg_mgr"
-decl_name: "struct mg_mgr"
-symbol_kind: "struct"
-signature: |
-  struct mg_mgr {
-    struct mg_connection *active_connections;
-    const char *hexdump_file; /* Debug hexdump file path */
-  #ifndef MG_DISABLE_SOCKETPAIR
-    sock_t ctl[2]; /* Socketpair for mg_wakeup() */
-  #endif
-    void *user_data; /* User data */
-    void *mgr_data;  /* Implementation-specific event manager's data. */
-  #ifdef MG_ENABLE_JAVASCRIPT
-    struct v7 *v7;
-  #endif
-  };
----
-
-Mongoose event manager. 
-
diff --git a/docs/c-api/net.h/struct_mg_str.md b/docs/c-api/net.h/struct_mg_str.md
deleted file mode 100644
index 6c0ad613b..000000000
--- a/docs/c-api/net.h/struct_mg_str.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "struct mg_str"
-decl_name: "struct mg_str"
-symbol_kind: "struct"
-signature: |
-  struct mg_str {
-    const char *p; /* Memory chunk pointer */
-    size_t len;    /* Memory chunk length */
-  };
----
-
-Describes chunk of memory 
-
diff --git a/docs/c-api/util.h/MG_MK_STR.md b/docs/c-api/util.h/MG_MK_STR.md
deleted file mode 100644
index 4862e8625..000000000
--- a/docs/c-api/util.h/MG_MK_STR.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "MG_MK_STR()"
-decl_name: "MG_MK_STR"
-symbol_kind: "func"
-signature: |
-  #define MG_MK_STR(str_literal);
----
-
-Macro for initializing mg_str. 
-
diff --git a/docs/c-api/util.h/intro.md b/docs/c-api/util.h/intro.md
deleted file mode 100644
index 3b516c8a7..000000000
--- a/docs/c-api/util.h/intro.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-title: "Utilities"
-symbol_kind: "intro"
-decl_name: "util.h"
----
-
-
-
diff --git a/docs/c-api/util.h/items.json b/docs/c-api/util.h/items.json
deleted file mode 100644
index 4b5b52e01..000000000
--- a/docs/c-api/util.h/items.json
+++ /dev/null
@@ -1,96 +0,0 @@
-{
-    "items": [
-        {
-            "type": "markdown",
-            "name": "intro.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_skip.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_ncasecmp.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_casecmp.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_vcmp.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_vcasecmp.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_base64_decode.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_base64_encode.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_stat.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_fopen.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_open.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_start_thread.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_conn_addr_to_str.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_sock_to_str.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_sock_addr_to_str.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_hexdump.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_hexdump_connection.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_avprintf.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_is_big_endian.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_next_comma_list_entry.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_match_prefix.md"
-        },
-        {
-            "type": "markdown",
-            "name": "mg_mk_str.md"
-        },
-        {
-            "type": "markdown",
-            "name": "MG_MK_STR.md"
-        }
-    ]
-}
diff --git a/docs/c-api/util.h/mg_avprintf.md b/docs/c-api/util.h/mg_avprintf.md
deleted file mode 100644
index efc424d00..000000000
--- a/docs/c-api/util.h/mg_avprintf.md
+++ /dev/null
@@ -1,22 +0,0 @@
----
-title: "mg_avprintf()"
-decl_name: "mg_avprintf"
-symbol_kind: "func"
-signature: |
-  int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
----
-
-Print message to buffer. If buffer is large enough to hold the message,
-return buffer. If buffer is to small, allocate large enough buffer on heap,
-and return allocated buffer.
-This is a supposed use case:
-
-   char buf[5], *p = buf;
-   p = mg_avprintf(&p, sizeof(buf), "%s", "hi there");
-   use_p_somehow(p);
-   if (p != buf) {
-     free(p);
-   }
-
-The purpose of this is to avoid malloc-ing if generated strings are small. 
-
diff --git a/docs/c-api/util.h/mg_base64_decode.md b/docs/c-api/util.h/mg_base64_decode.md
deleted file mode 100644
index 3fa77428f..000000000
--- a/docs/c-api/util.h/mg_base64_decode.md
+++ /dev/null
@@ -1,16 +0,0 @@
----
-title: "mg_base64_decode()"
-decl_name: "mg_base64_decode"
-symbol_kind: "func"
-signature: |
-  int mg_base64_decode(const unsigned char *s, int len, char *dst);
----
-
-Decode base64-encoded string `s`, `len` into the destination `dst`.
-Destination has to have enough space to hold decoded buffer.
-Decoding stops either when all string has been decoded, or invalid
-character appeared.
-Destination is '\0'-terminated.
-Return number of decoded characters. On success, that should be equal to
-`len`. On error (invalid character) the return value is smaller then `len`. 
-
diff --git a/docs/c-api/util.h/mg_base64_encode.md b/docs/c-api/util.h/mg_base64_encode.md
deleted file mode 100644
index c3b5c05e2..000000000
--- a/docs/c-api/util.h/mg_base64_encode.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "mg_base64_encode()"
-decl_name: "mg_base64_encode"
-symbol_kind: "func"
-signature: |
-  void mg_base64_encode(const unsigned char *src, int src_len, char *dst);
----
-
-Base64-encode chunk of memory `src`, `src_len` into the destination `dst`.
-Destination has to have enough space to hold encoded buffer.
-Destination is '\0'-terminated. 
-
diff --git a/docs/c-api/util.h/mg_casecmp.md b/docs/c-api/util.h/mg_casecmp.md
deleted file mode 100644
index 8d23dbf69..000000000
--- a/docs/c-api/util.h/mg_casecmp.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_casecmp()"
-decl_name: "mg_casecmp"
-symbol_kind: "func"
-signature: |
-  int mg_casecmp(const char *s1, const char *s2);
----
-
-Cross-platform version of `strcasecmp()`. 
-
diff --git a/docs/c-api/util.h/mg_conn_addr_to_str.md b/docs/c-api/util.h/mg_conn_addr_to_str.md
deleted file mode 100644
index f17bfb70f..000000000
--- a/docs/c-api/util.h/mg_conn_addr_to_str.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-title: "mg_conn_addr_to_str()"
-decl_name: "mg_conn_addr_to_str"
-symbol_kind: "func"
-signature: |
-  void mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len,
-                           int flags);
----
-
-Convert connection's local or remote address into string.
-
-The `flags` parameter is a bit mask that controls the behavior,
-see `MG_SOCK_STRINGIFY_*` definitions.
-
-- MG_SOCK_STRINGIFY_IP - print IP address
-- MG_SOCK_STRINGIFY_PORT - print port number
-- MG_SOCK_STRINGIFY_REMOTE - print remote peer's IP/port, not local address
-
-If both port number and IP address are printed, they are separated by `:`.
-If compiled with `-DMG_ENABLE_IPV6`, IPv6 addresses are supported. 
-
diff --git a/docs/c-api/util.h/mg_fopen.md b/docs/c-api/util.h/mg_fopen.md
deleted file mode 100644
index 3446670c2..000000000
--- a/docs/c-api/util.h/mg_fopen.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "mg_fopen()"
-decl_name: "mg_fopen"
-symbol_kind: "func"
-signature: |
-  FILE *mg_fopen(const char *path, const char *mode);
----
-
-Open the given file and return a file stream.
-
-`path` and `mode` should be UTF8 encoded.
-
-Return value is the same as for the `fopen()` call. 
-
diff --git a/docs/c-api/util.h/mg_hexdump.md b/docs/c-api/util.h/mg_hexdump.md
deleted file mode 100644
index ed02068aa..000000000
--- a/docs/c-api/util.h/mg_hexdump.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: "mg_hexdump()"
-decl_name: "mg_hexdump"
-symbol_kind: "func"
-signature: |
-  int mg_hexdump(const void *buf, int len, char *dst, int dst_len);
----
-
-Generates human-readable hexdump of memory chunk.
-
-Takes a memory buffer `buf` of length `len` and creates a hex dump of that
-buffer in `dst`. Generated output is a-la hexdump(1).
-Return length of generated string, excluding terminating `\0`. If returned
-length is bigger than `dst_len`, overflow bytes are discarded. 
-
diff --git a/docs/c-api/util.h/mg_hexdump_connection.md b/docs/c-api/util.h/mg_hexdump_connection.md
deleted file mode 100644
index 2e6d520d7..000000000
--- a/docs/c-api/util.h/mg_hexdump_connection.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: "mg_hexdump_connection()"
-decl_name: "mg_hexdump_connection"
-symbol_kind: "func"
-signature: |
-  void mg_hexdump_connection(struct mg_connection *nc, const char *path,
-                             const void *buf, int num_bytes, int ev);
----
-
-Generates human-readable hexdump of the data sent or received by connection.
-`path` is a file name where hexdump should be written. `num_bytes` is
-a number of bytes sent/received. `ev` is one of the `MG_*` events sent to
-an event handler. This function is supposed to be called from the
-event handler. 
-
diff --git a/docs/c-api/util.h/mg_is_big_endian.md b/docs/c-api/util.h/mg_is_big_endian.md
deleted file mode 100644
index ba33f4d7d..000000000
--- a/docs/c-api/util.h/mg_is_big_endian.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_is_big_endian()"
-decl_name: "mg_is_big_endian"
-symbol_kind: "func"
-signature: |
-  int mg_is_big_endian(void);
----
-
-Return true if target platform is big endian. 
-
diff --git a/docs/c-api/util.h/mg_match_prefix.md b/docs/c-api/util.h/mg_match_prefix.md
deleted file mode 100644
index 17da2ea7a..000000000
--- a/docs/c-api/util.h/mg_match_prefix.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: "mg_match_prefix()"
-decl_name: "mg_match_prefix"
-symbol_kind: "func"
-signature: |
-  int mg_match_prefix(const char *pattern, int pattern_len, const char *str);
----
-
-Match 0-terminated string (mg_match_prefix) or string with given length
-mg_match_prefix_n against a glob pattern.
-Match is case-insensitive. Return number of bytes matched, or -1 if no match. 
-
diff --git a/docs/c-api/util.h/mg_mk_str.md b/docs/c-api/util.h/mg_mk_str.md
deleted file mode 100644
index 4862e8625..000000000
--- a/docs/c-api/util.h/mg_mk_str.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "MG_MK_STR()"
-decl_name: "MG_MK_STR"
-symbol_kind: "func"
-signature: |
-  #define MG_MK_STR(str_literal);
----
-
-Macro for initializing mg_str. 
-
diff --git a/docs/c-api/util.h/mg_ncasecmp.md b/docs/c-api/util.h/mg_ncasecmp.md
deleted file mode 100644
index 3e113810d..000000000
--- a/docs/c-api/util.h/mg_ncasecmp.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_ncasecmp()"
-decl_name: "mg_ncasecmp"
-symbol_kind: "func"
-signature: |
-  int mg_ncasecmp(const char *s1, const char *s2, size_t len);
----
-
-Cross-platform version of `strncasecmp()`. 
-
diff --git a/docs/c-api/util.h/mg_next_comma_list_entry.md b/docs/c-api/util.h/mg_next_comma_list_entry.md
deleted file mode 100644
index e82d06095..000000000
--- a/docs/c-api/util.h/mg_next_comma_list_entry.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-title: "mg_next_comma_list_entry()"
-decl_name: "mg_next_comma_list_entry"
-symbol_kind: "func"
-signature: |
-  const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
-                                       struct mg_str *eq_val);
----
-
-A helper function for traversing a comma separated list of values.
-It returns a list pointer shifted to the next value, or NULL if the end
-of the list found.
-Value is stored in val vector. If value has form "x=y", then eq_val
-vector is initialized to point to the "y" part, and val vector length
-is adjusted to point only to "x".
-If list is just a comma separated list of entries, like "aa,bb,cc" then
-`eq_val` will contain zero-length string.
-
-The purpose of this function is to parse comma separated string without
-any copying/memory allocation. 
-
diff --git a/docs/c-api/util.h/mg_open.md b/docs/c-api/util.h/mg_open.md
deleted file mode 100644
index 385446709..000000000
--- a/docs/c-api/util.h/mg_open.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "mg_open()"
-decl_name: "mg_open"
-symbol_kind: "func"
-signature: |
-  int mg_open(const char *path, int flag, int mode);
----
-
-Open the given file and return a file stream.
-
-`path` should be UTF8 encoded.
-
-Return value is the same as for the `open()` syscall. 
-
diff --git a/docs/c-api/util.h/mg_skip.md b/docs/c-api/util.h/mg_skip.md
deleted file mode 100644
index 858dc1d77..000000000
--- a/docs/c-api/util.h/mg_skip.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-title: "mg_skip()"
-decl_name: "mg_skip"
-symbol_kind: "func"
-signature: |
-  const char *mg_skip(const char *s, const char *end_string,
-                      const char *delimiters, struct mg_str *v);
----
-
-Fetch substring from input string `s`, `end` into `v`.
-Skips initial delimiter characters. Records first non-delimiter character
-as the beginning of substring `v`. Then scans the rest of the string
-until a delimiter character or end-of-string is found.
-`delimiters` is a 0-terminated string containing delimiter characters.
-Either one of `delimiters` or `end_string` terminates the search.
-Return an `s` pointer, advanced forward where parsing stopped. 
-
diff --git a/docs/c-api/util.h/mg_sock_addr_to_str.md b/docs/c-api/util.h/mg_sock_addr_to_str.md
deleted file mode 100644
index 0563630b1..000000000
--- a/docs/c-api/util.h/mg_sock_addr_to_str.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "mg_sock_addr_to_str()"
-decl_name: "mg_sock_addr_to_str"
-symbol_kind: "func"
-signature: |
-  void mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len,
-                           int flags);
----
-
-Convert socket's address into string.
-
-`flags` is MG_SOCK_STRINGIFY_IP and/or MG_SOCK_STRINGIFY_PORT. 
-
diff --git a/docs/c-api/util.h/mg_sock_to_str.md b/docs/c-api/util.h/mg_sock_to_str.md
deleted file mode 100644
index fb233b560..000000000
--- a/docs/c-api/util.h/mg_sock_to_str.md
+++ /dev/null
@@ -1,10 +0,0 @@
----
-title: "mg_sock_to_str()"
-decl_name: "mg_sock_to_str"
-symbol_kind: "func"
-signature: |
-  void mg_sock_to_str(sock_t sock, char *buf, size_t len, int flags);
----
-
-Legacy interface. 
-
diff --git a/docs/c-api/util.h/mg_start_thread.md b/docs/c-api/util.h/mg_start_thread.md
deleted file mode 100644
index 11b66d30a..000000000
--- a/docs/c-api/util.h/mg_start_thread.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-title: "mg_start_thread()"
-decl_name: "mg_start_thread"
-symbol_kind: "func"
-signature: |
-  void *mg_start_thread(void *(*thread_func);
----
-
-Start a new detached thread.
-Arguments and semantic is the same as pthead's `pthread_create()`.
-`thread_func` is a thread function, `thread_func_param` is a parameter
-that is passed to the thread function. 
-
diff --git a/docs/c-api/util.h/mg_stat.md b/docs/c-api/util.h/mg_stat.md
deleted file mode 100644
index 66c3d75f5..000000000
--- a/docs/c-api/util.h/mg_stat.md
+++ /dev/null
@@ -1,14 +0,0 @@
----
-title: "mg_stat()"
-decl_name: "mg_stat"
-symbol_kind: "func"
-signature: |
-  int mg_stat(const char *path, cs_stat_t *st);
----
-
-Perform a 64-bit `stat()` call against given file.
-
-`path` should be UTF8 encoded.
-
-Return value is the same as for `stat()` syscall. 
-
diff --git a/docs/c-api/util.h/mg_vcasecmp.md b/docs/c-api/util.h/mg_vcasecmp.md
deleted file mode 100644
index 54cb1ab02..000000000
--- a/docs/c-api/util.h/mg_vcasecmp.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: "mg_vcasecmp()"
-decl_name: "mg_vcasecmp"
-symbol_kind: "func"
-signature: |
-  int mg_vcasecmp(const struct mg_str *str2, const char *str1);
----
-
-Cross-platform version of `strncasecmp()` where first string is
-specified by `struct mg_str`. 
-
diff --git a/docs/c-api/util.h/mg_vcmp.md b/docs/c-api/util.h/mg_vcmp.md
deleted file mode 100644
index 74c29d12a..000000000
--- a/docs/c-api/util.h/mg_vcmp.md
+++ /dev/null
@@ -1,11 +0,0 @@
----
-title: "mg_vcmp()"
-decl_name: "mg_vcmp"
-symbol_kind: "func"
-signature: |
-  int mg_vcmp(const struct mg_str *str2, const char *str1);
----
-
-Cross-platform version of `strcmp()` where where first string is
-specified by `struct mg_str`. 
-
diff --git a/docs/coap.adoc b/docs/coap.adoc
new file mode 100644
index 000000000..4881cae05
--- /dev/null
+++ b/docs/coap.adoc
@@ -0,0 +1,129 @@
+=== CoAP
+
+CoAP message format:
+
+```
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+|Ver| T | TKL | Code | Message ID | Token (if any, TKL bytes) ...
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+| Options (if any) ...            |1 1 1 1 1 1 1 1| Payload (if any) ...
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+``` 
+
+==== struct mg_coap_option
+
+[source,c]
+----
+struct mg_coap_option {
+  struct mg_coap_option *next;
+  uint32_t number;
+  struct mg_str value;
+};
+----
+CoAP options.
+Use mg_coap_add_option and mg_coap_free_options
+for creation and destruction. 
+
+==== struct mg_coap_message
+
+[source,c]
+----
+struct mg_coap_message {
+  uint32_t flags;
+  uint8_t msg_type;
+  uint8_t code_class;
+  uint8_t code_detail;
+  uint16_t msg_id;
+  struct mg_str token;
+  struct mg_coap_option *options;
+  struct mg_str payload;
+  struct mg_coap_option *optiomg_tail;
+};
+----
+CoAP message. See RFC 7252 for details. 
+
+==== mg_set_protocol_coap()
+
+[source,c]
+----
+int mg_set_protocol_coap(struct mg_connection *nc);
+----
+Set CoAP protocol handler - trigger CoAP specific events 
+
+==== mg_coap_add_option()
+
+[source,c]
+----
+struct mg_coap_option *mg_coap_add_option(struct mg_coap_message *cm,
+                                          uint32_t number, char *value,
+                                          size_t len);
+----
+Add new option to mg_coap_message structure.
+Returns pointer to the newly created option. 
+
+==== mg_coap_free_options()
+
+[source,c]
+----
+void mg_coap_free_options(struct mg_coap_message *cm);
+----
+Free the memory allocated for options,
+if cm paramater doesn't contain any option does nothing. 
+
+==== mg_coap_send_message()
+
+[source,c]
+----
+uint32_t mg_coap_send_message(struct mg_connection *nc,
+                              struct mg_coap_message *cm);
+----
+Compose CoAP message from `mg_coap_message`
+and send it into `nc` connection.
+Return 0 on success. On error, it is a bitmask:
+
+- `#define MG_COAP_ERROR 0x10000`
+- `#define MG_COAP_FORMAT_ERROR (MG_COAP_ERROR | 0x20000)`
+- `#define MG_COAP_IGNORE (MG_COAP_ERROR | 0x40000)`
+- `#define MG_COAP_NOT_ENOUGH_DATA (MG_COAP_ERROR | 0x80000)`
+- `#define MG_COAP_NETWORK_ERROR (MG_COAP_ERROR | 0x100000)` 
+
+==== mg_coap_send_ack()
+
+[source,c]
+----
+uint32_t mg_coap_send_ack(struct mg_connection *nc, uint16_t msg_id);
+----
+Compose CoAP acknowledgement from `mg_coap_message`
+and send it into `nc` connection.
+Return value: see `mg_coap_send_message()` 
+
+==== mg_coap_parse()
+
+[source,c]
+----
+uint32_t mg_coap_parse(struct mbuf *io, struct mg_coap_message *cm);
+----
+Parse COAP message and fills mg_coap_message and returns cm->flags.
+This is a helper function.
+
+NOTE: usually CoAP work over UDP, so lack of data means format error,
+but in theory it is possible to use CoAP over TCP (according to RFC)
+
+The caller have to check results and treat COAP_NOT_ENOUGH_DATA according to
+underlying protocol:
+
+- in case of UDP COAP_NOT_ENOUGH_DATA means COAP_FORMAT_ERROR,
+- in case of TCP client can try to receive more data
+
+Return value: see `mg_coap_send_message()` 
+
+==== mg_coap_compose()
+
+[source,c]
+----
+uint32_t mg_coap_compose(struct mg_coap_message *cm, struct mbuf *io);
+----
+Composes CoAP message from mg_coap_message structure.
+This is a helper function.
+Return value: see `mg_coap_send_message()` 
+
diff --git a/docs/common.adoc b/docs/common.adoc
new file mode 100644
index 000000000..160a79b53
--- /dev/null
+++ b/docs/common.adoc
@@ -0,0 +1,2 @@
+Local tweaks, applied before any of Mongoose's own headers. 
+
diff --git a/docs/concept.adoc b/docs/concept.adoc
new file mode 100644
index 000000000..d6edebb63
--- /dev/null
+++ b/docs/concept.adoc
@@ -0,0 +1,167 @@
+
+== Design Concept
+
+Mongoose is a multi-protocol networking library that implements non-blocking,
+asyncronous IO and provides event-based API. It has three basic data structures:
+
+- link:#_struct_mg_mgr[`struct mg_mgr`] is an event manager
+  that holds all active connections
+- link:#_struct_mg_connection[`struct mg_connection`] describes a connection
+- link:#_struct_mbuf[`struct mbuf`] describes data buffer
+  (received or sent data)
+
+Connections could be either *listening*, *outbound* or *inbound*.
+Outbound connections are created by link:#_mg_connect[`mg_connect()`] call.
+Listening connections are created by link:#_mg_bind[`mg_bind()`] call.
+Inbound connections are those accepted by a listening connection.
+Each connection is described by
+link:#_struct_mg_connection[`struct mg_connection`] structure, which has
+a number of fields like socket, event handler function, send/receive buffer,
+flags, et cetera.
+
+Mongoose usage pattern is to declare and initialize event manager, create
+connections and create an event loop by calling
+link:#_mg_mgr_poll[`mg_mgr_poll()`] in a loop.
+link:#_mg_mgr_poll[`mg_mgr_poll()`] iterates over all sockets,
+accepts new connections, sends and receives data, closes connections,
+and calls event handler functions for the respective events.
+
+=== Memory buffers
+
+Each connection has send and receive buffer,
+link:#_struct_mg_connection[`struct mg_connection::send_mbuf`]
+and
+link:#_struct_mg_connection[`struct mg_connection::recv_mbuf`] respectively.
+When data arrives,
+Mongoose appends received data to the `recv_mbuf` and
+triggers `MG_EV_RECV` event. User may send data back by calling one of the
+output functions, like link:#_mg_send[`mg_send()`] or
+link:#_mg_printf[`mg_printf()`]. Output functions append data to the
+`send_mbuf`. When Mongoose
+successfully writes data to the socket, it discards data from
+link:#_struct_mg_connection[`mg_connection::send_mbuf`] and
+sends `MG_EV_SEND` event. When connection is closed, `MG_EV_CLOSE` event is sent.
+
+image::mongoose/mbuf.png[width="600",align="center"]
+
+=== Event handler function
+
+Each connection has an event handler function associated with it. That
+function must be implemented by user. Event handler is the key element of
+the Mongoose application, since it defines application's behavior. This is how
+an event handler function looks like:
+
+[source,c]
+----
+static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
+  switch (ev) {
+    /* Event handler code that defines behavior of the connection */
+    ...
+  }
+}
+----
+
+struct mg_connection *nc::
+  Connection that has received an event.
+
+int ev::
+  Event number, defined in `mongoose.h`. For example, when data arrives
+  on inbound connection `ev` would be `MG_EV_RECV`.
+
+void *ev_data::
+  This pointer points to the event-specific data, and it has different
+  meaning for different events. For example, for `MG_EV_RECV` event,
+  `ev_data` is an `int *` pointer, pointing to the number of bytes received
+  from the remote peer and saved into the receive IO buffer. Exact meaning
+  of `ev_data` is described for each event. Protocol-specific events usually
+  have `ev_data` pointing to structures that hold protocol-specific information.
+
+NOTE: link:#_struct_mg_connection[`struct mg_connection`] has `void *user_data`
+which is a placeholder for a application-specific data. Mongoose does not use
+that pointer. Event handler can store any kind of information there.
+
+=== Events
+
+Mongoose accepts incoming connections, reads and writes data, and
+calls specified event handler for each connection when appropriate. Typical
+event sequence is this:
+
+- For outbound connection: `MG_EV_CONNECT` -> (`MG_EV_RECV`, `MG_EV_SEND`, `MG_EV_POLL` ...) -> `MG_EV_CLOSE`
+- For inbound connection: `MG_EV_ACCEPT` ->  (`MG_EV_RECV`, `MG_EV_SEND`, `MG_EV_POLL` ...) -> `MG_EV_CLOSE`
+
+
+Below is a list
+of core events triggered by Mongoose (note that each protocol triggers
+protocol-specific events in addition to the core ones):
+
+MG_EV_ACCEPT:: sent when new server connection is accepted by a
+listening connection. `void *ev_data` is `union socket_address`
+of the remote peer.
+MG_EV_CONNECT:: sent when a new outbound connection created by
+link:#_mg_connect[`mg_connect()`]
+either failed or succeeded. `void *ev_data` is `int *success`.
+If `success` is 0, then connection has been established,
+otherwise it contains error code. See
+link:#_mg_connect_opt[`mg_connect_opt()`] function for code example.
+
+MG_EV_RECV:: New data is received and appended to the end of `recv_mbuf`.
+`void *ev_data` is `int *num_received_bytes`. Typically, event handler
+should check received data in `nc->recv_mbuf`,
+discard processed data by calling link:#_mbuf_remove[`mbuf_remove()`],
+set connection flags `nc->flags` if necessary
+(see link:#_struct_mg_connection[`struct mg_connection`]), and write
+data the remote peer by output functions like link:#_mg_send[`mg_send()`].
+
+WARNING: Mongoose uses `realloc()` to expand receive buffer.
+It is user's responsibility to discard processed
+data from the beginning of receive buffer, note the `mbuf_remove()`
+call in the example above.
+
+MG_EV_SEND:: Mongoose has written data to the remote peer and discarded
+written data from the
+link:#_struct_mg_connection[`mg_connection::send_mbuf`]. `void *ev_data`
+is `int *num_sent_bytes`.
+
+NOTE: Mongoose output functions only append
+data to the `mg_connection::send_mbuf`, they do not do any socket writes.
+An actual IO is done by link:#_mg_mgr_poll[`mg_mgr_poll()`]. `MG_EV_SEND` event
+is just a notification about an IO has been done.
+
+MG_EV_POLL:: Sent to all connections on each invocation of
+link:#_mg_mgr_poll[`mg_mgr_poll()`].
+This event could be used to do any housekeeping, for example check whether
+certain timeout has expired and close the connection, or send heartbeet
+message, et cetera.
+
+MG_EV_TIMER:: Sent to the connection if
+link:#_mg_set_timer[`mg_set_timer()`] was called.
+
+=== Connection flags
+
+Each connection has a `flags` bit field. Some flags are set by Mongoose, for
+example if a user creates an outbound UDP connection using `udp://1.2.3.4:5678`
+address, Mongoose is going to set `MG_F_UDP` flag for that connection. Other flags
+are meant to be set only by user event handler to tell Mongoose how to behave.
+Below is a list of connection flags that are meant to be set by event handlers:
+
+* `MG_F_FINISHED_SENDING_DATA` tells Mongoose that all data has been
+  appended to the `send_mbuf`. As soon as Mongoose sends it to the
+  socket, the connection will be closed.
+* `MG_F_BUFFER_BUT_DONT_SEND` tells Mongoose to append data to the
+  `send_mbuf` but hold on sending it, because the data will be modified
+  later and then will be sent by clearing `MG_F_BUFFER_BUT_DONT_SEND` flag.
+* `MG_F_CLOSE_IMMEDIATELY` tells Mongoose to close the connection
+  immediately, usually after some error
+* `MG_F_USER_1`, `MG_F_USER_2`, `MG_F_USER_3`, `MG_F_USER_4` could be
+  used by a developer to store application-specific state
+
+Flags below are set by Mongoose:
+
+* `MG_F_SSL_HANDSHAKE_DONE` SSL only, set when SSL handshake is done.
+* `MG_F_CONNECTING` set when connection is in connecting state after
+  `mg_connect()` call but connect did not finish yet.
+* `MG_F_LISTENING` set for all listening connections
+* `MG_F_UDP` set if connection is UDP
+* `MG_F_IS_WEBSOCKET` set if connection is a Websocket connection
+* `MG_F_WEBSOCKET_NO_DEFRAG` should be set by a user if user wants to switch
+  off automatic Websocket frame defragmentation
diff --git a/docs/design-concept/conn-flags.md b/docs/design-concept/conn-flags.md
deleted file mode 100644
index e7533deba..000000000
--- a/docs/design-concept/conn-flags.md
+++ /dev/null
@@ -1,32 +0,0 @@
----
-title: Connection flags
----
-
-Each connection has a `flags` bit field. Some flags are set by Mongoose, for
-example if a user creates an outbound UDP connection using `udp://1.2.3.4:5678`
-address, Mongoose is going to set `MG_F_UDP` flag for that connection. Other
-flags are meant to be set only by user event handler to tell Mongoose how to
-behave.  Below is a list of connection flags that are meant to be set by event
-handlers:
-
-* `MG_F_FINISHED_SENDING_DATA` tells Mongoose that all data has been appended
-  to the `send_mbuf`. As soon as Mongoose sends it to the socket, the
-  connection will be closed.
-* `MG_F_BUFFER_BUT_DONT_SEND` tells Mongoose to append data to the `send_mbuf`
-  but hold on sending it, because the data will be modified later and then will
-  be sent by clearing `MG_F_BUFFER_BUT_DONT_SEND` flag.
-* `MG_F_CLOSE_IMMEDIATELY` tells Mongoose to close the connection immediately,
-  usually after some error
-* `MG_F_USER_1`, `MG_F_USER_2`, `MG_F_USER_3`, `MG_F_USER_4` could be used by a
-  developer to store application-specific state
-
-Flags below are set by Mongoose:
-
-* `MG_F_SSL_HANDSHAKE_DONE` SSL only, set when SSL handshake is done.
-* `MG_F_CONNECTING` set when connection is in connecting state after
-  `mg_connect()` call but connect did not finish yet.
-* `MG_F_LISTENING` set for all listening connections
-* `MG_F_UDP` set if connection is UDP
-* `MG_F_IS_WEBSOCKET` set if connection is a Websocket connection
-* `MG_F_WEBSOCKET_NO_DEFRAG` should be set by a user if user wants to switch
-  off automatic Websocket frame defragmentation
diff --git a/docs/design-concept/event-handler.md b/docs/design-concept/event-handler.md
deleted file mode 100644
index 264647cd1..000000000
--- a/docs/design-concept/event-handler.md
+++ /dev/null
@@ -1,31 +0,0 @@
----
-title: Event handler function
----
-
-Each connection has an event handler function associated with it. That function
-must be implemented by user. Event handler is the key element of the Mongoose
-application, since it defines application's behavior. This is how an event
-handler function looks like:
-
-```c
-static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
-  switch (ev) {
-    /* Event handler code that defines behavior of the connection */
-    ...
-  }
-}
-```
-
-- `struct mg_connection *nc`: Connection that has received an event.
-- `int ev`: Event number, defined in `mongoose.h`. For example, when data
-  arrives on inbound connection `ev` would be `MG_EV_RECV`.
-- `void *ev_data`: This pointer points to the event-specific data, and it has
-  different meaning for different events. For example, for `MG_EV_RECV` event,
-  `ev_data` is an `int *` pointer, pointing to the number of bytes received
-  from the remote peer and saved into the receive IO buffer. Exact meaning of
-  `ev_data` is described for each event. Protocol-specific events usually have
-  `ev_data` pointing to structures that hold protocol-specific information.
-
-NOTE: `struct mg_connection` has `void *user_data` which is a placeholder for
-an application-specific data. Mongoose does not use that pointer. Event handler
-can store any kind of information there.
diff --git a/docs/design-concept/events.md b/docs/design-concept/events.md
deleted file mode 100644
index d8d632c1a..000000000
--- a/docs/design-concept/events.md
+++ /dev/null
@@ -1,52 +0,0 @@
----
-title: Events
----
-
-Mongoose accepts incoming connections, reads and writes data, and calls
-specified event handler for each connection when appropriate. Typical event
-sequence is this:
-
-- For outbound connection: `MG_EV_CONNECT` -> (`MG_EV_RECV`, `MG_EV_SEND`,
-  `MG_EV_POLL` ...) -> `MG_EV_CLOSE`
-- For inbound connection: `MG_EV_ACCEPT` ->  (`MG_EV_RECV`, `MG_EV_SEND`,
-  `MG_EV_POLL` ...) -> `MG_EV_CLOSE`
-
-
-Below is a list of core events triggered by Mongoose (note that each protocol
-triggers protocol-specific events in addition to the core ones):
-
-- `MG_EV_ACCEPT`: sent when new server connection is accepted by a listening
-  connection. `void *ev_data` is `union socket_address` of the remote peer.
-
-- `MG_EV_CONNECT`: sent when a new outbound connection created by `mg_connect()`
-  either failed or succeeded. `void *ev_data` is `int *success`.  If `success`
-  is 0, then connection has been established, otherwise it contains error code.
-  See `mg_connect_opt()` function for code example.
-
-- `MG_EV_RECV`: New data is received and appended to the end of `recv_mbuf`.
-  `void *ev_data` is `int *num_received_bytes`. Typically, event handler should
-  check received data in `nc->recv_mbuf`, discard processed data by calling
-  `mbuf_remove()`, set connection flags `nc->flags` if necessary (see `struct
-  mg_connection`), and write data the remote peer by output functions like
-  `mg_send()`.
-
-  **WARNING**: Mongoose uses `realloc()` to expand receive buffer.  It is
-  user's responsibility to discard processed data from the beginning of receive
-  buffer, note the `mbuf_remove()` call in the example above.
-
-- `MG_EV_SEND`: Mongoose has written data to the remote peer and discarded
-  written data from the `mg_connection::send_mbuf`. `void *ev_data` is `int
-  *num_sent_bytes`.
-
-  **NOTE**: Mongoose output functions only append data to the
-  `mg_connection::send_mbuf`, they do not do any socket writes.  An actual IO
-  is done by `mg_mgr_poll()`. `MG_EV_SEND` event is just a notification about
-  an IO has been done.
-
-- `MG_EV_POLL`: Sent to all connections on each invocation of `mg_mgr_poll()`.
-  This event could be used to do any housekeeping, for example check whether
-  certain timeout has expired and close the connection, or send heartbeet
-  message, et cetera.
-
-- `MG_EV_TIMER`: Sent to the connection if `mg_set_timer()` was called.
-
diff --git a/docs/design-concept/intro.md b/docs/design-concept/intro.md
deleted file mode 100644
index 2142b62fd..000000000
--- a/docs/design-concept/intro.md
+++ /dev/null
@@ -1,24 +0,0 @@
----
-title: Design Concept
----
-
-Mongoose is a multi-protocol networking library that implements non-blocking,
-asyncronous IO and provides event-based API. It has three basic data
-structures:
-
-- `struct mg_mgr` is an event manager that holds all active connections
-- `struct mg_connection` describes a connection
-- `struct mbuf` describes data buffer (received or sent data)
-
-Connections could be either *listening*, *outbound* or *inbound*.  Outbound
-connections are created by `mg_connect()` call.  Listening connections are
-created by `mg_bind()` call.  Inbound connections are those accepted by a
-listening connection.  Each connection is described by `struct mg_connection`
-structure, which has a number of fields like socket, event handler function,
-send/receive buffer, flags, et cetera.
-
-Mongoose usage pattern is to declare and initialize event manager, create
-connections and create an event loop by calling `mg_mgr_poll()` in a loop.
-`mg_mgr_poll()` iterates over all sockets, accepts new connections, sends and
-receives data, closes connections, and calls event handler functions for the
-respective events.
diff --git a/docs/design-concept/items.json b/docs/design-concept/items.json
deleted file mode 100644
index c939cbe9b..000000000
--- a/docs/design-concept/items.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-  "items": [
-    { "type": "markdown", "name": "intro.md" },
-    { "type": "markdown", "name": "memory-buffers.md" },
-    { "type": "markdown", "name": "event-handler.md" },
-    { "type": "markdown", "name": "events.md" },
-    { "type": "markdown", "name": "conn-flags.md" }
-  ]
-}
diff --git a/docs/design-concept/memory-buffers.md b/docs/design-concept/memory-buffers.md
deleted file mode 100644
index 9f1ffb244..000000000
--- a/docs/design-concept/memory-buffers.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: Memory buffers
----
-
-Each connection has send and receive buffer, `struct mg_connection::send_mbuf`
-and `struct mg_connection::recv_mbuf` respectively.  When data arrives,
-Mongoose appends received data to the `recv_mbuf` and triggers `MG_EV_RECV`
-event. User may send data back by calling one of the output functions, like
-`mg_send()` or `mg_printf()`. Output functions append data to the `send_mbuf`.
-When Mongoose successfully writes data to the socket, it discards data from
-`struct mg_connection::send_mbuf` and sends `MG_EV_SEND` event. When connection
-is closed, `MG_EV_CLOSE` event is sent.
-
-![](mbuf.png)
-
diff --git a/docs/dns-server.adoc b/docs/dns-server.adoc
new file mode 100644
index 000000000..5a5ceea66
--- /dev/null
+++ b/docs/dns-server.adoc
@@ -0,0 +1,71 @@
+=== DNS server
+
+Disabled by default; enable with `-DMG_ENABLE_DNS_SERVER`. 
+
+==== mg_dns_create_reply()
+
+[source,c]
+----
+struct mg_dns_reply mg_dns_create_reply(struct mbuf *io,
+                                        struct mg_dns_message *msg);
+----
+Create a DNS reply.
+
+The reply will be based on an existing query message `msg`.
+The query body will be appended to the output buffer.
+"reply + recursion allowed" will be added to the message flags and
+message's num_answers will be set to 0.
+
+Answer records can be appended with `mg_dns_send_reply` or by lower
+level function defined in the DNS API.
+
+In order to send the reply use `mg_dns_send_reply`.
+It's possible to use a connection's send buffer as reply buffers,
+and it will work for both UDP and TCP connections.
+
+Example:
+
+```c
+reply = mg_dns_create_reply(&nc->send_mbuf, msg);
+for (i = 0; i < msg->num_questions; i++) {
+  rr = &msg->questions[i];
+  if (rr->rtype == MG_DNS_A_RECORD) {
+    mg_dns_reply_record(&reply, rr, 3600, &dummy_ip_addr, 4);
+  }
+}
+mg_dns_send_reply(nc, &reply);
+``` 
+
+==== mg_dns_reply_record()
+
+[source,c]
+----
+int mg_dns_reply_record(struct mg_dns_reply *reply,
+                        struct mg_dns_resource_record *question,
+                        const char *name, int rtype, int ttl, const void *rdata,
+                        size_t rdata_len);
+----
+Append a DNS reply record to the IO buffer and to the DNS message.
+
+The message num_answers field will be incremented. It's caller's duty
+to ensure num_answers is propertly initialized.
+
+Returns -1 on error. 
+
+==== mg_dns_send_reply()
+
+[source,c]
+----
+void mg_dns_send_reply(struct mg_connection *nc, struct mg_dns_reply *r);
+----
+Send a DNS reply through a connection.
+
+The DNS data is stored in an IO buffer pointed by reply structure in `r`.
+This function mutates the content of that buffer in order to ensure that
+the DNS header reflects size and flags of the mssage, that might have been
+updated either with `mg_dns_reply_record` or by direct manipulation of
+`r->message`.
+
+Once sent, the IO buffer will be trimmed unless the reply IO buffer
+is the connection's send buffer and the connection is not in UDP mode. 
+
diff --git a/docs/dns.adoc b/docs/dns.adoc
new file mode 100644
index 000000000..9868a0b79
--- /dev/null
+++ b/docs/dns.adoc
@@ -0,0 +1,151 @@
+=== DNS 
+
+==== struct mg_dns_resource_record
+
+[source,c]
+----
+struct mg_dns_resource_record {
+  struct mg_str name; /* buffer with compressed name */
+  int rtype;
+  int rclass;
+  int ttl;
+  enum mg_dns_resource_record_kind kind;
+  struct mg_str rdata; /* protocol data (can be a compressed name) */
+};
+----
+DNS resource record. 
+
+==== struct mg_dns_message
+
+[source,c]
+----
+struct mg_dns_message {
+  struct mg_str pkt; /* packet body */
+  uint16_t flags;
+  uint16_t transaction_id;
+  int num_questions;
+  int num_answers;
+  struct mg_dns_resource_record questions[MG_MAX_DNS_QUESTIONS];
+  struct mg_dns_resource_record answers[MG_MAX_DNS_ANSWERS];
+};
+----
+DNS message (request and response). 
+
+==== mg_dns_parse_record_data()
+
+[source,c]
+----
+int mg_dns_parse_record_data(struct mg_dns_message *msg,
+                             struct mg_dns_resource_record *rr, void *data,
+                             size_t data_len);
+----
+Parse the record data from a DNS resource record.
+
+ - A:     struct in_addr *ina
+ - AAAA:  struct in6_addr *ina
+ - CNAME: char buffer
+
+Returns -1 on error.
+
+TODO(mkm): MX 
+
+==== mg_send_dns_query()
+
+[source,c]
+----
+void mg_send_dns_query(struct mg_connection *nc, const char *name,
+                       int query_type);
+----
+Send a DNS query to the remote end. 
+
+==== mg_dns_insert_header()
+
+[source,c]
+----
+int mg_dns_insert_header(struct mbuf *io, size_t pos,
+                         struct mg_dns_message *msg);
+----
+Insert a DNS header to an IO buffer.
+
+Return number of bytes inserted. 
+
+==== mg_dns_copy_questions()
+
+[source,c]
+----
+int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg);
+----
+Append already encoded questions from an existing message.
+
+This is useful when generating a DNS reply message which includes
+all question records.
+
+Return number of appened bytes. 
+
+==== mg_dns_encode_record()
+
+[source,c]
+----
+int mg_dns_encode_record(struct mbuf *io, struct mg_dns_resource_record *rr,
+                         const char *name, size_t nlen, const void *rdata,
+                         size_t rlen);
+----
+Encode and append a DNS resource record to an IO buffer.
+
+The record metadata is taken from the `rr` parameter, while the name and data
+are taken from the parameters, encoded in the appropriate format depending on
+record type, and stored in the IO buffer. The encoded values might contain
+offsets within the IO buffer. It's thus important that the IO buffer doesn't
+get trimmed while a sequence of records are encoded while preparing a DNS
+*reply.
+
+This function doesn't update the `name` and `rdata` pointers in the `rr`
+*struct
+because they might be invalidated as soon as the IO buffer grows again.
+
+Return the number of bytes appened or -1 in case of error. 
+
+==== mg_parse_dns()
+
+[source,c]
+----
+int mg_parse_dns(const char *buf, int len, struct mg_dns_message *msg);
+----
+Low-level: parses a DNS response. 
+
+==== mg_dns_uncompress_name()
+
+[source,c]
+----
+size_t mg_dns_uncompress_name(struct mg_dns_message *msg, struct mg_str *name,
+                              char *dst, int dst_len);
+----
+Uncompress a DNS compressed name.
+
+The containing dns message is required because the compressed encoding
+and reference suffixes present elsewhere in the packet.
+
+If name is less than `dst_len` characters long, the remainder
+of `dst` is terminated with `\0' characters. Otherwise, `dst` is not
+*terminated.
+
+If `dst_len` is 0 `dst` can be NULL.
+Return the uncompressed name length. 
+
+==== mg_set_protocol_dns()
+
+[source,c]
+----
+void mg_set_protocol_dns(struct mg_connection *nc);
+----
+Attach built-in DNS event handler to the given listening connection.
+
+DNS event handler parses incoming UDP packets, treating them as DNS
+requests. If incoming packet gets successfully parsed by the DNS event
+handler, a user event handler will receive `MG_DNS_REQUEST` event, with
+`ev_data` pointing to the parsed `struct mg_dns_message`.
+
+See
+[captive_dns_server](https://github.com/cesanta/mongoose/tree/master/examples/captive_dns_server)
+example on how to handle DNS request and send DNS reply. 
+
diff --git a/docs/http.adoc b/docs/http.adoc
new file mode 100644
index 000000000..8317a4455
--- /dev/null
+++ b/docs/http.adoc
@@ -0,0 +1,694 @@
+=== HTTP + Websocket 
+
+==== struct http_message
+
+[source,c]
+----
+struct http_message {
+  struct mg_str message; /* Whole message: request line + headers + body */
+
+  /* HTTP Request line (or HTTP response line) */
+  struct mg_str method; /* "GET" */
+  struct mg_str uri;    /* "/my_file.html" */
+  struct mg_str proto;  /* "HTTP/1.1" -- for both request and response */
+
+  /* For responses, code and response status message are set */
+  int resp_code;
+  struct mg_str resp_status_msg;
+
+  /*
+   * Query-string part of the URI. For example, for HTTP request
+   *    GET /foo/bar?param1=val1&param2=val2
+   *    |    uri    |     query_string     |
+   *
+   * Note that question mark character doesn't belong neither to the uri,
+   * nor to the query_string
+   */
+  struct mg_str query_string;
+
+  /* Headers */
+  struct mg_str header_names[MG_MAX_HTTP_HEADERS];
+  struct mg_str header_values[MG_MAX_HTTP_HEADERS];
+
+  /* Message body */
+  struct mg_str body; /* Zero-length for requests with no body */
+};
+----
+HTTP message 
+
+==== struct websocket_message
+
+[source,c]
+----
+struct websocket_message {
+  unsigned char *data;
+  size_t size;
+  unsigned char flags;
+};
+----
+WebSocket message 
+
+==== struct mg_http_multipart_part
+
+[source,c]
+----
+struct mg_http_multipart_part {
+  const char *file_name;
+  const char *var_name;
+  struct mg_str data;
+  int status; /* <0 on error */
+  void *user_data;
+};
+----
+HTTP multipart part 
+
+==== struct mg_serve_http_opts
+
+[source,c]
+----
+struct mg_serve_http_opts {
+  /* Path to web root directory */
+  const char *document_root;
+
+  /* List of index files. Default is "" */
+  const char *index_files;
+
+  /*
+   * Leave as NULL to disable authentication.
+   * To enable directory protection with authentication, set this to ".htpasswd"
+   * Then, creating ".htpasswd" file in any directory automatically protects
+   * it with digest authentication.
+   * Use `mongoose` web server binary, or `htdigest` Apache utility to
+   * create/manipulate passwords file.
+   * Make sure `auth_domain` is set to a valid domain name.
+   */
+  const char *per_directory_auth_file;
+
+  /* Authorization domain (domain name of this web server) */
+  const char *auth_domain;
+
+  /*
+   * Leave as NULL to disable authentication.
+   * Normally, only selected directories in the document root are protected.
+   * If absolutely every access to the web server needs to be authenticated,
+   * regardless of the URI, set this option to the path to the passwords file.
+   * Format of that file is the same as ".htpasswd" file. Make sure that file
+   * is located outside document root to prevent people fetching it.
+   */
+  const char *global_auth_file;
+
+  /* Set to "no" to disable directory listing. Enabled by default. */
+  const char *enable_directory_listing;
+
+  /* SSI files pattern. If not set, "**.shtml$|**.shtm$" is used. */
+  const char *ssi_pattern;
+
+  /* IP ACL. By default, NULL, meaning all IPs are allowed to connect */
+  const char *ip_acl;
+
+  /* URL rewrites.
+   *
+   * Comma-separated list of `uri_pattern=file_or_directory_path` rewrites.
+   * When HTTP request is received, Mongoose constructs a file name from the
+   * requested URI by combining `document_root` and the URI. However, if the
+   * rewrite option is used and `uri_pattern` matches requested URI, then
+   * `document_root` is ignored. Instead, `file_or_directory_path` is used,
+   * which should be a full path name or a path relative to the web server's
+   * current working directory. Note that `uri_pattern`, as all Mongoose
+   * patterns, is a prefix pattern.
+   *
+   * If uri_pattern starts with `@` symbol, then Mongoose compares it with the
+   * HOST header of the request. If they are equal, Mongoose sets document root
+   * to `file_or_directory_path`, implementing virtual hosts support.
+   * Example: `@foo.com=/document/root/for/foo.com`
+   *
+   * If `uri_pattern` starts with `%` symbol, then Mongoose compares it with
+   * the listening port. If they match, then Mongoose issues a 301 redirect.
+   * For example, to redirect all HTTP requests to the
+   * HTTPS port, do `%80=https://my.site.com`. Note that the request URI is
+   * automatically appended to the redirect location.
+   */
+  const char *url_rewrites;
+
+  /* DAV document root. If NULL, DAV requests are going to fail. */
+  const char *dav_document_root;
+
+  /*
+   * DAV passwords file. If NULL, DAV requests are going to fail.
+   * If passwords file is set to "-", then DAV auth is disabled.
+   */
+  const char *dav_auth_file;
+
+  /* Glob pattern for the files to hide. */
+  const char *hidden_file_pattern;
+
+  /* Set to non-NULL to enable CGI, e.g. **.cgi$|**.php$" */
+  const char *cgi_file_pattern;
+
+  /* If not NULL, ignore CGI script hashbang and use this interpreter */
+  const char *cgi_interpreter;
+
+  /*
+   * Comma-separated list of Content-Type overrides for path suffixes, e.g.
+   * ".txt=text/plain; charset=utf-8,.c=text/plain"
+   */
+  const char *custom_mime_types;
+
+  /*
+   * Extra HTTP headers to add to each server response.
+   * Example: to enable CORS, set this to "Access-Control-Allow-Origin: *".
+   */
+  const char *extra_headers;
+};
+----
+This structure defines how `mg_serve_http()` works.
+Best practice is to set only required settings, and leave the rest as NULL. 
+
+==== mg_set_protocol_http_websocket()
+
+[source,c]
+----
+void mg_set_protocol_http_websocket(struct mg_connection *nc);
+----
+Attach built-in HTTP event handler to the given connection.
+User-defined event handler will receive following extra events:
+
+- MG_EV_HTTP_REQUEST: HTTP request has arrived. Parsed HTTP request
+ is passed as
+  `struct http_message` through the handler's `void *ev_data` pointer.
+- MG_EV_HTTP_MULTIPART_REQUEST: A multipart POST request has received.
+  This event is sent before body is parsed. After this user
+  should expect a sequence of MG_EV_HTTP_PART_BEGIN/DATA/END requests.
+  This is also the last time when headers and other request fields are
+  accessible.
+- MG_EV_HTTP_REPLY: HTTP reply has arrived. Parsed HTTP reply is passed as
+  `struct http_message` through the handler's `void *ev_data` pointer.
+- MG_EV_HTTP_CHUNK: HTTP chunked-encoding chunk has arrived.
+  Parsed HTTP reply is passed as `struct http_message` through the
+  handler's `void *ev_data` pointer. `http_message::body` would contain
+  incomplete, reassembled HTTP body.
+  It will grow with every new chunk arrived, and
+  potentially can consume a lot of memory. An event handler may process
+  the body as chunks are coming, and signal Mongoose to delete processed
+  body by setting `MG_F_DELETE_CHUNK` in `mg_connection::flags`. When
+  the last zero chunk is received,
+  Mongoose sends `MG_EV_HTTP_REPLY` event with
+  full reassembled body (if handler did not signal to delete chunks) or
+  with empty body (if handler did signal to delete chunks).
+- MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received websocket handshake
+  request. `ev_data` contains parsed HTTP request.
+- MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed Websocket handshake.
+  `ev_data` is `NULL`.
+- MG_EV_WEBSOCKET_FRAME: new websocket frame has arrived. `ev_data` is
+  `struct websocket_message *`
+- MG_EV_HTTP_PART_BEGIN: new part of multipart message is started,
+  extra parameters are passed in mg_http_multipart_part
+- MG_EV_HTTP_PART_DATA: new portion of data from multiparted message
+  no additional headers are available, only data and data size
+- MG_EV_HTTP_PART_END: final boundary received, analogue to maybe used to
+  find the end of packet
+  Note: Mongoose should be compiled with MG_ENABLE_HTTP_STREAMING_MULTIPART
+  to enable MG_EV_HTTP_MULTIPART_REQUEST, MG_EV_HTTP_REQUEST_END,
+  MG_EV_HTTP_REQUEST_CANCEL, MG_EV_HTTP_PART_BEGIN, MG_EV_HTTP_PART_DATA,
+  MG_EV_HTTP_PART_END constants 
+
+==== mg_send_websocket_handshake()
+
+[source,c]
+----
+void mg_send_websocket_handshake(struct mg_connection *nc, const char *uri,
+                                 const char *extra_headers);
+----
+Send websocket handshake to the server.
+
+`nc` must be a valid connection, connected to a server. `uri` is an URI
+to fetch, extra_headers` is extra HTTP headers to send or `NULL`.
+
+This function is intended to be used by websocket client.
+
+Note that the Host header is mandatory in HTTP/1.1 and must be
+included in `extra_headers`. `mg_send_websocket_handshake2` offers
+a better API for that.
+
+Deprecated in favour of `mg_send_websocket_handshake2` 
+
+==== mg_send_websocket_handshake2()
+
+[source,c]
+----
+void mg_send_websocket_handshake2(struct mg_connection *nc, const char *path,
+                                  const char *host, const char *protocol,
+                                  const char *extra_headers);
+----
+Send websocket handshake to the server.
+
+`nc` must be a valid connection, connected to a server. `uri` is an URI
+to fetch, `host` goes into the `Host` header, `protocol` goes into the
+`Sec-WebSocket-Proto` header (NULL to omit), extra_headers` is extra HTTP
+headers to send or `NULL`.
+
+This function is intended to be used by websocket client. 
+
+==== mg_connect_ws()
+
+[source,c]
+----
+struct mg_connection *mg_connect_ws(struct mg_mgr *mgr,
+                                    mg_event_handler_t event_handler,
+                                    const char *url, const char *protocol,
+                                    const char *extra_headers);
+----
+Helper function that creates an outbound WebSocket connection.
+
+`url` is a URL to connect to. It must be properly URL-encoded, e.g. have
+no spaces, etc. By default, `mg_connect_ws()` sends Connection and
+Host headers. `extra_headers` is an extra HTTP headers to send, e.g.
+`"User-Agent: my-app\r\n"`.
+If `protocol` is not NULL, then a `Sec-WebSocket-Protocol` header is sent.
+
+Examples:
+
+```c
+  nc1 = mg_connect_ws(mgr, ev_handler_1, "ws://echo.websocket.org", NULL,
+                      NULL);
+  nc2 = mg_connect_ws(mgr, ev_handler_1, "wss://echo.websocket.org", NULL,
+                      NULL);
+  nc3 = mg_connect_ws(mgr, ev_handler_1, "ws://api.cesanta.com",
+                      "clubby.cesanta.com", NULL);
+``` 
+
+==== mg_connect_ws_opt()
+
+[source,c]
+----
+struct mg_connection *mg_connect_ws_opt(struct mg_mgr *mgr,
+                                        mg_event_handler_t ev_handler,
+                                        struct mg_connect_opts opts,
+                                        const char *url, const char *protocol,
+                                        const char *extra_headers);
+----
+Helper function that creates an outbound WebSocket connection
+
+Mostly identical to mg_connect_ws, but allows to provide extra parameters
+(for example, SSL parameters 
+
+==== mg_send_websocket_frame()
+
+[source,c]
+----
+void mg_send_websocket_frame(struct mg_connection *nc, int op_and_flags,
+                             const void *data, size_t data_len);
+----
+Send websocket frame to the remote end.
+
+`op_and_flags` specifies frame's type, one of:
+
+- WEBSOCKET_OP_CONTINUE
+- WEBSOCKET_OP_TEXT
+- WEBSOCKET_OP_BINARY
+- WEBSOCKET_OP_CLOSE
+- WEBSOCKET_OP_PING
+- WEBSOCKET_OP_PONG
+
+Orred with one of the flags:
+
+- WEBSOCKET_DONT_FIN: Don't set the FIN flag on the frame to be sent.
+
+`data` and `data_len` contain frame data. 
+
+==== mg_send_websocket_framev()
+
+[source,c]
+----
+void mg_send_websocket_framev(struct mg_connection *nc, int op_and_flags,
+                              const struct mg_str *strings, int num_strings);
+----
+Send multiple websocket frames.
+
+Like `mg_send_websocket_frame()`, but composes a frame from multiple buffers. 
+
+==== mg_printf_websocket_frame()
+
+[source,c]
+----
+void mg_printf_websocket_frame(struct mg_connection *nc, int op_and_flags,
+                               const char *fmt, ...);
+----
+Send websocket frame to the remote end.
+
+Like `mg_send_websocket_frame()`, but allows to create formatted message
+with `printf()`-like semantics. 
+
+==== mg_send_http_chunk()
+
+[source,c]
+----
+void mg_send_http_chunk(struct mg_connection *nc, const char *buf, size_t len);
+----
+Send buffer `buf` of size `len` to the client using chunked HTTP encoding.
+This function first sends buffer size as hex number + newline, then
+buffer itself, then newline. For example,
+  `mg_send_http_chunk(nc, "foo", 3)` whill append `3\r\nfoo\r\n` string to
+the `nc->send_mbuf` output IO buffer.
+
+NOTE: HTTP header "Transfer-Encoding: chunked" should be sent prior to
+using this function.
+
+NOTE: do not forget to send empty chunk at the end of the response,
+to tell the client that everything was sent. Example:
+
+```
+  mg_printf_http_chunk(nc, "%s", "my response!");
+  mg_send_http_chunk(nc, "", 0); // Tell the client we're finished
+``` 
+
+==== mg_printf_http_chunk()
+
+[source,c]
+----
+void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt, ...);
+----
+Send printf-formatted HTTP chunk.
+Functionality is similar to `mg_send_http_chunk()`. 
+
+==== mg_send_response_line()
+
+[source,c]
+----
+void mg_send_response_line(struct mg_connection *c, int status_code,
+                           const char *extra_headers);
+----
+Send response status line.
+If `extra_headers` is not NULL, then `extra_headers` are also sent
+after the reponse line. `extra_headers` must NOT end end with new line.
+Example:
+
+     mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");
+
+Will result in:
+
+     HTTP/1.1 200 OK\r\n
+     Access-Control-Allow-Origin: *\r\n 
+
+==== mg_send_head()
+
+[source,c]
+----
+void mg_send_head(struct mg_connection *n, int status_code,
+                  int64_t content_length, const char *extra_headers);
+----
+Send response line and headers.
+This function sends response line with the `status_code`, and automatically
+sends one header: either "Content-Length", or "Transfer-Encoding".
+If `content_length` is negative, then "Transfer-Encoding: chunked" header
+is sent, otherwise, "Content-Length" header is sent.
+
+NOTE: If `Transfer-Encoding` is `chunked`, then message body must be sent
+using `mg_send_http_chunk()` or `mg_printf_http_chunk()` functions.
+Otherwise, `mg_send()` or `mg_printf()` must be used.
+Extra headers could be set through `extra_headers` - and note `extra_headers`
+must NOT be terminated by a new line. 
+
+==== mg_printf_html_escape()
+
+[source,c]
+----
+void mg_printf_html_escape(struct mg_connection *nc, const char *fmt, ...);
+----
+Send printf-formatted HTTP chunk, escaping HTML tags. 
+
+==== mg_parse_http()
+
+[source,c]
+----
+int mg_parse_http(const char *s, int n, struct http_message *hm, int is_req);
+----
+Parse a HTTP message.
+
+`is_req` should be set to 1 if parsing request, 0 if reply.
+
+Return number of bytes parsed. If HTTP message is
+incomplete, `0` is returned. On parse error, negative number is returned. 
+
+==== mg_get_http_header()
+
+[source,c]
+----
+struct mg_str *mg_get_http_header(struct http_message *hm, const char *name);
+----
+Search and return header `name` in parsed HTTP message `hm`.
+If header is not found, NULL is returned. Example:
+
+    struct mg_str *host_hdr = mg_get_http_header(hm, "Host"); 
+
+==== mg_http_parse_header()
+
+[source,c]
+----
+int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf,
+                         size_t buf_size);
+----
+Parse HTTP header `hdr`. Find variable `var_name` and store it's value
+in the buffer `buf`, `buf_size`. Return 0 if variable not found, non-zero
+otherwise.
+
+This function is supposed to parse
+cookies, authentication headers, etcetera. Example (error handling omitted):
+
+    char user[20];
+    struct mg_str *hdr = mg_get_http_header(hm, "Authorization");
+    mg_http_parse_header(hdr, "username", user, sizeof(user));
+
+Return length of the variable's value. If buffer is not large enough,
+or variable not found, 0 is returned. 
+
+==== mg_parse_multipart()
+
+[source,c]
+----
+size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name,
+                          size_t var_name_len, char *file_name,
+                          size_t file_name_len, const char **chunk,
+                          size_t *chunk_len);
+----
+Parse buffer `buf`, `buf_len` that contains multipart form data chunks.
+Store chunk name in a `var_name`, `var_name_len` buffer.
+If a chunk is an uploaded file, then `file_name`, `file_name_len` is
+filled with an uploaded file name. `chunk`, `chunk_len`
+points to the chunk data.
+
+Return: number of bytes to skip to the next chunk, or 0 if there are
+        no more chunks.
+
+Usage example:
+
+```c
+   static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
+     switch(ev) {
+       case MG_EV_HTTP_REQUEST: {
+         struct http_message *hm = (struct http_message *) ev_data;
+         char var_name[100], file_name[100];
+         const char *chunk;
+         size_t chunk_len, n1, n2;
+
+         n1 = n2 = 0;
+         while ((n2 = mg_parse_multipart(hm->body.p + n1,
+                                         hm->body.len - n1,
+                                         var_name, sizeof(var_name),
+                                         file_name, sizeof(file_name),
+                                         &chunk, &chunk_len)) > 0) {
+           printf("var: %s, file_name: %s, size: %d, chunk: [%.*s]\n",
+                  var_name, file_name, (int) chunk_len,
+                  (int) chunk_len, chunk);
+           n1 += n2;
+         }
+       }
+       break;
+``` 
+
+==== mg_get_http_var()
+
+[source,c]
+----
+int mg_get_http_var(const struct mg_str *buf, const char *name, char *dst,
+                    size_t dst_len);
+----
+Fetch an HTTP form variable.
+
+Fetch a variable `name` from a `buf` into a buffer specified by
+`dst`, `dst_len`. Destination is always zero-terminated. Return length
+of a fetched variable. If not found, 0 is returned. `buf` must be
+valid url-encoded buffer. If destination is too small, `-1` is returned. 
+
+==== mg_url_decode()
+
+[source,c]
+----
+int mg_url_decode(const char *src, int src_len, char *dst, int dst_len,
+                  int is_form_url_encoded);
+----
+Decode URL-encoded string.
+
+Source string is specified by (`src`, `src_len`), and destination is
+(`dst`, `dst_len`). If `is_form_url_encoded` is non-zero, then
+`+` character is decoded as a blank space character. This function
+guarantees to `\0`-terminate the destination. If destination is too small,
+then source string is partially decoded and `-1` is returned. Otherwise,
+a length of decoded string is returned, not counting final `\0`. 
+
+==== mg_http_create_digest_auth_header()
+
+[source,c]
+----
+int mg_http_create_digest_auth_header(char *buf, size_t buf_len,
+                                      const char *method, const char *uri,
+                                      const char *auth_domain, const char *user,
+                                      const char *passwd);
+----
+Create Digest authentication header for client request. 
+
+==== mg_connect_http()
+
+[source,c]
+----
+struct mg_connection *mg_connect_http(struct mg_mgr *mgr,
+                                      mg_event_handler_t event_handler,
+                                      const char *url,
+                                      const char *extra_headers,
+                                      const char *post_data);
+----
+Helper function that creates outbound HTTP connection.
+
+`url` is a URL to fetch. It must be properly URL-encoded, e.g. have
+no spaces, etc. By default, `mg_connect_http()` sends Connection and
+Host headers. `extra_headers` is an extra HTTP headers to send, e.g.
+`"User-Agent: my-app\r\n"`.
+If `post_data` is NULL, then GET request is created. Otherwise, POST request
+is created with the specified POST data. Note that if the data being posted
+is a form submission, the `Content-Type` header should be set accordingly
+(see example below).
+
+Examples:
+
+```c
+  nc1 = mg_connect_http(mgr, ev_handler_1, "http://www.google.com", NULL,
+                        NULL);
+  nc2 = mg_connect_http(mgr, ev_handler_1, "https://github.com", NULL, NULL);
+  nc3 = mg_connect_http(
+      mgr, ev_handler_1, "my_server:8000/form_submit/",
+      "Content-Type: application/x-www-form-urlencoded\r\n",
+      "var_1=value_1&var_2=value_2");
+``` 
+
+==== mg_connect_http_opt()
+
+[source,c]
+----
+struct mg_connection *mg_connect_http_opt(struct mg_mgr *mgr,
+                                          mg_event_handler_t ev_handler,
+                                          struct mg_connect_opts opts,
+                                          const char *url,
+                                          const char *extra_headers,
+                                          const char *post_data);
+----
+Helper function that creates outbound HTTP connection.
+
+Mostly identical to mg_connect_http, but allows to provide extra parameters
+(for example, SSL parameters 
+
+==== mg_serve_http()
+
+[source,c]
+----
+void mg_serve_http(struct mg_connection *nc, struct http_message *hm,
+                   struct mg_serve_http_opts opts);
+----
+Serve given HTTP request according to the `options`.
+
+Example code snippet:
+
+```c
+static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
+  struct http_message *hm = (struct http_message *) ev_data;
+  struct mg_serve_http_opts opts = { .document_root = "/var/www" };  // C99
+
+  switch (ev) {
+    case MG_EV_HTTP_REQUEST:
+      mg_serve_http(nc, hm, opts);
+      break;
+    default:
+      break;
+  }
+}
+``` 
+
+==== mg_register_http_endpoint()
+
+[source,c]
+----
+void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
+                               mg_event_handler_t handler);
+----
+Register callback for specified http endpoint
+Note: if callback is registered it is called instead of
+callback provided in mg_bind
+
+Example code snippet:
+
+```c
+static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
+  (void) ev; (void) ev_data;
+  mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello1]");
+ nc->flags |= MG_F_SEND_AND_CLOSE;
+}
+
+static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
+ (void) ev; (void) ev_data;
+  mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello2]");
+ nc->flags |= MG_F_SEND_AND_CLOSE;
+}
+
+void init() {
+  nc = mg_bind(&mgr, local_addr, cb1);
+  mg_register_http_endpoint(nc, "/hello1", handle_hello1);
+  mg_register_http_endpoint(nc, "/hello1/hello2", handle_hello2);
+}
+``` 
+
+==== mg_file_upload_handler()
+
+[source,c]
+----
+void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
+                            mg_fu_fname_fn local_name_fn);
+----
+File upload handler.
+This handler can be used to implement file uploads with minimum code.
+This handler will process MG_EV_HTTP_PART_* events and store file data into
+a local file.
+`local_name_fn` will be invoked with whatever name was provided by the client
+and will expect the name of the local file to open. Return value of NULL will
+abort file upload (client will get a "403 Forbidden" response). If non-null,
+the returned string must be heap-allocated and will be freed by the caller.
+Exception: it is ok to return the same string verbatim.
+
+Example:
+
+```c
+struct mg_str upload_fname(struct mg_connection *nc, struct mg_str fname) {
+  // Just return the same filename. Do not actually do this except in test!
+  // fname is user-controlled and needs to be sanitized.
+  return fname;
+}
+void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
+  switch (ev) {
+    ...
+    case MG_EV_HTTP_PART_BEGIN:
+    case MG_EV_HTTP_PART_DATA:
+    case MG_EV_HTTP_PART_END:
+      mg_file_upload_handler(nc, ev, ev_data, upload_fname);
+      break;
+  }
+}
+``` 
+
diff --git a/docs/img/mbuf.png b/docs/img/mbuf.png
deleted file mode 100644
index a162abc3d6ce0df95ad9fa725cc54337b1ceb64f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 73349
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

diff --git a/docs/index-docinfo.html b/docs/index-docinfo.html
new file mode 100644
index 000000000..ad5a8e744
--- /dev/null
+++ b/docs/index-docinfo.html
@@ -0,0 +1,10396 @@
+<script>
+/*!
+ * jQuery JavaScript Library v1.11.1
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-05-01T17:42Z
+ */
+
+(function( global, factory ) {
+
+	if ( typeof module === "object" && typeof module.exports === "object" ) {
+		// For CommonJS and CommonJS-like environments where a proper window is present,
+		// execute the factory and get jQuery
+		// For environments that do not inherently posses a window with a document
+		// (such as Node.js), expose a jQuery-making 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 ) {
+
+// Can't do this because several apps including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+// Support: Firefox 18+
+//
+
+var deletedIds = [];
+
+var slice = deletedIds.slice;
+
+var concat = deletedIds.concat;
+
+var push = deletedIds.push;
+
+var indexOf = deletedIds.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var support = {};
+
+
+
+var
+	version = "1.11.1",
+
+	// Define a local copy of jQuery
+	jQuery = function( selector, context ) {
+		// The jQuery object is actually just the init constructor 'enhanced'
+		// Need init if jQuery is called (just allow error to be thrown if not included)
+		return new jQuery.fn.init( selector, context );
+	},
+
+	// Support: Android<4.1, IE<9
+	// Make sure we trim BOM and NBSP
+	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+	// Matches dashed string for camelizing
+	rmsPrefix = /^-ms-/,
+	rdashAlpha = /-([\da-z])/gi,
+
+	// Used by jQuery.camelCase as callback to replace()
+	fcamelCase = function( all, letter ) {
+		return letter.toUpperCase();
+	};
+
+jQuery.fn = jQuery.prototype = {
+	// The current version of jQuery being used
+	jquery: version,
+
+	constructor: jQuery,
+
+	// Start with an empty selector
+	selector: "",
+
+	// The default length of a jQuery object is 0
+	length: 0,
+
+	toArray: function() {
+		return slice.call( this );
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num != null ?
+
+			// Return just the one element from the set
+			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
+
+			// Return all the elements in a clean array
+			slice.call( this );
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems ) {
+
+		// Build a new jQuery matched element set
+		var ret = jQuery.merge( this.constructor(), elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+		ret.context = this.context;
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	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(null);
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: push,
+	sort: deletedIds.sort,
+	splice: deletedIds.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+	var src, copyIsArray, copy, name, options, 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() {},
+
+	// See test/unit/core.js for details concerning isFunction.
+	// Since version 1.3, DOM methods and functions like alert
+	// aren't supported. They return false on IE (#2968).
+	isFunction: function( obj ) {
+		return jQuery.type(obj) === "function";
+	},
+
+	isArray: Array.isArray || function( obj ) {
+		return jQuery.type(obj) === "array";
+	},
+
+	isWindow: function( obj ) {
+		/* jshint eqeqeq: false */
+		return obj != null && obj == obj.window;
+	},
+
+	isNumeric: function( obj ) {
+		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
+		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+		// subtraction forces infinities to NaN
+		return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0;
+	},
+
+	isEmptyObject: function( obj ) {
+		var name;
+		for ( name in obj ) {
+			return false;
+		}
+		return true;
+	},
+
+	isPlainObject: function( obj ) {
+		var key;
+
+		// Must be an Object.
+		// Because of IE, we also have to check the presence of the constructor property.
+		// Make sure that DOM nodes and window objects don't pass through, as well
+		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+			return false;
+		}
+
+		try {
+			// Not own constructor property must be Object
+			if ( obj.constructor &&
+				!hasOwn.call(obj, "constructor") &&
+				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+				return false;
+			}
+		} catch ( e ) {
+			// IE8,9 Will throw exceptions on certain host objects #9897
+			return false;
+		}
+
+		// Support: IE<9
+		// Handle iteration over inherited properties before own properties.
+		if ( support.ownLast ) {
+			for ( key in obj ) {
+				return hasOwn.call( obj, key );
+			}
+		}
+
+		// Own properties are enumerated firstly, so to speed up,
+		// if last one is own, then all properties are own.
+		for ( key in obj ) {}
+
+		return key === undefined || hasOwn.call( obj, key );
+	},
+
+	type: function( obj ) {
+		if ( obj == null ) {
+			return obj + "";
+		}
+		return typeof obj === "object" || typeof obj === "function" ?
+			class2type[ toString.call(obj) ] || "object" :
+			typeof obj;
+	},
+
+	// Evaluates a script in a global context
+	// Workarounds based on findings by Jim Driscoll
+	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+	globalEval: function( data ) {
+		if ( data && jQuery.trim( data ) ) {
+			// We use execScript on Internet Explorer
+			// We use an anonymous function so that context is window
+			// rather than jQuery in Firefox
+			( window.execScript || function( data ) {
+				window[ "eval" ].call( window, data );
+			} )( data );
+		}
+	},
+
+	// Convert dashed to camelCase; used by the css and data modules
+	// 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();
+	},
+
+	// args is for internal usage only
+	each: function( obj, callback, args ) {
+		var value,
+			i = 0,
+			length = obj.length,
+			isArray = isArraylike( obj );
+
+		if ( args ) {
+			if ( isArray ) {
+				for ( ; i < length; i++ ) {
+					value = callback.apply( obj[ i ], args );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( i in obj ) {
+					value = callback.apply( obj[ i ], args );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			}
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( isArray ) {
+				for ( ; i < length; i++ ) {
+					value = callback.call( obj[ i ], i, obj[ i ] );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( i in obj ) {
+					value = callback.call( obj[ i ], i, obj[ i ] );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			}
+		}
+
+		return obj;
+	},
+
+	// Support: Android<4.1, IE<9
+	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 ) {
+		var len;
+
+		if ( arr ) {
+			if ( indexOf ) {
+				return indexOf.call( arr, elem, i );
+			}
+
+			len = arr.length;
+			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+			for ( ; i < len; i++ ) {
+				// Skip accessing in sparse arrays
+				if ( i in arr && arr[ i ] === elem ) {
+					return i;
+				}
+			}
+		}
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		var len = +second.length,
+			j = 0,
+			i = first.length;
+
+		while ( j < len ) {
+			first[ i++ ] = second[ j++ ];
+		}
+
+		// Support: IE<9
+		// Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
+		if ( len !== len ) {
+			while ( second[j] !== undefined ) {
+				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 value,
+			i = 0,
+			length = elems.length,
+			isArray = isArraylike( elems ),
+			ret = [];
+
+		// Go through the array, translating each of the items to their new values
+		if ( isArray ) {
+			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 args, proxy, tmp;
+
+		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: function() {
+		return +( new Date() );
+	},
+
+	// jQuery.support is not used in Core but other projects attach their
+	// properties to it so it needs to exist.
+	support: support
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+	class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+function isArraylike( obj ) {
+	var length = obj.length,
+		type = jQuery.type( obj );
+
+	if ( type === "function" || jQuery.isWindow( obj ) ) {
+		return false;
+	}
+
+	if ( obj.nodeType === 1 && length ) {
+		return true;
+	}
+
+	return type === "array" || length === 0 ||
+		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v1.10.19
+ * http://sizzlejs.com/
+ *
+ * Copyright 2013 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-04-18
+ */
+(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" + -(new Date()),
+	preferredDoc = window.document,
+	dirruns = 0,
+	done = 0,
+	classCache = createCache(),
+	tokenCache = createCache(),
+	compilerCache = createCache(),
+	sortOrder = function( a, b ) {
+		if ( a === b ) {
+			hasDuplicate = true;
+		}
+		return 0;
+	},
+
+	// General-purpose constants
+	strundefined = typeof undefined,
+	MAX_NEGATIVE = 1 << 31,
+
+	// Instance methods
+	hasOwn = ({}).hasOwnProperty,
+	arr = [],
+	pop = arr.pop,
+	push_native = arr.push,
+	push = arr.push,
+	slice = arr.slice,
+	// Use a stripped-down indexOf if we can't use a native one
+	indexOf = arr.indexOf || function( elem ) {
+		var i = 0,
+			len = this.length;
+		for ( ; i < len; i++ ) {
+			if ( this[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
+
+	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+	whitespace = "[\\x20\\t\\r\\n\\f]",
+	// http://www.w3.org/TR/css3-syntax/#characters
+	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+	// Loosely modeled on CSS identifier characters
+	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+	identifier = characterEncoding.replace( "w", "w#" ),
+
+	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
+		// Operator (capture 2)
+		"*([*^$|!~]?=)" + whitespace +
+		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+		"*\\]",
+
+	pseudos = ":(" + characterEncoding + ")(?:\\((" +
+		// 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
+	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( "^#(" + characterEncoding + ")" ),
+		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+		"ATTR": new RegExp( "^" + attributes ),
+		"PSEUDO": new RegExp( "^" + pseudos ),
+		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+		// For use in libraries implementing .is()
+		// We use this for POS matching in `select`
+		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+	},
+
+	rinputs = /^(?:input|select|textarea|button)$/i,
+	rheader = /^h\d$/i,
+
+	rnative = /^[^{]+\{\s*\[native \w/,
+
+	// Easily-parseable/retrievable ID or TAG or CLASS selectors
+	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+	rsibling = /[+~]/,
+	rescape = /'|\\/g,
+
+	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+	funescape = function( _, escaped, escapedWhitespace ) {
+		var high = "0x" + escaped - 0x10000;
+		// NaN means non-codepoint
+		// Support: Firefox<24
+		// Workaround erroneous numeric interpretation of +"0x"
+		return high !== high || escapedWhitespace ?
+			escaped :
+			high < 0 ?
+				// BMP codepoint
+				String.fromCharCode( high + 0x10000 ) :
+				// Supplemental Plane codepoint (surrogate pair)
+				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+	};
+
+// 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 match, elem, m, nodeType,
+		// QSA vars
+		i, groups, old, nid, newContext, newSelector;
+
+	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+		setDocument( context );
+	}
+
+	context = context || document;
+	results = results || [];
+
+	if ( !selector || typeof selector !== "string" ) {
+		return results;
+	}
+
+	if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
+		return [];
+	}
+
+	if ( documentIsHTML && !seed ) {
+
+		// Shortcuts
+		if ( (match = rquickExpr.exec( selector )) ) {
+			// Speed-up: Sizzle("#ID")
+			if ( (m = match[1]) ) {
+				if ( nodeType === 9 ) {
+					elem = context.getElementById( m );
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document (jQuery #6963)
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE, Opera, and Webkit return items
+						// by name instead of ID
+						if ( elem.id === m ) {
+							results.push( elem );
+							return results;
+						}
+					} else {
+						return results;
+					}
+				} else {
+					// Context is not a document
+					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+						contains( context, elem ) && elem.id === m ) {
+						results.push( elem );
+						return results;
+					}
+				}
+
+			// Speed-up: Sizzle("TAG")
+			} else if ( match[2] ) {
+				push.apply( results, context.getElementsByTagName( selector ) );
+				return results;
+
+			// Speed-up: Sizzle(".CLASS")
+			} else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
+				push.apply( results, context.getElementsByClassName( m ) );
+				return results;
+			}
+		}
+
+		// QSA path
+		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+			nid = old = expando;
+			newContext = context;
+			newSelector = nodeType === 9 && selector;
+
+			// qSA works strangely on Element-rooted queries
+			// We can work around this by specifying an extra ID on the root
+			// and working up from there (Thanks to Andrew Dupont for the technique)
+			// IE 8 doesn't work on object elements
+			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+				groups = tokenize( selector );
+
+				if ( (old = context.getAttribute("id")) ) {
+					nid = old.replace( rescape, "\\$&" );
+				} else {
+					context.setAttribute( "id", nid );
+				}
+				nid = "[id='" + nid + "'] ";
+
+				i = groups.length;
+				while ( i-- ) {
+					groups[i] = nid + toSelector( groups[i] );
+				}
+				newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
+				newSelector = groups.join(",");
+			}
+
+			if ( newSelector ) {
+				try {
+					push.apply( results,
+						newContext.querySelectorAll( newSelector )
+					);
+					return results;
+				} catch(qsaError) {
+				} finally {
+					if ( !old ) {
+						context.removeAttribute("id");
+					}
+				}
+			}
+		}
+	}
+
+	// All others
+	return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ *	deleting the oldest entry
+ */
+function createCache() {
+	var keys = [];
+
+	function cache( key, value ) {
+		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+		if ( keys.push( key + " " ) > Expr.cacheLength ) {
+			// Only keep the most recent entries
+			delete cache[ keys.shift() ];
+		}
+		return (cache[ key + " " ] = value);
+	}
+	return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+	fn[ expando ] = true;
+	return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+	var div = document.createElement("div");
+
+	try {
+		return !!fn( div );
+	} catch (e) {
+		return false;
+	} finally {
+		// Remove from its parent by default
+		if ( div.parentNode ) {
+			div.parentNode.removeChild( div );
+		}
+		// release memory in IE
+		div = null;
+	}
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+	var arr = attrs.split("|"),
+		i = attrs.length;
+
+	while ( i-- ) {
+		Expr.attrHandle[ arr[i] ] = handler;
+	}
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+	var cur = b && a,
+		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+			( ~b.sourceIndex || MAX_NEGATIVE ) -
+			( ~a.sourceIndex || MAX_NEGATIVE );
+
+	// Use IE sourceIndex if available on both nodes
+	if ( diff ) {
+		return diff;
+	}
+
+	// Check if b follows a
+	if ( cur ) {
+		while ( (cur = cur.nextSibling) ) {
+			if ( cur === b ) {
+				return -1;
+			}
+		}
+	}
+
+	return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return name === "input" && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return (name === "input" || name === "button") && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+	return markFunction(function( argument ) {
+		argument = +argument;
+		return markFunction(function( seed, matches ) {
+			var j,
+				matchIndexes = fn( [], seed.length, argument ),
+				i = matchIndexes.length;
+
+			// Match elements found at the specified indexes
+			while ( i-- ) {
+				if ( seed[ (j = matchIndexes[i]) ] ) {
+					seed[j] = !(matches[j] = seed[j]);
+				}
+			}
+		});
+	});
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+	return context && typeof context.getElementsByTagName !== strundefined && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+	// documentElement is verified for cases where it doesn't yet exist
+	// (such as loading iframes in IE - #4833)
+	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+	return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+	var hasCompare,
+		doc = node ? node.ownerDocument || node : preferredDoc,
+		parent = doc.defaultView;
+
+	// If no document and documentElement is available, return
+	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+		return document;
+	}
+
+	// Set our document
+	document = doc;
+	docElem = doc.documentElement;
+
+	// Support tests
+	documentIsHTML = !isXML( doc );
+
+	// Support: IE>8
+	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
+	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
+	// IE6-8 do not support the defaultView property so parent will be undefined
+	if ( parent && parent !== parent.top ) {
+		// IE11 does not have attachEvent, so all must suffer
+		if ( parent.addEventListener ) {
+			parent.addEventListener( "unload", function() {
+				setDocument();
+			}, false );
+		} else if ( parent.attachEvent ) {
+			parent.attachEvent( "onunload", function() {
+				setDocument();
+			});
+		}
+	}
+
+	/* Attributes
+	---------------------------------------------------------------------- */
+
+	// Support: IE<8
+	// Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
+	support.attributes = assert(function( div ) {
+		div.className = "i";
+		return !div.getAttribute("className");
+	});
+
+	/* getElement(s)By*
+	---------------------------------------------------------------------- */
+
+	// Check if getElementsByTagName("*") returns only elements
+	support.getElementsByTagName = assert(function( div ) {
+		div.appendChild( doc.createComment("") );
+		return !div.getElementsByTagName("*").length;
+	});
+
+	// Check if getElementsByClassName can be trusted
+	support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
+		div.innerHTML = "<div class='a'></div><div class='a i'></div>";
+
+		// Support: Safari<4
+		// Catch class over-caching
+		div.firstChild.className = "i";
+		// Support: Opera<10
+		// Catch gEBCN failure to find non-leading classes
+		return div.getElementsByClassName("i").length === 2;
+	});
+
+	// Support: IE<10
+	// Check if getElementById returns elements by name
+	// The broken getElementById methods don't pick up programatically-set names,
+	// so use a roundabout getElementsByName test
+	support.getById = assert(function( div ) {
+		docElem.appendChild( div ).id = expando;
+		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
+	});
+
+	// ID find and filter
+	if ( support.getById ) {
+		Expr.find["ID"] = function( id, context ) {
+			if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
+				var m = context.getElementById( id );
+				// Check parentNode to catch when Blackberry 4.6 returns
+				// nodes that are no longer in the document #6963
+				return m && m.parentNode ? [ m ] : [];
+			}
+		};
+		Expr.filter["ID"] = function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				return elem.getAttribute("id") === attrId;
+			};
+		};
+	} else {
+		// Support: IE6/7
+		// getElementById is not reliable as a find shortcut
+		delete Expr.find["ID"];
+
+		Expr.filter["ID"] =  function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+				return node && node.value === attrId;
+			};
+		};
+	}
+
+	// Tag
+	Expr.find["TAG"] = support.getElementsByTagName ?
+		function( tag, context ) {
+			if ( typeof context.getElementsByTagName !== strundefined ) {
+				return context.getElementsByTagName( tag );
+			}
+		} :
+		function( tag, context ) {
+			var elem,
+				tmp = [],
+				i = 0,
+				results = context.getElementsByTagName( tag );
+
+			// Filter out possible comments
+			if ( tag === "*" ) {
+				while ( (elem = results[i++]) ) {
+					if ( elem.nodeType === 1 ) {
+						tmp.push( elem );
+					}
+				}
+
+				return tmp;
+			}
+			return results;
+		};
+
+	// Class
+	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+		if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
+			return context.getElementsByClassName( className );
+		}
+	};
+
+	/* QSA/matchesSelector
+	---------------------------------------------------------------------- */
+
+	// QSA and matchesSelector support
+
+	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+	rbuggyMatches = [];
+
+	// qSa(:focus) reports false when true (Chrome 21)
+	// We allow this because of a bug in IE8/9 that throws an error
+	// whenever `document.activeElement` is accessed on an iframe
+	// So, we allow :focus to pass through QSA all the time to avoid the IE error
+	// See http://bugs.jquery.com/ticket/13378
+	rbuggyQSA = [];
+
+	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
+		// Build QSA regex
+		// Regex strategy adopted from Diego Perini
+		assert(function( div ) {
+			// Select is set to empty string on purpose
+			// This is to test IE's treatment of not explicitly
+			// setting a boolean content attribute,
+			// since its presence should be enough
+			// http://bugs.jquery.com/ticket/12359
+			div.innerHTML = "<select msallowclip=''><option selected=''></option></select>";
+
+			// Support: IE8, Opera 11-12.16
+			// Nothing should be selected when empty strings follow ^= or $= or *=
+			// The test attribute must be unknown in Opera but "safe" for WinRT
+			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+			if ( div.querySelectorAll("[msallowclip^='']").length ) {
+				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+			}
+
+			// Support: IE8
+			// Boolean attributes and "value" are not treated correctly
+			if ( !div.querySelectorAll("[selected]").length ) {
+				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+			}
+
+			// Webkit/Opera - :checked should return selected option elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			// IE8 throws error here and will not see later tests
+			if ( !div.querySelectorAll(":checked").length ) {
+				rbuggyQSA.push(":checked");
+			}
+		});
+
+		assert(function( div ) {
+			// Support: Windows 8 Native Apps
+			// The type and name attributes are restricted during .innerHTML assignment
+			var input = doc.createElement("input");
+			input.setAttribute( "type", "hidden" );
+			div.appendChild( input ).setAttribute( "name", "D" );
+
+			// Support: IE8
+			// Enforce case-sensitivity of name attribute
+			if ( div.querySelectorAll("[name=d]").length ) {
+				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+			}
+
+			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+			// IE8 throws error here and will not see later tests
+			if ( !div.querySelectorAll(":enabled").length ) {
+				rbuggyQSA.push( ":enabled", ":disabled" );
+			}
+
+			// Opera 10-11 does not throw on post-comma invalid pseudos
+			div.querySelectorAll("*,:x");
+			rbuggyQSA.push(",.*:");
+		});
+	}
+
+	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+		docElem.webkitMatchesSelector ||
+		docElem.mozMatchesSelector ||
+		docElem.oMatchesSelector ||
+		docElem.msMatchesSelector) )) ) {
+
+		assert(function( div ) {
+			// Check to see if it's possible to do matchesSelector
+			// on a disconnected node (IE 9)
+			support.disconnectedMatch = matches.call( div, "div" );
+
+			// This should fail with an exception
+			// Gecko does not error, returns false instead
+			matches.call( div, "[s!='']:x" );
+			rbuggyMatches.push( "!=", pseudos );
+		});
+	}
+
+	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+	/* Contains
+	---------------------------------------------------------------------- */
+	hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+	// Element contains another
+	// Purposefully does not implement inclusive descendent
+	// As in, an element does not contain itself
+	contains = hasCompare || rnative.test( docElem.contains ) ?
+		function( a, b ) {
+			var adown = a.nodeType === 9 ? a.documentElement : a,
+				bup = b && b.parentNode;
+			return a === bup || !!( bup && bup.nodeType === 1 && (
+				adown.contains ?
+					adown.contains( bup ) :
+					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+			));
+		} :
+		function( a, b ) {
+			if ( b ) {
+				while ( (b = b.parentNode) ) {
+					if ( b === a ) {
+						return true;
+					}
+				}
+			}
+			return false;
+		};
+
+	/* Sorting
+	---------------------------------------------------------------------- */
+
+	// Document order sorting
+	sortOrder = hasCompare ?
+	function( a, b ) {
+
+		// Flag for duplicate removal
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		// Sort on method existence if only one input has compareDocumentPosition
+		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+		if ( compare ) {
+			return compare;
+		}
+
+		// Calculate position if both inputs belong to the same document
+		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+			a.compareDocumentPosition( b ) :
+
+			// Otherwise we know they are disconnected
+			1;
+
+		// Disconnected nodes
+		if ( compare & 1 ||
+			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+			// Choose the first element that is related to our preferred document
+			if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+				return -1;
+			}
+			if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+				return 1;
+			}
+
+			// Maintain original order
+			return sortInput ?
+				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
+				0;
+		}
+
+		return compare & 4 ? -1 : 1;
+	} :
+	function( a, b ) {
+		// Exit early if the nodes are identical
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		var cur,
+			i = 0,
+			aup = a.parentNode,
+			bup = b.parentNode,
+			ap = [ a ],
+			bp = [ b ];
+
+		// Parentless nodes are either documents or disconnected
+		if ( !aup || !bup ) {
+			return a === doc ? -1 :
+				b === doc ? 1 :
+				aup ? -1 :
+				bup ? 1 :
+				sortInput ?
+				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
+				0;
+
+		// If the nodes are siblings, we can do a quick check
+		} else if ( aup === bup ) {
+			return siblingCheck( a, b );
+		}
+
+		// Otherwise we need full lists of their ancestors for comparison
+		cur = a;
+		while ( (cur = cur.parentNode) ) {
+			ap.unshift( cur );
+		}
+		cur = b;
+		while ( (cur = cur.parentNode) ) {
+			bp.unshift( cur );
+		}
+
+		// Walk down the tree looking for a discrepancy
+		while ( ap[i] === bp[i] ) {
+			i++;
+		}
+
+		return i ?
+			// Do a sibling check if the nodes have a common ancestor
+			siblingCheck( ap[i], bp[i] ) :
+
+			// Otherwise nodes in our document sort first
+			ap[i] === preferredDoc ? -1 :
+			bp[i] === preferredDoc ? 1 :
+			0;
+	};
+
+	return doc;
+};
+
+Sizzle.matches = function( expr, elements ) {
+	return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	// Make sure that attribute selectors are quoted
+	expr = expr.replace( rattributeQuotes, "='$1']" );
+
+	if ( support.matchesSelector && documentIsHTML &&
+		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
+
+		try {
+			var ret = matches.call( elem, expr );
+
+			// IE 9's matchesSelector returns false on disconnected nodes
+			if ( ret || support.disconnectedMatch ||
+					// As well, disconnected nodes are said to be in a document
+					// fragment in IE 9
+					elem.document && elem.document.nodeType !== 11 ) {
+				return ret;
+			}
+		} catch(e) {}
+	}
+
+	return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+	// Set document vars if needed
+	if ( ( context.ownerDocument || context ) !== document ) {
+		setDocument( context );
+	}
+	return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	var fn = Expr.attrHandle[ name.toLowerCase() ],
+		// Don't get fooled by Object.prototype properties (jQuery #13807)
+		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+			fn( elem, name, !documentIsHTML ) :
+			undefined;
+
+	return val !== undefined ?
+		val :
+		support.attributes || !documentIsHTML ?
+			elem.getAttribute( name ) :
+			(val = elem.getAttributeNode(name)) && val.specified ?
+				val.value :
+				null;
+};
+
+Sizzle.error = function( msg ) {
+	throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+	var elem,
+		duplicates = [],
+		j = 0,
+		i = 0;
+
+	// Unless we *know* we can detect duplicates, assume their presence
+	hasDuplicate = !support.detectDuplicates;
+	sortInput = !support.sortStable && results.slice( 0 );
+	results.sort( sortOrder );
+
+	if ( hasDuplicate ) {
+		while ( (elem = results[i++]) ) {
+			if ( elem === results[ i ] ) {
+				j = duplicates.push( i );
+			}
+		}
+		while ( j-- ) {
+			results.splice( duplicates[ j ], 1 );
+		}
+	}
+
+	// Clear input after sorting to release objects
+	// See https://github.com/jquery/sizzle/pull/225
+	sortInput = null;
+
+	return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+	var node,
+		ret = "",
+		i = 0,
+		nodeType = elem.nodeType;
+
+	if ( !nodeType ) {
+		// If no nodeType, this is expected to be an array
+		while ( (node = elem[i++]) ) {
+			// Do not traverse comment nodes
+			ret += getText( node );
+		}
+	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+		// Use textContent for elements
+		// innerText usage removed for consistency of new lines (jQuery #11153)
+		if ( typeof elem.textContent === "string" ) {
+			return elem.textContent;
+		} else {
+			// Traverse its children
+			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+				ret += getText( elem );
+			}
+		}
+	} else if ( nodeType === 3 || nodeType === 4 ) {
+		return elem.nodeValue;
+	}
+	// Do not include comment or processing instruction nodes
+
+	return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+	// Can be adjusted by the user
+	cacheLength: 50,
+
+	createPseudo: markFunction,
+
+	match: matchExpr,
+
+	attrHandle: {},
+
+	find: {},
+
+	relative: {
+		">": { dir: "parentNode", first: true },
+		" ": { dir: "parentNode" },
+		"+": { dir: "previousSibling", first: true },
+		"~": { dir: "previousSibling" }
+	},
+
+	preFilter: {
+		"ATTR": function( match ) {
+			match[1] = match[1].replace( runescape, funescape );
+
+			// Move the given value to match[3] whether quoted or unquoted
+			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+			if ( match[2] === "~=" ) {
+				match[3] = " " + match[3] + " ";
+			}
+
+			return match.slice( 0, 4 );
+		},
+
+		"CHILD": function( match ) {
+			/* matches from matchExpr["CHILD"]
+				1 type (only|nth|...)
+				2 what (child|of-type)
+				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+				4 xn-component of xn+y argument ([+-]?\d*n|)
+				5 sign of xn-component
+				6 x of xn-component
+				7 sign of y-component
+				8 y of y-component
+			*/
+			match[1] = match[1].toLowerCase();
+
+			if ( match[1].slice( 0, 3 ) === "nth" ) {
+				// nth-* requires argument
+				if ( !match[3] ) {
+					Sizzle.error( match[0] );
+				}
+
+				// numeric x and y parameters for Expr.filter.CHILD
+				// remember that false/true cast respectively to 0/1
+				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+			// other types prohibit arguments
+			} else if ( match[3] ) {
+				Sizzle.error( match[0] );
+			}
+
+			return match;
+		},
+
+		"PSEUDO": function( match ) {
+			var excess,
+				unquoted = !match[6] && match[2];
+
+			if ( matchExpr["CHILD"].test( match[0] ) ) {
+				return null;
+			}
+
+			// Accept quoted arguments as-is
+			if ( match[3] ) {
+				match[2] = match[4] || match[5] || "";
+
+			// Strip excess characters from unquoted arguments
+			} else if ( unquoted && rpseudo.test( unquoted ) &&
+				// Get excess from tokenize (recursively)
+				(excess = tokenize( unquoted, true )) &&
+				// advance to the next closing parenthesis
+				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+				// excess is a negative index
+				match[0] = match[0].slice( 0, excess );
+				match[2] = unquoted.slice( 0, excess );
+			}
+
+			// Return only captures needed by the pseudo filter method (type and argument)
+			return match.slice( 0, 3 );
+		}
+	},
+
+	filter: {
+
+		"TAG": function( nodeNameSelector ) {
+			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+			return nodeNameSelector === "*" ?
+				function() { return true; } :
+				function( elem ) {
+					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+				};
+		},
+
+		"CLASS": function( className ) {
+			var pattern = classCache[ className + " " ];
+
+			return pattern ||
+				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+				classCache( className, function( elem ) {
+					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
+				});
+		},
+
+		"ATTR": function( name, operator, check ) {
+			return function( elem ) {
+				var result = Sizzle.attr( elem, name );
+
+				if ( result == null ) {
+					return operator === "!=";
+				}
+				if ( !operator ) {
+					return true;
+				}
+
+				result += "";
+
+				return operator === "=" ? result === check :
+					operator === "!=" ? result !== check :
+					operator === "^=" ? check && result.indexOf( check ) === 0 :
+					operator === "*=" ? check && result.indexOf( check ) > -1 :
+					operator === "$=" ? check && result.slice( -check.length ) === check :
+					operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
+					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+					false;
+			};
+		},
+
+		"CHILD": function( type, what, argument, first, last ) {
+			var simple = type.slice( 0, 3 ) !== "nth",
+				forward = type.slice( -4 ) !== "last",
+				ofType = what === "of-type";
+
+			return first === 1 && last === 0 ?
+
+				// Shortcut for :nth-*(n)
+				function( elem ) {
+					return !!elem.parentNode;
+				} :
+
+				function( elem, context, xml ) {
+					var cache, outerCache, node, diff, nodeIndex, start,
+						dir = simple !== forward ? "nextSibling" : "previousSibling",
+						parent = elem.parentNode,
+						name = ofType && elem.nodeName.toLowerCase(),
+						useCache = !xml && !ofType;
+
+					if ( parent ) {
+
+						// :(first|last|only)-(child|of-type)
+						if ( simple ) {
+							while ( dir ) {
+								node = elem;
+								while ( (node = node[ dir ]) ) {
+									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+										return false;
+									}
+								}
+								// Reverse direction for :only-* (if we haven't yet done so)
+								start = dir = type === "only" && !start && "nextSibling";
+							}
+							return true;
+						}
+
+						start = [ forward ? parent.firstChild : parent.lastChild ];
+
+						// non-xml :nth-child(...) stores cache data on `parent`
+						if ( forward && useCache ) {
+							// Seek `elem` from a previously-cached index
+							outerCache = parent[ expando ] || (parent[ expando ] = {});
+							cache = outerCache[ type ] || [];
+							nodeIndex = cache[0] === dirruns && cache[1];
+							diff = cache[0] === dirruns && cache[2];
+							node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+							while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+								// Fallback to seeking `elem` from the start
+								(diff = nodeIndex = 0) || start.pop()) ) {
+
+								// When found, cache indexes on `parent` and break
+								if ( node.nodeType === 1 && ++diff && node === elem ) {
+									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+									break;
+								}
+							}
+
+						// Use previously-cached element index if available
+						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+							diff = cache[1];
+
+						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+						} else {
+							// Use the same loop as above to seek `elem` from the start
+							while ( (node = ++nodeIndex && node && node[ dir ] ||
+								(diff = nodeIndex = 0) || start.pop()) ) {
+
+								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+									// Cache the index of each encountered element
+									if ( useCache ) {
+										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+									}
+
+									if ( node === elem ) {
+										break;
+									}
+								}
+							}
+						}
+
+						// Incorporate the offset, then check against cycle size
+						diff -= last;
+						return diff === first || ( diff % first === 0 && diff / first >= 0 );
+					}
+				};
+		},
+
+		"PSEUDO": function( pseudo, argument ) {
+			// pseudo-class names are case-insensitive
+			// http://www.w3.org/TR/selectors/#pseudo-classes
+			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+			// Remember that setFilters inherits from pseudos
+			var args,
+				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+					Sizzle.error( "unsupported pseudo: " + pseudo );
+
+			// The user may use createPseudo to indicate that
+			// arguments are needed to create the filter function
+			// just as Sizzle does
+			if ( fn[ expando ] ) {
+				return fn( argument );
+			}
+
+			// But maintain support for old signatures
+			if ( fn.length > 1 ) {
+				args = [ pseudo, pseudo, "", argument ];
+				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+					markFunction(function( seed, matches ) {
+						var idx,
+							matched = fn( seed, argument ),
+							i = matched.length;
+						while ( i-- ) {
+							idx = indexOf.call( seed, matched[i] );
+							seed[ idx ] = !( matches[ idx ] = matched[i] );
+						}
+					}) :
+					function( elem ) {
+						return fn( elem, 0, args );
+					};
+			}
+
+			return fn;
+		}
+	},
+
+	pseudos: {
+		// Potentially complex pseudos
+		"not": markFunction(function( selector ) {
+			// Trim the selector passed to compile
+			// to avoid treating leading and trailing
+			// spaces as combinators
+			var input = [],
+				results = [],
+				matcher = compile( selector.replace( rtrim, "$1" ) );
+
+			return matcher[ expando ] ?
+				markFunction(function( seed, matches, context, xml ) {
+					var elem,
+						unmatched = matcher( seed, null, xml, [] ),
+						i = seed.length;
+
+					// Match elements unmatched by `matcher`
+					while ( i-- ) {
+						if ( (elem = unmatched[i]) ) {
+							seed[i] = !(matches[i] = elem);
+						}
+					}
+				}) :
+				function( elem, context, xml ) {
+					input[0] = elem;
+					matcher( input, null, xml, results );
+					return !results.pop();
+				};
+		}),
+
+		"has": markFunction(function( selector ) {
+			return function( elem ) {
+				return Sizzle( selector, elem ).length > 0;
+			};
+		}),
+
+		"contains": markFunction(function( text ) {
+			return function( elem ) {
+				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+			};
+		}),
+
+		// "Whether an element is represented by a :lang() selector
+		// is based solely on the element's language value
+		// being equal to the identifier C,
+		// or beginning with the identifier C immediately followed by "-".
+		// The matching of C against the element's language value is performed case-insensitively.
+		// The identifier C does not have to be a valid language name."
+		// http://www.w3.org/TR/selectors/#lang-pseudo
+		"lang": markFunction( function( lang ) {
+			// lang value must be a valid identifier
+			if ( !ridentifier.test(lang || "") ) {
+				Sizzle.error( "unsupported lang: " + lang );
+			}
+			lang = lang.replace( runescape, funescape ).toLowerCase();
+			return function( elem ) {
+				var elemLang;
+				do {
+					if ( (elemLang = documentIsHTML ?
+						elem.lang :
+						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+						elemLang = elemLang.toLowerCase();
+						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+					}
+				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+				return false;
+			};
+		}),
+
+		// Miscellaneous
+		"target": function( elem ) {
+			var hash = window.location && window.location.hash;
+			return hash && hash.slice( 1 ) === elem.id;
+		},
+
+		"root": function( elem ) {
+			return elem === docElem;
+		},
+
+		"focus": function( elem ) {
+			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+		},
+
+		// Boolean properties
+		"enabled": function( elem ) {
+			return elem.disabled === false;
+		},
+
+		"disabled": function( elem ) {
+			return elem.disabled === true;
+		},
+
+		"checked": function( elem ) {
+			// In CSS3, :checked should return both checked and selected elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			var nodeName = elem.nodeName.toLowerCase();
+			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+		},
+
+		"selected": function( elem ) {
+			// Accessing this property makes selected-by-default
+			// options in Safari work properly
+			if ( elem.parentNode ) {
+				elem.parentNode.selectedIndex;
+			}
+
+			return elem.selected === true;
+		},
+
+		// Contents
+		"empty": function( elem ) {
+			// http://www.w3.org/TR/selectors/#empty-pseudo
+			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+			//   but not by others (comment: 8; processing instruction: 7; etc.)
+			// nodeType < 6 works because attributes (2) do not appear as children
+			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+				if ( elem.nodeType < 6 ) {
+					return false;
+				}
+			}
+			return true;
+		},
+
+		"parent": function( elem ) {
+			return !Expr.pseudos["empty"]( elem );
+		},
+
+		// Element/input types
+		"header": function( elem ) {
+			return rheader.test( elem.nodeName );
+		},
+
+		"input": function( elem ) {
+			return rinputs.test( elem.nodeName );
+		},
+
+		"button": function( elem ) {
+			var name = elem.nodeName.toLowerCase();
+			return name === "input" && elem.type === "button" || name === "button";
+		},
+
+		"text": function( elem ) {
+			var attr;
+			return elem.nodeName.toLowerCase() === "input" &&
+				elem.type === "text" &&
+
+				// Support: IE<8
+				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+		},
+
+		// Position-in-collection
+		"first": createPositionalPseudo(function() {
+			return [ 0 ];
+		}),
+
+		"last": createPositionalPseudo(function( matchIndexes, length ) {
+			return [ length - 1 ];
+		}),
+
+		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			return [ argument < 0 ? argument + length : argument ];
+		}),
+
+		"even": createPositionalPseudo(function( matchIndexes, length ) {
+			var i = 0;
+			for ( ; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"odd": createPositionalPseudo(function( matchIndexes, length ) {
+			var i = 1;
+			for ( ; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			var i = argument < 0 ? argument + length : argument;
+			for ( ; --i >= 0; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			var i = argument < 0 ? argument + length : argument;
+			for ( ; ++i < length; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		})
+	}
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+	Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+	Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+	var matched, match, tokens, type,
+		soFar, groups, preFilters,
+		cached = tokenCache[ selector + " " ];
+
+	if ( cached ) {
+		return parseOnly ? 0 : cached.slice( 0 );
+	}
+
+	soFar = selector;
+	groups = [];
+	preFilters = Expr.preFilter;
+
+	while ( soFar ) {
+
+		// Comma and first run
+		if ( !matched || (match = rcomma.exec( soFar )) ) {
+			if ( match ) {
+				// Don't consume trailing commas as valid
+				soFar = soFar.slice( match[0].length ) || soFar;
+			}
+			groups.push( (tokens = []) );
+		}
+
+		matched = false;
+
+		// Combinators
+		if ( (match = rcombinators.exec( soFar )) ) {
+			matched = match.shift();
+			tokens.push({
+				value: matched,
+				// Cast descendant combinators to space
+				type: match[0].replace( rtrim, " " )
+			});
+			soFar = soFar.slice( matched.length );
+		}
+
+		// Filters
+		for ( type in Expr.filter ) {
+			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+				(match = preFilters[ type ]( match ))) ) {
+				matched = match.shift();
+				tokens.push({
+					value: matched,
+					type: type,
+					matches: match
+				});
+				soFar = soFar.slice( matched.length );
+			}
+		}
+
+		if ( !matched ) {
+			break;
+		}
+	}
+
+	// Return the length of the invalid excess
+	// if we're just parsing
+	// Otherwise, throw an error or return tokens
+	return parseOnly ?
+		soFar.length :
+		soFar ?
+			Sizzle.error( selector ) :
+			// Cache the tokens
+			tokenCache( selector, groups ).slice( 0 );
+};
+
+function toSelector( tokens ) {
+	var i = 0,
+		len = tokens.length,
+		selector = "";
+	for ( ; i < len; i++ ) {
+		selector += tokens[i].value;
+	}
+	return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+	var dir = combinator.dir,
+		checkNonElements = base && dir === "parentNode",
+		doneName = done++;
+
+	return combinator.first ?
+		// Check against closest ancestor/preceding element
+		function( elem, context, xml ) {
+			while ( (elem = elem[ dir ]) ) {
+				if ( elem.nodeType === 1 || checkNonElements ) {
+					return matcher( elem, context, xml );
+				}
+			}
+		} :
+
+		// Check against all ancestor/preceding elements
+		function( elem, context, xml ) {
+			var oldCache, outerCache,
+				newCache = [ dirruns, doneName ];
+
+			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+			if ( xml ) {
+				while ( (elem = elem[ dir ]) ) {
+					if ( elem.nodeType === 1 || checkNonElements ) {
+						if ( matcher( elem, context, xml ) ) {
+							return true;
+						}
+					}
+				}
+			} else {
+				while ( (elem = elem[ dir ]) ) {
+					if ( elem.nodeType === 1 || checkNonElements ) {
+						outerCache = elem[ expando ] || (elem[ expando ] = {});
+						if ( (oldCache = outerCache[ dir ]) &&
+							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+							// Assign to newCache so results back-propagate to previous elements
+							return (newCache[ 2 ] = oldCache[ 2 ]);
+						} else {
+							// Reuse newcache so results back-propagate to previous elements
+							outerCache[ dir ] = newCache;
+
+							// A match means we're done; a fail means we have to keep checking
+							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+								return true;
+							}
+						}
+					}
+				}
+			}
+		};
+}
+
+function elementMatcher( matchers ) {
+	return matchers.length > 1 ?
+		function( elem, context, xml ) {
+			var i = matchers.length;
+			while ( i-- ) {
+				if ( !matchers[i]( elem, context, xml ) ) {
+					return false;
+				}
+			}
+			return true;
+		} :
+		matchers[0];
+}
+
+function multipleContexts( selector, contexts, results ) {
+	var i = 0,
+		len = contexts.length;
+	for ( ; i < len; i++ ) {
+		Sizzle( selector, contexts[i], results );
+	}
+	return results;
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+	var elem,
+		newUnmatched = [],
+		i = 0,
+		len = unmatched.length,
+		mapped = map != null;
+
+	for ( ; i < len; i++ ) {
+		if ( (elem = unmatched[i]) ) {
+			if ( !filter || filter( elem, context, xml ) ) {
+				newUnmatched.push( elem );
+				if ( mapped ) {
+					map.push( i );
+				}
+			}
+		}
+	}
+
+	return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+	if ( postFilter && !postFilter[ expando ] ) {
+		postFilter = setMatcher( postFilter );
+	}
+	if ( postFinder && !postFinder[ expando ] ) {
+		postFinder = setMatcher( postFinder, postSelector );
+	}
+	return markFunction(function( seed, results, context, xml ) {
+		var temp, i, elem,
+			preMap = [],
+			postMap = [],
+			preexisting = results.length,
+
+			// Get initial elements from seed or context
+			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+			// Prefilter to get matcher input, preserving a map for seed-results synchronization
+			matcherIn = preFilter && ( seed || !selector ) ?
+				condense( elems, preMap, preFilter, context, xml ) :
+				elems,
+
+			matcherOut = matcher ?
+				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+					// ...intermediate processing is necessary
+					[] :
+
+					// ...otherwise use results directly
+					results :
+				matcherIn;
+
+		// Find primary matches
+		if ( matcher ) {
+			matcher( matcherIn, matcherOut, context, xml );
+		}
+
+		// Apply postFilter
+		if ( postFilter ) {
+			temp = condense( matcherOut, postMap );
+			postFilter( temp, [], context, xml );
+
+			// Un-match failing elements by moving them back to matcherIn
+			i = temp.length;
+			while ( i-- ) {
+				if ( (elem = temp[i]) ) {
+					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+				}
+			}
+		}
+
+		if ( seed ) {
+			if ( postFinder || preFilter ) {
+				if ( postFinder ) {
+					// Get the final matcherOut by condensing this intermediate into postFinder contexts
+					temp = [];
+					i = matcherOut.length;
+					while ( i-- ) {
+						if ( (elem = matcherOut[i]) ) {
+							// Restore matcherIn since elem is not yet a final match
+							temp.push( (matcherIn[i] = elem) );
+						}
+					}
+					postFinder( null, (matcherOut = []), temp, xml );
+				}
+
+				// Move matched elements from seed to results to keep them synchronized
+				i = matcherOut.length;
+				while ( i-- ) {
+					if ( (elem = matcherOut[i]) &&
+						(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
+
+						seed[temp] = !(results[temp] = elem);
+					}
+				}
+			}
+
+		// Add elements to results, through postFinder if defined
+		} else {
+			matcherOut = condense(
+				matcherOut === results ?
+					matcherOut.splice( preexisting, matcherOut.length ) :
+					matcherOut
+			);
+			if ( postFinder ) {
+				postFinder( null, results, matcherOut, xml );
+			} else {
+				push.apply( results, matcherOut );
+			}
+		}
+	});
+}
+
+function matcherFromTokens( tokens ) {
+	var checkContext, matcher, j,
+		len = tokens.length,
+		leadingRelative = Expr.relative[ tokens[0].type ],
+		implicitRelative = leadingRelative || Expr.relative[" "],
+		i = leadingRelative ? 1 : 0,
+
+		// The foundational matcher ensures that elements are reachable from top-level context(s)
+		matchContext = addCombinator( function( elem ) {
+			return elem === checkContext;
+		}, implicitRelative, true ),
+		matchAnyContext = addCombinator( function( elem ) {
+			return indexOf.call( checkContext, elem ) > -1;
+		}, implicitRelative, true ),
+		matchers = [ function( elem, context, xml ) {
+			return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+				(checkContext = context).nodeType ?
+					matchContext( elem, context, xml ) :
+					matchAnyContext( elem, context, xml ) );
+		} ];
+
+	for ( ; i < len; i++ ) {
+		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+		} else {
+			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+			// Return special upon seeing a positional matcher
+			if ( matcher[ expando ] ) {
+				// Find the next relative operator (if any) for proper handling
+				j = ++i;
+				for ( ; j < len; j++ ) {
+					if ( Expr.relative[ tokens[j].type ] ) {
+						break;
+					}
+				}
+				return setMatcher(
+					i > 1 && elementMatcher( matchers ),
+					i > 1 && toSelector(
+						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
+						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+					).replace( rtrim, "$1" ),
+					matcher,
+					i < j && matcherFromTokens( tokens.slice( i, j ) ),
+					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+					j < len && toSelector( tokens )
+				);
+			}
+			matchers.push( matcher );
+		}
+	}
+
+	return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+	var bySet = setMatchers.length > 0,
+		byElement = elementMatchers.length > 0,
+		superMatcher = function( seed, context, xml, results, outermost ) {
+			var elem, j, matcher,
+				matchedCount = 0,
+				i = "0",
+				unmatched = seed && [],
+				setMatched = [],
+				contextBackup = outermostContext,
+				// We must always have either seed elements or outermost context
+				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+				// Use integer dirruns iff this is the outermost matcher
+				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+				len = elems.length;
+
+			if ( outermost ) {
+				outermostContext = context !== document && context;
+			}
+
+			// Add elements passing elementMatchers directly to results
+			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+			// Support: IE<9, Safari
+			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+				if ( byElement && elem ) {
+					j = 0;
+					while ( (matcher = elementMatchers[j++]) ) {
+						if ( matcher( elem, context, xml ) ) {
+							results.push( elem );
+							break;
+						}
+					}
+					if ( outermost ) {
+						dirruns = dirrunsUnique;
+					}
+				}
+
+				// Track unmatched elements for set filters
+				if ( bySet ) {
+					// They will have gone through all possible matchers
+					if ( (elem = !matcher && elem) ) {
+						matchedCount--;
+					}
+
+					// Lengthen the array for every element, matched or not
+					if ( seed ) {
+						unmatched.push( elem );
+					}
+				}
+			}
+
+			// Apply set filters to unmatched elements
+			matchedCount += i;
+			if ( bySet && i !== matchedCount ) {
+				j = 0;
+				while ( (matcher = setMatchers[j++]) ) {
+					matcher( unmatched, setMatched, context, xml );
+				}
+
+				if ( seed ) {
+					// Reintegrate element matches to eliminate the need for sorting
+					if ( matchedCount > 0 ) {
+						while ( i-- ) {
+							if ( !(unmatched[i] || setMatched[i]) ) {
+								setMatched[i] = pop.call( results );
+							}
+						}
+					}
+
+					// Discard index placeholder values to get only actual matches
+					setMatched = condense( setMatched );
+				}
+
+				// Add matches to results
+				push.apply( results, setMatched );
+
+				// Seedless set matches succeeding multiple successful matchers stipulate sorting
+				if ( outermost && !seed && setMatched.length > 0 &&
+					( matchedCount + setMatchers.length ) > 1 ) {
+
+					Sizzle.uniqueSort( results );
+				}
+			}
+
+			// Override manipulation of globals by nested matchers
+			if ( outermost ) {
+				dirruns = dirrunsUnique;
+				outermostContext = contextBackup;
+			}
+
+			return unmatched;
+		};
+
+	return bySet ?
+		markFunction( superMatcher ) :
+		superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+	var i,
+		setMatchers = [],
+		elementMatchers = [],
+		cached = compilerCache[ selector + " " ];
+
+	if ( !cached ) {
+		// Generate a function of recursive functions that can be used to check each element
+		if ( !match ) {
+			match = tokenize( selector );
+		}
+		i = match.length;
+		while ( i-- ) {
+			cached = matcherFromTokens( match[i] );
+			if ( cached[ expando ] ) {
+				setMatchers.push( cached );
+			} else {
+				elementMatchers.push( cached );
+			}
+		}
+
+		// Cache the compiled function
+		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+		// Save selector and tokenization
+		cached.selector = selector;
+	}
+	return cached;
+};
+
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ *  selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ *  selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+	var i, tokens, token, type, find,
+		compiled = typeof selector === "function" && selector,
+		match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+	results = results || [];
+
+	// Try to minimize operations if there is no seed and only one group
+	if ( match.length === 1 ) {
+
+		// Take a shortcut and set the context if the root selector is an ID
+		tokens = match[0] = match[0].slice( 0 );
+		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+				support.getById && context.nodeType === 9 && documentIsHTML &&
+				Expr.relative[ tokens[1].type ] ) {
+
+			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+			if ( !context ) {
+				return results;
+
+			// Precompiled matchers will still verify ancestry, so step up a level
+			} else if ( compiled ) {
+				context = context.parentNode;
+			}
+
+			selector = selector.slice( tokens.shift().value.length );
+		}
+
+		// Fetch a seed set for right-to-left matching
+		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+		while ( i-- ) {
+			token = tokens[i];
+
+			// Abort if we hit a combinator
+			if ( Expr.relative[ (type = token.type) ] ) {
+				break;
+			}
+			if ( (find = Expr.find[ type ]) ) {
+				// Search, expanding context for leading sibling combinators
+				if ( (seed = find(
+					token.matches[0].replace( runescape, funescape ),
+					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+				)) ) {
+
+					// If seed is empty or no tokens remain, we can return early
+					tokens.splice( i, 1 );
+					selector = seed.length && toSelector( tokens );
+					if ( !selector ) {
+						push.apply( results, seed );
+						return results;
+					}
+
+					break;
+				}
+			}
+		}
+	}
+
+	// Compile and execute a filtering function if one is not provided
+	// Provide `match` to avoid retokenization if we modified the selector above
+	( compiled || compile( selector, match ) )(
+		seed,
+		context,
+		!documentIsHTML,
+		results,
+		rsibling.test( selector ) && testContext( context.parentNode ) || context
+	);
+	return results;
+};
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome<14
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( div1 ) {
+	// Should return 1, but returns 4 (following)
+	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( div ) {
+	div.innerHTML = "<a href='#'></a>";
+	return div.firstChild.getAttribute("href") === "#" ;
+}) ) {
+	addHandle( "type|href|height|width", function( elem, name, isXML ) {
+		if ( !isXML ) {
+			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+		}
+	});
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( div ) {
+	div.innerHTML = "<input/>";
+	div.firstChild.setAttribute( "value", "" );
+	return div.firstChild.getAttribute( "value" ) === "";
+}) ) {
+	addHandle( "value", function( elem, name, isXML ) {
+		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+			return elem.defaultValue;
+		}
+	});
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( div ) {
+	return div.getAttribute("disabled") == null;
+}) ) {
+	addHandle( booleans, function( elem, name, isXML ) {
+		var val;
+		if ( !isXML ) {
+			return elem[ name ] === true ? name.toLowerCase() :
+					(val = elem.getAttributeNode( name )) && val.specified ?
+					val.value :
+				null;
+		}
+	});
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+	if ( jQuery.isFunction( qualifier ) ) {
+		return jQuery.grep( elements, function( elem, i ) {
+			/* jshint -W018 */
+			return !!qualifier.call( elem, i, elem ) !== not;
+		});
+
+	}
+
+	if ( qualifier.nodeType ) {
+		return jQuery.grep( elements, function( elem ) {
+			return ( elem === qualifier ) !== not;
+		});
+
+	}
+
+	if ( typeof qualifier === "string" ) {
+		if ( risSimple.test( qualifier ) ) {
+			return jQuery.filter( qualifier, elements, not );
+		}
+
+		qualifier = jQuery.filter( qualifier, elements );
+	}
+
+	return jQuery.grep( elements, function( elem ) {
+		return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
+	});
+}
+
+jQuery.filter = function( expr, elems, not ) {
+	var elem = elems[ 0 ];
+
+	if ( not ) {
+		expr = ":not(" + expr + ")";
+	}
+
+	return elems.length === 1 && elem.nodeType === 1 ?
+		jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+		jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+			return elem.nodeType === 1;
+		}));
+};
+
+jQuery.fn.extend({
+	find: function( selector ) {
+		var i,
+			ret = [],
+			self = this,
+			len = self.length;
+
+		if ( typeof selector !== "string" ) {
+			return this.pushStack( jQuery( selector ).filter(function() {
+				for ( i = 0; i < len; i++ ) {
+					if ( jQuery.contains( self[ i ], this ) ) {
+						return true;
+					}
+				}
+			}) );
+		}
+
+		for ( i = 0; i < len; i++ ) {
+			jQuery.find( selector, self[ i ], ret );
+		}
+
+		// Needed because $( selector, context ) becomes $( context ).find( selector )
+		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+		ret.selector = this.selector ? this.selector + " " + selector : selector;
+		return ret;
+	},
+	filter: function( selector ) {
+		return this.pushStack( winnow(this, selector || [], false) );
+	},
+	not: function( selector ) {
+		return this.pushStack( winnow(this, selector || [], true) );
+	},
+	is: function( selector ) {
+		return !!winnow(
+			this,
+
+			// If this is a positional/relative selector, check membership in the returned set
+			// so $("p:first").is("p:last") won't return true for a doc with two "p".
+			typeof selector === "string" && rneedsContext.test( selector ) ?
+				jQuery( selector ) :
+				selector || [],
+			false
+		).length;
+	}
+});
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+	// Use the correct document accordingly with window argument (sandbox)
+	document = window.document,
+
+	// A simple way to check for HTML strings
+	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+	// Strict HTML recognition (#11290: must start with <)
+	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+	init = jQuery.fn.init = function( selector, context ) {
+		var match, elem;
+
+		// HANDLE: $(""), $(null), $(undefined), $(false)
+		if ( !selector ) {
+			return this;
+		}
+
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+				// Assume that strings that start and end with <> are HTML and skip the regex check
+				match = [ null, selector, null ];
+
+			} else {
+				match = rquickExpr.exec( selector );
+			}
+
+			// Match html or make sure no context is specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] ) {
+					context = context instanceof jQuery ? context[0] : context;
+
+					// scripts is true for back-compat
+					// Intentionally let the error be thrown if parseHTML is not present
+					jQuery.merge( this, jQuery.parseHTML(
+						match[1],
+						context && context.nodeType ? context.ownerDocument || context : document,
+						true
+					) );
+
+					// HANDLE: $(html, props)
+					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+						for ( match in context ) {
+							// Properties of context are called as methods if possible
+							if ( jQuery.isFunction( this[ match ] ) ) {
+								this[ match ]( context[ match ] );
+
+							// ...and otherwise set as attributes
+							} else {
+								this.attr( match, context[ match ] );
+							}
+						}
+					}
+
+					return this;
+
+				// HANDLE: $(#id)
+				} else {
+					elem = document.getElementById( match[2] );
+
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document #6963
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id !== match[2] ) {
+							return rootjQuery.find( selector );
+						}
+
+						// Otherwise, we inject the element directly into the jQuery object
+						this.length = 1;
+						this[0] = elem;
+					}
+
+					this.context = document;
+					this.selector = selector;
+					return this;
+				}
+
+			// HANDLE: $(expr, $(...))
+			} else if ( !context || context.jquery ) {
+				return ( context || rootjQuery ).find( selector );
+
+			// HANDLE: $(expr, context)
+			// (which is just equivalent to: $(context).find(expr)
+			} else {
+				return this.constructor( context ).find( selector );
+			}
+
+		// HANDLE: $(DOMElement)
+		} else if ( selector.nodeType ) {
+			this.context = this[0] = selector;
+			this.length = 1;
+			return this;
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) ) {
+			return typeof rootjQuery.ready !== "undefined" ?
+				rootjQuery.ready( selector ) :
+				// Execute immediately if ready is not present
+				selector( jQuery );
+		}
+
+		if ( selector.selector !== undefined ) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return jQuery.makeArray( selector, this );
+	};
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+	// methods guaranteed to produce a unique set when starting from a unique set
+	guaranteedUnique = {
+		children: true,
+		contents: true,
+		next: true,
+		prev: true
+	};
+
+jQuery.extend({
+	dir: function( elem, dir, until ) {
+		var matched = [],
+			cur = elem[ dir ];
+
+		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+			if ( cur.nodeType === 1 ) {
+				matched.push( cur );
+			}
+			cur = cur[dir];
+		}
+		return matched;
+	},
+
+	sibling: function( n, elem ) {
+		var r = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType === 1 && n !== elem ) {
+				r.push( n );
+			}
+		}
+
+		return r;
+	}
+});
+
+jQuery.fn.extend({
+	has: function( target ) {
+		var i,
+			targets = jQuery( target, this ),
+			len = targets.length;
+
+		return this.filter(function() {
+			for ( i = 0; i < len; i++ ) {
+				if ( jQuery.contains( this, targets[i] ) ) {
+					return true;
+				}
+			}
+		});
+	},
+
+	closest: function( selectors, context ) {
+		var cur,
+			i = 0,
+			l = this.length,
+			matched = [],
+			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+				jQuery( selectors, context || this.context ) :
+				0;
+
+		for ( ; i < l; i++ ) {
+			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
+				// Always skip document fragments
+				if ( cur.nodeType < 11 && (pos ?
+					pos.index(cur) > -1 :
+
+					// Don't pass non-elements to Sizzle
+					cur.nodeType === 1 &&
+						jQuery.find.matchesSelector(cur, selectors)) ) {
+
+					matched.push( cur );
+					break;
+				}
+			}
+		}
+
+		return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
+	},
+
+	// Determine the position of an element within
+	// the matched set of elements
+	index: function( elem ) {
+
+		// No argument, return index in parent
+		if ( !elem ) {
+			return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
+		}
+
+		// index in selector
+		if ( typeof elem === "string" ) {
+			return jQuery.inArray( this[0], jQuery( elem ) );
+		}
+
+		// Locate the position of the desired element
+		return jQuery.inArray(
+			// If it receives a jQuery object, the first element is used
+			elem.jquery ? elem[0] : elem, this );
+	},
+
+	add: function( selector, context ) {
+		return this.pushStack(
+			jQuery.unique(
+				jQuery.merge( this.get(), jQuery( selector, context ) )
+			)
+		);
+	},
+
+	addBack: function( selector ) {
+		return this.add( selector == null ?
+			this.prevObject : this.prevObject.filter(selector)
+		);
+	}
+});
+
+function sibling( cur, dir ) {
+	do {
+		cur = cur[ dir ];
+	} while ( cur && cur.nodeType !== 1 );
+
+	return cur;
+}
+
+jQuery.each({
+	parent: function( elem ) {
+		var parent = elem.parentNode;
+		return parent && parent.nodeType !== 11 ? parent : null;
+	},
+	parents: function( elem ) {
+		return jQuery.dir( elem, "parentNode" );
+	},
+	parentsUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "parentNode", until );
+	},
+	next: function( elem ) {
+		return sibling( elem, "nextSibling" );
+	},
+	prev: function( elem ) {
+		return sibling( elem, "previousSibling" );
+	},
+	nextAll: function( elem ) {
+		return jQuery.dir( elem, "nextSibling" );
+	},
+	prevAll: function( elem ) {
+		return jQuery.dir( elem, "previousSibling" );
+	},
+	nextUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "nextSibling", until );
+	},
+	prevUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "previousSibling", until );
+	},
+	siblings: function( elem ) {
+		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+	},
+	children: function( elem ) {
+		return jQuery.sibling( elem.firstChild );
+	},
+	contents: function( elem ) {
+		return jQuery.nodeName( elem, "iframe" ) ?
+			elem.contentDocument || elem.contentWindow.document :
+			jQuery.merge( [], elem.childNodes );
+	}
+}, function( name, fn ) {
+	jQuery.fn[ name ] = function( until, selector ) {
+		var ret = jQuery.map( this, fn, until );
+
+		if ( name.slice( -5 ) !== "Until" ) {
+			selector = until;
+		}
+
+		if ( selector && typeof selector === "string" ) {
+			ret = jQuery.filter( selector, ret );
+		}
+
+		if ( this.length > 1 ) {
+			// Remove duplicates
+			if ( !guaranteedUnique[ name ] ) {
+				ret = jQuery.unique( ret );
+			}
+
+			// Reverse order for parents* and prev-derivatives
+			if ( rparentsprev.test( name ) ) {
+				ret = ret.reverse();
+			}
+		}
+
+		return this.pushStack( ret );
+	};
+});
+var rnotwhite = (/\S+/g);
+
+
+
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+	var object = optionsCache[ options ] = {};
+	jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+		object[ flag ] = true;
+	});
+	return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ *	options: an optional list of space-separated options that will change how
+ *			the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ *	once:			will ensure the callback list can only be fired once (like a Deferred)
+ *
+ *	memory:			will keep track of previous values and will call any callback added
+ *					after the list has been fired right away with the latest "memorized"
+ *					values (like a Deferred)
+ *
+ *	unique:			will ensure a callback can only be added once (no duplicate in the list)
+ *
+ *	stopOnFalse:	interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+	// Convert options from String-formatted to Object-formatted if needed
+	// (we check in cache first)
+	options = typeof options === "string" ?
+		( optionsCache[ options ] || createOptions( options ) ) :
+		jQuery.extend( {}, options );
+
+	var // Flag to know if list is currently firing
+		firing,
+		// Last fire value (for non-forgettable lists)
+		memory,
+		// Flag to know if list was already fired
+		fired,
+		// End of the loop when firing
+		firingLength,
+		// Index of currently firing callback (modified by remove if needed)
+		firingIndex,
+		// First callback to fire (used internally by add and fireWith)
+		firingStart,
+		// Actual callback list
+		list = [],
+		// Stack of fire calls for repeatable lists
+		stack = !options.once && [],
+		// Fire callbacks
+		fire = function( data ) {
+			memory = options.memory && data;
+			fired = true;
+			firingIndex = firingStart || 0;
+			firingStart = 0;
+			firingLength = list.length;
+			firing = true;
+			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+					memory = false; // To prevent further calls using add
+					break;
+				}
+			}
+			firing = false;
+			if ( list ) {
+				if ( stack ) {
+					if ( stack.length ) {
+						fire( stack.shift() );
+					}
+				} else if ( memory ) {
+					list = [];
+				} else {
+					self.disable();
+				}
+			}
+		},
+		// Actual Callbacks object
+		self = {
+			// Add a callback or a collection of callbacks to the list
+			add: function() {
+				if ( list ) {
+					// First, we save the current length
+					var start = list.length;
+					(function add( args ) {
+						jQuery.each( args, function( _, arg ) {
+							var type = jQuery.type( arg );
+							if ( type === "function" ) {
+								if ( !options.unique || !self.has( arg ) ) {
+									list.push( arg );
+								}
+							} else if ( arg && arg.length && type !== "string" ) {
+								// Inspect recursively
+								add( arg );
+							}
+						});
+					})( arguments );
+					// Do we need to add the callbacks to the
+					// current firing batch?
+					if ( firing ) {
+						firingLength = list.length;
+					// With memory, if we're not firing then
+					// we should call right away
+					} else if ( memory ) {
+						firingStart = start;
+						fire( memory );
+					}
+				}
+				return this;
+			},
+			// Remove a callback from the list
+			remove: function() {
+				if ( list ) {
+					jQuery.each( arguments, function( _, arg ) {
+						var index;
+						while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+							list.splice( index, 1 );
+							// Handle firing indexes
+							if ( firing ) {
+								if ( index <= firingLength ) {
+									firingLength--;
+								}
+								if ( index <= firingIndex ) {
+									firingIndex--;
+								}
+							}
+						}
+					});
+				}
+				return this;
+			},
+			// Check if a given callback is in the list.
+			// If no argument is given, return whether or not list has callbacks attached.
+			has: function( fn ) {
+				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+			},
+			// Remove all callbacks from the list
+			empty: function() {
+				list = [];
+				firingLength = 0;
+				return this;
+			},
+			// Have the list do nothing anymore
+			disable: function() {
+				list = stack = memory = undefined;
+				return this;
+			},
+			// Is it disabled?
+			disabled: function() {
+				return !list;
+			},
+			// Lock the list in its current state
+			lock: function() {
+				stack = undefined;
+				if ( !memory ) {
+					self.disable();
+				}
+				return this;
+			},
+			// Is it locked?
+			locked: function() {
+				return !stack;
+			},
+			// Call all callbacks with the given context and arguments
+			fireWith: function( context, args ) {
+				if ( list && ( !fired || stack ) ) {
+					args = args || [];
+					args = [ context, args.slice ? args.slice() : args ];
+					if ( firing ) {
+						stack.push( args );
+					} else {
+						fire( args );
+					}
+				}
+				return this;
+			},
+			// Call all the callbacks with the given arguments
+			fire: function() {
+				self.fireWith( this, arguments );
+				return this;
+			},
+			// To know if the callbacks have already been called at least once
+			fired: function() {
+				return !!fired;
+			}
+		};
+
+	return self;
+};
+
+
+jQuery.extend({
+
+	Deferred: function( func ) {
+		var tuples = [
+				// action, add listener, listener list, final state
+				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+				[ "notify", "progress", jQuery.Callbacks("memory") ]
+			],
+			state = "pending",
+			promise = {
+				state: function() {
+					return state;
+				},
+				always: function() {
+					deferred.done( arguments ).fail( arguments );
+					return this;
+				},
+				then: function( /* fnDone, fnFail, fnProgress */ ) {
+					var fns = arguments;
+					return jQuery.Deferred(function( newDefer ) {
+						jQuery.each( tuples, function( i, tuple ) {
+							var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+							// deferred[ done | fail | progress ] for forwarding actions to newDefer
+							deferred[ tuple[1] ](function() {
+								var returned = fn && fn.apply( this, arguments );
+								if ( returned && jQuery.isFunction( returned.promise ) ) {
+									returned.promise()
+										.done( newDefer.resolve )
+										.fail( newDefer.reject )
+										.progress( newDefer.notify );
+								} else {
+									newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+								}
+							});
+						});
+						fns = null;
+					}).promise();
+				},
+				// Get a promise for this deferred
+				// If obj is provided, the promise aspect is added to the object
+				promise: function( obj ) {
+					return obj != null ? jQuery.extend( obj, promise ) : promise;
+				}
+			},
+			deferred = {};
+
+		// Keep pipe for back-compat
+		promise.pipe = promise.then;
+
+		// Add list-specific methods
+		jQuery.each( tuples, function( i, tuple ) {
+			var list = tuple[ 2 ],
+				stateString = tuple[ 3 ];
+
+			// promise[ done | fail | progress ] = list.add
+			promise[ tuple[1] ] = list.add;
+
+			// Handle state
+			if ( stateString ) {
+				list.add(function() {
+					// state = [ resolved | rejected ]
+					state = stateString;
+
+				// [ reject_list | resolve_list ].disable; progress_list.lock
+				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+			}
+
+			// deferred[ resolve | reject | notify ]
+			deferred[ tuple[0] ] = function() {
+				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+				return this;
+			};
+			deferred[ tuple[0] + "With" ] = list.fireWith;
+		});
+
+		// Make the deferred a promise
+		promise.promise( deferred );
+
+		// Call given func if any
+		if ( func ) {
+			func.call( deferred, deferred );
+		}
+
+		// All done!
+		return deferred;
+	},
+
+	// Deferred helper
+	when: function( subordinate /* , ..., subordinateN */ ) {
+		var i = 0,
+			resolveValues = slice.call( arguments ),
+			length = resolveValues.length,
+
+			// the count of uncompleted subordinates
+			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+			// Update function for both resolve and progress values
+			updateFunc = function( i, contexts, values ) {
+				return function( value ) {
+					contexts[ i ] = this;
+					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+					if ( values === progressValues ) {
+						deferred.notifyWith( contexts, values );
+
+					} else if ( !(--remaining) ) {
+						deferred.resolveWith( contexts, values );
+					}
+				};
+			},
+
+			progressValues, progressContexts, resolveContexts;
+
+		// add listeners to Deferred subordinates; treat others as resolved
+		if ( length > 1 ) {
+			progressValues = new Array( length );
+			progressContexts = new Array( length );
+			resolveContexts = new Array( length );
+			for ( ; i < length; i++ ) {
+				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+					resolveValues[ i ].promise()
+						.done( updateFunc( i, resolveContexts, resolveValues ) )
+						.fail( deferred.reject )
+						.progress( updateFunc( i, progressContexts, progressValues ) );
+				} else {
+					--remaining;
+				}
+			}
+		}
+
+		// if we're not waiting on anything, resolve the master
+		if ( !remaining ) {
+			deferred.resolveWith( resolveContexts, resolveValues );
+		}
+
+		return deferred.promise();
+	}
+});
+
+
+// The deferred used on DOM ready
+var readyList;
+
+jQuery.fn.ready = function( fn ) {
+	// Add the callback
+	jQuery.ready.promise().done( fn );
+
+	return this;
+};
+
+jQuery.extend({
+	// Is the DOM ready to be used? Set to true once it occurs.
+	isReady: false,
+
+	// A counter to track how many items to wait for before
+	// the ready event fires. See #6781
+	readyWait: 1,
+
+	// Hold (or release) the ready event
+	holdReady: function( hold ) {
+		if ( hold ) {
+			jQuery.readyWait++;
+		} else {
+			jQuery.ready( true );
+		}
+	},
+
+	// Handle when the DOM is ready
+	ready: function( wait ) {
+
+		// Abort if there are pending holds or we're already ready
+		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+			return;
+		}
+
+		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+		if ( !document.body ) {
+			return setTimeout( jQuery.ready );
+		}
+
+		// Remember that the DOM is ready
+		jQuery.isReady = true;
+
+		// If a normal DOM Ready event fired, decrement, and wait if need be
+		if ( wait !== true && --jQuery.readyWait > 0 ) {
+			return;
+		}
+
+		// If there are functions bound, to execute
+		readyList.resolveWith( document, [ jQuery ] );
+
+		// Trigger any bound ready events
+		if ( jQuery.fn.triggerHandler ) {
+			jQuery( document ).triggerHandler( "ready" );
+			jQuery( document ).off( "ready" );
+		}
+	}
+});
+
+/**
+ * Clean-up method for dom ready events
+ */
+function detach() {
+	if ( document.addEventListener ) {
+		document.removeEventListener( "DOMContentLoaded", completed, false );
+		window.removeEventListener( "load", completed, false );
+
+	} else {
+		document.detachEvent( "onreadystatechange", completed );
+		window.detachEvent( "onload", completed );
+	}
+}
+
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+	// readyState === "complete" is good enough for us to call the dom ready in oldIE
+	if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
+		detach();
+		jQuery.ready();
+	}
+}
+
+jQuery.ready.promise = function( obj ) {
+	if ( !readyList ) {
+
+		readyList = jQuery.Deferred();
+
+		// Catch cases where $(document).ready() is called after the browser event has already occurred.
+		// we once tried to use readyState "interactive" here, but it caused issues like the one
+		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+		if ( document.readyState === "complete" ) {
+			// Handle it asynchronously to allow scripts the opportunity to delay ready
+			setTimeout( jQuery.ready );
+
+		// Standards-based browsers support DOMContentLoaded
+		} else if ( document.addEventListener ) {
+			// Use the handy event callback
+			document.addEventListener( "DOMContentLoaded", completed, false );
+
+			// A fallback to window.onload, that will always work
+			window.addEventListener( "load", completed, false );
+
+		// If IE event model is used
+		} else {
+			// Ensure firing before onload, maybe late but safe also for iframes
+			document.attachEvent( "onreadystatechange", completed );
+
+			// A fallback to window.onload, that will always work
+			window.attachEvent( "onload", completed );
+
+			// If IE and not a frame
+			// continually check to see if the document is ready
+			var top = false;
+
+			try {
+				top = window.frameElement == null && document.documentElement;
+			} catch(e) {}
+
+			if ( top && top.doScroll ) {
+				(function doScrollCheck() {
+					if ( !jQuery.isReady ) {
+
+						try {
+							// Use the trick by Diego Perini
+							// http://javascript.nwbox.com/IEContentLoaded/
+							top.doScroll("left");
+						} catch(e) {
+							return setTimeout( doScrollCheck, 50 );
+						}
+
+						// detach all dom ready events
+						detach();
+
+						// and execute any waiting functions
+						jQuery.ready();
+					}
+				})();
+			}
+		}
+	}
+	return readyList.promise( obj );
+};
+
+
+var strundefined = typeof undefined;
+
+
+
+// Support: IE<9
+// Iteration over object's inherited properties before its own
+var i;
+for ( i in jQuery( support ) ) {
+	break;
+}
+support.ownLast = i !== "0";
+
+// Note: most support tests are defined in their respective modules.
+// false until the test is run
+support.inlineBlockNeedsLayout = false;
+
+// Execute ASAP in case we need to set body.style.zoom
+jQuery(function() {
+	// Minified: var a,b,c,d
+	var val, div, body, container;
+
+	body = document.getElementsByTagName( "body" )[ 0 ];
+	if ( !body || !body.style ) {
+		// Return for frameset docs that don't have a body
+		return;
+	}
+
+	// Setup
+	div = document.createElement( "div" );
+	container = document.createElement( "div" );
+	container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+	body.appendChild( container ).appendChild( div );
+
+	if ( typeof div.style.zoom !== strundefined ) {
+		// Support: IE<8
+		// Check if natively block-level elements act like inline-block
+		// elements when setting their display to 'inline' and giving
+		// them layout
+		div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
+
+		support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
+		if ( val ) {
+			// Prevent IE 6 from affecting layout for positioned elements #11048
+			// Prevent IE from shrinking the body in IE 7 mode #12869
+			// Support: IE<8
+			body.style.zoom = 1;
+		}
+	}
+
+	body.removeChild( container );
+});
+
+
+
+
+(function() {
+	var div = document.createElement( "div" );
+
+	// Execute the test only if not already executed in another module.
+	if (support.deleteExpando == null) {
+		// Support: IE<9
+		support.deleteExpando = true;
+		try {
+			delete div.test;
+		} catch( e ) {
+			support.deleteExpando = false;
+		}
+	}
+
+	// Null elements to avoid leaks in IE.
+	div = null;
+})();
+
+
+/**
+ * Determines whether an object can have data
+ */
+jQuery.acceptData = function( elem ) {
+	var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
+		nodeType = +elem.nodeType || 1;
+
+	// Do not set data on non-element DOM nodes because it will not be cleared (#8335).
+	return nodeType !== 1 && nodeType !== 9 ?
+		false :
+
+		// Nodes accept data unless otherwise specified; rejection can be conditional
+		!noData || noData !== true && elem.getAttribute("classid") === noData;
+};
+
+
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+	rmultiDash = /([A-Z])/g;
+
+function dataAttr( elem, key, data ) {
+	// If nothing was found internally, try to fetch any
+	// data from the HTML5 data-* attribute
+	if ( data === undefined && elem.nodeType === 1 ) {
+
+		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+		data = elem.getAttribute( name );
+
+		if ( typeof data === "string" ) {
+			try {
+				data = data === "true" ? true :
+					data === "false" ? false :
+					data === "null" ? null :
+					// Only convert to a number if it doesn't change the string
+					+data + "" === data ? +data :
+					rbrace.test( data ) ? jQuery.parseJSON( data ) :
+					data;
+			} catch( e ) {}
+
+			// Make sure we set the data so it isn't changed later
+			jQuery.data( elem, key, data );
+
+		} else {
+			data = undefined;
+		}
+	}
+
+	return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+	var name;
+	for ( name in obj ) {
+
+		// if the public data object is empty, the private is still empty
+		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+			continue;
+		}
+		if ( name !== "toJSON" ) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
+	if ( !jQuery.acceptData( elem ) ) {
+		return;
+	}
+
+	var ret, thisCache,
+		internalKey = jQuery.expando,
+
+		// We have to handle DOM nodes and JS objects differently because IE6-7
+		// can't GC object references properly across the DOM-JS boundary
+		isNode = elem.nodeType,
+
+		// Only DOM nodes need the global jQuery cache; JS object data is
+		// attached directly to the object so GC can occur automatically
+		cache = isNode ? jQuery.cache : elem,
+
+		// Only defining an ID for JS objects if its cache already exists allows
+		// the code to shortcut on the same path as a DOM node with no cache
+		id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+	// Avoid doing any more work than we need to when trying to get data on an
+	// object that has no data at all
+	if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
+		return;
+	}
+
+	if ( !id ) {
+		// Only DOM nodes need a new unique ID for each element since their data
+		// ends up in the global cache
+		if ( isNode ) {
+			id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
+		} else {
+			id = internalKey;
+		}
+	}
+
+	if ( !cache[ id ] ) {
+		// Avoid exposing jQuery metadata on plain JS objects when the object
+		// is serialized using JSON.stringify
+		cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
+	}
+
+	// An object can be passed to jQuery.data instead of a key/value pair; this gets
+	// shallow copied over onto the existing cache
+	if ( typeof name === "object" || typeof name === "function" ) {
+		if ( pvt ) {
+			cache[ id ] = jQuery.extend( cache[ id ], name );
+		} else {
+			cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+		}
+	}
+
+	thisCache = cache[ id ];
+
+	// jQuery data() is stored in a separate object inside the object's internal data
+	// cache in order to avoid key collisions between internal data and user-defined
+	// data.
+	if ( !pvt ) {
+		if ( !thisCache.data ) {
+			thisCache.data = {};
+		}
+
+		thisCache = thisCache.data;
+	}
+
+	if ( data !== undefined ) {
+		thisCache[ jQuery.camelCase( name ) ] = data;
+	}
+
+	// Check for both converted-to-camel and non-converted data property names
+	// If a data property was specified
+	if ( typeof name === "string" ) {
+
+		// First Try to find as-is property data
+		ret = thisCache[ name ];
+
+		// Test for null|undefined property data
+		if ( ret == null ) {
+
+			// Try to find the camelCased property
+			ret = thisCache[ jQuery.camelCase( name ) ];
+		}
+	} else {
+		ret = thisCache;
+	}
+
+	return ret;
+}
+
+function internalRemoveData( elem, name, pvt ) {
+	if ( !jQuery.acceptData( elem ) ) {
+		return;
+	}
+
+	var thisCache, i,
+		isNode = elem.nodeType,
+
+		// See jQuery.data for more information
+		cache = isNode ? jQuery.cache : elem,
+		id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+	// If there is already no cache entry for this object, there is no
+	// purpose in continuing
+	if ( !cache[ id ] ) {
+		return;
+	}
+
+	if ( name ) {
+
+		thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+		if ( thisCache ) {
+
+			// Support array or space separated string names for data keys
+			if ( !jQuery.isArray( name ) ) {
+
+				// try the string as a key before any manipulation
+				if ( name in thisCache ) {
+					name = [ name ];
+				} else {
+
+					// split the camel cased version by spaces unless a key with the spaces exists
+					name = jQuery.camelCase( name );
+					if ( name in thisCache ) {
+						name = [ name ];
+					} else {
+						name = name.split(" ");
+					}
+				}
+			} else {
+				// If "name" is an array of keys...
+				// When data is initially created, via ("key", "val") signature,
+				// keys will be converted to camelCase.
+				// Since there is no way to tell _how_ a key was added, remove
+				// both plain key and camelCase key. #12786
+				// This will only penalize the array argument path.
+				name = name.concat( jQuery.map( name, jQuery.camelCase ) );
+			}
+
+			i = name.length;
+			while ( i-- ) {
+				delete thisCache[ name[i] ];
+			}
+
+			// If there is no data left in the cache, we want to continue
+			// and let the cache object itself get destroyed
+			if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
+				return;
+			}
+		}
+	}
+
+	// See jQuery.data for more information
+	if ( !pvt ) {
+		delete cache[ id ].data;
+
+		// Don't destroy the parent cache unless the internal data object
+		// had been the only thing left in it
+		if ( !isEmptyDataObject( cache[ id ] ) ) {
+			return;
+		}
+	}
+
+	// Destroy the cache
+	if ( isNode ) {
+		jQuery.cleanData( [ elem ], true );
+
+	// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+	/* jshint eqeqeq: false */
+	} else if ( support.deleteExpando || cache != cache.window ) {
+		/* jshint eqeqeq: true */
+		delete cache[ id ];
+
+	// When all else fails, null
+	} else {
+		cache[ id ] = null;
+	}
+}
+
+jQuery.extend({
+	cache: {},
+
+	// The following elements (space-suffixed to avoid Object.prototype collisions)
+	// throw uncatchable exceptions if you attempt to set expando properties
+	noData: {
+		"applet ": true,
+		"embed ": true,
+		// ...but Flash objects (which have this classid) *can* handle expandos
+		"object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
+	},
+
+	hasData: function( elem ) {
+		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+		return !!elem && !isEmptyDataObject( elem );
+	},
+
+	data: function( elem, name, data ) {
+		return internalData( elem, name, data );
+	},
+
+	removeData: function( elem, name ) {
+		return internalRemoveData( elem, name );
+	},
+
+	// For internal use only.
+	_data: function( elem, name, data ) {
+		return internalData( elem, name, data, true );
+	},
+
+	_removeData: function( elem, name ) {
+		return internalRemoveData( elem, name, true );
+	}
+});
+
+jQuery.fn.extend({
+	data: function( key, value ) {
+		var i, name, data,
+			elem = this[0],
+			attrs = elem && elem.attributes;
+
+		// Special expections of .data basically thwart jQuery.access,
+		// so implement the relevant behavior ourselves
+
+		// Gets all values
+		if ( key === undefined ) {
+			if ( this.length ) {
+				data = jQuery.data( elem );
+
+				if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+					i = attrs.length;
+					while ( i-- ) {
+
+						// Support: IE11+
+						// The attrs elements can be null (#14894)
+						if ( attrs[ i ] ) {
+							name = attrs[ i ].name;
+							if ( name.indexOf( "data-" ) === 0 ) {
+								name = jQuery.camelCase( name.slice(5) );
+								dataAttr( elem, name, data[ name ] );
+							}
+						}
+					}
+					jQuery._data( elem, "parsedAttrs", true );
+				}
+			}
+
+			return data;
+		}
+
+		// Sets multiple values
+		if ( typeof key === "object" ) {
+			return this.each(function() {
+				jQuery.data( this, key );
+			});
+		}
+
+		return arguments.length > 1 ?
+
+			// Sets one value
+			this.each(function() {
+				jQuery.data( this, key, value );
+			}) :
+
+			// Gets one value
+			// Try to fetch any internally stored data first
+			elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
+	},
+
+	removeData: function( key ) {
+		return this.each(function() {
+			jQuery.removeData( this, key );
+		});
+	}
+});
+
+
+jQuery.extend({
+	queue: function( elem, type, data ) {
+		var queue;
+
+		if ( elem ) {
+			type = ( type || "fx" ) + "queue";
+			queue = jQuery._data( elem, type );
+
+			// Speed up dequeue by getting out quickly if this is just a lookup
+			if ( data ) {
+				if ( !queue || jQuery.isArray(data) ) {
+					queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+				} else {
+					queue.push( data );
+				}
+			}
+			return queue || [];
+		}
+	},
+
+	dequeue: function( elem, type ) {
+		type = type || "fx";
+
+		var queue = jQuery.queue( elem, type ),
+			startLength = queue.length,
+			fn = queue.shift(),
+			hooks = jQuery._queueHooks( elem, type ),
+			next = function() {
+				jQuery.dequeue( elem, type );
+			};
+
+		// If the fx queue is dequeued, always remove the progress sentinel
+		if ( fn === "inprogress" ) {
+			fn = queue.shift();
+			startLength--;
+		}
+
+		if ( fn ) {
+
+			// Add a progress sentinel to prevent the fx queue from being
+			// automatically dequeued
+			if ( type === "fx" ) {
+				queue.unshift( "inprogress" );
+			}
+
+			// clear up the last queue stop function
+			delete hooks.stop;
+			fn.call( elem, next, hooks );
+		}
+
+		if ( !startLength && hooks ) {
+			hooks.empty.fire();
+		}
+	},
+
+	// not intended for public consumption - generates a queueHooks object, or returns the current one
+	_queueHooks: function( elem, type ) {
+		var key = type + "queueHooks";
+		return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+			empty: jQuery.Callbacks("once memory").add(function() {
+				jQuery._removeData( elem, type + "queue" );
+				jQuery._removeData( elem, key );
+			})
+		});
+	}
+});
+
+jQuery.fn.extend({
+	queue: function( type, data ) {
+		var setter = 2;
+
+		if ( typeof type !== "string" ) {
+			data = type;
+			type = "fx";
+			setter--;
+		}
+
+		if ( arguments.length < setter ) {
+			return jQuery.queue( this[0], type );
+		}
+
+		return data === undefined ?
+			this :
+			this.each(function() {
+				var queue = jQuery.queue( this, type, data );
+
+				// ensure a hooks for this queue
+				jQuery._queueHooks( this, type );
+
+				if ( type === "fx" && queue[0] !== "inprogress" ) {
+					jQuery.dequeue( this, type );
+				}
+			});
+	},
+	dequeue: function( type ) {
+		return this.each(function() {
+			jQuery.dequeue( this, type );
+		});
+	},
+	clearQueue: function( type ) {
+		return this.queue( type || "fx", [] );
+	},
+	// Get a promise resolved when queues of a certain type
+	// are emptied (fx is the type by default)
+	promise: function( type, obj ) {
+		var tmp,
+			count = 1,
+			defer = jQuery.Deferred(),
+			elements = this,
+			i = this.length,
+			resolve = function() {
+				if ( !( --count ) ) {
+					defer.resolveWith( elements, [ elements ] );
+				}
+			};
+
+		if ( typeof type !== "string" ) {
+			obj = type;
+			type = undefined;
+		}
+		type = type || "fx";
+
+		while ( i-- ) {
+			tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+			if ( tmp && tmp.empty ) {
+				count++;
+				tmp.empty.add( resolve );
+			}
+		}
+		resolve();
+		return defer.promise( obj );
+	}
+});
+var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
+
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+var isHidden = function( elem, el ) {
+		// isHidden might be called from jQuery#filter function;
+		// in that case, element will be second argument
+		elem = el || elem;
+		return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+	};
+
+
+
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+	var i = 0,
+		length = elems.length,
+		bulk = key == null;
+
+	// Sets many values
+	if ( jQuery.type( key ) === "object" ) {
+		chainable = true;
+		for ( i in key ) {
+			jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+		}
+
+	// Sets one value
+	} else if ( value !== undefined ) {
+		chainable = true;
+
+		if ( !jQuery.isFunction( value ) ) {
+			raw = true;
+		}
+
+		if ( bulk ) {
+			// Bulk operations run against the entire set
+			if ( raw ) {
+				fn.call( elems, value );
+				fn = null;
+
+			// ...except when executing function values
+			} else {
+				bulk = fn;
+				fn = function( elem, key, value ) {
+					return bulk.call( jQuery( elem ), value );
+				};
+			}
+		}
+
+		if ( fn ) {
+			for ( ; i < length; i++ ) {
+				fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+			}
+		}
+	}
+
+	return chainable ?
+		elems :
+
+		// Gets
+		bulk ?
+			fn.call( elems ) :
+			length ? fn( elems[0], key ) : emptyGet;
+};
+var rcheckableType = (/^(?:checkbox|radio)$/i);
+
+
+
+(function() {
+	// Minified: var a,b,c
+	var input = document.createElement( "input" ),
+		div = document.createElement( "div" ),
+		fragment = document.createDocumentFragment();
+
+	// Setup
+	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+
+	// IE strips leading whitespace when .innerHTML is used
+	support.leadingWhitespace = div.firstChild.nodeType === 3;
+
+	// Make sure that tbody elements aren't automatically inserted
+	// IE will insert them into empty tables
+	support.tbody = !div.getElementsByTagName( "tbody" ).length;
+
+	// Make sure that link elements get serialized correctly by innerHTML
+	// This requires a wrapper element in IE
+	support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
+
+	// Makes sure cloning an html5 element does not cause problems
+	// Where outerHTML is undefined, this still works
+	support.html5Clone =
+		document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
+
+	// Check if a disconnected checkbox will retain its checked
+	// value of true after appended to the DOM (IE6/7)
+	input.type = "checkbox";
+	input.checked = true;
+	fragment.appendChild( input );
+	support.appendChecked = input.checked;
+
+	// Make sure textarea (and checkbox) defaultValue is properly cloned
+	// Support: IE6-IE11+
+	div.innerHTML = "<textarea>x</textarea>";
+	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+
+	// #11217 - WebKit loses check when the name is after the checked attribute
+	fragment.appendChild( div );
+	div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
+
+	// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
+	// old WebKit doesn't clone checked state correctly in fragments
+	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+	// Support: IE<9
+	// Opera does not clone events (and typeof div.attachEvent === undefined).
+	// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
+	support.noCloneEvent = true;
+	if ( div.attachEvent ) {
+		div.attachEvent( "onclick", function() {
+			support.noCloneEvent = false;
+		});
+
+		div.cloneNode( true ).click();
+	}
+
+	// Execute the test only if not already executed in another module.
+	if (support.deleteExpando == null) {
+		// Support: IE<9
+		support.deleteExpando = true;
+		try {
+			delete div.test;
+		} catch( e ) {
+			support.deleteExpando = false;
+		}
+	}
+})();
+
+
+(function() {
+	var i, eventName,
+		div = document.createElement( "div" );
+
+	// Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
+	for ( i in { submit: true, change: true, focusin: true }) {
+		eventName = "on" + i;
+
+		if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
+			// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
+			div.setAttribute( eventName, "t" );
+			support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
+		}
+	}
+
+	// Null elements to avoid leaks in IE.
+	div = null;
+})();
+
+
+var rformElems = /^(?:input|select|textarea)$/i,
+	rkeyEvent = /^key/,
+	rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
+	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+
+function returnTrue() {
+	return true;
+}
+
+function returnFalse() {
+	return false;
+}
+
+function safeActiveElement() {
+	try {
+		return document.activeElement;
+	} catch ( err ) { }
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+	global: {},
+
+	add: function( elem, types, handler, data, selector ) {
+		var tmp, events, t, handleObjIn,
+			special, eventHandle, handleObj,
+			handlers, type, namespaces, origType,
+			elemData = jQuery._data( elem );
+
+		// Don't attach events to noData or text/comment nodes (but allow plain objects)
+		if ( !elemData ) {
+			return;
+		}
+
+		// Caller can pass in an object of custom data in lieu of the handler
+		if ( handler.handler ) {
+			handleObjIn = handler;
+			handler = handleObjIn.handler;
+			selector = handleObjIn.selector;
+		}
+
+		// Make sure that the handler has a unique ID, used to find/remove it later
+		if ( !handler.guid ) {
+			handler.guid = jQuery.guid++;
+		}
+
+		// Init the element's event structure and main handler, if this is the first
+		if ( !(events = elemData.events) ) {
+			events = elemData.events = {};
+		}
+		if ( !(eventHandle = elemData.handle) ) {
+			eventHandle = elemData.handle = function( e ) {
+				// Discard the second event of a jQuery.event.trigger() and
+				// when an event is called after a page has unloaded
+				return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
+					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+					undefined;
+			};
+			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+			eventHandle.elem = elem;
+		}
+
+		// Handle multiple events separated by a space
+		types = ( types || "" ).match( rnotwhite ) || [ "" ];
+		t = types.length;
+		while ( t-- ) {
+			tmp = rtypenamespace.exec( types[t] ) || [];
+			type = origType = tmp[1];
+			namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+			// There *must* be a type, no attaching namespace-only handlers
+			if ( !type ) {
+				continue;
+			}
+
+			// If event changes its type, use the special event handlers for the changed type
+			special = jQuery.event.special[ type ] || {};
+
+			// If selector defined, determine special event api type, otherwise given type
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+
+			// Update special based on newly reset type
+			special = jQuery.event.special[ type ] || {};
+
+			// handleObj is passed to all event handlers
+			handleObj = jQuery.extend({
+				type: type,
+				origType: origType,
+				data: data,
+				handler: handler,
+				guid: handler.guid,
+				selector: selector,
+				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+				namespace: namespaces.join(".")
+			}, handleObjIn );
+
+			// Init the event handler queue if we're the first
+			if ( !(handlers = events[ type ]) ) {
+				handlers = events[ type ] = [];
+				handlers.delegateCount = 0;
+
+				// Only use addEventListener/attachEvent if the special events handler returns false
+				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+					// Bind the global event handler to the element
+					if ( elem.addEventListener ) {
+						elem.addEventListener( type, eventHandle, false );
+
+					} else if ( elem.attachEvent ) {
+						elem.attachEvent( "on" + type, eventHandle );
+					}
+				}
+			}
+
+			if ( special.add ) {
+				special.add.call( elem, handleObj );
+
+				if ( !handleObj.handler.guid ) {
+					handleObj.handler.guid = handler.guid;
+				}
+			}
+
+			// Add to the element's handler list, delegates in front
+			if ( selector ) {
+				handlers.splice( handlers.delegateCount++, 0, handleObj );
+			} else {
+				handlers.push( handleObj );
+			}
+
+			// Keep track of which events have ever been used, for event optimization
+			jQuery.event.global[ type ] = true;
+		}
+
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	// Detach an event or set of events from an element
+	remove: function( elem, types, handler, selector, mappedTypes ) {
+		var j, handleObj, tmp,
+			origCount, t, events,
+			special, handlers, type,
+			namespaces, origType,
+			elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+		if ( !elemData || !(events = elemData.events) ) {
+			return;
+		}
+
+		// Once for each type.namespace in types; type may be omitted
+		types = ( types || "" ).match( rnotwhite ) || [ "" ];
+		t = types.length;
+		while ( t-- ) {
+			tmp = rtypenamespace.exec( types[t] ) || [];
+			type = origType = tmp[1];
+			namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+			// Unbind all events (on this namespace, if provided) for the element
+			if ( !type ) {
+				for ( type in events ) {
+					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+				}
+				continue;
+			}
+
+			special = jQuery.event.special[ type ] || {};
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+			handlers = events[ type ] || [];
+			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+			// Remove matching events
+			origCount = j = handlers.length;
+			while ( j-- ) {
+				handleObj = handlers[ j ];
+
+				if ( ( mappedTypes || origType === handleObj.origType ) &&
+					( !handler || handler.guid === handleObj.guid ) &&
+					( !tmp || tmp.test( handleObj.namespace ) ) &&
+					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+					handlers.splice( j, 1 );
+
+					if ( handleObj.selector ) {
+						handlers.delegateCount--;
+					}
+					if ( special.remove ) {
+						special.remove.call( elem, handleObj );
+					}
+				}
+			}
+
+			// Remove generic event handler if we removed something and no more handlers exist
+			// (avoids potential for endless recursion during removal of special event handlers)
+			if ( origCount && !handlers.length ) {
+				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+					jQuery.removeEvent( elem, type, elemData.handle );
+				}
+
+				delete events[ type ];
+			}
+		}
+
+		// Remove the expando if it's no longer used
+		if ( jQuery.isEmptyObject( events ) ) {
+			delete elemData.handle;
+
+			// removeData also checks for emptiness and clears the expando if empty
+			// so use it instead of delete
+			jQuery._removeData( elem, "events" );
+		}
+	},
+
+	trigger: function( event, data, elem, onlyHandlers ) {
+		var handle, ontype, cur,
+			bubbleType, special, tmp, i,
+			eventPath = [ elem || document ],
+			type = hasOwn.call( event, "type" ) ? event.type : event,
+			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
+
+		cur = tmp = elem = elem || document;
+
+		// Don't do events on text and comment nodes
+		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return;
+		}
+
+		// focus/blur morphs to focusin/out; ensure we're not firing them right now
+		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+			return;
+		}
+
+		if ( type.indexOf(".") >= 0 ) {
+			// Namespaced trigger; create a regexp to match event type in handle()
+			namespaces = type.split(".");
+			type = namespaces.shift();
+			namespaces.sort();
+		}
+		ontype = type.indexOf(":") < 0 && "on" + type;
+
+		// Caller can pass in a jQuery.Event object, Object, or just an event type string
+		event = event[ jQuery.expando ] ?
+			event :
+			new jQuery.Event( type, typeof event === "object" && event );
+
+		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+		event.isTrigger = onlyHandlers ? 2 : 3;
+		event.namespace = namespaces.join(".");
+		event.namespace_re = event.namespace ?
+			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+			null;
+
+		// Clean up the event in case it is being reused
+		event.result = undefined;
+		if ( !event.target ) {
+			event.target = elem;
+		}
+
+		// Clone any incoming data and prepend the event, creating the handler arg list
+		data = data == null ?
+			[ event ] :
+			jQuery.makeArray( data, [ event ] );
+
+		// Allow special events to draw outside the lines
+		special = jQuery.event.special[ type ] || {};
+		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+			return;
+		}
+
+		// Determine event propagation path in advance, per W3C events spec (#9951)
+		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+			bubbleType = special.delegateType || type;
+			if ( !rfocusMorph.test( bubbleType + type ) ) {
+				cur = cur.parentNode;
+			}
+			for ( ; cur; cur = cur.parentNode ) {
+				eventPath.push( cur );
+				tmp = cur;
+			}
+
+			// Only add window if we got to document (e.g., not plain obj or detached DOM)
+			if ( tmp === (elem.ownerDocument || document) ) {
+				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+			}
+		}
+
+		// Fire handlers on the event path
+		i = 0;
+		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
+
+			event.type = i > 1 ?
+				bubbleType :
+				special.bindType || type;
+
+			// jQuery handler
+			handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+			if ( handle ) {
+				handle.apply( cur, data );
+			}
+
+			// Native handler
+			handle = ontype && cur[ ontype ];
+			if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
+				event.result = handle.apply( cur, data );
+				if ( event.result === false ) {
+					event.preventDefault();
+				}
+			}
+		}
+		event.type = type;
+
+		// If nobody prevented the default action, do it now
+		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+			if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
+				jQuery.acceptData( elem ) ) {
+
+				// Call a native DOM method on the target with the same name name as the event.
+				// Can't use an .isFunction() check here because IE6/7 fails that test.
+				// Don't do default actions on window, that's where global variables be (#6170)
+				if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
+
+					// Don't re-trigger an onFOO event when we call its FOO() method
+					tmp = elem[ ontype ];
+
+					if ( tmp ) {
+						elem[ ontype ] = null;
+					}
+
+					// Prevent re-triggering of the same event, since we already bubbled it above
+					jQuery.event.triggered = type;
+					try {
+						elem[ type ]();
+					} catch ( e ) {
+						// IE<9 dies on focus/blur to hidden element (#1486,#12518)
+						// only reproducible on winXP IE8 native, not IE9 in IE8 mode
+					}
+					jQuery.event.triggered = undefined;
+
+					if ( tmp ) {
+						elem[ ontype ] = tmp;
+					}
+				}
+			}
+		}
+
+		return event.result;
+	},
+
+	dispatch: function( event ) {
+
+		// Make a writable jQuery.Event from the native event object
+		event = jQuery.event.fix( event );
+
+		var i, ret, handleObj, matched, j,
+			handlerQueue = [],
+			args = slice.call( arguments ),
+			handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
+			special = jQuery.event.special[ event.type ] || {};
+
+		// Use the fix-ed jQuery.Event rather than the (read-only) native event
+		args[0] = event;
+		event.delegateTarget = this;
+
+		// Call the preDispatch hook for the mapped type, and let it bail if desired
+		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+			return;
+		}
+
+		// Determine handlers
+		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+		// Run delegates first; they may want to stop propagation beneath us
+		i = 0;
+		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+			event.currentTarget = matched.elem;
+
+			j = 0;
+			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+
+				// Triggered event must either 1) have no namespace, or
+				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+
+					event.handleObj = handleObj;
+					event.data = handleObj.data;
+
+					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+							.apply( matched.elem, args );
+
+					if ( ret !== undefined ) {
+						if ( (event.result = ret) === false ) {
+							event.preventDefault();
+							event.stopPropagation();
+						}
+					}
+				}
+			}
+		}
+
+		// Call the postDispatch hook for the mapped type
+		if ( special.postDispatch ) {
+			special.postDispatch.call( this, event );
+		}
+
+		return event.result;
+	},
+
+	handlers: function( event, handlers ) {
+		var sel, handleObj, matches, i,
+			handlerQueue = [],
+			delegateCount = handlers.delegateCount,
+			cur = event.target;
+
+		// Find delegate handlers
+		// Black-hole SVG <use> instance trees (#13180)
+		// Avoid non-left-click bubbling in Firefox (#3861)
+		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
+
+			/* jshint eqeqeq: false */
+			for ( ; cur != this; cur = cur.parentNode || this ) {
+				/* jshint eqeqeq: true */
+
+				// Don't check non-elements (#13208)
+				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+				if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
+					matches = [];
+					for ( i = 0; i < delegateCount; i++ ) {
+						handleObj = handlers[ i ];
+
+						// Don't conflict with Object.prototype properties (#13203)
+						sel = handleObj.selector + " ";
+
+						if ( matches[ sel ] === undefined ) {
+							matches[ sel ] = handleObj.needsContext ?
+								jQuery( sel, this ).index( cur ) >= 0 :
+								jQuery.find( sel, this, null, [ cur ] ).length;
+						}
+						if ( matches[ sel ] ) {
+							matches.push( handleObj );
+						}
+					}
+					if ( matches.length ) {
+						handlerQueue.push({ elem: cur, handlers: matches });
+					}
+				}
+			}
+		}
+
+		// Add the remaining (directly-bound) handlers
+		if ( delegateCount < handlers.length ) {
+			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+		}
+
+		return handlerQueue;
+	},
+
+	fix: function( event ) {
+		if ( event[ jQuery.expando ] ) {
+			return event;
+		}
+
+		// Create a writable copy of the event object and normalize some properties
+		var i, prop, copy,
+			type = event.type,
+			originalEvent = event,
+			fixHook = this.fixHooks[ type ];
+
+		if ( !fixHook ) {
+			this.fixHooks[ type ] = fixHook =
+				rmouseEvent.test( type ) ? this.mouseHooks :
+				rkeyEvent.test( type ) ? this.keyHooks :
+				{};
+		}
+		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+		event = new jQuery.Event( originalEvent );
+
+		i = copy.length;
+		while ( i-- ) {
+			prop = copy[ i ];
+			event[ prop ] = originalEvent[ prop ];
+		}
+
+		// Support: IE<9
+		// Fix target property (#1925)
+		if ( !event.target ) {
+			event.target = originalEvent.srcElement || document;
+		}
+
+		// Support: Chrome 23+, Safari?
+		// Target should not be a text node (#504, #13143)
+		if ( event.target.nodeType === 3 ) {
+			event.target = event.target.parentNode;
+		}
+
+		// Support: IE<9
+		// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
+		event.metaKey = !!event.metaKey;
+
+		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+	},
+
+	// Includes some event props shared by KeyEvent and MouseEvent
+	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+	fixHooks: {},
+
+	keyHooks: {
+		props: "char charCode key keyCode".split(" "),
+		filter: function( event, original ) {
+
+			// Add which for key events
+			if ( event.which == null ) {
+				event.which = original.charCode != null ? original.charCode : original.keyCode;
+			}
+
+			return event;
+		}
+	},
+
+	mouseHooks: {
+		props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+		filter: function( event, original ) {
+			var body, eventDoc, doc,
+				button = original.button,
+				fromElement = original.fromElement;
+
+			// Calculate pageX/Y if missing and clientX/Y available
+			if ( event.pageX == null && original.clientX != null ) {
+				eventDoc = event.target.ownerDocument || document;
+				doc = eventDoc.documentElement;
+				body = eventDoc.body;
+
+				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
+			}
+
+			// Add relatedTarget, if necessary
+			if ( !event.relatedTarget && fromElement ) {
+				event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+			}
+
+			// Add which for click: 1 === left; 2 === middle; 3 === right
+			// Note: button is not normalized, so don't use it
+			if ( !event.which && button !== undefined ) {
+				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+			}
+
+			return event;
+		}
+	},
+
+	special: {
+		load: {
+			// Prevent triggered image.load events from bubbling to window.load
+			noBubble: true
+		},
+		focus: {
+			// Fire native event if possible so blur/focus sequence is correct
+			trigger: function() {
+				if ( this !== safeActiveElement() && this.focus ) {
+					try {
+						this.focus();
+						return false;
+					} catch ( e ) {
+						// Support: IE<9
+						// If we error on focus to hidden element (#1486, #12518),
+						// let .trigger() run the handlers
+					}
+				}
+			},
+			delegateType: "focusin"
+		},
+		blur: {
+			trigger: function() {
+				if ( this === safeActiveElement() && this.blur ) {
+					this.blur();
+					return false;
+				}
+			},
+			delegateType: "focusout"
+		},
+		click: {
+			// For checkbox, fire native event so checked state will be right
+			trigger: function() {
+				if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
+					this.click();
+					return false;
+				}
+			},
+
+			// For cross-browser consistency, don't fire native .click() on links
+			_default: function( event ) {
+				return jQuery.nodeName( event.target, "a" );
+			}
+		},
+
+		beforeunload: {
+			postDispatch: function( event ) {
+
+				// Support: Firefox 20+
+				// Firefox doesn't alert if the returnValue field is not set.
+				if ( event.result !== undefined && event.originalEvent ) {
+					event.originalEvent.returnValue = event.result;
+				}
+			}
+		}
+	},
+
+	simulate: function( type, elem, event, bubble ) {
+		// Piggyback on a donor event to simulate a different one.
+		// Fake originalEvent to avoid donor's stopPropagation, but if the
+		// simulated event prevents default then we do the same on the donor.
+		var e = jQuery.extend(
+			new jQuery.Event(),
+			event,
+			{
+				type: type,
+				isSimulated: true,
+				originalEvent: {}
+			}
+		);
+		if ( bubble ) {
+			jQuery.event.trigger( e, null, elem );
+		} else {
+			jQuery.event.dispatch.call( elem, e );
+		}
+		if ( e.isDefaultPrevented() ) {
+			event.preventDefault();
+		}
+	}
+};
+
+jQuery.removeEvent = document.removeEventListener ?
+	function( elem, type, handle ) {
+		if ( elem.removeEventListener ) {
+			elem.removeEventListener( type, handle, false );
+		}
+	} :
+	function( elem, type, handle ) {
+		var name = "on" + type;
+
+		if ( elem.detachEvent ) {
+
+			// #8545, #7054, preventing memory leaks for custom events in IE6-8
+			// detachEvent needed property on element, by name of that event, to properly expose it to GC
+			if ( typeof elem[ name ] === strundefined ) {
+				elem[ name ] = null;
+			}
+
+			elem.detachEvent( name, handle );
+		}
+	};
+
+jQuery.Event = function( src, props ) {
+	// Allow instantiation without the 'new' keyword
+	if ( !(this instanceof jQuery.Event) ) {
+		return new jQuery.Event( src, props );
+	}
+
+	// Event object
+	if ( src && src.type ) {
+		this.originalEvent = src;
+		this.type = src.type;
+
+		// Events bubbling up the document may have been marked as prevented
+		// by a handler lower down the tree; reflect the correct value.
+		this.isDefaultPrevented = src.defaultPrevented ||
+				src.defaultPrevented === undefined &&
+				// Support: IE < 9, Android < 4.0
+				src.returnValue === false ?
+			returnTrue :
+			returnFalse;
+
+	// Event type
+	} else {
+		this.type = src;
+	}
+
+	// Put explicitly provided properties onto the event object
+	if ( props ) {
+		jQuery.extend( this, props );
+	}
+
+	// Create a timestamp if incoming event doesn't have one
+	this.timeStamp = src && src.timeStamp || jQuery.now();
+
+	// Mark it as fixed
+	this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+	isDefaultPrevented: returnFalse,
+	isPropagationStopped: returnFalse,
+	isImmediatePropagationStopped: returnFalse,
+
+	preventDefault: function() {
+		var e = this.originalEvent;
+
+		this.isDefaultPrevented = returnTrue;
+		if ( !e ) {
+			return;
+		}
+
+		// If preventDefault exists, run it on the original event
+		if ( e.preventDefault ) {
+			e.preventDefault();
+
+		// Support: IE
+		// Otherwise set the returnValue property of the original event to false
+		} else {
+			e.returnValue = false;
+		}
+	},
+	stopPropagation: function() {
+		var e = this.originalEvent;
+
+		this.isPropagationStopped = returnTrue;
+		if ( !e ) {
+			return;
+		}
+		// If stopPropagation exists, run it on the original event
+		if ( e.stopPropagation ) {
+			e.stopPropagation();
+		}
+
+		// Support: IE
+		// Set the cancelBubble property of the original event to true
+		e.cancelBubble = true;
+	},
+	stopImmediatePropagation: function() {
+		var e = this.originalEvent;
+
+		this.isImmediatePropagationStopped = returnTrue;
+
+		if ( e && e.stopImmediatePropagation ) {
+			e.stopImmediatePropagation();
+		}
+
+		this.stopPropagation();
+	}
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+	mouseenter: "mouseover",
+	mouseleave: "mouseout",
+	pointerenter: "pointerover",
+	pointerleave: "pointerout"
+}, function( orig, fix ) {
+	jQuery.event.special[ orig ] = {
+		delegateType: fix,
+		bindType: fix,
+
+		handle: function( event ) {
+			var ret,
+				target = this,
+				related = event.relatedTarget,
+				handleObj = event.handleObj;
+
+			// For mousenter/leave call the handler if related is outside the target.
+			// NB: No relatedTarget if the mouse left/entered the browser window
+			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+				event.type = handleObj.origType;
+				ret = handleObj.handler.apply( this, arguments );
+				event.type = fix;
+			}
+			return ret;
+		}
+	};
+});
+
+// IE submit delegation
+if ( !support.submitBubbles ) {
+
+	jQuery.event.special.submit = {
+		setup: function() {
+			// Only need this for delegated form submit events
+			if ( jQuery.nodeName( this, "form" ) ) {
+				return false;
+			}
+
+			// Lazy-add a submit handler when a descendant form may potentially be submitted
+			jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+				// Node name check avoids a VML-related crash in IE (#9807)
+				var elem = e.target,
+					form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+				if ( form && !jQuery._data( form, "submitBubbles" ) ) {
+					jQuery.event.add( form, "submit._submit", function( event ) {
+						event._submit_bubble = true;
+					});
+					jQuery._data( form, "submitBubbles", true );
+				}
+			});
+			// return undefined since we don't need an event listener
+		},
+
+		postDispatch: function( event ) {
+			// If form was submitted by the user, bubble the event up the tree
+			if ( event._submit_bubble ) {
+				delete event._submit_bubble;
+				if ( this.parentNode && !event.isTrigger ) {
+					jQuery.event.simulate( "submit", this.parentNode, event, true );
+				}
+			}
+		},
+
+		teardown: function() {
+			// Only need this for delegated form submit events
+			if ( jQuery.nodeName( this, "form" ) ) {
+				return false;
+			}
+
+			// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+			jQuery.event.remove( this, "._submit" );
+		}
+	};
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !support.changeBubbles ) {
+
+	jQuery.event.special.change = {
+
+		setup: function() {
+
+			if ( rformElems.test( this.nodeName ) ) {
+				// IE doesn't fire change on a check/radio until blur; trigger it on click
+				// after a propertychange. Eat the blur-change in special.change.handle.
+				// This still fires onchange a second time for check/radio after blur.
+				if ( this.type === "checkbox" || this.type === "radio" ) {
+					jQuery.event.add( this, "propertychange._change", function( event ) {
+						if ( event.originalEvent.propertyName === "checked" ) {
+							this._just_changed = true;
+						}
+					});
+					jQuery.event.add( this, "click._change", function( event ) {
+						if ( this._just_changed && !event.isTrigger ) {
+							this._just_changed = false;
+						}
+						// Allow triggered, simulated change events (#11500)
+						jQuery.event.simulate( "change", this, event, true );
+					});
+				}
+				return false;
+			}
+			// Delegated event; lazy-add a change handler on descendant inputs
+			jQuery.event.add( this, "beforeactivate._change", function( e ) {
+				var elem = e.target;
+
+				if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
+					jQuery.event.add( elem, "change._change", function( event ) {
+						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+							jQuery.event.simulate( "change", this.parentNode, event, true );
+						}
+					});
+					jQuery._data( elem, "changeBubbles", true );
+				}
+			});
+		},
+
+		handle: function( event ) {
+			var elem = event.target;
+
+			// Swallow native change events from checkbox/radio, we already triggered them above
+			if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+				return event.handleObj.handler.apply( this, arguments );
+			}
+		},
+
+		teardown: function() {
+			jQuery.event.remove( this, "._change" );
+
+			return !rformElems.test( this.nodeName );
+		}
+	};
+}
+
+// Create "bubbling" focus and blur events
+if ( !support.focusinBubbles ) {
+	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+		// Attach a single capturing handler on the document while someone wants focusin/focusout
+		var handler = function( event ) {
+				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+			};
+
+		jQuery.event.special[ fix ] = {
+			setup: function() {
+				var doc = this.ownerDocument || this,
+					attaches = jQuery._data( doc, fix );
+
+				if ( !attaches ) {
+					doc.addEventListener( orig, handler, true );
+				}
+				jQuery._data( doc, fix, ( attaches || 0 ) + 1 );
+			},
+			teardown: function() {
+				var doc = this.ownerDocument || this,
+					attaches = jQuery._data( doc, fix ) - 1;
+
+				if ( !attaches ) {
+					doc.removeEventListener( orig, handler, true );
+					jQuery._removeData( doc, fix );
+				} else {
+					jQuery._data( doc, fix, attaches );
+				}
+			}
+		};
+	});
+}
+
+jQuery.fn.extend({
+
+	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+		var type, origFn;
+
+		// Types can be a map of types/handlers
+		if ( typeof types === "object" ) {
+			// ( types-Object, selector, data )
+			if ( typeof selector !== "string" ) {
+				// ( types-Object, data )
+				data = data || selector;
+				selector = undefined;
+			}
+			for ( type in types ) {
+				this.on( type, selector, data, types[ type ], one );
+			}
+			return this;
+		}
+
+		if ( data == null && fn == null ) {
+			// ( types, fn )
+			fn = selector;
+			data = selector = undefined;
+		} else if ( fn == null ) {
+			if ( typeof selector === "string" ) {
+				// ( types, selector, fn )
+				fn = data;
+				data = undefined;
+			} else {
+				// ( types, data, fn )
+				fn = data;
+				data = selector;
+				selector = undefined;
+			}
+		}
+		if ( fn === false ) {
+			fn = returnFalse;
+		} else if ( !fn ) {
+			return this;
+		}
+
+		if ( one === 1 ) {
+			origFn = fn;
+			fn = function( event ) {
+				// Can use an empty set, since event contains the info
+				jQuery().off( event );
+				return origFn.apply( this, arguments );
+			};
+			// Use same guid so caller can remove using origFn
+			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+		}
+		return this.each( function() {
+			jQuery.event.add( this, types, fn, data, selector );
+		});
+	},
+	one: function( types, selector, data, fn ) {
+		return this.on( types, selector, data, fn, 1 );
+	},
+	off: function( types, selector, fn ) {
+		var handleObj, type;
+		if ( types && types.preventDefault && types.handleObj ) {
+			// ( event )  dispatched jQuery.Event
+			handleObj = types.handleObj;
+			jQuery( types.delegateTarget ).off(
+				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+				handleObj.selector,
+				handleObj.handler
+			);
+			return this;
+		}
+		if ( typeof types === "object" ) {
+			// ( types-object [, selector] )
+			for ( type in types ) {
+				this.off( type, selector, types[ type ] );
+			}
+			return this;
+		}
+		if ( selector === false || typeof selector === "function" ) {
+			// ( types [, fn] )
+			fn = selector;
+			selector = undefined;
+		}
+		if ( fn === false ) {
+			fn = returnFalse;
+		}
+		return this.each(function() {
+			jQuery.event.remove( this, types, fn, selector );
+		});
+	},
+
+	trigger: function( type, data ) {
+		return this.each(function() {
+			jQuery.event.trigger( type, data, this );
+		});
+	},
+	triggerHandler: function( type, data ) {
+		var elem = this[0];
+		if ( elem ) {
+			return jQuery.event.trigger( type, data, elem, true );
+		}
+	}
+});
+
+
+function createSafeFragment( document ) {
+	var list = nodeNames.split( "|" ),
+		safeFrag = document.createDocumentFragment();
+
+	if ( safeFrag.createElement ) {
+		while ( list.length ) {
+			safeFrag.createElement(
+				list.pop()
+			);
+		}
+	}
+	return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+	rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
+	rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+	rleadingWhitespace = /^\s+/,
+	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+	rtagName = /<([\w:]+)/,
+	rtbody = /<tbody/i,
+	rhtml = /<|&#?\w+;/,
+	rnoInnerhtml = /<(?:script|style|link)/i,
+	// checked="checked" or checked
+	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+	rscriptType = /^$|\/(?:java|ecma)script/i,
+	rscriptTypeMasked = /^true\/(.*)/,
+	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
+
+	// We have to close these tags to support XHTML (#13200)
+	wrapMap = {
+		option: [ 1, "<select multiple='multiple'>", "</select>" ],
+		legend: [ 1, "<fieldset>", "</fieldset>" ],
+		area: [ 1, "<map>", "</map>" ],
+		param: [ 1, "<object>", "</object>" ],
+		thead: [ 1, "<table>", "</table>" ],
+		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+		// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
+		// unless wrapped in a div with non-breaking characters in front of it.
+		_default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>"  ]
+	},
+	safeFragment = createSafeFragment( document ),
+	fragmentDiv = safeFragment.appendChild( document.createElement("div") );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+function getAll( context, tag ) {
+	var elems, elem,
+		i = 0,
+		found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
+			typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
+			undefined;
+
+	if ( !found ) {
+		for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
+			if ( !tag || jQuery.nodeName( elem, tag ) ) {
+				found.push( elem );
+			} else {
+				jQuery.merge( found, getAll( elem, tag ) );
+			}
+		}
+	}
+
+	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+		jQuery.merge( [ context ], found ) :
+		found;
+}
+
+// Used in buildFragment, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+	if ( rcheckableType.test( elem.type ) ) {
+		elem.defaultChecked = elem.checked;
+	}
+}
+
+// Support: IE<8
+// Manipulating tables requires a tbody
+function manipulationTarget( elem, content ) {
+	return jQuery.nodeName( elem, "table" ) &&
+		jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
+
+		elem.getElementsByTagName("tbody")[0] ||
+			elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
+		elem;
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+	elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
+	return elem;
+}
+function restoreScript( elem ) {
+	var match = rscriptTypeMasked.exec( elem.type );
+	if ( match ) {
+		elem.type = match[1];
+	} else {
+		elem.removeAttribute("type");
+	}
+	return elem;
+}
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+	var elem,
+		i = 0;
+	for ( ; (elem = elems[i]) != null; i++ ) {
+		jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
+	}
+}
+
+function cloneCopyEvent( src, dest ) {
+
+	if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+		return;
+	}
+
+	var type, i, l,
+		oldData = jQuery._data( src ),
+		curData = jQuery._data( dest, oldData ),
+		events = oldData.events;
+
+	if ( events ) {
+		delete curData.handle;
+		curData.events = {};
+
+		for ( type in events ) {
+			for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+				jQuery.event.add( dest, type, events[ type ][ i ] );
+			}
+		}
+	}
+
+	// make the cloned public data object a copy from the original
+	if ( curData.data ) {
+		curData.data = jQuery.extend( {}, curData.data );
+	}
+}
+
+function fixCloneNodeIssues( src, dest ) {
+	var nodeName, e, data;
+
+	// We do not need to do anything for non-Elements
+	if ( dest.nodeType !== 1 ) {
+		return;
+	}
+
+	nodeName = dest.nodeName.toLowerCase();
+
+	// IE6-8 copies events bound via attachEvent when using cloneNode.
+	if ( !support.noCloneEvent && dest[ jQuery.expando ] ) {
+		data = jQuery._data( dest );
+
+		for ( e in data.events ) {
+			jQuery.removeEvent( dest, e, data.handle );
+		}
+
+		// Event data gets referenced instead of copied if the expando gets copied too
+		dest.removeAttribute( jQuery.expando );
+	}
+
+	// IE blanks contents when cloning scripts, and tries to evaluate newly-set text
+	if ( nodeName === "script" && dest.text !== src.text ) {
+		disableScript( dest ).text = src.text;
+		restoreScript( dest );
+
+	// IE6-10 improperly clones children of object elements using classid.
+	// IE10 throws NoModificationAllowedError if parent is null, #12132.
+	} else if ( nodeName === "object" ) {
+		if ( dest.parentNode ) {
+			dest.outerHTML = src.outerHTML;
+		}
+
+		// This path appears unavoidable for IE9. When cloning an object
+		// element in IE9, the outerHTML strategy above is not sufficient.
+		// If the src has innerHTML and the destination does not,
+		// copy the src.innerHTML into the dest.innerHTML. #10324
+		if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
+			dest.innerHTML = src.innerHTML;
+		}
+
+	} else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+		// IE6-8 fails to persist the checked state of a cloned checkbox
+		// or radio button. Worse, IE6-7 fail to give the cloned element
+		// a checked appearance if the defaultChecked value isn't also set
+
+		dest.defaultChecked = dest.checked = src.checked;
+
+		// IE6-7 get confused and end up setting the value of a cloned
+		// checkbox/radio button to an empty string instead of "on"
+		if ( dest.value !== src.value ) {
+			dest.value = src.value;
+		}
+
+	// IE6-8 fails to return the selected option to the default selected
+	// state when cloning options
+	} else if ( nodeName === "option" ) {
+		dest.defaultSelected = dest.selected = src.defaultSelected;
+
+	// IE6-8 fails to set the defaultValue to the correct value when
+	// cloning other types of input fields
+	} else if ( nodeName === "input" || nodeName === "textarea" ) {
+		dest.defaultValue = src.defaultValue;
+	}
+}
+
+jQuery.extend({
+	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+		var destElements, node, clone, i, srcElements,
+			inPage = jQuery.contains( elem.ownerDocument, elem );
+
+		if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
+			clone = elem.cloneNode( true );
+
+		// IE<=8 does not properly clone detached, unknown element nodes
+		} else {
+			fragmentDiv.innerHTML = elem.outerHTML;
+			fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+		}
+
+		if ( (!support.noCloneEvent || !support.noCloneChecked) &&
+				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+
+			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+			destElements = getAll( clone );
+			srcElements = getAll( elem );
+
+			// Fix all IE cloning issues
+			for ( i = 0; (node = srcElements[i]) != null; ++i ) {
+				// Ensure that the destination node is not null; Fixes #9587
+				if ( destElements[i] ) {
+					fixCloneNodeIssues( node, destElements[i] );
+				}
+			}
+		}
+
+		// Copy the events from the original to the clone
+		if ( dataAndEvents ) {
+			if ( deepDataAndEvents ) {
+				srcElements = srcElements || getAll( elem );
+				destElements = destElements || getAll( clone );
+
+				for ( i = 0; (node = srcElements[i]) != null; i++ ) {
+					cloneCopyEvent( node, destElements[i] );
+				}
+			} else {
+				cloneCopyEvent( elem, clone );
+			}
+		}
+
+		// Preserve script evaluation history
+		destElements = getAll( clone, "script" );
+		if ( destElements.length > 0 ) {
+			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+		}
+
+		destElements = srcElements = node = null;
+
+		// Return the cloned set
+		return clone;
+	},
+
+	buildFragment: function( elems, context, scripts, selection ) {
+		var j, elem, contains,
+			tmp, tag, tbody, wrap,
+			l = elems.length,
+
+			// Ensure a safe fragment
+			safe = createSafeFragment( context ),
+
+			nodes = [],
+			i = 0;
+
+		for ( ; i < l; i++ ) {
+			elem = elems[ i ];
+
+			if ( elem || elem === 0 ) {
+
+				// Add nodes directly
+				if ( jQuery.type( elem ) === "object" ) {
+					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+				// Convert non-html into a text node
+				} else if ( !rhtml.test( elem ) ) {
+					nodes.push( context.createTextNode( elem ) );
+
+				// Convert html into DOM nodes
+				} else {
+					tmp = tmp || safe.appendChild( context.createElement("div") );
+
+					// Deserialize a standard representation
+					tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
+					wrap = wrapMap[ tag ] || wrapMap._default;
+
+					tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
+
+					// Descend through wrappers to the right content
+					j = wrap[0];
+					while ( j-- ) {
+						tmp = tmp.lastChild;
+					}
+
+					// Manually add leading whitespace removed by IE
+					if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+						nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
+					}
+
+					// Remove IE's autoinserted <tbody> from table fragments
+					if ( !support.tbody ) {
+
+						// String was a <table>, *may* have spurious <tbody>
+						elem = tag === "table" && !rtbody.test( elem ) ?
+							tmp.firstChild :
+
+							// String was a bare <thead> or <tfoot>
+							wrap[1] === "<table>" && !rtbody.test( elem ) ?
+								tmp :
+								0;
+
+						j = elem && elem.childNodes.length;
+						while ( j-- ) {
+							if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
+								elem.removeChild( tbody );
+							}
+						}
+					}
+
+					jQuery.merge( nodes, tmp.childNodes );
+
+					// Fix #12392 for WebKit and IE > 9
+					tmp.textContent = "";
+
+					// Fix #12392 for oldIE
+					while ( tmp.firstChild ) {
+						tmp.removeChild( tmp.firstChild );
+					}
+
+					// Remember the top-level container for proper cleanup
+					tmp = safe.lastChild;
+				}
+			}
+		}
+
+		// Fix #11356: Clear elements from fragment
+		if ( tmp ) {
+			safe.removeChild( tmp );
+		}
+
+		// Reset defaultChecked for any radios and checkboxes
+		// about to be appended to the DOM in IE 6/7 (#8060)
+		if ( !support.appendChecked ) {
+			jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
+		}
+
+		i = 0;
+		while ( (elem = nodes[ i++ ]) ) {
+
+			// #4087 - If origin and destination elements are the same, and this is
+			// that element, do not do anything
+			if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
+				continue;
+			}
+
+			contains = jQuery.contains( elem.ownerDocument, elem );
+
+			// Append to fragment
+			tmp = getAll( safe.appendChild( elem ), "script" );
+
+			// Preserve script evaluation history
+			if ( contains ) {
+				setGlobalEval( tmp );
+			}
+
+			// Capture executables
+			if ( scripts ) {
+				j = 0;
+				while ( (elem = tmp[ j++ ]) ) {
+					if ( rscriptType.test( elem.type || "" ) ) {
+						scripts.push( elem );
+					}
+				}
+			}
+		}
+
+		tmp = null;
+
+		return safe;
+	},
+
+	cleanData: function( elems, /* internal */ acceptData ) {
+		var elem, type, id, data,
+			i = 0,
+			internalKey = jQuery.expando,
+			cache = jQuery.cache,
+			deleteExpando = support.deleteExpando,
+			special = jQuery.event.special;
+
+		for ( ; (elem = elems[i]) != null; i++ ) {
+			if ( acceptData || jQuery.acceptData( elem ) ) {
+
+				id = elem[ internalKey ];
+				data = id && cache[ id ];
+
+				if ( data ) {
+					if ( data.events ) {
+						for ( type in data.events ) {
+							if ( special[ type ] ) {
+								jQuery.event.remove( elem, type );
+
+							// This is a shortcut to avoid jQuery.event.remove's overhead
+							} else {
+								jQuery.removeEvent( elem, type, data.handle );
+							}
+						}
+					}
+
+					// Remove cache only if it was not already removed by jQuery.event.remove
+					if ( cache[ id ] ) {
+
+						delete cache[ id ];
+
+						// IE does not allow us to delete expando properties from nodes,
+						// nor does it have a removeAttribute function on Document nodes;
+						// we must handle all of these cases
+						if ( deleteExpando ) {
+							delete elem[ internalKey ];
+
+						} else if ( typeof elem.removeAttribute !== strundefined ) {
+							elem.removeAttribute( internalKey );
+
+						} else {
+							elem[ internalKey ] = null;
+						}
+
+						deletedIds.push( id );
+					}
+				}
+			}
+		}
+	}
+});
+
+jQuery.fn.extend({
+	text: function( value ) {
+		return access( this, function( value ) {
+			return value === undefined ?
+				jQuery.text( this ) :
+				this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+		}, null, value, arguments.length );
+	},
+
+	append: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+				var target = manipulationTarget( this, elem );
+				target.appendChild( elem );
+			}
+		});
+	},
+
+	prepend: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+				var target = manipulationTarget( this, elem );
+				target.insertBefore( elem, target.firstChild );
+			}
+		});
+	},
+
+	before: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.parentNode ) {
+				this.parentNode.insertBefore( elem, this );
+			}
+		});
+	},
+
+	after: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.parentNode ) {
+				this.parentNode.insertBefore( elem, this.nextSibling );
+			}
+		});
+	},
+
+	remove: function( selector, keepData /* Internal Use Only */ ) {
+		var elem,
+			elems = selector ? jQuery.filter( selector, this ) : this,
+			i = 0;
+
+		for ( ; (elem = elems[i]) != null; i++ ) {
+
+			if ( !keepData && elem.nodeType === 1 ) {
+				jQuery.cleanData( getAll( elem ) );
+			}
+
+			if ( elem.parentNode ) {
+				if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
+					setGlobalEval( getAll( elem, "script" ) );
+				}
+				elem.parentNode.removeChild( elem );
+			}
+		}
+
+		return this;
+	},
+
+	empty: function() {
+		var elem,
+			i = 0;
+
+		for ( ; (elem = this[i]) != null; i++ ) {
+			// Remove element nodes and prevent memory leaks
+			if ( elem.nodeType === 1 ) {
+				jQuery.cleanData( getAll( elem, false ) );
+			}
+
+			// Remove any remaining nodes
+			while ( elem.firstChild ) {
+				elem.removeChild( elem.firstChild );
+			}
+
+			// If this is a select, ensure that it displays empty (#12336)
+			// Support: IE<9
+			if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
+				elem.options.length = 0;
+			}
+		}
+
+		return this;
+	},
+
+	clone: function( dataAndEvents, deepDataAndEvents ) {
+		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+		return this.map(function() {
+			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+		});
+	},
+
+	html: function( value ) {
+		return access( this, function( value ) {
+			var elem = this[ 0 ] || {},
+				i = 0,
+				l = this.length;
+
+			if ( value === undefined ) {
+				return elem.nodeType === 1 ?
+					elem.innerHTML.replace( rinlinejQuery, "" ) :
+					undefined;
+			}
+
+			// See if we can take a shortcut and just use innerHTML
+			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+				( support.htmlSerialize || !rnoshimcache.test( value )  ) &&
+				( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+				!wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
+
+				value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+				try {
+					for (; i < l; i++ ) {
+						// Remove element nodes and prevent memory leaks
+						elem = this[i] || {};
+						if ( elem.nodeType === 1 ) {
+							jQuery.cleanData( getAll( elem, false ) );
+							elem.innerHTML = value;
+						}
+					}
+
+					elem = 0;
+
+				// If using innerHTML throws an exception, use the fallback method
+				} catch(e) {}
+			}
+
+			if ( elem ) {
+				this.empty().append( value );
+			}
+		}, null, value, arguments.length );
+	},
+
+	replaceWith: function() {
+		var arg = arguments[ 0 ];
+
+		// Make the changes, replacing each context element with the new content
+		this.domManip( arguments, function( elem ) {
+			arg = this.parentNode;
+
+			jQuery.cleanData( getAll( this ) );
+
+			if ( arg ) {
+				arg.replaceChild( elem, this );
+			}
+		});
+
+		// Force removal if there was no new content (e.g., from empty arguments)
+		return arg && (arg.length || arg.nodeType) ? this : this.remove();
+	},
+
+	detach: function( selector ) {
+		return this.remove( selector, true );
+	},
+
+	domManip: function( args, callback ) {
+
+		// Flatten any nested arrays
+		args = concat.apply( [], args );
+
+		var first, node, hasScripts,
+			scripts, doc, fragment,
+			i = 0,
+			l = this.length,
+			set = this,
+			iNoClone = l - 1,
+			value = args[0],
+			isFunction = jQuery.isFunction( value );
+
+		// We can't cloneNode fragments that contain checked, in WebKit
+		if ( isFunction ||
+				( l > 1 && typeof value === "string" &&
+					!support.checkClone && rchecked.test( value ) ) ) {
+			return this.each(function( index ) {
+				var self = set.eq( index );
+				if ( isFunction ) {
+					args[0] = value.call( this, index, self.html() );
+				}
+				self.domManip( args, callback );
+			});
+		}
+
+		if ( l ) {
+			fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
+			first = fragment.firstChild;
+
+			if ( fragment.childNodes.length === 1 ) {
+				fragment = first;
+			}
+
+			if ( first ) {
+				scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+				hasScripts = scripts.length;
+
+				// Use the original fragment for the last item instead of the first because it can end up
+				// being emptied incorrectly in certain situations (#8070).
+				for ( ; i < l; i++ ) {
+					node = fragment;
+
+					if ( i !== iNoClone ) {
+						node = jQuery.clone( node, true, true );
+
+						// Keep references to cloned scripts for later restoration
+						if ( hasScripts ) {
+							jQuery.merge( scripts, getAll( node, "script" ) );
+						}
+					}
+
+					callback.call( this[i], node, i );
+				}
+
+				if ( hasScripts ) {
+					doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+					// Reenable scripts
+					jQuery.map( scripts, restoreScript );
+
+					// Evaluate executable scripts on first document insertion
+					for ( i = 0; i < hasScripts; i++ ) {
+						node = scripts[ i ];
+						if ( rscriptType.test( node.type || "" ) &&
+							!jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
+
+							if ( node.src ) {
+								// Optional AJAX dependency, but won't run scripts if not present
+								if ( jQuery._evalUrl ) {
+									jQuery._evalUrl( node.src );
+								}
+							} else {
+								jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
+							}
+						}
+					}
+				}
+
+				// Fix #11809: Avoid leaking memory
+				fragment = first = null;
+			}
+		}
+
+		return this;
+	}
+});
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function( name, original ) {
+	jQuery.fn[ name ] = function( selector ) {
+		var elems,
+			i = 0,
+			ret = [],
+			insert = jQuery( selector ),
+			last = insert.length - 1;
+
+		for ( ; i <= last; i++ ) {
+			elems = i === last ? this : this.clone(true);
+			jQuery( insert[i] )[ original ]( elems );
+
+			// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
+			push.apply( ret, elems.get() );
+		}
+
+		return this.pushStack( ret );
+	};
+});
+
+
+var iframe,
+	elemdisplay = {};
+
+/**
+ * Retrieve the actual display of a element
+ * @param {String} name nodeName of the element
+ * @param {Object} doc Document object
+ */
+// Called only from within defaultDisplay
+function actualDisplay( name, doc ) {
+	var style,
+		elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+
+		// getDefaultComputedStyle might be reliably used only on attached element
+		display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
+
+			// Use of this method is a temporary fix (more like optmization) until something better comes along,
+			// since it was removed from specification and supported only in FF
+			style.display : jQuery.css( elem[ 0 ], "display" );
+
+	// We don't have any data stored on the element,
+	// so use "detach" method as fast way to get rid of the element
+	elem.detach();
+
+	return display;
+}
+
+/**
+ * Try to determine the default display value of an element
+ * @param {String} nodeName
+ */
+function defaultDisplay( nodeName ) {
+	var doc = document,
+		display = elemdisplay[ nodeName ];
+
+	if ( !display ) {
+		display = actualDisplay( nodeName, doc );
+
+		// If the simple way fails, read from inside an iframe
+		if ( display === "none" || !display ) {
+
+			// Use the already-created iframe if possible
+			iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
+
+			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+			doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
+
+			// Support: IE
+			doc.write();
+			doc.close();
+
+			display = actualDisplay( nodeName, doc );
+			iframe.detach();
+		}
+
+		// Store the correct default display
+		elemdisplay[ nodeName ] = display;
+	}
+
+	return display;
+}
+
+
+(function() {
+	var shrinkWrapBlocksVal;
+
+	support.shrinkWrapBlocks = function() {
+		if ( shrinkWrapBlocksVal != null ) {
+			return shrinkWrapBlocksVal;
+		}
+
+		// Will be changed later if needed.
+		shrinkWrapBlocksVal = false;
+
+		// Minified: var b,c,d
+		var div, body, container;
+
+		body = document.getElementsByTagName( "body" )[ 0 ];
+		if ( !body || !body.style ) {
+			// Test fired too early or in an unsupported environment, exit.
+			return;
+		}
+
+		// Setup
+		div = document.createElement( "div" );
+		container = document.createElement( "div" );
+		container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+		body.appendChild( container ).appendChild( div );
+
+		// Support: IE6
+		// Check if elements with layout shrink-wrap their children
+		if ( typeof div.style.zoom !== strundefined ) {
+			// Reset CSS: box-sizing; display; margin; border
+			div.style.cssText =
+				// Support: Firefox<29, Android 2.3
+				// Vendor-prefix box-sizing
+				"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
+				"box-sizing:content-box;display:block;margin:0;border:0;" +
+				"padding:1px;width:1px;zoom:1";
+			div.appendChild( document.createElement( "div" ) ).style.width = "5px";
+			shrinkWrapBlocksVal = div.offsetWidth !== 3;
+		}
+
+		body.removeChild( container );
+
+		return shrinkWrapBlocksVal;
+	};
+
+})();
+var rmargin = (/^margin/);
+
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+
+
+var getStyles, curCSS,
+	rposition = /^(top|right|bottom|left)$/;
+
+if ( window.getComputedStyle ) {
+	getStyles = function( elem ) {
+		return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
+	};
+
+	curCSS = function( elem, name, computed ) {
+		var width, minWidth, maxWidth, ret,
+			style = elem.style;
+
+		computed = computed || getStyles( elem );
+
+		// getPropertyValue is only needed for .css('filter') in IE9, see #12537
+		ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
+
+		if ( computed ) {
+
+			if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+				ret = jQuery.style( elem, name );
+			}
+
+			// A tribute to the "awesome hack by Dean Edwards"
+			// Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
+			// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+			// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+			if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+				// Remember the original values
+				width = style.width;
+				minWidth = style.minWidth;
+				maxWidth = style.maxWidth;
+
+				// Put in the new values to get a computed value out
+				style.minWidth = style.maxWidth = style.width = ret;
+				ret = computed.width;
+
+				// Revert the changed values
+				style.width = width;
+				style.minWidth = minWidth;
+				style.maxWidth = maxWidth;
+			}
+		}
+
+		// Support: IE
+		// IE returns zIndex value as an integer.
+		return ret === undefined ?
+			ret :
+			ret + "";
+	};
+} else if ( document.documentElement.currentStyle ) {
+	getStyles = function( elem ) {
+		return elem.currentStyle;
+	};
+
+	curCSS = function( elem, name, computed ) {
+		var left, rs, rsLeft, ret,
+			style = elem.style;
+
+		computed = computed || getStyles( elem );
+		ret = computed ? computed[ name ] : undefined;
+
+		// Avoid setting ret to empty string here
+		// so we don't default to auto
+		if ( ret == null && style && style[ name ] ) {
+			ret = style[ name ];
+		}
+
+		// From the awesome hack by Dean Edwards
+		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+		// If we're not dealing with a regular pixel number
+		// but a number that has a weird ending, we need to convert it to pixels
+		// but not position css attributes, as those are proportional to the parent element instead
+		// and we can't measure the parent instead because it might trigger a "stacking dolls" problem
+		if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+
+			// Remember the original values
+			left = style.left;
+			rs = elem.runtimeStyle;
+			rsLeft = rs && rs.left;
+
+			// Put in the new values to get a computed value out
+			if ( rsLeft ) {
+				rs.left = elem.currentStyle.left;
+			}
+			style.left = name === "fontSize" ? "1em" : ret;
+			ret = style.pixelLeft + "px";
+
+			// Revert the changed values
+			style.left = left;
+			if ( rsLeft ) {
+				rs.left = rsLeft;
+			}
+		}
+
+		// Support: IE
+		// IE returns zIndex value as an integer.
+		return ret === undefined ?
+			ret :
+			ret + "" || "auto";
+	};
+}
+
+
+
+
+function addGetHookIf( conditionFn, hookFn ) {
+	// Define the hook, we'll check on the first run if it's really needed.
+	return {
+		get: function() {
+			var condition = conditionFn();
+
+			if ( condition == null ) {
+				// The test was not ready at this point; screw the hook this time
+				// but check again when needed next time.
+				return;
+			}
+
+			if ( condition ) {
+				// Hook not needed (or it's not possible to use it due to missing dependency),
+				// remove it.
+				// Since there are no other hooks for marginRight, remove the whole object.
+				delete this.get;
+				return;
+			}
+
+			// Hook needed; redefine it so that the support test is not executed again.
+
+			return (this.get = hookFn).apply( this, arguments );
+		}
+	};
+}
+
+
+(function() {
+	// Minified: var b,c,d,e,f,g, h,i
+	var div, style, a, pixelPositionVal, boxSizingReliableVal,
+		reliableHiddenOffsetsVal, reliableMarginRightVal;
+
+	// Setup
+	div = document.createElement( "div" );
+	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+	a = div.getElementsByTagName( "a" )[ 0 ];
+	style = a && a.style;
+
+	// Finish early in limited (non-browser) environments
+	if ( !style ) {
+		return;
+	}
+
+	style.cssText = "float:left;opacity:.5";
+
+	// Support: IE<9
+	// Make sure that element opacity exists (as opposed to filter)
+	support.opacity = style.opacity === "0.5";
+
+	// Verify style float existence
+	// (IE uses styleFloat instead of cssFloat)
+	support.cssFloat = !!style.cssFloat;
+
+	div.style.backgroundClip = "content-box";
+	div.cloneNode( true ).style.backgroundClip = "";
+	support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+	// Support: Firefox<29, Android 2.3
+	// Vendor-prefix box-sizing
+	support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" ||
+		style.WebkitBoxSizing === "";
+
+	jQuery.extend(support, {
+		reliableHiddenOffsets: function() {
+			if ( reliableHiddenOffsetsVal == null ) {
+				computeStyleTests();
+			}
+			return reliableHiddenOffsetsVal;
+		},
+
+		boxSizingReliable: function() {
+			if ( boxSizingReliableVal == null ) {
+				computeStyleTests();
+			}
+			return boxSizingReliableVal;
+		},
+
+		pixelPosition: function() {
+			if ( pixelPositionVal == null ) {
+				computeStyleTests();
+			}
+			return pixelPositionVal;
+		},
+
+		// Support: Android 2.3
+		reliableMarginRight: function() {
+			if ( reliableMarginRightVal == null ) {
+				computeStyleTests();
+			}
+			return reliableMarginRightVal;
+		}
+	});
+
+	function computeStyleTests() {
+		// Minified: var b,c,d,j
+		var div, body, container, contents;
+
+		body = document.getElementsByTagName( "body" )[ 0 ];
+		if ( !body || !body.style ) {
+			// Test fired too early or in an unsupported environment, exit.
+			return;
+		}
+
+		// Setup
+		div = document.createElement( "div" );
+		container = document.createElement( "div" );
+		container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+		body.appendChild( container ).appendChild( div );
+
+		div.style.cssText =
+			// Support: Firefox<29, Android 2.3
+			// Vendor-prefix box-sizing
+			"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
+			"box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
+			"border:1px;padding:1px;width:4px;position:absolute";
+
+		// Support: IE<9
+		// Assume reasonable values in the absence of getComputedStyle
+		pixelPositionVal = boxSizingReliableVal = false;
+		reliableMarginRightVal = true;
+
+		// Check for getComputedStyle so that this code is not run in IE<9.
+		if ( window.getComputedStyle ) {
+			pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+			boxSizingReliableVal =
+				( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+
+			// Support: Android 2.3
+			// Div with explicit width and no margin-right incorrectly
+			// gets computed margin-right based on width of container (#3333)
+			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+			contents = div.appendChild( document.createElement( "div" ) );
+
+			// Reset CSS: box-sizing; display; margin; border; padding
+			contents.style.cssText = div.style.cssText =
+				// Support: Firefox<29, Android 2.3
+				// Vendor-prefix box-sizing
+				"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
+				"box-sizing:content-box;display:block;margin:0;border:0;padding:0";
+			contents.style.marginRight = contents.style.width = "0";
+			div.style.width = "1px";
+
+			reliableMarginRightVal =
+				!parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
+		}
+
+		// Support: IE8
+		// Check if table cells still have offsetWidth/Height when they are set
+		// to display:none and there are still other visible table cells in a
+		// table row; if so, offsetWidth/Height are not reliable for use when
+		// determining if an element has been hidden directly using
+		// display:none (it is still safe to use offsets if a parent element is
+		// hidden; don safety goggles and see bug #4512 for more information).
+		div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
+		contents = div.getElementsByTagName( "td" );
+		contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
+		reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
+		if ( reliableHiddenOffsetsVal ) {
+			contents[ 0 ].style.display = "";
+			contents[ 1 ].style.display = "none";
+			reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
+		}
+
+		body.removeChild( container );
+	}
+
+})();
+
+
+// A method for quickly swapping in/out CSS properties to get correct calculations.
+jQuery.swap = function( elem, options, callback, args ) {
+	var ret, name,
+		old = {};
+
+	// Remember the old values, and insert the new ones
+	for ( name in options ) {
+		old[ name ] = elem.style[ name ];
+		elem.style[ name ] = options[ name ];
+	}
+
+	ret = callback.apply( elem, args || [] );
+
+	// Revert the old values
+	for ( name in options ) {
+		elem.style[ name ] = old[ name ];
+	}
+
+	return ret;
+};
+
+
+var
+		ralpha = /alpha\([^)]*\)/i,
+	ropacity = /opacity\s*=\s*([^)]*)/,
+
+	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
+	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
+
+	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+	cssNormalTransform = {
+		letterSpacing: "0",
+		fontWeight: "400"
+	},
+
+	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
+
+
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+	// shortcut for names that are not vendor prefixed
+	if ( name in style ) {
+		return name;
+	}
+
+	// check for vendor prefixed names
+	var capName = name.charAt(0).toUpperCase() + name.slice(1),
+		origName = name,
+		i = cssPrefixes.length;
+
+	while ( i-- ) {
+		name = cssPrefixes[ i ] + capName;
+		if ( name in style ) {
+			return name;
+		}
+	}
+
+	return origName;
+}
+
+function showHide( elements, show ) {
+	var display, elem, hidden,
+		values = [],
+		index = 0,
+		length = elements.length;
+
+	for ( ; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+
+		values[ index ] = jQuery._data( elem, "olddisplay" );
+		display = elem.style.display;
+		if ( show ) {
+			// Reset the inline display of this element to learn if it is
+			// being hidden by cascaded rules or not
+			if ( !values[ index ] && display === "none" ) {
+				elem.style.display = "";
+			}
+
+			// Set elements which have been overridden with display: none
+			// in a stylesheet to whatever the default browser style is
+			// for such an element
+			if ( elem.style.display === "" && isHidden( elem ) ) {
+				values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+			}
+		} else {
+			hidden = isHidden( elem );
+
+			if ( display && display !== "none" || !hidden ) {
+				jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
+			}
+		}
+	}
+
+	// Set the display of most of the elements in a second loop
+	// to avoid the constant reflow
+	for ( index = 0; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+			elem.style.display = show ? values[ index ] || "" : "none";
+		}
+	}
+
+	return elements;
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+	var matches = rnumsplit.exec( value );
+	return matches ?
+		// Guard against undefined "subtract", e.g., when used as in cssHooks
+		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+		value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+	var i = extra === ( isBorderBox ? "border" : "content" ) ?
+		// If we already have the right measurement, avoid augmentation
+		4 :
+		// Otherwise initialize for horizontal or vertical properties
+		name === "width" ? 1 : 0,
+
+		val = 0;
+
+	for ( ; i < 4; i += 2 ) {
+		// both box models exclude margin, so add it if we want it
+		if ( extra === "margin" ) {
+			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+		}
+
+		if ( isBorderBox ) {
+			// border-box includes padding, so remove it if we want content
+			if ( extra === "content" ) {
+				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+			}
+
+			// at this point, extra isn't border nor margin, so remove border
+			if ( extra !== "margin" ) {
+				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+			}
+		} else {
+			// at this point, extra isn't content, so add padding
+			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+			// at this point, extra isn't content nor padding, so add border
+			if ( extra !== "padding" ) {
+				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+			}
+		}
+	}
+
+	return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+	// Start with offset property, which is equivalent to the border-box value
+	var valueIsBorderBox = true,
+		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+		styles = getStyles( elem ),
+		isBorderBox = support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+	// some non-html elements return undefined for offsetWidth, so check for null/undefined
+	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+	if ( val <= 0 || val == null ) {
+		// Fall back to computed then uncomputed css if necessary
+		val = curCSS( elem, name, styles );
+		if ( val < 0 || val == null ) {
+			val = elem.style[ name ];
+		}
+
+		// Computed unit is not pixels. Stop here and return.
+		if ( rnumnonpx.test(val) ) {
+			return val;
+		}
+
+		// we need the check for style in case a browser which returns unreliable values
+		// for getComputedStyle silently falls back to the reliable elem.style
+		valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );
+
+		// Normalize "", auto, and prepare for extra
+		val = parseFloat( val ) || 0;
+	}
+
+	// use the active box-sizing model to add/subtract irrelevant styles
+	return ( val +
+		augmentWidthOrHeight(
+			elem,
+			name,
+			extra || ( isBorderBox ? "border" : "content" ),
+			valueIsBorderBox,
+			styles
+		)
+	) + "px";
+}
+
+jQuery.extend({
+	// Add in style property hooks for overriding the default
+	// behavior of getting and setting a style property
+	cssHooks: {
+		opacity: {
+			get: function( elem, computed ) {
+				if ( computed ) {
+					// We should always get a number back from opacity
+					var ret = curCSS( elem, "opacity" );
+					return ret === "" ? "1" : ret;
+				}
+			}
+		}
+	},
+
+	// Don't automatically add "px" to these possibly-unitless properties
+	cssNumber: {
+		"columnCount": true,
+		"fillOpacity": true,
+		"flexGrow": true,
+		"flexShrink": true,
+		"fontWeight": true,
+		"lineHeight": true,
+		"opacity": true,
+		"order": true,
+		"orphans": true,
+		"widows": true,
+		"zIndex": true,
+		"zoom": true
+	},
+
+	// Add in properties whose names you wish to fix before
+	// setting or getting the value
+	cssProps: {
+		// normalize float css property
+		"float": support.cssFloat ? "cssFloat" : "styleFloat"
+	},
+
+	// Get and set the style property on a DOM Node
+	style: function( elem, name, value, extra ) {
+		// Don't set styles on text and comment nodes
+		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+			return;
+		}
+
+		// Make sure that we're working with the right name
+		var ret, type, hooks,
+			origName = jQuery.camelCase( name ),
+			style = elem.style;
+
+		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+		// gets hook for the prefixed version
+		// followed by the unprefixed version
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// Check if we're setting a value
+		if ( value !== undefined ) {
+			type = typeof value;
+
+			// convert relative number strings (+= or -=) to relative numbers. #7345
+			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+				// Fixes bug #9237
+				type = "number";
+			}
+
+			// Make sure that null and NaN values aren't set. See: #7116
+			if ( value == null || value !== value ) {
+				return;
+			}
+
+			// If a number was passed in, add 'px' to the (except for certain CSS properties)
+			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+				value += "px";
+			}
+
+			// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
+			// but it would mean to define eight (for every problematic property) identical functions
+			if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
+				style[ name ] = "inherit";
+			}
+
+			// If a hook was provided, use that value, otherwise just set the specified value
+			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+
+				// Support: IE
+				// Swallow errors from 'invalid' CSS values (#5509)
+				try {
+					style[ name ] = value;
+				} catch(e) {}
+			}
+
+		} else {
+			// If a hook was provided get the non-computed value from there
+			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+				return ret;
+			}
+
+			// Otherwise just get the value from the style object
+			return style[ name ];
+		}
+	},
+
+	css: function( elem, name, extra, styles ) {
+		var num, val, hooks,
+			origName = jQuery.camelCase( name );
+
+		// Make sure that we're working with the right name
+		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+		// gets hook for the prefixed version
+		// followed by the unprefixed version
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// If a hook was provided get the computed value from there
+		if ( hooks && "get" in hooks ) {
+			val = hooks.get( elem, true, extra );
+		}
+
+		// Otherwise, if a way to get the computed value exists, use that
+		if ( val === undefined ) {
+			val = curCSS( elem, name, styles );
+		}
+
+		//convert "normal" to computed value
+		if ( val === "normal" && name in cssNormalTransform ) {
+			val = cssNormalTransform[ name ];
+		}
+
+		// Return, converting to number if forced or a qualifier was provided and val looks numeric
+		if ( extra === "" || extra ) {
+			num = parseFloat( val );
+			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
+		}
+		return val;
+	}
+});
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+	jQuery.cssHooks[ name ] = {
+		get: function( elem, computed, extra ) {
+			if ( computed ) {
+				// certain elements can have dimension info if we invisibly show them
+				// however, it must have a current display style that would benefit from this
+				return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
+					jQuery.swap( elem, cssShow, function() {
+						return getWidthOrHeight( elem, name, extra );
+					}) :
+					getWidthOrHeight( elem, name, extra );
+			}
+		},
+
+		set: function( elem, value, extra ) {
+			var styles = extra && getStyles( elem );
+			return setPositiveNumber( elem, value, extra ?
+				augmentWidthOrHeight(
+					elem,
+					name,
+					extra,
+					support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+					styles
+				) : 0
+			);
+		}
+	};
+});
+
+if ( !support.opacity ) {
+	jQuery.cssHooks.opacity = {
+		get: function( elem, computed ) {
+			// IE uses filters for opacity
+			return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+				( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
+				computed ? "1" : "";
+		},
+
+		set: function( elem, value ) {
+			var style = elem.style,
+				currentStyle = elem.currentStyle,
+				opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+				filter = currentStyle && currentStyle.filter || style.filter || "";
+
+			// IE has trouble with opacity if it does not have layout
+			// Force it by setting the zoom level
+			style.zoom = 1;
+
+			// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+			// if value === "", then remove inline opacity #12685
+			if ( ( value >= 1 || value === "" ) &&
+					jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
+					style.removeAttribute ) {
+
+				// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+				// if "filter:" is present at all, clearType is disabled, we want to avoid this
+				// style.removeAttribute is IE Only, but so apparently is this code path...
+				style.removeAttribute( "filter" );
+
+				// if there is no filter style applied in a css rule or unset inline opacity, we are done
+				if ( value === "" || currentStyle && !currentStyle.filter ) {
+					return;
+				}
+			}
+
+			// otherwise, set new filter values
+			style.filter = ralpha.test( filter ) ?
+				filter.replace( ralpha, opacity ) :
+				filter + " " + opacity;
+		}
+	};
+}
+
+jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
+	function( elem, computed ) {
+		if ( computed ) {
+			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+			// Work around by temporarily setting element display to inline-block
+			return jQuery.swap( elem, { "display": "inline-block" },
+				curCSS, [ elem, "marginRight" ] );
+		}
+	}
+);
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+	margin: "",
+	padding: "",
+	border: "Width"
+}, function( prefix, suffix ) {
+	jQuery.cssHooks[ prefix + suffix ] = {
+		expand: function( value ) {
+			var i = 0,
+				expanded = {},
+
+				// assumes a single number if not a string
+				parts = typeof value === "string" ? value.split(" ") : [ value ];
+
+			for ( ; i < 4; i++ ) {
+				expanded[ prefix + cssExpand[ i ] + suffix ] =
+					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+			}
+
+			return expanded;
+		}
+	};
+
+	if ( !rmargin.test( prefix ) ) {
+		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+	}
+});
+
+jQuery.fn.extend({
+	css: function( name, value ) {
+		return access( this, function( elem, name, value ) {
+			var styles, len,
+				map = {},
+				i = 0;
+
+			if ( jQuery.isArray( name ) ) {
+				styles = getStyles( elem );
+				len = name.length;
+
+				for ( ; i < len; i++ ) {
+					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+				}
+
+				return map;
+			}
+
+			return value !== undefined ?
+				jQuery.style( elem, name, value ) :
+				jQuery.css( elem, name );
+		}, name, value, arguments.length > 1 );
+	},
+	show: function() {
+		return showHide( this, true );
+	},
+	hide: function() {
+		return showHide( this );
+	},
+	toggle: function( state ) {
+		if ( typeof state === "boolean" ) {
+			return state ? this.show() : this.hide();
+		}
+
+		return this.each(function() {
+			if ( isHidden( this ) ) {
+				jQuery( this ).show();
+			} else {
+				jQuery( this ).hide();
+			}
+		});
+	}
+});
+
+
+function Tween( elem, options, prop, end, easing ) {
+	return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+	constructor: Tween,
+	init: function( elem, options, prop, end, easing, unit ) {
+		this.elem = elem;
+		this.prop = prop;
+		this.easing = easing || "swing";
+		this.options = options;
+		this.start = this.now = this.cur();
+		this.end = end;
+		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+	},
+	cur: function() {
+		var hooks = Tween.propHooks[ this.prop ];
+
+		return hooks && hooks.get ?
+			hooks.get( this ) :
+			Tween.propHooks._default.get( this );
+	},
+	run: function( percent ) {
+		var eased,
+			hooks = Tween.propHooks[ this.prop ];
+
+		if ( this.options.duration ) {
+			this.pos = eased = jQuery.easing[ this.easing ](
+				percent, this.options.duration * percent, 0, 1, this.options.duration
+			);
+		} else {
+			this.pos = eased = percent;
+		}
+		this.now = ( this.end - this.start ) * eased + this.start;
+
+		if ( this.options.step ) {
+			this.options.step.call( this.elem, this.now, this );
+		}
+
+		if ( hooks && hooks.set ) {
+			hooks.set( this );
+		} else {
+			Tween.propHooks._default.set( this );
+		}
+		return this;
+	}
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+	_default: {
+		get: function( tween ) {
+			var result;
+
+			if ( tween.elem[ tween.prop ] != null &&
+				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+				return tween.elem[ tween.prop ];
+			}
+
+			// passing an empty string as a 3rd parameter to .css will automatically
+			// attempt a parseFloat and fallback to a string if the parse fails
+			// so, simple values such as "10px" are parsed to Float.
+			// complex values such as "rotate(1rad)" are returned as is.
+			result = jQuery.css( tween.elem, tween.prop, "" );
+			// Empty strings, null, undefined and "auto" are converted to 0.
+			return !result || result === "auto" ? 0 : result;
+		},
+		set: function( tween ) {
+			// use step hook for back compat - use cssHook if its there - use .style if its
+			// available and use plain properties where available
+			if ( jQuery.fx.step[ tween.prop ] ) {
+				jQuery.fx.step[ tween.prop ]( tween );
+			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+			} else {
+				tween.elem[ tween.prop ] = tween.now;
+			}
+		}
+	}
+};
+
+// Support: IE <=9
+// Panic based approach to setting things on disconnected nodes
+
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+	set: function( tween ) {
+		if ( tween.elem.nodeType && tween.elem.parentNode ) {
+			tween.elem[ tween.prop ] = tween.now;
+		}
+	}
+};
+
+jQuery.easing = {
+	linear: function( p ) {
+		return p;
+	},
+	swing: function( p ) {
+		return 0.5 - Math.cos( p * Math.PI ) / 2;
+	}
+};
+
+jQuery.fx = Tween.prototype.init;
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+
+
+
+var
+	fxNow, timerId,
+	rfxtypes = /^(?:toggle|show|hide)$/,
+	rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
+	rrun = /queueHooks$/,
+	animationPrefilters = [ defaultPrefilter ],
+	tweeners = {
+		"*": [ function( prop, value ) {
+			var tween = this.createTween( prop, value ),
+				target = tween.cur(),
+				parts = rfxnum.exec( value ),
+				unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+				// Starting value computation is required for potential unit mismatches
+				start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
+					rfxnum.exec( jQuery.css( tween.elem, prop ) ),
+				scale = 1,
+				maxIterations = 20;
+
+			if ( start && start[ 3 ] !== unit ) {
+				// Trust units reported by jQuery.css
+				unit = unit || start[ 3 ];
+
+				// Make sure we update the tween properties later on
+				parts = parts || [];
+
+				// Iteratively approximate from a nonzero starting point
+				start = +target || 1;
+
+				do {
+					// If previous iteration zeroed out, double until we get *something*
+					// Use a string for doubling factor so we don't accidentally see scale as unchanged below
+					scale = scale || ".5";
+
+					// Adjust and apply
+					start = start / scale;
+					jQuery.style( tween.elem, prop, start + unit );
+
+				// Update scale, tolerating zero or NaN from tween.cur()
+				// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+			}
+
+			// Update tween properties
+			if ( parts ) {
+				start = tween.start = +start || +target || 0;
+				tween.unit = unit;
+				// If a +=/-= token was provided, we're doing a relative animation
+				tween.end = parts[ 1 ] ?
+					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
+					+parts[ 2 ];
+			}
+
+			return tween;
+		} ]
+	};
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+	setTimeout(function() {
+		fxNow = undefined;
+	});
+	return ( fxNow = jQuery.now() );
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+	var which,
+		attrs = { height: type },
+		i = 0;
+
+	// if we include width, step value is 1 to do all cssExpand values,
+	// if we don't include width, step value is 2 to skip over Left and Right
+	includeWidth = includeWidth ? 1 : 0;
+	for ( ; i < 4 ; i += 2 - includeWidth ) {
+		which = cssExpand[ i ];
+		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+	}
+
+	if ( includeWidth ) {
+		attrs.opacity = attrs.width = type;
+	}
+
+	return attrs;
+}
+
+function createTween( value, prop, animation ) {
+	var tween,
+		collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+		index = 0,
+		length = collection.length;
+	for ( ; index < length; index++ ) {
+		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
+
+			// we're done with this property
+			return tween;
+		}
+	}
+}
+
+function defaultPrefilter( elem, props, opts ) {
+	/* jshint validthis: true */
+	var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
+		anim = this,
+		orig = {},
+		style = elem.style,
+		hidden = elem.nodeType && isHidden( elem ),
+		dataShow = jQuery._data( elem, "fxshow" );
+
+	// handle queue: false promises
+	if ( !opts.queue ) {
+		hooks = jQuery._queueHooks( elem, "fx" );
+		if ( hooks.unqueued == null ) {
+			hooks.unqueued = 0;
+			oldfire = hooks.empty.fire;
+			hooks.empty.fire = function() {
+				if ( !hooks.unqueued ) {
+					oldfire();
+				}
+			};
+		}
+		hooks.unqueued++;
+
+		anim.always(function() {
+			// doing this makes sure that the complete handler will be called
+			// before this completes
+			anim.always(function() {
+				hooks.unqueued--;
+				if ( !jQuery.queue( elem, "fx" ).length ) {
+					hooks.empty.fire();
+				}
+			});
+		});
+	}
+
+	// height/width overflow pass
+	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+		// Make sure that nothing sneaks out
+		// Record all 3 overflow attributes because IE does not
+		// change the overflow attribute when overflowX and
+		// overflowY are set to the same value
+		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+		// Set display property to inline-block for height/width
+		// animations on inline elements that are having width/height animated
+		display = jQuery.css( elem, "display" );
+
+		// Test default display if display is currently "none"
+		checkDisplay = display === "none" ?
+			jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
+
+		if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
+
+			// inline-level elements accept inline-block;
+			// block-level elements need to be inline with layout
+			if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
+				style.display = "inline-block";
+			} else {
+				style.zoom = 1;
+			}
+		}
+	}
+
+	if ( opts.overflow ) {
+		style.overflow = "hidden";
+		if ( !support.shrinkWrapBlocks() ) {
+			anim.always(function() {
+				style.overflow = opts.overflow[ 0 ];
+				style.overflowX = opts.overflow[ 1 ];
+				style.overflowY = opts.overflow[ 2 ];
+			});
+		}
+	}
+
+	// show/hide pass
+	for ( prop in props ) {
+		value = props[ prop ];
+		if ( rfxtypes.exec( value ) ) {
+			delete props[ prop ];
+			toggle = toggle || value === "toggle";
+			if ( value === ( hidden ? "hide" : "show" ) ) {
+
+				// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
+				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+					hidden = true;
+				} else {
+					continue;
+				}
+			}
+			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+
+		// Any non-fx value stops us from restoring the original display value
+		} else {
+			display = undefined;
+		}
+	}
+
+	if ( !jQuery.isEmptyObject( orig ) ) {
+		if ( dataShow ) {
+			if ( "hidden" in dataShow ) {
+				hidden = dataShow.hidden;
+			}
+		} else {
+			dataShow = jQuery._data( elem, "fxshow", {} );
+		}
+
+		// store state if its toggle - enables .stop().toggle() to "reverse"
+		if ( toggle ) {
+			dataShow.hidden = !hidden;
+		}
+		if ( hidden ) {
+			jQuery( elem ).show();
+		} else {
+			anim.done(function() {
+				jQuery( elem ).hide();
+			});
+		}
+		anim.done(function() {
+			var prop;
+			jQuery._removeData( elem, "fxshow" );
+			for ( prop in orig ) {
+				jQuery.style( elem, prop, orig[ prop ] );
+			}
+		});
+		for ( prop in orig ) {
+			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+
+			if ( !( prop in dataShow ) ) {
+				dataShow[ prop ] = tween.start;
+				if ( hidden ) {
+					tween.end = tween.start;
+					tween.start = prop === "width" || prop === "height" ? 1 : 0;
+				}
+			}
+		}
+
+	// If this is a noop like .hide().hide(), restore an overwritten display value
+	} else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
+		style.display = display;
+	}
+}
+
+function propFilter( props, specialEasing ) {
+	var index, name, easing, value, hooks;
+
+	// camelCase, specialEasing and expand cssHook pass
+	for ( index in props ) {
+		name = jQuery.camelCase( index );
+		easing = specialEasing[ name ];
+		value = props[ index ];
+		if ( jQuery.isArray( value ) ) {
+			easing = value[ 1 ];
+			value = props[ index ] = value[ 0 ];
+		}
+
+		if ( index !== name ) {
+			props[ name ] = value;
+			delete props[ index ];
+		}
+
+		hooks = jQuery.cssHooks[ name ];
+		if ( hooks && "expand" in hooks ) {
+			value = hooks.expand( value );
+			delete props[ name ];
+
+			// not quite $.extend, this wont overwrite keys already present.
+			// also - reusing 'index' from above because we have the correct "name"
+			for ( index in value ) {
+				if ( !( index in props ) ) {
+					props[ index ] = value[ index ];
+					specialEasing[ index ] = easing;
+				}
+			}
+		} else {
+			specialEasing[ name ] = easing;
+		}
+	}
+}
+
+function Animation( elem, properties, options ) {
+	var result,
+		stopped,
+		index = 0,
+		length = animationPrefilters.length,
+		deferred = jQuery.Deferred().always( function() {
+			// don't match elem in the :animated selector
+			delete tick.elem;
+		}),
+		tick = function() {
+			if ( stopped ) {
+				return false;
+			}
+			var currentTime = fxNow || createFxNow(),
+				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+				// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+				temp = remaining / animation.duration || 0,
+				percent = 1 - temp,
+				index = 0,
+				length = animation.tweens.length;
+
+			for ( ; index < length ; index++ ) {
+				animation.tweens[ index ].run( percent );
+			}
+
+			deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+			if ( percent < 1 && length ) {
+				return remaining;
+			} else {
+				deferred.resolveWith( elem, [ animation ] );
+				return false;
+			}
+		},
+		animation = deferred.promise({
+			elem: elem,
+			props: jQuery.extend( {}, properties ),
+			opts: jQuery.extend( true, { specialEasing: {} }, options ),
+			originalProperties: properties,
+			originalOptions: options,
+			startTime: fxNow || createFxNow(),
+			duration: options.duration,
+			tweens: [],
+			createTween: function( prop, end ) {
+				var tween = jQuery.Tween( elem, animation.opts, prop, end,
+						animation.opts.specialEasing[ prop ] || animation.opts.easing );
+				animation.tweens.push( tween );
+				return tween;
+			},
+			stop: function( gotoEnd ) {
+				var index = 0,
+					// if we are going to the end, we want to run all the tweens
+					// otherwise we skip this part
+					length = gotoEnd ? animation.tweens.length : 0;
+				if ( stopped ) {
+					return this;
+				}
+				stopped = true;
+				for ( ; index < length ; index++ ) {
+					animation.tweens[ index ].run( 1 );
+				}
+
+				// resolve when we played the last frame
+				// otherwise, reject
+				if ( gotoEnd ) {
+					deferred.resolveWith( elem, [ animation, gotoEnd ] );
+				} else {
+					deferred.rejectWith( elem, [ animation, gotoEnd ] );
+				}
+				return this;
+			}
+		}),
+		props = animation.props;
+
+	propFilter( props, animation.opts.specialEasing );
+
+	for ( ; index < length ; index++ ) {
+		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+		if ( result ) {
+			return result;
+		}
+	}
+
+	jQuery.map( props, createTween, animation );
+
+	if ( jQuery.isFunction( animation.opts.start ) ) {
+		animation.opts.start.call( elem, animation );
+	}
+
+	jQuery.fx.timer(
+		jQuery.extend( tick, {
+			elem: elem,
+			anim: animation,
+			queue: animation.opts.queue
+		})
+	);
+
+	// attach callbacks from options
+	return animation.progress( animation.opts.progress )
+		.done( animation.opts.done, animation.opts.complete )
+		.fail( animation.opts.fail )
+		.always( animation.opts.always );
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+	tweener: function( props, callback ) {
+		if ( jQuery.isFunction( props ) ) {
+			callback = props;
+			props = [ "*" ];
+		} else {
+			props = props.split(" ");
+		}
+
+		var prop,
+			index = 0,
+			length = props.length;
+
+		for ( ; index < length ; index++ ) {
+			prop = props[ index ];
+			tweeners[ prop ] = tweeners[ prop ] || [];
+			tweeners[ prop ].unshift( callback );
+		}
+	},
+
+	prefilter: function( callback, prepend ) {
+		if ( prepend ) {
+			animationPrefilters.unshift( callback );
+		} else {
+			animationPrefilters.push( callback );
+		}
+	}
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+		complete: fn || !fn && easing ||
+			jQuery.isFunction( speed ) && speed,
+		duration: speed,
+		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+	};
+
+	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+	// normalize opt.queue - true/undefined/null -> "fx"
+	if ( opt.queue == null || opt.queue === true ) {
+		opt.queue = "fx";
+	}
+
+	// Queueing
+	opt.old = opt.complete;
+
+	opt.complete = function() {
+		if ( jQuery.isFunction( opt.old ) ) {
+			opt.old.call( this );
+		}
+
+		if ( opt.queue ) {
+			jQuery.dequeue( this, opt.queue );
+		}
+	};
+
+	return opt;
+};
+
+jQuery.fn.extend({
+	fadeTo: function( speed, to, easing, callback ) {
+
+		// show any hidden elements after setting opacity to 0
+		return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+			// animate to the value specified
+			.end().animate({ opacity: to }, speed, easing, callback );
+	},
+	animate: function( prop, speed, easing, callback ) {
+		var empty = jQuery.isEmptyObject( prop ),
+			optall = jQuery.speed( speed, easing, callback ),
+			doAnimation = function() {
+				// Operate on a copy of prop so per-property easing won't be lost
+				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+				// Empty animations, or finishing resolves immediately
+				if ( empty || jQuery._data( this, "finish" ) ) {
+					anim.stop( true );
+				}
+			};
+			doAnimation.finish = doAnimation;
+
+		return empty || optall.queue === false ?
+			this.each( doAnimation ) :
+			this.queue( optall.queue, doAnimation );
+	},
+	stop: function( type, clearQueue, gotoEnd ) {
+		var stopQueue = function( hooks ) {
+			var stop = hooks.stop;
+			delete hooks.stop;
+			stop( gotoEnd );
+		};
+
+		if ( typeof type !== "string" ) {
+			gotoEnd = clearQueue;
+			clearQueue = type;
+			type = undefined;
+		}
+		if ( clearQueue && type !== false ) {
+			this.queue( type || "fx", [] );
+		}
+
+		return this.each(function() {
+			var dequeue = true,
+				index = type != null && type + "queueHooks",
+				timers = jQuery.timers,
+				data = jQuery._data( this );
+
+			if ( index ) {
+				if ( data[ index ] && data[ index ].stop ) {
+					stopQueue( data[ index ] );
+				}
+			} else {
+				for ( index in data ) {
+					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+						stopQueue( data[ index ] );
+					}
+				}
+			}
+
+			for ( index = timers.length; index--; ) {
+				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+					timers[ index ].anim.stop( gotoEnd );
+					dequeue = false;
+					timers.splice( index, 1 );
+				}
+			}
+
+			// start the next in the queue if the last step wasn't forced
+			// timers currently will call their complete callbacks, which will dequeue
+			// but only if they were gotoEnd
+			if ( dequeue || !gotoEnd ) {
+				jQuery.dequeue( this, type );
+			}
+		});
+	},
+	finish: function( type ) {
+		if ( type !== false ) {
+			type = type || "fx";
+		}
+		return this.each(function() {
+			var index,
+				data = jQuery._data( this ),
+				queue = data[ type + "queue" ],
+				hooks = data[ type + "queueHooks" ],
+				timers = jQuery.timers,
+				length = queue ? queue.length : 0;
+
+			// enable finishing flag on private data
+			data.finish = true;
+
+			// empty the queue first
+			jQuery.queue( this, type, [] );
+
+			if ( hooks && hooks.stop ) {
+				hooks.stop.call( this, true );
+			}
+
+			// look for any active animations, and finish them
+			for ( index = timers.length; index--; ) {
+				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+					timers[ index ].anim.stop( true );
+					timers.splice( index, 1 );
+				}
+			}
+
+			// look for any animations in the old queue and finish them
+			for ( index = 0; index < length; index++ ) {
+				if ( queue[ index ] && queue[ index ].finish ) {
+					queue[ index ].finish.call( this );
+				}
+			}
+
+			// turn off finishing flag
+			delete data.finish;
+		});
+	}
+});
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+	var cssFn = jQuery.fn[ name ];
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return speed == null || typeof speed === "boolean" ?
+			cssFn.apply( this, arguments ) :
+			this.animate( genFx( name, true ), speed, easing, callback );
+	};
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+	slideDown: genFx("show"),
+	slideUp: genFx("hide"),
+	slideToggle: genFx("toggle"),
+	fadeIn: { opacity: "show" },
+	fadeOut: { opacity: "hide" },
+	fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return this.animate( props, speed, easing, callback );
+	};
+});
+
+jQuery.timers = [];
+jQuery.fx.tick = function() {
+	var timer,
+		timers = jQuery.timers,
+		i = 0;
+
+	fxNow = jQuery.now();
+
+	for ( ; i < timers.length; i++ ) {
+		timer = timers[ i ];
+		// Checks the timer has not already been removed
+		if ( !timer() && timers[ i ] === timer ) {
+			timers.splice( i--, 1 );
+		}
+	}
+
+	if ( !timers.length ) {
+		jQuery.fx.stop();
+	}
+	fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+	jQuery.timers.push( timer );
+	if ( timer() ) {
+		jQuery.fx.start();
+	} else {
+		jQuery.timers.pop();
+	}
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.start = function() {
+	if ( !timerId ) {
+		timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+	}
+};
+
+jQuery.fx.stop = function() {
+	clearInterval( timerId );
+	timerId = null;
+};
+
+jQuery.fx.speeds = {
+	slow: 600,
+	fast: 200,
+	// Default speed
+	_default: 400
+};
+
+
+// Based off of the plugin by Clint Helfers, with permission.
+// http://blindsignals.com/index.php/2009/07/jquery-delay/
+jQuery.fn.delay = function( time, type ) {
+	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+	type = type || "fx";
+
+	return this.queue( type, function( next, hooks ) {
+		var timeout = setTimeout( next, time );
+		hooks.stop = function() {
+			clearTimeout( timeout );
+		};
+	});
+};
+
+
+(function() {
+	// Minified: var a,b,c,d,e
+	var input, div, select, a, opt;
+
+	// Setup
+	div = document.createElement( "div" );
+	div.setAttribute( "className", "t" );
+	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+	a = div.getElementsByTagName("a")[ 0 ];
+
+	// First batch of tests.
+	select = document.createElement("select");
+	opt = select.appendChild( document.createElement("option") );
+	input = div.getElementsByTagName("input")[ 0 ];
+
+	a.style.cssText = "top:1px";
+
+	// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+	support.getSetAttribute = div.className !== "t";
+
+	// Get the style information from getAttribute
+	// (IE uses .cssText instead)
+	support.style = /top/.test( a.getAttribute("style") );
+
+	// Make sure that URLs aren't manipulated
+	// (IE normalizes it by default)
+	support.hrefNormalized = a.getAttribute("href") === "/a";
+
+	// Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
+	support.checkOn = !!input.value;
+
+	// Make sure that a selected-by-default option has a working selected property.
+	// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+	support.optSelected = opt.selected;
+
+	// Tests for enctype support on a form (#6743)
+	support.enctype = !!document.createElement("form").enctype;
+
+	// Make sure that the options inside disabled selects aren't marked as disabled
+	// (WebKit marks them as disabled)
+	select.disabled = true;
+	support.optDisabled = !opt.disabled;
+
+	// Support: IE8 only
+	// Check if we can trust getAttribute("value")
+	input = document.createElement( "input" );
+	input.setAttribute( "value", "" );
+	support.input = input.getAttribute( "value" ) === "";
+
+	// Check if an input maintains its value after becoming a radio
+	input.value = "t";
+	input.setAttribute( "type", "radio" );
+	support.radioValue = input.value === "t";
+})();
+
+
+var rreturn = /\r/g;
+
+jQuery.fn.extend({
+	val: function( value ) {
+		var hooks, ret, isFunction,
+			elem = this[0];
+
+		if ( !arguments.length ) {
+			if ( elem ) {
+				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+					return ret;
+				}
+
+				ret = elem.value;
+
+				return typeof ret === "string" ?
+					// handle most common string cases
+					ret.replace(rreturn, "") :
+					// handle cases where value is null/undef or number
+					ret == null ? "" : ret;
+			}
+
+			return;
+		}
+
+		isFunction = jQuery.isFunction( value );
+
+		return this.each(function( i ) {
+			var val;
+
+			if ( this.nodeType !== 1 ) {
+				return;
+			}
+
+			if ( isFunction ) {
+				val = value.call( this, i, jQuery( this ).val() );
+			} else {
+				val = value;
+			}
+
+			// Treat null/undefined as ""; convert numbers to string
+			if ( val == null ) {
+				val = "";
+			} else if ( typeof val === "number" ) {
+				val += "";
+			} else if ( jQuery.isArray( val ) ) {
+				val = jQuery.map( val, function( value ) {
+					return value == null ? "" : value + "";
+				});
+			}
+
+			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+			// If set returns undefined, fall back to normal setting
+			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+				this.value = val;
+			}
+		});
+	}
+});
+
+jQuery.extend({
+	valHooks: {
+		option: {
+			get: function( elem ) {
+				var val = jQuery.find.attr( elem, "value" );
+				return val != null ?
+					val :
+					// Support: IE10-11+
+					// option.text throws exceptions (#14686, #14858)
+					jQuery.trim( jQuery.text( elem ) );
+			}
+		},
+		select: {
+			get: function( elem ) {
+				var value, option,
+					options = elem.options,
+					index = elem.selectedIndex,
+					one = elem.type === "select-one" || index < 0,
+					values = one ? null : [],
+					max = one ? index + 1 : options.length,
+					i = index < 0 ?
+						max :
+						one ? index : 0;
+
+				// Loop through all the selected options
+				for ( ; i < max; i++ ) {
+					option = options[ i ];
+
+					// oldIE doesn't update selected after form reset (#2551)
+					if ( ( option.selected || i === index ) &&
+							// Don't return options that are disabled or in a disabled optgroup
+							( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
+							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+						// Get the specific value for the option
+						value = jQuery( option ).val();
+
+						// We don't need an array for one selects
+						if ( one ) {
+							return value;
+						}
+
+						// Multi-Selects return an array
+						values.push( value );
+					}
+				}
+
+				return values;
+			},
+
+			set: function( elem, value ) {
+				var optionSet, option,
+					options = elem.options,
+					values = jQuery.makeArray( value ),
+					i = options.length;
+
+				while ( i-- ) {
+					option = options[ i ];
+
+					if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {
+
+						// Support: IE6
+						// When new option element is added to select box we need to
+						// force reflow of newly added node in order to workaround delay
+						// of initialization properties
+						try {
+							option.selected = optionSet = true;
+
+						} catch ( _ ) {
+
+							// Will be executed only in IE6
+							option.scrollHeight;
+						}
+
+					} else {
+						option.selected = false;
+					}
+				}
+
+				// Force browsers to behave consistently when non-matching value is set
+				if ( !optionSet ) {
+					elem.selectedIndex = -1;
+				}
+
+				return options;
+			}
+		}
+	}
+});
+
+// Radios and checkboxes getter/setter
+jQuery.each([ "radio", "checkbox" ], function() {
+	jQuery.valHooks[ this ] = {
+		set: function( elem, value ) {
+			if ( jQuery.isArray( value ) ) {
+				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+			}
+		}
+	};
+	if ( !support.checkOn ) {
+		jQuery.valHooks[ this ].get = function( elem ) {
+			// Support: Webkit
+			// "" is returned instead of "on" if a value isn't specified
+			return elem.getAttribute("value") === null ? "on" : elem.value;
+		};
+	}
+});
+
+
+
+
+var nodeHook, boolHook,
+	attrHandle = jQuery.expr.attrHandle,
+	ruseDefault = /^(?:checked|selected)$/i,
+	getSetAttribute = support.getSetAttribute,
+	getSetInput = support.input;
+
+jQuery.fn.extend({
+	attr: function( name, value ) {
+		return access( this, jQuery.attr, name, value, arguments.length > 1 );
+	},
+
+	removeAttr: function( name ) {
+		return this.each(function() {
+			jQuery.removeAttr( this, name );
+		});
+	}
+});
+
+jQuery.extend({
+	attr: function( elem, name, value ) {
+		var hooks, ret,
+			nType = elem.nodeType;
+
+		// don't get/set attributes on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		// Fallback to prop when attributes are not supported
+		if ( typeof elem.getAttribute === strundefined ) {
+			return jQuery.prop( elem, name, value );
+		}
+
+		// All attributes are lowercase
+		// Grab necessary hook if one is defined
+		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+			name = name.toLowerCase();
+			hooks = jQuery.attrHooks[ name ] ||
+				( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
+		}
+
+		if ( value !== undefined ) {
+
+			if ( value === null ) {
+				jQuery.removeAttr( elem, name );
+
+			} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				elem.setAttribute( name, value + "" );
+				return value;
+			}
+
+		} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+			return ret;
+
+		} else {
+			ret = jQuery.find.attr( elem, name );
+
+			// Non-existent attributes return null, we normalize to undefined
+			return ret == null ?
+				undefined :
+				ret;
+		}
+	},
+
+	removeAttr: function( elem, value ) {
+		var name, propName,
+			i = 0,
+			attrNames = value && value.match( rnotwhite );
+
+		if ( attrNames && elem.nodeType === 1 ) {
+			while ( (name = attrNames[i++]) ) {
+				propName = jQuery.propFix[ name ] || name;
+
+				// Boolean attributes get special treatment (#10870)
+				if ( jQuery.expr.match.bool.test( name ) ) {
+					// Set corresponding property to false
+					if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+						elem[ propName ] = false;
+					// Support: IE<9
+					// Also clear defaultChecked/defaultSelected (if appropriate)
+					} else {
+						elem[ jQuery.camelCase( "default-" + name ) ] =
+							elem[ propName ] = false;
+					}
+
+				// See #9699 for explanation of this approach (setting first, then removal)
+				} else {
+					jQuery.attr( elem, name, "" );
+				}
+
+				elem.removeAttribute( getSetAttribute ? name : propName );
+			}
+		}
+	},
+
+	attrHooks: {
+		type: {
+			set: function( elem, value ) {
+				if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+					// Setting the type on a radio button after the value resets the value in IE6-9
+					// Reset value to default in case type is set after value during creation
+					var val = elem.value;
+					elem.setAttribute( "type", value );
+					if ( val ) {
+						elem.value = val;
+					}
+					return value;
+				}
+			}
+		}
+	}
+});
+
+// Hook for boolean attributes
+boolHook = {
+	set: function( elem, value, name ) {
+		if ( value === false ) {
+			// Remove boolean attributes when set to false
+			jQuery.removeAttr( elem, name );
+		} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+			// IE<8 needs the *property* name
+			elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
+
+		// Use defaultChecked and defaultSelected for oldIE
+		} else {
+			elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
+		}
+
+		return name;
+	}
+};
+
+// Retrieve booleans specially
+jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+
+	var getter = attrHandle[ name ] || jQuery.find.attr;
+
+	attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
+		function( elem, name, isXML ) {
+			var ret, handle;
+			if ( !isXML ) {
+				// Avoid an infinite loop by temporarily removing this function from the getter
+				handle = attrHandle[ name ];
+				attrHandle[ name ] = ret;
+				ret = getter( elem, name, isXML ) != null ?
+					name.toLowerCase() :
+					null;
+				attrHandle[ name ] = handle;
+			}
+			return ret;
+		} :
+		function( elem, name, isXML ) {
+			if ( !isXML ) {
+				return elem[ jQuery.camelCase( "default-" + name ) ] ?
+					name.toLowerCase() :
+					null;
+			}
+		};
+});
+
+// fix oldIE attroperties
+if ( !getSetInput || !getSetAttribute ) {
+	jQuery.attrHooks.value = {
+		set: function( elem, value, name ) {
+			if ( jQuery.nodeName( elem, "input" ) ) {
+				// Does not return so that setAttribute is also used
+				elem.defaultValue = value;
+			} else {
+				// Use nodeHook if defined (#1954); otherwise setAttribute is fine
+				return nodeHook && nodeHook.set( elem, value, name );
+			}
+		}
+	};
+}
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+	// Use this for any attribute in IE6/7
+	// This fixes almost every IE6/7 issue
+	nodeHook = {
+		set: function( elem, value, name ) {
+			// Set the existing or create a new attribute node
+			var ret = elem.getAttributeNode( name );
+			if ( !ret ) {
+				elem.setAttributeNode(
+					(ret = elem.ownerDocument.createAttribute( name ))
+				);
+			}
+
+			ret.value = value += "";
+
+			// Break association with cloned elements by also using setAttribute (#9646)
+			if ( name === "value" || value === elem.getAttribute( name ) ) {
+				return value;
+			}
+		}
+	};
+
+	// Some attributes are constructed with empty-string values when not defined
+	attrHandle.id = attrHandle.name = attrHandle.coords =
+		function( elem, name, isXML ) {
+			var ret;
+			if ( !isXML ) {
+				return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
+					ret.value :
+					null;
+			}
+		};
+
+	// Fixing value retrieval on a button requires this module
+	jQuery.valHooks.button = {
+		get: function( elem, name ) {
+			var ret = elem.getAttributeNode( name );
+			if ( ret && ret.specified ) {
+				return ret.value;
+			}
+		},
+		set: nodeHook.set
+	};
+
+	// Set contenteditable to false on removals(#10429)
+	// Setting to empty string throws an error as an invalid value
+	jQuery.attrHooks.contenteditable = {
+		set: function( elem, value, name ) {
+			nodeHook.set( elem, value === "" ? false : value, name );
+		}
+	};
+
+	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
+	// This is for removals
+	jQuery.each([ "width", "height" ], function( i, name ) {
+		jQuery.attrHooks[ name ] = {
+			set: function( elem, value ) {
+				if ( value === "" ) {
+					elem.setAttribute( name, "auto" );
+					return value;
+				}
+			}
+		};
+	});
+}
+
+if ( !support.style ) {
+	jQuery.attrHooks.style = {
+		get: function( elem ) {
+			// Return undefined in the case of empty string
+			// Note: IE uppercases css property names, but if we were to .toLowerCase()
+			// .cssText, that would destroy case senstitivity in URL's, like in "background"
+			return elem.style.cssText || undefined;
+		},
+		set: function( elem, value ) {
+			return ( elem.style.cssText = value + "" );
+		}
+	};
+}
+
+
+
+
+var rfocusable = /^(?:input|select|textarea|button|object)$/i,
+	rclickable = /^(?:a|area)$/i;
+
+jQuery.fn.extend({
+	prop: function( name, value ) {
+		return access( this, jQuery.prop, name, value, arguments.length > 1 );
+	},
+
+	removeProp: function( name ) {
+		name = jQuery.propFix[ name ] || name;
+		return this.each(function() {
+			// try/catch handles cases where IE balks (such as removing a property on window)
+			try {
+				this[ name ] = undefined;
+				delete this[ name ];
+			} catch( e ) {}
+		});
+	}
+});
+
+jQuery.extend({
+	propFix: {
+		"for": "htmlFor",
+		"class": "className"
+	},
+
+	prop: function( elem, name, value ) {
+		var ret, hooks, notxml,
+			nType = elem.nodeType;
+
+		// don't get/set properties on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+		if ( notxml ) {
+			// Fix name and attach hooks
+			name = jQuery.propFix[ name ] || name;
+			hooks = jQuery.propHooks[ name ];
+		}
+
+		if ( value !== undefined ) {
+			return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
+				ret :
+				( elem[ name ] = value );
+
+		} else {
+			return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
+				ret :
+				elem[ name ];
+		}
+	},
+
+	propHooks: {
+		tabIndex: {
+			get: function( elem ) {
+				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+				// Use proper attribute retrieval(#12072)
+				var tabindex = jQuery.find.attr( elem, "tabindex" );
+
+				return tabindex ?
+					parseInt( tabindex, 10 ) :
+					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+						0 :
+						-1;
+			}
+		}
+	}
+});
+
+// Some attributes require a special call on IE
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !support.hrefNormalized ) {
+	// href/src property should get the full normalized URL (#10299/#12915)
+	jQuery.each([ "href", "src" ], function( i, name ) {
+		jQuery.propHooks[ name ] = {
+			get: function( elem ) {
+				return elem.getAttribute( name, 4 );
+			}
+		};
+	});
+}
+
+// Support: Safari, IE9+
+// mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !support.optSelected ) {
+	jQuery.propHooks.selected = {
+		get: function( elem ) {
+			var parent = elem.parentNode;
+
+			if ( parent ) {
+				parent.selectedIndex;
+
+				// Make sure that it also works with optgroups, see #5701
+				if ( parent.parentNode ) {
+					parent.parentNode.selectedIndex;
+				}
+			}
+			return null;
+		}
+	};
+}
+
+jQuery.each([
+	"tabIndex",
+	"readOnly",
+	"maxLength",
+	"cellSpacing",
+	"cellPadding",
+	"rowSpan",
+	"colSpan",
+	"useMap",
+	"frameBorder",
+	"contentEditable"
+], function() {
+	jQuery.propFix[ this.toLowerCase() ] = this;
+});
+
+// IE6/7 call enctype encoding
+if ( !support.enctype ) {
+	jQuery.propFix.enctype = "encoding";
+}
+
+
+
+
+var rclass = /[\t\r\n\f]/g;
+
+jQuery.fn.extend({
+	addClass: function( value ) {
+		var classes, elem, cur, clazz, j, finalValue,
+			i = 0,
+			len = this.length,
+			proceed = typeof value === "string" && value;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).addClass( value.call( this, j, this.className ) );
+			});
+		}
+
+		if ( proceed ) {
+			// The disjunction here is for better compressibility (see removeClass)
+			classes = ( value || "" ).match( rnotwhite ) || [];
+
+			for ( ; i < len; i++ ) {
+				elem = this[ i ];
+				cur = elem.nodeType === 1 && ( elem.className ?
+					( " " + elem.className + " " ).replace( rclass, " " ) :
+					" "
+				);
+
+				if ( cur ) {
+					j = 0;
+					while ( (clazz = classes[j++]) ) {
+						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+							cur += clazz + " ";
+						}
+					}
+
+					// only assign if different to avoid unneeded rendering.
+					finalValue = jQuery.trim( cur );
+					if ( elem.className !== finalValue ) {
+						elem.className = finalValue;
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	removeClass: function( value ) {
+		var classes, elem, cur, clazz, j, finalValue,
+			i = 0,
+			len = this.length,
+			proceed = arguments.length === 0 || typeof value === "string" && value;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).removeClass( value.call( this, j, this.className ) );
+			});
+		}
+		if ( proceed ) {
+			classes = ( value || "" ).match( rnotwhite ) || [];
+
+			for ( ; i < len; i++ ) {
+				elem = this[ i ];
+				// This expression is here for better compressibility (see addClass)
+				cur = elem.nodeType === 1 && ( elem.className ?
+					( " " + elem.className + " " ).replace( rclass, " " ) :
+					""
+				);
+
+				if ( cur ) {
+					j = 0;
+					while ( (clazz = classes[j++]) ) {
+						// Remove *all* instances
+						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+							cur = cur.replace( " " + clazz + " ", " " );
+						}
+					}
+
+					// only assign if different to avoid unneeded rendering.
+					finalValue = value ? jQuery.trim( cur ) : "";
+					if ( elem.className !== finalValue ) {
+						elem.className = finalValue;
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	toggleClass: function( value, stateVal ) {
+		var type = typeof value;
+
+		if ( typeof stateVal === "boolean" && type === "string" ) {
+			return stateVal ? this.addClass( value ) : this.removeClass( value );
+		}
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( i ) {
+				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+			});
+		}
+
+		return this.each(function() {
+			if ( type === "string" ) {
+				// toggle individual class names
+				var className,
+					i = 0,
+					self = jQuery( this ),
+					classNames = value.match( rnotwhite ) || [];
+
+				while ( (className = classNames[ i++ ]) ) {
+					// check each className given, space separated list
+					if ( self.hasClass( className ) ) {
+						self.removeClass( className );
+					} else {
+						self.addClass( className );
+					}
+				}
+
+			// Toggle whole class name
+			} else if ( type === strundefined || type === "boolean" ) {
+				if ( this.className ) {
+					// store className if set
+					jQuery._data( this, "__className__", this.className );
+				}
+
+				// If the element has a class name or if we're passed "false",
+				// then remove the whole classname (if there was one, the above saved it).
+				// Otherwise bring back whatever was previously saved (if anything),
+				// falling back to the empty string if nothing was stored.
+				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+			}
+		});
+	},
+
+	hasClass: function( selector ) {
+		var className = " " + selector + " ",
+			i = 0,
+			l = this.length;
+		for ( ; i < l; i++ ) {
+			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+});
+
+
+
+
+// Return jQuery for attributes-only inclusion
+
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+	// Handle event binding
+	jQuery.fn[ name ] = function( data, fn ) {
+		return arguments.length > 0 ?
+			this.on( name, null, data, fn ) :
+			this.trigger( name );
+	};
+});
+
+jQuery.fn.extend({
+	hover: function( fnOver, fnOut ) {
+		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+	},
+
+	bind: function( types, data, fn ) {
+		return this.on( types, null, data, fn );
+	},
+	unbind: function( types, fn ) {
+		return this.off( types, null, fn );
+	},
+
+	delegate: function( selector, types, data, fn ) {
+		return this.on( types, selector, data, fn );
+	},
+	undelegate: function( selector, types, fn ) {
+		// ( namespace ) or ( selector, types [, fn] )
+		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+	}
+});
+
+
+var nonce = jQuery.now();
+
+var rquery = (/\?/);
+
+
+
+var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
+
+jQuery.parseJSON = function( data ) {
+	// Attempt to parse using the native JSON parser first
+	if ( window.JSON && window.JSON.parse ) {
+		// Support: Android 2.3
+		// Workaround failure to string-cast null input
+		return window.JSON.parse( data + "" );
+	}
+
+	var requireNonComma,
+		depth = null,
+		str = jQuery.trim( data + "" );
+
+	// Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
+	// after removing valid tokens
+	return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
+
+		// Force termination if we see a misplaced comma
+		if ( requireNonComma && comma ) {
+			depth = 0;
+		}
+
+		// Perform no more replacements after returning to outermost depth
+		if ( depth === 0 ) {
+			return token;
+		}
+
+		// Commas must not follow "[", "{", or ","
+		requireNonComma = open || comma;
+
+		// Determine new depth
+		// array/object open ("[" or "{"): depth += true - false (increment)
+		// array/object close ("]" or "}"): depth += false - true (decrement)
+		// other cases ("," or primitive): depth += true - true (numeric cast)
+		depth += !close - !open;
+
+		// Remove this token
+		return "";
+	}) ) ?
+		( Function( "return " + str ) )() :
+		jQuery.error( "Invalid JSON: " + data );
+};
+
+
+// Cross-browser xml parsing
+jQuery.parseXML = function( data ) {
+	var xml, tmp;
+	if ( !data || typeof data !== "string" ) {
+		return null;
+	}
+	try {
+		if ( window.DOMParser ) { // Standard
+			tmp = new DOMParser();
+			xml = tmp.parseFromString( data, "text/xml" );
+		} else { // IE
+			xml = new ActiveXObject( "Microsoft.XMLDOM" );
+			xml.async = "false";
+			xml.loadXML( data );
+		}
+	} catch( e ) {
+		xml = undefined;
+	}
+	if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+		jQuery.error( "Invalid XML: " + data );
+	}
+	return xml;
+};
+
+
+var
+	// Document location
+	ajaxLocParts,
+	ajaxLocation,
+
+	rhash = /#.*$/,
+	rts = /([?&])_=[^&]*/,
+	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+	// #7653, #8125, #8152: local protocol detection
+	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+	rnoContent = /^(?:GET|HEAD)$/,
+	rprotocol = /^\/\//,
+	rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
+
+	/* Prefilters
+	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+	 * 2) These are called:
+	 *    - BEFORE asking for a transport
+	 *    - AFTER param serialization (s.data is a string if s.processData is true)
+	 * 3) key is the dataType
+	 * 4) the catchall symbol "*" can be used
+	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+	 */
+	prefilters = {},
+
+	/* Transports bindings
+	 * 1) key is the dataType
+	 * 2) the catchall symbol "*" can be used
+	 * 3) selection will start with transport dataType and THEN go to "*" if needed
+	 */
+	transports = {},
+
+	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+	allTypes = "*/".concat("*");
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+	ajaxLocation = location.href;
+} catch( e ) {
+	// Use the href attribute of an A element
+	// since IE will modify it given document.location
+	ajaxLocation = document.createElement( "a" );
+	ajaxLocation.href = "";
+	ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+	// dataTypeExpression is optional and defaults to "*"
+	return function( dataTypeExpression, func ) {
+
+		if ( typeof dataTypeExpression !== "string" ) {
+			func = dataTypeExpression;
+			dataTypeExpression = "*";
+		}
+
+		var dataType,
+			i = 0,
+			dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
+
+		if ( jQuery.isFunction( func ) ) {
+			// For each dataType in the dataTypeExpression
+			while ( (dataType = dataTypes[i++]) ) {
+				// Prepend if requested
+				if ( dataType.charAt( 0 ) === "+" ) {
+					dataType = dataType.slice( 1 ) || "*";
+					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+
+				// Otherwise append
+				} else {
+					(structure[ dataType ] = structure[ dataType ] || []).push( func );
+				}
+			}
+		}
+	};
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+	var inspected = {},
+		seekingTransport = ( structure === transports );
+
+	function inspect( dataType ) {
+		var selected;
+		inspected[ dataType ] = true;
+		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+			if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+				options.dataTypes.unshift( dataTypeOrTransport );
+				inspect( dataTypeOrTransport );
+				return false;
+			} else if ( seekingTransport ) {
+				return !( selected = dataTypeOrTransport );
+			}
+		});
+		return selected;
+	}
+
+	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+	var deep, key,
+		flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+	for ( key in src ) {
+		if ( src[ key ] !== undefined ) {
+			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+		}
+	}
+	if ( deep ) {
+		jQuery.extend( true, target, deep );
+	}
+
+	return target;
+}
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+	var firstDataType, ct, finalDataType, type,
+		contents = s.contents,
+		dataTypes = s.dataTypes;
+
+	// Remove auto dataType and get content-type in the process
+	while ( dataTypes[ 0 ] === "*" ) {
+		dataTypes.shift();
+		if ( ct === undefined ) {
+			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+		}
+	}
+
+	// Check if we're dealing with a known content-type
+	if ( ct ) {
+		for ( type in contents ) {
+			if ( contents[ type ] && contents[ type ].test( ct ) ) {
+				dataTypes.unshift( type );
+				break;
+			}
+		}
+	}
+
+	// Check to see if we have a response for the expected dataType
+	if ( dataTypes[ 0 ] in responses ) {
+		finalDataType = dataTypes[ 0 ];
+	} else {
+		// Try convertible dataTypes
+		for ( type in responses ) {
+			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+				finalDataType = type;
+				break;
+			}
+			if ( !firstDataType ) {
+				firstDataType = type;
+			}
+		}
+		// Or just use first one
+		finalDataType = finalDataType || firstDataType;
+	}
+
+	// If we found a dataType
+	// We add the dataType to the list if needed
+	// and return the corresponding response
+	if ( finalDataType ) {
+		if ( finalDataType !== dataTypes[ 0 ] ) {
+			dataTypes.unshift( finalDataType );
+		}
+		return responses[ finalDataType ];
+	}
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+	var conv2, current, conv, tmp, prev,
+		converters = {},
+		// Work with a copy of dataTypes in case we need to modify it for conversion
+		dataTypes = s.dataTypes.slice();
+
+	// Create converters map with lowercased keys
+	if ( dataTypes[ 1 ] ) {
+		for ( conv in s.converters ) {
+			converters[ conv.toLowerCase() ] = s.converters[ conv ];
+		}
+	}
+
+	current = dataTypes.shift();
+
+	// Convert to each sequential dataType
+	while ( current ) {
+
+		if ( s.responseFields[ current ] ) {
+			jqXHR[ s.responseFields[ current ] ] = response;
+		}
+
+		// Apply the dataFilter if provided
+		if ( !prev && isSuccess && s.dataFilter ) {
+			response = s.dataFilter( response, s.dataType );
+		}
+
+		prev = current;
+		current = dataTypes.shift();
+
+		if ( current ) {
+
+			// There's only work to do if current dataType is non-auto
+			if ( current === "*" ) {
+
+				current = prev;
+
+			// Convert response if prev dataType is non-auto and differs from current
+			} else if ( prev !== "*" && prev !== current ) {
+
+				// Seek a direct converter
+				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+				// If none found, seek a pair
+				if ( !conv ) {
+					for ( conv2 in converters ) {
+
+						// If conv2 outputs current
+						tmp = conv2.split( " " );
+						if ( tmp[ 1 ] === current ) {
+
+							// If prev can be converted to accepted input
+							conv = converters[ prev + " " + tmp[ 0 ] ] ||
+								converters[ "* " + tmp[ 0 ] ];
+							if ( conv ) {
+								// Condense equivalence converters
+								if ( conv === true ) {
+									conv = converters[ conv2 ];
+
+								// Otherwise, insert the intermediate dataType
+								} else if ( converters[ conv2 ] !== true ) {
+									current = tmp[ 0 ];
+									dataTypes.unshift( tmp[ 1 ] );
+								}
+								break;
+							}
+						}
+					}
+				}
+
+				// Apply converter (if not an equivalence)
+				if ( conv !== true ) {
+
+					// Unless errors are allowed to bubble, catch and return them
+					if ( conv && s[ "throws" ] ) {
+						response = conv( response );
+					} else {
+						try {
+							response = conv( response );
+						} catch ( e ) {
+							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return { state: "success", data: response };
+}
+
+jQuery.extend({
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Last-Modified header cache for next request
+	lastModified: {},
+	etag: {},
+
+	ajaxSettings: {
+		url: ajaxLocation,
+		type: "GET",
+		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+		global: true,
+		processData: true,
+		async: true,
+		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+		/*
+		timeout: 0,
+		data: null,
+		dataType: null,
+		username: null,
+		password: null,
+		cache: null,
+		throws: false,
+		traditional: false,
+		headers: {},
+		*/
+
+		accepts: {
+			"*": allTypes,
+			text: "text/plain",
+			html: "text/html",
+			xml: "application/xml, text/xml",
+			json: "application/json, text/javascript"
+		},
+
+		contents: {
+			xml: /xml/,
+			html: /html/,
+			json: /json/
+		},
+
+		responseFields: {
+			xml: "responseXML",
+			text: "responseText",
+			json: "responseJSON"
+		},
+
+		// Data converters
+		// Keys separate source (or catchall "*") and destination types with a single space
+		converters: {
+
+			// Convert anything to text
+			"* text": String,
+
+			// Text to html (true = no transformation)
+			"text html": true,
+
+			// Evaluate text as a json expression
+			"text json": jQuery.parseJSON,
+
+			// Parse text as xml
+			"text xml": jQuery.parseXML
+		},
+
+		// For options that shouldn't be deep extended:
+		// you can add your own custom options here if
+		// and when you create one that shouldn't be
+		// deep extended (see ajaxExtend)
+		flatOptions: {
+			url: true,
+			context: true
+		}
+	},
+
+	// Creates a full fledged settings object into target
+	// with both ajaxSettings and settings fields.
+	// If target is omitted, writes into ajaxSettings.
+	ajaxSetup: function( target, settings ) {
+		return settings ?
+
+			// Building a settings object
+			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+			// Extending ajaxSettings
+			ajaxExtend( jQuery.ajaxSettings, target );
+	},
+
+	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+	ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+	// Main method
+	ajax: function( url, options ) {
+
+		// If url is an object, simulate pre-1.5 signature
+		if ( typeof url === "object" ) {
+			options = url;
+			url = undefined;
+		}
+
+		// Force options to be an object
+		options = options || {};
+
+		var // Cross-domain detection vars
+			parts,
+			// Loop variable
+			i,
+			// URL without anti-cache param
+			cacheURL,
+			// Response headers as string
+			responseHeadersString,
+			// timeout handle
+			timeoutTimer,
+
+			// To know if global events are to be dispatched
+			fireGlobals,
+
+			transport,
+			// Response headers
+			responseHeaders,
+			// Create the final options object
+			s = jQuery.ajaxSetup( {}, options ),
+			// Callbacks context
+			callbackContext = s.context || s,
+			// Context for global events is callbackContext if it is a DOM node or jQuery collection
+			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+				jQuery( callbackContext ) :
+				jQuery.event,
+			// Deferreds
+			deferred = jQuery.Deferred(),
+			completeDeferred = jQuery.Callbacks("once memory"),
+			// Status-dependent callbacks
+			statusCode = s.statusCode || {},
+			// Headers (they are sent all at once)
+			requestHeaders = {},
+			requestHeadersNames = {},
+			// The jqXHR state
+			state = 0,
+			// Default abort message
+			strAbort = "canceled",
+			// Fake xhr
+			jqXHR = {
+				readyState: 0,
+
+				// Builds headers hashtable if needed
+				getResponseHeader: function( key ) {
+					var match;
+					if ( state === 2 ) {
+						if ( !responseHeaders ) {
+							responseHeaders = {};
+							while ( (match = rheaders.exec( responseHeadersString )) ) {
+								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+							}
+						}
+						match = responseHeaders[ key.toLowerCase() ];
+					}
+					return match == null ? null : match;
+				},
+
+				// Raw string
+				getAllResponseHeaders: function() {
+					return state === 2 ? responseHeadersString : null;
+				},
+
+				// Caches the header
+				setRequestHeader: function( name, value ) {
+					var lname = name.toLowerCase();
+					if ( !state ) {
+						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+						requestHeaders[ name ] = value;
+					}
+					return this;
+				},
+
+				// Overrides response content-type header
+				overrideMimeType: function( type ) {
+					if ( !state ) {
+						s.mimeType = type;
+					}
+					return this;
+				},
+
+				// Status-dependent callbacks
+				statusCode: function( map ) {
+					var code;
+					if ( map ) {
+						if ( state < 2 ) {
+							for ( code in map ) {
+								// Lazy-add the new callback in a way that preserves old ones
+								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+							}
+						} else {
+							// Execute the appropriate callbacks
+							jqXHR.always( map[ jqXHR.status ] );
+						}
+					}
+					return this;
+				},
+
+				// Cancel the request
+				abort: function( statusText ) {
+					var finalText = statusText || strAbort;
+					if ( transport ) {
+						transport.abort( finalText );
+					}
+					done( 0, finalText );
+					return this;
+				}
+			};
+
+		// Attach deferreds
+		deferred.promise( jqXHR ).complete = completeDeferred.add;
+		jqXHR.success = jqXHR.done;
+		jqXHR.error = jqXHR.fail;
+
+		// Remove hash character (#7531: and string promotion)
+		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+		// Handle falsy url in the settings object (#10093: consistency with old signature)
+		// We also use the url parameter if available
+		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+		// Alias method option to type as per ticket #12004
+		s.type = options.method || options.type || s.method || s.type;
+
+		// Extract dataTypes list
+		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
+
+		// A cross-domain request is in order when we have a protocol:host:port mismatch
+		if ( s.crossDomain == null ) {
+			parts = rurl.exec( s.url.toLowerCase() );
+			s.crossDomain = !!( parts &&
+				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
+						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
+			);
+		}
+
+		// Convert data if not already a string
+		if ( s.data && s.processData && typeof s.data !== "string" ) {
+			s.data = jQuery.param( s.data, s.traditional );
+		}
+
+		// Apply prefilters
+		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+		// If request was aborted inside a prefilter, stop there
+		if ( state === 2 ) {
+			return jqXHR;
+		}
+
+		// We can fire global events as of now if asked to
+		fireGlobals = s.global;
+
+		// Watch for a new set of requests
+		if ( fireGlobals && jQuery.active++ === 0 ) {
+			jQuery.event.trigger("ajaxStart");
+		}
+
+		// Uppercase the type
+		s.type = s.type.toUpperCase();
+
+		// Determine if request has content
+		s.hasContent = !rnoContent.test( s.type );
+
+		// Save the URL in case we're toying with the If-Modified-Since
+		// and/or If-None-Match header later on
+		cacheURL = s.url;
+
+		// More options handling for requests with no content
+		if ( !s.hasContent ) {
+
+			// If data is available, append data to url
+			if ( s.data ) {
+				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+				// #9682: remove data so that it's not used in an eventual retry
+				delete s.data;
+			}
+
+			// Add anti-cache in url if needed
+			if ( s.cache === false ) {
+				s.url = rts.test( cacheURL ) ?
+
+					// If there is already a '_' parameter, set its value
+					cacheURL.replace( rts, "$1_=" + nonce++ ) :
+
+					// Otherwise add one to the end
+					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
+			}
+		}
+
+		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+		if ( s.ifModified ) {
+			if ( jQuery.lastModified[ cacheURL ] ) {
+				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+			}
+			if ( jQuery.etag[ cacheURL ] ) {
+				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+			}
+		}
+
+		// Set the correct header, if data is being sent
+		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+			jqXHR.setRequestHeader( "Content-Type", s.contentType );
+		}
+
+		// Set the Accepts header for the server, depending on the dataType
+		jqXHR.setRequestHeader(
+			"Accept",
+			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+				s.accepts[ "*" ]
+		);
+
+		// Check for headers option
+		for ( i in s.headers ) {
+			jqXHR.setRequestHeader( i, s.headers[ i ] );
+		}
+
+		// Allow custom headers/mimetypes and early abort
+		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+			// Abort if not done already and return
+			return jqXHR.abort();
+		}
+
+		// aborting is no longer a cancellation
+		strAbort = "abort";
+
+		// Install callbacks on deferreds
+		for ( i in { success: 1, error: 1, complete: 1 } ) {
+			jqXHR[ i ]( s[ i ] );
+		}
+
+		// Get transport
+		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+		// If no transport, we auto-abort
+		if ( !transport ) {
+			done( -1, "No Transport" );
+		} else {
+			jqXHR.readyState = 1;
+
+			// Send global event
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+			}
+			// Timeout
+			if ( s.async && s.timeout > 0 ) {
+				timeoutTimer = setTimeout(function() {
+					jqXHR.abort("timeout");
+				}, s.timeout );
+			}
+
+			try {
+				state = 1;
+				transport.send( requestHeaders, done );
+			} catch ( e ) {
+				// Propagate exception as error if not done
+				if ( state < 2 ) {
+					done( -1, e );
+				// Simply rethrow otherwise
+				} else {
+					throw e;
+				}
+			}
+		}
+
+		// Callback for when everything is done
+		function done( status, nativeStatusText, responses, headers ) {
+			var isSuccess, success, error, response, modified,
+				statusText = nativeStatusText;
+
+			// Called once
+			if ( state === 2 ) {
+				return;
+			}
+
+			// State is "done" now
+			state = 2;
+
+			// Clear timeout if it exists
+			if ( timeoutTimer ) {
+				clearTimeout( timeoutTimer );
+			}
+
+			// Dereference transport for early garbage collection
+			// (no matter how long the jqXHR object will be used)
+			transport = undefined;
+
+			// Cache response headers
+			responseHeadersString = headers || "";
+
+			// Set readyState
+			jqXHR.readyState = status > 0 ? 4 : 0;
+
+			// Determine if successful
+			isSuccess = status >= 200 && status < 300 || status === 304;
+
+			// Get response data
+			if ( responses ) {
+				response = ajaxHandleResponses( s, jqXHR, responses );
+			}
+
+			// Convert no matter what (that way responseXXX fields are always set)
+			response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+			// If successful, handle type chaining
+			if ( isSuccess ) {
+
+				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+				if ( s.ifModified ) {
+					modified = jqXHR.getResponseHeader("Last-Modified");
+					if ( modified ) {
+						jQuery.lastModified[ cacheURL ] = modified;
+					}
+					modified = jqXHR.getResponseHeader("etag");
+					if ( modified ) {
+						jQuery.etag[ cacheURL ] = modified;
+					}
+				}
+
+				// if no content
+				if ( status === 204 || s.type === "HEAD" ) {
+					statusText = "nocontent";
+
+				// if not modified
+				} else if ( status === 304 ) {
+					statusText = "notmodified";
+
+				// If we have data, let's convert it
+				} else {
+					statusText = response.state;
+					success = response.data;
+					error = response.error;
+					isSuccess = !error;
+				}
+			} else {
+				// We extract error from statusText
+				// then normalize statusText and status for non-aborts
+				error = statusText;
+				if ( status || !statusText ) {
+					statusText = "error";
+					if ( status < 0 ) {
+						status = 0;
+					}
+				}
+			}
+
+			// Set data for the fake xhr object
+			jqXHR.status = status;
+			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+			// Success/Error
+			if ( isSuccess ) {
+				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+			} else {
+				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+			}
+
+			// Status-dependent callbacks
+			jqXHR.statusCode( statusCode );
+			statusCode = undefined;
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+					[ jqXHR, s, isSuccess ? success : error ] );
+			}
+
+			// Complete
+			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+				// Handle the global AJAX counter
+				if ( !( --jQuery.active ) ) {
+					jQuery.event.trigger("ajaxStop");
+				}
+			}
+		}
+
+		return jqXHR;
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get( url, data, callback, "json" );
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get( url, undefined, callback, "script" );
+	}
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+	jQuery[ method ] = function( url, data, callback, type ) {
+		// shift arguments if data argument was omitted
+		if ( jQuery.isFunction( data ) ) {
+			type = type || callback;
+			callback = data;
+			data = undefined;
+		}
+
+		return jQuery.ajax({
+			url: url,
+			type: method,
+			dataType: type,
+			data: data,
+			success: callback
+		});
+	};
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
+	jQuery.fn[ type ] = function( fn ) {
+		return this.on( type, fn );
+	};
+});
+
+
+jQuery._evalUrl = function( url ) {
+	return jQuery.ajax({
+		url: url,
+		type: "GET",
+		dataType: "script",
+		async: false,
+		global: false,
+		"throws": true
+	});
+};
+
+
+jQuery.fn.extend({
+	wrapAll: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapAll( html.call(this, i) );
+			});
+		}
+
+		if ( this[0] ) {
+			// The elements to wrap the target around
+			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+			if ( this[0].parentNode ) {
+				wrap.insertBefore( this[0] );
+			}
+
+			wrap.map(function() {
+				var elem = this;
+
+				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+					elem = elem.firstChild;
+				}
+
+				return elem;
+			}).append( this );
+		}
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapInner( html.call(this, i) );
+			});
+		}
+
+		return this.each(function() {
+			var self = jQuery( this ),
+				contents = self.contents();
+
+			if ( contents.length ) {
+				contents.wrapAll( html );
+
+			} else {
+				self.append( html );
+			}
+		});
+	},
+
+	wrap: function( html ) {
+		var isFunction = jQuery.isFunction( html );
+
+		return this.each(function(i) {
+			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+		});
+	},
+
+	unwrap: function() {
+		return this.parent().each(function() {
+			if ( !jQuery.nodeName( this, "body" ) ) {
+				jQuery( this ).replaceWith( this.childNodes );
+			}
+		}).end();
+	}
+});
+
+
+jQuery.expr.filters.hidden = function( elem ) {
+	// Support: Opera <= 12.12
+	// Opera reports offsetWidths and offsetHeights less than zero on some elements
+	return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
+		(!support.reliableHiddenOffsets() &&
+			((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+};
+
+jQuery.expr.filters.visible = function( elem ) {
+	return !jQuery.expr.filters.hidden( elem );
+};
+
+
+
+
+var r20 = /%20/g,
+	rbracket = /\[\]$/,
+	rCRLF = /\r?\n/g,
+	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+	rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+function buildParams( prefix, obj, traditional, add ) {
+	var name;
+
+	if ( jQuery.isArray( obj ) ) {
+		// Serialize array item.
+		jQuery.each( obj, function( i, v ) {
+			if ( traditional || rbracket.test( prefix ) ) {
+				// Treat each array item as a scalar.
+				add( prefix, v );
+
+			} else {
+				// Item is non-scalar (array or object), encode its numeric index.
+				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+			}
+		});
+
+	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
+		// Serialize object item.
+		for ( name in obj ) {
+			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+		}
+
+	} else {
+		// Serialize scalar item.
+		add( prefix, obj );
+	}
+}
+
+// Serialize an array of form elements or a set of
+// key/values into a query string
+jQuery.param = function( a, traditional ) {
+	var prefix,
+		s = [],
+		add = function( key, value ) {
+			// If value is a function, invoke it and return its value
+			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+		};
+
+	// Set traditional to true for jQuery <= 1.3.2 behavior.
+	if ( traditional === undefined ) {
+		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+	}
+
+	// If an array was passed in, assume that it is an array of form elements.
+	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+		// Serialize the form elements
+		jQuery.each( a, function() {
+			add( this.name, this.value );
+		});
+
+	} else {
+		// If traditional, encode the "old" way (the way 1.3.2 or older
+		// did it), otherwise encode params recursively.
+		for ( prefix in a ) {
+			buildParams( prefix, a[ prefix ], traditional, add );
+		}
+	}
+
+	// Return the resulting serialization
+	return s.join( "&" ).replace( r20, "+" );
+};
+
+jQuery.fn.extend({
+	serialize: function() {
+		return jQuery.param( this.serializeArray() );
+	},
+	serializeArray: function() {
+		return this.map(function() {
+			// Can add propHook for "elements" to filter or add form elements
+			var elements = jQuery.prop( this, "elements" );
+			return elements ? jQuery.makeArray( elements ) : this;
+		})
+		.filter(function() {
+			var type = this.type;
+			// Use .is(":disabled") so that fieldset[disabled] works
+			return this.name && !jQuery( this ).is( ":disabled" ) &&
+				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+				( this.checked || !rcheckableType.test( type ) );
+		})
+		.map(function( i, elem ) {
+			var val = jQuery( this ).val();
+
+			return val == null ?
+				null :
+				jQuery.isArray( val ) ?
+					jQuery.map( val, function( val ) {
+						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+					}) :
+					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+		}).get();
+	}
+});
+
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
+	// Support: IE6+
+	function() {
+
+		// XHR cannot access local files, always use ActiveX for that case
+		return !this.isLocal &&
+
+			// Support: IE7-8
+			// oldIE XHR does not support non-RFC2616 methods (#13240)
+			// See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
+			// and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
+			// Although this check for six methods instead of eight
+			// since IE also does not support "trace" and "connect"
+			/^(get|post|head|put|delete|options)$/i.test( this.type ) &&
+
+			createStandardXHR() || createActiveXHR();
+	} :
+	// For all other browsers, use the standard XMLHttpRequest object
+	createStandardXHR;
+
+var xhrId = 0,
+	xhrCallbacks = {},
+	xhrSupported = jQuery.ajaxSettings.xhr();
+
+// Support: IE<10
+// Open requests must be manually aborted on unload (#5280)
+if ( window.ActiveXObject ) {
+	jQuery( window ).on( "unload", function() {
+		for ( var key in xhrCallbacks ) {
+			xhrCallbacks[ key ]( undefined, true );
+		}
+	});
+}
+
+// Determine support properties
+support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+xhrSupported = support.ajax = !!xhrSupported;
+
+// Create transport if the browser can provide an xhr
+if ( xhrSupported ) {
+
+	jQuery.ajaxTransport(function( options ) {
+		// Cross domain only allowed if supported through XMLHttpRequest
+		if ( !options.crossDomain || support.cors ) {
+
+			var callback;
+
+			return {
+				send: function( headers, complete ) {
+					var i,
+						xhr = options.xhr(),
+						id = ++xhrId;
+
+					// Open the socket
+					xhr.open( options.type, options.url, options.async, options.username, options.password );
+
+					// Apply custom fields if provided
+					if ( options.xhrFields ) {
+						for ( i in options.xhrFields ) {
+							xhr[ i ] = options.xhrFields[ i ];
+						}
+					}
+
+					// Override mime type if needed
+					if ( options.mimeType && xhr.overrideMimeType ) {
+						xhr.overrideMimeType( options.mimeType );
+					}
+
+					// X-Requested-With header
+					// For cross-domain requests, seeing as conditions for a preflight are
+					// akin to a jigsaw puzzle, we simply never set it to be sure.
+					// (it can always be set on a per-request basis or even using ajaxSetup)
+					// For same-domain requests, won't change header if already provided.
+					if ( !options.crossDomain && !headers["X-Requested-With"] ) {
+						headers["X-Requested-With"] = "XMLHttpRequest";
+					}
+
+					// Set headers
+					for ( i in headers ) {
+						// Support: IE<9
+						// IE's ActiveXObject throws a 'Type Mismatch' exception when setting
+						// request header to a null-value.
+						//
+						// To keep consistent with other XHR implementations, cast the value
+						// to string and ignore `undefined`.
+						if ( headers[ i ] !== undefined ) {
+							xhr.setRequestHeader( i, headers[ i ] + "" );
+						}
+					}
+
+					// Do send the request
+					// This may raise an exception which is actually
+					// handled in jQuery.ajax (so no try/catch here)
+					xhr.send( ( options.hasContent && options.data ) || null );
+
+					// Listener
+					callback = function( _, isAbort ) {
+						var status, statusText, responses;
+
+						// Was never called and is aborted or complete
+						if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+							// Clean up
+							delete xhrCallbacks[ id ];
+							callback = undefined;
+							xhr.onreadystatechange = jQuery.noop;
+
+							// Abort manually if needed
+							if ( isAbort ) {
+								if ( xhr.readyState !== 4 ) {
+									xhr.abort();
+								}
+							} else {
+								responses = {};
+								status = xhr.status;
+
+								// Support: IE<10
+								// Accessing binary-data responseText throws an exception
+								// (#11426)
+								if ( typeof xhr.responseText === "string" ) {
+									responses.text = xhr.responseText;
+								}
+
+								// Firefox throws an exception when accessing
+								// statusText for faulty cross-domain requests
+								try {
+									statusText = xhr.statusText;
+								} catch( e ) {
+									// We normalize with Webkit giving an empty statusText
+									statusText = "";
+								}
+
+								// Filter status for non standard behaviors
+
+								// If the request is local and we have data: assume a success
+								// (success with no data won't get notified, that's the best we
+								// can do given current implementations)
+								if ( !status && options.isLocal && !options.crossDomain ) {
+									status = responses.text ? 200 : 404;
+								// IE - #1450: sometimes returns 1223 when it should be 204
+								} else if ( status === 1223 ) {
+									status = 204;
+								}
+							}
+						}
+
+						// Call complete if needed
+						if ( responses ) {
+							complete( status, statusText, responses, xhr.getAllResponseHeaders() );
+						}
+					};
+
+					if ( !options.async ) {
+						// if we're in sync mode we fire the callback
+						callback();
+					} else if ( xhr.readyState === 4 ) {
+						// (IE6 & IE7) if it's in cache and has been
+						// retrieved directly we need to fire the callback
+						setTimeout( callback );
+					} else {
+						// Add to the list of active xhr callbacks
+						xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
+					}
+				},
+
+				abort: function() {
+					if ( callback ) {
+						callback( undefined, true );
+					}
+				}
+			};
+		}
+	});
+}
+
+// Functions to create xhrs
+function createStandardXHR() {
+	try {
+		return new window.XMLHttpRequest();
+	} catch( e ) {}
+}
+
+function createActiveXHR() {
+	try {
+		return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+	} catch( e ) {}
+}
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup({
+	accepts: {
+		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+	},
+	contents: {
+		script: /(?:java|ecma)script/
+	},
+	converters: {
+		"text script": function( text ) {
+			jQuery.globalEval( text );
+			return text;
+		}
+	}
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+	if ( s.cache === undefined ) {
+		s.cache = false;
+	}
+	if ( s.crossDomain ) {
+		s.type = "GET";
+		s.global = false;
+	}
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+	// This transport only deals with cross domain requests
+	if ( s.crossDomain ) {
+
+		var script,
+			head = document.head || jQuery("head")[0] || document.documentElement;
+
+		return {
+
+			send: function( _, callback ) {
+
+				script = document.createElement("script");
+
+				script.async = true;
+
+				if ( s.scriptCharset ) {
+					script.charset = s.scriptCharset;
+				}
+
+				script.src = s.url;
+
+				// Attach handlers for all browsers
+				script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+					if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+						// Handle memory leak in IE
+						script.onload = script.onreadystatechange = null;
+
+						// Remove the script
+						if ( script.parentNode ) {
+							script.parentNode.removeChild( script );
+						}
+
+						// Dereference the script
+						script = null;
+
+						// Callback if not abort
+						if ( !isAbort ) {
+							callback( 200, "success" );
+						}
+					}
+				};
+
+				// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
+				// Use native DOM manipulation to avoid our domManip AJAX trickery
+				head.insertBefore( script, head.firstChild );
+			},
+
+			abort: function() {
+				if ( script ) {
+					script.onload( undefined, true );
+				}
+			}
+		};
+	}
+});
+
+
+
+
+var oldCallbacks = [],
+	rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+	jsonp: "callback",
+	jsonpCallback: function() {
+		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+		this[ callback ] = true;
+		return callback;
+	}
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+	var callbackName, overwritten, responseContainer,
+		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+			"url" :
+			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+		);
+
+	// Handle iff the expected data type is "jsonp" or we have a parameter to set
+	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+		// Get callback name, remembering preexisting value associated with it
+		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+			s.jsonpCallback() :
+			s.jsonpCallback;
+
+		// Insert callback into url or form data
+		if ( jsonProp ) {
+			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+		} else if ( s.jsonp !== false ) {
+			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+		}
+
+		// Use data converter to retrieve json after script execution
+		s.converters["script json"] = function() {
+			if ( !responseContainer ) {
+				jQuery.error( callbackName + " was not called" );
+			}
+			return responseContainer[ 0 ];
+		};
+
+		// force json dataType
+		s.dataTypes[ 0 ] = "json";
+
+		// Install callback
+		overwritten = window[ callbackName ];
+		window[ callbackName ] = function() {
+			responseContainer = arguments;
+		};
+
+		// Clean-up function (fires after converters)
+		jqXHR.always(function() {
+			// Restore preexisting value
+			window[ callbackName ] = overwritten;
+
+			// Save back as free
+			if ( s[ callbackName ] ) {
+				// make sure that re-using the options doesn't screw things around
+				s.jsonpCallback = originalSettings.jsonpCallback;
+
+				// save the callback name for future use
+				oldCallbacks.push( callbackName );
+			}
+
+			// Call if it was a function and we have a response
+			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+				overwritten( responseContainer[ 0 ] );
+			}
+
+			responseContainer = overwritten = undefined;
+		});
+
+		// Delegate to script
+		return "script";
+	}
+});
+
+
+
+
+// data: string of html
+// context (optional): If specified, the fragment will be created in this context, defaults to document
+// keepScripts (optional): If true, will include scripts passed in the html string
+jQuery.parseHTML = function( data, context, keepScripts ) {
+	if ( !data || typeof data !== "string" ) {
+		return null;
+	}
+	if ( typeof context === "boolean" ) {
+		keepScripts = context;
+		context = false;
+	}
+	context = context || document;
+
+	var parsed = rsingleTag.exec( data ),
+		scripts = !keepScripts && [];
+
+	// Single tag
+	if ( parsed ) {
+		return [ context.createElement( parsed[1] ) ];
+	}
+
+	parsed = jQuery.buildFragment( [ data ], context, scripts );
+
+	if ( scripts && scripts.length ) {
+		jQuery( scripts ).remove();
+	}
+
+	return jQuery.merge( [], parsed.childNodes );
+};
+
+
+// Keep a copy of the old load method
+var _load = jQuery.fn.load;
+
+/**
+ * Load a url into a page
+ */
+jQuery.fn.load = function( url, params, callback ) {
+	if ( typeof url !== "string" && _load ) {
+		return _load.apply( this, arguments );
+	}
+
+	var selector, response, type,
+		self = this,
+		off = url.indexOf(" ");
+
+	if ( off >= 0 ) {
+		selector = jQuery.trim( url.slice( off, url.length ) );
+		url = url.slice( 0, off );
+	}
+
+	// If it's a function
+	if ( jQuery.isFunction( params ) ) {
+
+		// We assume that it's the callback
+		callback = params;
+		params = undefined;
+
+	// Otherwise, build a param string
+	} else if ( params && typeof params === "object" ) {
+		type = "POST";
+	}
+
+	// If we have elements to modify, make the request
+	if ( self.length > 0 ) {
+		jQuery.ajax({
+			url: url,
+
+			// if "type" variable is undefined, then "GET" method will be used
+			type: type,
+			dataType: "html",
+			data: params
+		}).done(function( responseText ) {
+
+			// Save response for use in complete callback
+			response = arguments;
+
+			self.html( selector ?
+
+				// If a selector was specified, locate the right elements in a dummy div
+				// Exclude scripts to avoid IE 'Permission Denied' errors
+				jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+				// Otherwise use the full result
+				responseText );
+
+		}).complete( callback && function( jqXHR, status ) {
+			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+		});
+	}
+
+	return this;
+};
+
+
+
+
+jQuery.expr.filters.animated = function( elem ) {
+	return jQuery.grep(jQuery.timers, function( fn ) {
+		return elem === fn.elem;
+	}).length;
+};
+
+
+
+
+
+var docElem = window.document.documentElement;
+
+/**
+ * Gets a window from an element
+ */
+function getWindow( elem ) {
+	return jQuery.isWindow( elem ) ?
+		elem :
+		elem.nodeType === 9 ?
+			elem.defaultView || elem.parentWindow :
+			false;
+}
+
+jQuery.offset = {
+	setOffset: function( elem, options, i ) {
+		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+			position = jQuery.css( elem, "position" ),
+			curElem = jQuery( elem ),
+			props = {};
+
+		// set position first, in-case top/left are set even on static elem
+		if ( position === "static" ) {
+			elem.style.position = "relative";
+		}
+
+		curOffset = curElem.offset();
+		curCSSTop = jQuery.css( elem, "top" );
+		curCSSLeft = jQuery.css( elem, "left" );
+		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+			jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
+
+		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+		if ( calculatePosition ) {
+			curPosition = curElem.position();
+			curTop = curPosition.top;
+			curLeft = curPosition.left;
+		} else {
+			curTop = parseFloat( curCSSTop ) || 0;
+			curLeft = parseFloat( curCSSLeft ) || 0;
+		}
+
+		if ( jQuery.isFunction( options ) ) {
+			options = options.call( elem, i, curOffset );
+		}
+
+		if ( options.top != null ) {
+			props.top = ( options.top - curOffset.top ) + curTop;
+		}
+		if ( options.left != null ) {
+			props.left = ( options.left - curOffset.left ) + curLeft;
+		}
+
+		if ( "using" in options ) {
+			options.using.call( elem, props );
+		} else {
+			curElem.css( props );
+		}
+	}
+};
+
+jQuery.fn.extend({
+	offset: function( options ) {
+		if ( arguments.length ) {
+			return options === undefined ?
+				this :
+				this.each(function( i ) {
+					jQuery.offset.setOffset( this, options, i );
+				});
+		}
+
+		var docElem, win,
+			box = { top: 0, left: 0 },
+			elem = this[ 0 ],
+			doc = elem && elem.ownerDocument;
+
+		if ( !doc ) {
+			return;
+		}
+
+		docElem = doc.documentElement;
+
+		// Make sure it's not a disconnected DOM node
+		if ( !jQuery.contains( docElem, elem ) ) {
+			return box;
+		}
+
+		// If we don't have gBCR, just use 0,0 rather than error
+		// BlackBerry 5, iOS 3 (original iPhone)
+		if ( typeof elem.getBoundingClientRect !== strundefined ) {
+			box = elem.getBoundingClientRect();
+		}
+		win = getWindow( doc );
+		return {
+			top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
+			left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+		};
+	},
+
+	position: function() {
+		if ( !this[ 0 ] ) {
+			return;
+		}
+
+		var offsetParent, offset,
+			parentOffset = { top: 0, left: 0 },
+			elem = this[ 0 ];
+
+		// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
+		if ( jQuery.css( elem, "position" ) === "fixed" ) {
+			// we assume that getBoundingClientRect is available when computed position is fixed
+			offset = elem.getBoundingClientRect();
+		} else {
+			// Get *real* offsetParent
+			offsetParent = this.offsetParent();
+
+			// Get correct offsets
+			offset = this.offset();
+			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+				parentOffset = offsetParent.offset();
+			}
+
+			// Add offsetParent borders
+			parentOffset.top  += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+		}
+
+		// Subtract parent offsets and element margins
+		// note: when an element has margin: auto the offsetLeft and marginLeft
+		// are the same in Safari causing offset.left to incorrectly be 0
+		return {
+			top:  offset.top  - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
+		};
+	},
+
+	offsetParent: function() {
+		return this.map(function() {
+			var offsetParent = this.offsetParent || docElem;
+
+			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
+				offsetParent = offsetParent.offsetParent;
+			}
+			return offsetParent || docElem;
+		});
+	}
+});
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+	var top = /Y/.test( prop );
+
+	jQuery.fn[ method ] = function( val ) {
+		return access( this, function( elem, method, val ) {
+			var win = getWindow( elem );
+
+			if ( val === undefined ) {
+				return win ? (prop in win) ? win[ prop ] :
+					win.document.documentElement[ method ] :
+					elem[ method ];
+			}
+
+			if ( win ) {
+				win.scrollTo(
+					!top ? val : jQuery( win ).scrollLeft(),
+					top ? val : jQuery( win ).scrollTop()
+				);
+
+			} else {
+				elem[ method ] = val;
+			}
+		}, method, val, arguments.length, null );
+	};
+});
+
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// getComputedStyle returns percent when specified for top/left/bottom/right
+// rather than make the css module depend on the offset module, we just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+		function( elem, computed ) {
+			if ( computed ) {
+				computed = curCSS( elem, prop );
+				// if curCSS returns percentage, fallback to offset
+				return rnumnonpx.test( computed ) ?
+					jQuery( elem ).position()[ prop ] + "px" :
+					computed;
+			}
+		}
+	);
+});
+
+
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+		// margin is only for outerHeight, outerWidth
+		jQuery.fn[ funcName ] = function( margin, value ) {
+			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+			return access( this, function( elem, type, value ) {
+				var doc;
+
+				if ( jQuery.isWindow( elem ) ) {
+					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+					// isn't a whole lot we can do. See pull request at this URL for discussion:
+					// https://github.com/jquery/jquery/pull/764
+					return elem.document.documentElement[ "client" + name ];
+				}
+
+				// Get document width or height
+				if ( elem.nodeType === 9 ) {
+					doc = elem.documentElement;
+
+					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+					// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+					return Math.max(
+						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+						elem.body[ "offset" + name ], doc[ "offset" + name ],
+						doc[ "client" + name ]
+					);
+				}
+
+				return value === undefined ?
+					// Get width or height on the element, requesting but not forcing parseFloat
+					jQuery.css( elem, type, extra ) :
+
+					// Set width or height on the element
+					jQuery.style( elem, type, value, extra );
+			}, type, chainable ? margin : undefined, chainable, null );
+		};
+	});
+});
+
+
+// The number of elements contained in the matched element set
+jQuery.fn.size = function() {
+	return this.length;
+};
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+
+
+
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( typeof define === "function" && define.amd ) {
+	define( "jquery", [], function() {
+		return jQuery;
+	});
+}
+
+
+
+
+var
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+
+	// Map over the $ in case of overwrite
+	_$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+	if ( window.$ === jQuery ) {
+		window.$ = _$;
+	}
+
+	if ( deep && window.jQuery === jQuery ) {
+		window.jQuery = _jQuery;
+	}
+
+	return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in
+// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( typeof noGlobal === strundefined ) {
+	window.jQuery = window.$ = jQuery;
+}
+
+
+
+
+return jQuery;
+
+}));
+/**
+ * Copyright (c) 2007-2014 Ariel Flesler - aflesler<a>gmail<d>com | http://flesler.blogspot.com
+ * Licensed under MIT
+ * @author Ariel Flesler
+ * @version 1.4.13
+ */
+;(function(k){'use strict';k(['jquery'],function($){var j=$.scrollTo=function(a,b,c){return $(window).scrollTo(a,b,c)};j.defaults={axis:'xy',duration:parseFloat($.fn.jquery)>=1.3?0:1,limit:!0};j.window=function(a){return $(window)._scrollable()};$.fn._scrollable=function(){return this.map(function(){var a=this,isWin=!a.nodeName||$.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!isWin)return a;var b=(a.contentWindow||a).document||a.ownerDocument||a;return/webkit/i.test(navigator.userAgent)||b.compatMode=='BackCompat'?b.body:b.documentElement})};$.fn.scrollTo=function(f,g,h){if(typeof g=='object'){h=g;g=0}if(typeof h=='function')h={onAfter:h};if(f=='max')f=9e9;h=$.extend({},j.defaults,h);g=g||h.duration;h.queue=h.queue&&h.axis.length>1;if(h.queue)g/=2;h.offset=both(h.offset);h.over=both(h.over);return this._scrollable().each(function(){if(f==null)return;var d=this,$elem=$(d),targ=f,toff,attr={},win=$elem.is('html,body');switch(typeof targ){case'number':case'string':if(/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)){targ=both(targ);break}targ=win?$(targ):$(targ,this);if(!targ.length)return;case'object':if(targ.is||targ.style)toff=(targ=$(targ)).offset()}var e=$.isFunction(h.offset)&&h.offset(d,targ)||h.offset;$.each(h.axis.split(''),function(i,a){var b=a=='x'?'Left':'Top',pos=b.toLowerCase(),key='scroll'+b,old=d[key],max=j.max(d,a);if(toff){attr[key]=toff[pos]+(win?0:old-$elem.offset()[pos]);if(h.margin){attr[key]-=parseInt(targ.css('margin'+b))||0;attr[key]-=parseInt(targ.css('border'+b+'Width'))||0}attr[key]+=e[pos]||0;if(h.over[pos])attr[key]+=targ[a=='x'?'width':'height']()*h.over[pos]}else{var c=targ[pos];attr[key]=c.slice&&c.slice(-1)=='%'?parseFloat(c)/100*max:c}if(h.limit&&/^\d+$/.test(attr[key]))attr[key]=attr[key]<=0?0:Math.min(attr[key],max);if(!i&&h.queue){if(old!=attr[key])animate(h.onAfterFirst);delete attr[key]}});animate(h.onAfter);function animate(a){$elem.animate(attr,g,h.easing,a&&function(){a.call(this,targ,h)})}}).end()};j.max=function(a,b){var c=b=='x'?'Width':'Height',scroll='scroll'+c;if(!$(a).is('html,body'))return a[scroll]-$(a)[c.toLowerCase()]();var d='client'+c,html=a.ownerDocument.documentElement,body=a.ownerDocument.body;return Math.max(html[scroll],body[scroll])-Math.min(html[d],body[d])};function both(a){return $.isFunction(a)||typeof a=='object'?a:{top:a,left:a}}return j})}(typeof define==='function'&&define.amd?define:function(a,b){if(typeof module!=='undefined'&&module.exports){module.exports=b(require('jquery'))}else{b(jQuery)}}));$(function() {
+  var className = 'active';
+  var topMenu = $("#toc");
+  var menuItems = topMenu.find("a");
+  var scrollItems = menuItems.map(function() {
+    var item = $($(this).attr("href"));
+    if (item.length) { return item; }
+  });
+
+  var lastTocScroll = 0;
+  var lastTocScrollHuman = true;
+
+  // Scroll an element so that it becomes visible
+  // unless the user recently scrolled the toc div.
+  // If the user scrolls to the top or the bottom of an overflow:scroll
+  // element, the browser will scroll the main area, which will cause
+  // another element to be activated (and scrolled to) in the toc pane.
+  function scrollToView(pane, element) {
+    if (new Date().getTime() - lastTocScroll < 2000) return;
+
+    var y = element.position().top;
+    if (y < 0 || y > pane.height()) {
+      lastTocScrollHuman = false;
+      pane.scrollTo(element, { axis: 'y' });
+    }
+  }
+
+  topMenu.scroll(function() {
+    if (lastTocScrollHuman) {
+      lastTocScroll = new Date().getTime();
+    } else {
+      lastTocScrollHuman = true;
+    }
+  });
+
+  $(window).scroll(function() {
+    // Get container scroll position
+   var fromTop = $(this).scrollTop() + 40;
+
+   // Get id of current scroll item
+   var cur = scrollItems.map(function(){
+     if ($(this).offset().top < fromTop)
+       return this;
+   });
+   // Get the id of the current element
+   cur = cur[cur.length-1];
+   var id = cur && cur.length ? cur[0].id : "";
+   $('#toc a').removeClass(className);
+   var item = menuItems.filter("[href=#"+id+"]");
+   if (item.length != 0) {
+     item.addClass(className);
+     scrollToView(topMenu, item);
+   }
+ });
+});
+// Borrowed from http://asciidoctor.org/javascripts/view-result.js
+function insert_unhide_links() {
+  $('.example').each(function(idx, node) {
+    var example_block = $(node);
+    var view_example_link = $('<p><a class="view-example" href="#">Show example</a></p>');
+    example_block.before(view_example_link);
+    example_block.toggle();
+    view_example_link.on('click', function(event) {
+      event.preventDefault();
+      example_block.toggle();
+    });
+  });
+  $('.definition').each(function(idx, node) {
+    var definition_block = $(node);
+    var view_definition_link = $('<p><a class="view-definition" href="#">Show definition</a></p>');
+    definition_block.before(view_definition_link);
+    definition_block.toggle();
+    view_definition_link.on('click', function(event) {
+      event.preventDefault();
+      definition_block.toggle();
+    });
+  });
+}
+
+$(insert_unhide_links);
+</script>
diff --git a/docs/index.adoc b/docs/index.adoc
new file mode 100644
index 000000000..e29d1bf9e
--- /dev/null
+++ b/docs/index.adoc
@@ -0,0 +1,23 @@
+:toc2:
+:toclevels: 2
+:source-highlighter: pygments
+:pygments-style: xcode
+:docinfo:
+
+= Multi-Protocol Networking Library
+
+include::tutorial.adoc[]
+include::concept.adoc[]
+include::build_opts.adoc[]
+
+== API Reference
+include::mbuf.adoc[]
+include::net.adoc[]
+include::http.adoc[]
+include::json-rpc.adoc[]
+include::dns.adoc[]
+include::dns-server.adoc[]
+include::mqtt.adoc[]
+include::mqtt-broker.adoc[]
+include::coap.adoc[]
+include::util.adoc[]
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 000000000..15a947c6e
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,14093 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 1.5.4">
+<title>Multi-Protocol Networking Library</title>
+<style>
+@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic|Inconsolata');
+
+*, *:after, *:before {
+  -moz-box-sizing: border-box;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
+  outline: 0;
+}
+
+html, body { margin: 0; padding: 0; }
+
+body {
+  font: 14px/1.4 'Open Sans', Helvetica, Arial, sans-serif;
+  color: #444;
+  background-image: url(/images/cesanta_logo.svg);
+  background-position: 95% 5px;
+  background-size: 160px 60px;
+  background-repeat: no-repeat;
+}
+
+a { color: #369; }
+li > p { margin: 0; padding: 0; }
+dt { font-weight: bold; }
+h1, h2, h3, h4 { color: #369; }
+h2 { border-bottom: 1px solid #69c; }
+h4 { border-bottom: 1px solid #ccc; }
+code, pre { font: 14px/1.0 Inconsolata, Consolas, monospace !important; }
+p > code { background: #f0f0f0; padding: 1px 4px; border-radius: 4px; }
+pre, pre > code { border-radius: 4px; }
+pre { background: #f5f5f5 !important; }
+pre > code { padding: 0.5em; display:block; border: 1px solid #ccc; }
+dd > p { margin: 0.4em; }
+
+#toc.toc2 {
+  position: fixed; width: 20%; left: 0; top: 0;
+  border-right: 1px solid #e5e5e5; z-index: 1000;
+  height: 100%; overflow: auto; line-height: 1.5em;
+}
+#toc { background: #f5f5f5; }
+#toc ul { list-style-type: none; margin-left: 0.8em; padding: 0; }
+#toctitle { margin: 0.5em 1em;}
+#toc ul.sectlevel3 > li { xfont-size: 90%; line-height: 1.4em; }
+#toc a {
+  text-decoration: none; padding: 0 6px;
+  display: inline-block; border: 1px solid transparent; border-radius: 4px;
+}
+#toc .active { border: 1px solid #aaa; background: #fff; }
+
+#content, h1 { margin: 1em 3em 0 22%; }
+#footer { margin: 0.2em 1em; font-size: 90%; color: silver; text-align: right; }
+
+.listingblock .title { font-weight: bold; }
+
+.hidden { display: none; }
+
+table thead,table tfoot{background:#f7f8f7;font-weight:bold}
+table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
+table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
+table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
+table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
+table.tableblock{max-width:100%;border-collapse:separate}
+table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
+table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
+table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
+table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
+table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
+table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
+table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
+table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
+table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
+table.frame-all{border-width:1px}
+table.frame-sides{border-width:0 1px}
+table.frame-topbot{border-width:1px 0}
+th.halign-left,td.halign-left{text-align:left}
+th.halign-right,td.halign-right{text-align:right}
+th.halign-center,td.halign-center{text-align:center}
+th.valign-top,td.valign-top{vertical-align:top}
+th.valign-bottom,td.valign-bottom{vertical-align:bottom}
+th.valign-middle,td.valign-middle{vertical-align:middle}
+table thead th,table tfoot th{font-weight:bold}
+tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
+tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
+p.tableblock>code:only-child{background:none;padding:0}
+p.tableblock{font-size:1em}
+td>div.verse{white-space:pre}
+
+.needsmorework:before {
+  content: "NOTE: this section needs more work.";
+}
+
+.needsmorework {
+  background-color: rgba(255, 0, 0, 0.1);
+}
+
+.todo>p:before {
+  content: "TODO: ";
+}
+
+.todo {
+  color: rgb(255, 0, 0);
+}
+
+</style>
+<style>
+/* Pygments styles disabled. Pygments is not available. */
+</style>
+<script>
+/*!
+ * jQuery JavaScript Library v1.11.1
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-05-01T17:42Z
+ */
+
+(function( global, factory ) {
+
+	if ( typeof module === "object" && typeof module.exports === "object" ) {
+		// For CommonJS and CommonJS-like environments where a proper window is present,
+		// execute the factory and get jQuery
+		// For environments that do not inherently posses a window with a document
+		// (such as Node.js), expose a jQuery-making 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 ) {
+
+// Can't do this because several apps including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+// Support: Firefox 18+
+//
+
+var deletedIds = [];
+
+var slice = deletedIds.slice;
+
+var concat = deletedIds.concat;
+
+var push = deletedIds.push;
+
+var indexOf = deletedIds.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var support = {};
+
+
+
+var
+	version = "1.11.1",
+
+	// Define a local copy of jQuery
+	jQuery = function( selector, context ) {
+		// The jQuery object is actually just the init constructor 'enhanced'
+		// Need init if jQuery is called (just allow error to be thrown if not included)
+		return new jQuery.fn.init( selector, context );
+	},
+
+	// Support: Android<4.1, IE<9
+	// Make sure we trim BOM and NBSP
+	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+	// Matches dashed string for camelizing
+	rmsPrefix = /^-ms-/,
+	rdashAlpha = /-([\da-z])/gi,
+
+	// Used by jQuery.camelCase as callback to replace()
+	fcamelCase = function( all, letter ) {
+		return letter.toUpperCase();
+	};
+
+jQuery.fn = jQuery.prototype = {
+	// The current version of jQuery being used
+	jquery: version,
+
+	constructor: jQuery,
+
+	// Start with an empty selector
+	selector: "",
+
+	// The default length of a jQuery object is 0
+	length: 0,
+
+	toArray: function() {
+		return slice.call( this );
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num != null ?
+
+			// Return just the one element from the set
+			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
+
+			// Return all the elements in a clean array
+			slice.call( this );
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems ) {
+
+		// Build a new jQuery matched element set
+		var ret = jQuery.merge( this.constructor(), elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+		ret.context = this.context;
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Execute a callback for every element in the matched set.
+	// (You can seed the arguments with an array of args, but this is
+	// only used internally.)
+	each: function( callback, args ) {
+		return jQuery.each( this, callback, args );
+	},
+
+	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(null);
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: push,
+	sort: deletedIds.sort,
+	splice: deletedIds.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+	var src, copyIsArray, copy, name, options, 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() {},
+
+	// See test/unit/core.js for details concerning isFunction.
+	// Since version 1.3, DOM methods and functions like alert
+	// aren't supported. They return false on IE (#2968).
+	isFunction: function( obj ) {
+		return jQuery.type(obj) === "function";
+	},
+
+	isArray: Array.isArray || function( obj ) {
+		return jQuery.type(obj) === "array";
+	},
+
+	isWindow: function( obj ) {
+		/* jshint eqeqeq: false */
+		return obj != null && obj == obj.window;
+	},
+
+	isNumeric: function( obj ) {
+		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
+		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+		// subtraction forces infinities to NaN
+		return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0;
+	},
+
+	isEmptyObject: function( obj ) {
+		var name;
+		for ( name in obj ) {
+			return false;
+		}
+		return true;
+	},
+
+	isPlainObject: function( obj ) {
+		var key;
+
+		// Must be an Object.
+		// Because of IE, we also have to check the presence of the constructor property.
+		// Make sure that DOM nodes and window objects don't pass through, as well
+		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+			return false;
+		}
+
+		try {
+			// Not own constructor property must be Object
+			if ( obj.constructor &&
+				!hasOwn.call(obj, "constructor") &&
+				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+				return false;
+			}
+		} catch ( e ) {
+			// IE8,9 Will throw exceptions on certain host objects #9897
+			return false;
+		}
+
+		// Support: IE<9
+		// Handle iteration over inherited properties before own properties.
+		if ( support.ownLast ) {
+			for ( key in obj ) {
+				return hasOwn.call( obj, key );
+			}
+		}
+
+		// Own properties are enumerated firstly, so to speed up,
+		// if last one is own, then all properties are own.
+		for ( key in obj ) {}
+
+		return key === undefined || hasOwn.call( obj, key );
+	},
+
+	type: function( obj ) {
+		if ( obj == null ) {
+			return obj + "";
+		}
+		return typeof obj === "object" || typeof obj === "function" ?
+			class2type[ toString.call(obj) ] || "object" :
+			typeof obj;
+	},
+
+	// Evaluates a script in a global context
+	// Workarounds based on findings by Jim Driscoll
+	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+	globalEval: function( data ) {
+		if ( data && jQuery.trim( data ) ) {
+			// We use execScript on Internet Explorer
+			// We use an anonymous function so that context is window
+			// rather than jQuery in Firefox
+			( window.execScript || function( data ) {
+				window[ "eval" ].call( window, data );
+			} )( data );
+		}
+	},
+
+	// Convert dashed to camelCase; used by the css and data modules
+	// 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();
+	},
+
+	// args is for internal usage only
+	each: function( obj, callback, args ) {
+		var value,
+			i = 0,
+			length = obj.length,
+			isArray = isArraylike( obj );
+
+		if ( args ) {
+			if ( isArray ) {
+				for ( ; i < length; i++ ) {
+					value = callback.apply( obj[ i ], args );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( i in obj ) {
+					value = callback.apply( obj[ i ], args );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			}
+
+		// A special, fast, case for the most common use of each
+		} else {
+			if ( isArray ) {
+				for ( ; i < length; i++ ) {
+					value = callback.call( obj[ i ], i, obj[ i ] );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			} else {
+				for ( i in obj ) {
+					value = callback.call( obj[ i ], i, obj[ i ] );
+
+					if ( value === false ) {
+						break;
+					}
+				}
+			}
+		}
+
+		return obj;
+	},
+
+	// Support: Android<4.1, IE<9
+	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 ) {
+		var len;
+
+		if ( arr ) {
+			if ( indexOf ) {
+				return indexOf.call( arr, elem, i );
+			}
+
+			len = arr.length;
+			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+			for ( ; i < len; i++ ) {
+				// Skip accessing in sparse arrays
+				if ( i in arr && arr[ i ] === elem ) {
+					return i;
+				}
+			}
+		}
+
+		return -1;
+	},
+
+	merge: function( first, second ) {
+		var len = +second.length,
+			j = 0,
+			i = first.length;
+
+		while ( j < len ) {
+			first[ i++ ] = second[ j++ ];
+		}
+
+		// Support: IE<9
+		// Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
+		if ( len !== len ) {
+			while ( second[j] !== undefined ) {
+				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 value,
+			i = 0,
+			length = elems.length,
+			isArray = isArraylike( elems ),
+			ret = [];
+
+		// Go through the array, translating each of the items to their new values
+		if ( isArray ) {
+			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 args, proxy, tmp;
+
+		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: function() {
+		return +( new Date() );
+	},
+
+	// jQuery.support is not used in Core but other projects attach their
+	// properties to it so it needs to exist.
+	support: support
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+	class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+function isArraylike( obj ) {
+	var length = obj.length,
+		type = jQuery.type( obj );
+
+	if ( type === "function" || jQuery.isWindow( obj ) ) {
+		return false;
+	}
+
+	if ( obj.nodeType === 1 && length ) {
+		return true;
+	}
+
+	return type === "array" || length === 0 ||
+		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v1.10.19
+ * http://sizzlejs.com/
+ *
+ * Copyright 2013 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-04-18
+ */
+(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" + -(new Date()),
+	preferredDoc = window.document,
+	dirruns = 0,
+	done = 0,
+	classCache = createCache(),
+	tokenCache = createCache(),
+	compilerCache = createCache(),
+	sortOrder = function( a, b ) {
+		if ( a === b ) {
+			hasDuplicate = true;
+		}
+		return 0;
+	},
+
+	// General-purpose constants
+	strundefined = typeof undefined,
+	MAX_NEGATIVE = 1 << 31,
+
+	// Instance methods
+	hasOwn = ({}).hasOwnProperty,
+	arr = [],
+	pop = arr.pop,
+	push_native = arr.push,
+	push = arr.push,
+	slice = arr.slice,
+	// Use a stripped-down indexOf if we can't use a native one
+	indexOf = arr.indexOf || function( elem ) {
+		var i = 0,
+			len = this.length;
+		for ( ; i < len; i++ ) {
+			if ( this[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
+
+	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+	whitespace = "[\\x20\\t\\r\\n\\f]",
+	// http://www.w3.org/TR/css3-syntax/#characters
+	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+	// Loosely modeled on CSS identifier characters
+	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+	identifier = characterEncoding.replace( "w", "w#" ),
+
+	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
+		// Operator (capture 2)
+		"*([*^$|!~]?=)" + whitespace +
+		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+		"*\\]",
+
+	pseudos = ":(" + characterEncoding + ")(?:\\((" +
+		// 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
+	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( "^#(" + characterEncoding + ")" ),
+		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+		"ATTR": new RegExp( "^" + attributes ),
+		"PSEUDO": new RegExp( "^" + pseudos ),
+		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+		// For use in libraries implementing .is()
+		// We use this for POS matching in `select`
+		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+	},
+
+	rinputs = /^(?:input|select|textarea|button)$/i,
+	rheader = /^h\d$/i,
+
+	rnative = /^[^{]+\{\s*\[native \w/,
+
+	// Easily-parseable/retrievable ID or TAG or CLASS selectors
+	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+	rsibling = /[+~]/,
+	rescape = /'|\\/g,
+
+	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+	funescape = function( _, escaped, escapedWhitespace ) {
+		var high = "0x" + escaped - 0x10000;
+		// NaN means non-codepoint
+		// Support: Firefox<24
+		// Workaround erroneous numeric interpretation of +"0x"
+		return high !== high || escapedWhitespace ?
+			escaped :
+			high < 0 ?
+				// BMP codepoint
+				String.fromCharCode( high + 0x10000 ) :
+				// Supplemental Plane codepoint (surrogate pair)
+				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+	};
+
+// 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 match, elem, m, nodeType,
+		// QSA vars
+		i, groups, old, nid, newContext, newSelector;
+
+	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+		setDocument( context );
+	}
+
+	context = context || document;
+	results = results || [];
+
+	if ( !selector || typeof selector !== "string" ) {
+		return results;
+	}
+
+	if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
+		return [];
+	}
+
+	if ( documentIsHTML && !seed ) {
+
+		// Shortcuts
+		if ( (match = rquickExpr.exec( selector )) ) {
+			// Speed-up: Sizzle("#ID")
+			if ( (m = match[1]) ) {
+				if ( nodeType === 9 ) {
+					elem = context.getElementById( m );
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document (jQuery #6963)
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE, Opera, and Webkit return items
+						// by name instead of ID
+						if ( elem.id === m ) {
+							results.push( elem );
+							return results;
+						}
+					} else {
+						return results;
+					}
+				} else {
+					// Context is not a document
+					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+						contains( context, elem ) && elem.id === m ) {
+						results.push( elem );
+						return results;
+					}
+				}
+
+			// Speed-up: Sizzle("TAG")
+			} else if ( match[2] ) {
+				push.apply( results, context.getElementsByTagName( selector ) );
+				return results;
+
+			// Speed-up: Sizzle(".CLASS")
+			} else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
+				push.apply( results, context.getElementsByClassName( m ) );
+				return results;
+			}
+		}
+
+		// QSA path
+		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+			nid = old = expando;
+			newContext = context;
+			newSelector = nodeType === 9 && selector;
+
+			// qSA works strangely on Element-rooted queries
+			// We can work around this by specifying an extra ID on the root
+			// and working up from there (Thanks to Andrew Dupont for the technique)
+			// IE 8 doesn't work on object elements
+			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+				groups = tokenize( selector );
+
+				if ( (old = context.getAttribute("id")) ) {
+					nid = old.replace( rescape, "\\$&" );
+				} else {
+					context.setAttribute( "id", nid );
+				}
+				nid = "[id='" + nid + "'] ";
+
+				i = groups.length;
+				while ( i-- ) {
+					groups[i] = nid + toSelector( groups[i] );
+				}
+				newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
+				newSelector = groups.join(",");
+			}
+
+			if ( newSelector ) {
+				try {
+					push.apply( results,
+						newContext.querySelectorAll( newSelector )
+					);
+					return results;
+				} catch(qsaError) {
+				} finally {
+					if ( !old ) {
+						context.removeAttribute("id");
+					}
+				}
+			}
+		}
+	}
+
+	// All others
+	return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ *	deleting the oldest entry
+ */
+function createCache() {
+	var keys = [];
+
+	function cache( key, value ) {
+		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+		if ( keys.push( key + " " ) > Expr.cacheLength ) {
+			// Only keep the most recent entries
+			delete cache[ keys.shift() ];
+		}
+		return (cache[ key + " " ] = value);
+	}
+	return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+	fn[ expando ] = true;
+	return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+	var div = document.createElement("div");
+
+	try {
+		return !!fn( div );
+	} catch (e) {
+		return false;
+	} finally {
+		// Remove from its parent by default
+		if ( div.parentNode ) {
+			div.parentNode.removeChild( div );
+		}
+		// release memory in IE
+		div = null;
+	}
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+	var arr = attrs.split("|"),
+		i = attrs.length;
+
+	while ( i-- ) {
+		Expr.attrHandle[ arr[i] ] = handler;
+	}
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+	var cur = b && a,
+		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+			( ~b.sourceIndex || MAX_NEGATIVE ) -
+			( ~a.sourceIndex || MAX_NEGATIVE );
+
+	// Use IE sourceIndex if available on both nodes
+	if ( diff ) {
+		return diff;
+	}
+
+	// Check if b follows a
+	if ( cur ) {
+		while ( (cur = cur.nextSibling) ) {
+			if ( cur === b ) {
+				return -1;
+			}
+		}
+	}
+
+	return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return name === "input" && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return (name === "input" || name === "button") && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+	return markFunction(function( argument ) {
+		argument = +argument;
+		return markFunction(function( seed, matches ) {
+			var j,
+				matchIndexes = fn( [], seed.length, argument ),
+				i = matchIndexes.length;
+
+			// Match elements found at the specified indexes
+			while ( i-- ) {
+				if ( seed[ (j = matchIndexes[i]) ] ) {
+					seed[j] = !(matches[j] = seed[j]);
+				}
+			}
+		});
+	});
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+	return context && typeof context.getElementsByTagName !== strundefined && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+	// documentElement is verified for cases where it doesn't yet exist
+	// (such as loading iframes in IE - #4833)
+	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+	return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+	var hasCompare,
+		doc = node ? node.ownerDocument || node : preferredDoc,
+		parent = doc.defaultView;
+
+	// If no document and documentElement is available, return
+	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+		return document;
+	}
+
+	// Set our document
+	document = doc;
+	docElem = doc.documentElement;
+
+	// Support tests
+	documentIsHTML = !isXML( doc );
+
+	// Support: IE>8
+	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
+	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
+	// IE6-8 do not support the defaultView property so parent will be undefined
+	if ( parent && parent !== parent.top ) {
+		// IE11 does not have attachEvent, so all must suffer
+		if ( parent.addEventListener ) {
+			parent.addEventListener( "unload", function() {
+				setDocument();
+			}, false );
+		} else if ( parent.attachEvent ) {
+			parent.attachEvent( "onunload", function() {
+				setDocument();
+			});
+		}
+	}
+
+	/* Attributes
+	---------------------------------------------------------------------- */
+
+	// Support: IE<8
+	// Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
+	support.attributes = assert(function( div ) {
+		div.className = "i";
+		return !div.getAttribute("className");
+	});
+
+	/* getElement(s)By*
+	---------------------------------------------------------------------- */
+
+	// Check if getElementsByTagName("*") returns only elements
+	support.getElementsByTagName = assert(function( div ) {
+		div.appendChild( doc.createComment("") );
+		return !div.getElementsByTagName("*").length;
+	});
+
+	// Check if getElementsByClassName can be trusted
+	support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
+		div.innerHTML = "<div class='a'></div><div class='a i'></div>";
+
+		// Support: Safari<4
+		// Catch class over-caching
+		div.firstChild.className = "i";
+		// Support: Opera<10
+		// Catch gEBCN failure to find non-leading classes
+		return div.getElementsByClassName("i").length === 2;
+	});
+
+	// Support: IE<10
+	// Check if getElementById returns elements by name
+	// The broken getElementById methods don't pick up programatically-set names,
+	// so use a roundabout getElementsByName test
+	support.getById = assert(function( div ) {
+		docElem.appendChild( div ).id = expando;
+		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
+	});
+
+	// ID find and filter
+	if ( support.getById ) {
+		Expr.find["ID"] = function( id, context ) {
+			if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
+				var m = context.getElementById( id );
+				// Check parentNode to catch when Blackberry 4.6 returns
+				// nodes that are no longer in the document #6963
+				return m && m.parentNode ? [ m ] : [];
+			}
+		};
+		Expr.filter["ID"] = function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				return elem.getAttribute("id") === attrId;
+			};
+		};
+	} else {
+		// Support: IE6/7
+		// getElementById is not reliable as a find shortcut
+		delete Expr.find["ID"];
+
+		Expr.filter["ID"] =  function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+				return node && node.value === attrId;
+			};
+		};
+	}
+
+	// Tag
+	Expr.find["TAG"] = support.getElementsByTagName ?
+		function( tag, context ) {
+			if ( typeof context.getElementsByTagName !== strundefined ) {
+				return context.getElementsByTagName( tag );
+			}
+		} :
+		function( tag, context ) {
+			var elem,
+				tmp = [],
+				i = 0,
+				results = context.getElementsByTagName( tag );
+
+			// Filter out possible comments
+			if ( tag === "*" ) {
+				while ( (elem = results[i++]) ) {
+					if ( elem.nodeType === 1 ) {
+						tmp.push( elem );
+					}
+				}
+
+				return tmp;
+			}
+			return results;
+		};
+
+	// Class
+	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+		if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
+			return context.getElementsByClassName( className );
+		}
+	};
+
+	/* QSA/matchesSelector
+	---------------------------------------------------------------------- */
+
+	// QSA and matchesSelector support
+
+	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+	rbuggyMatches = [];
+
+	// qSa(:focus) reports false when true (Chrome 21)
+	// We allow this because of a bug in IE8/9 that throws an error
+	// whenever `document.activeElement` is accessed on an iframe
+	// So, we allow :focus to pass through QSA all the time to avoid the IE error
+	// See http://bugs.jquery.com/ticket/13378
+	rbuggyQSA = [];
+
+	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
+		// Build QSA regex
+		// Regex strategy adopted from Diego Perini
+		assert(function( div ) {
+			// Select is set to empty string on purpose
+			// This is to test IE's treatment of not explicitly
+			// setting a boolean content attribute,
+			// since its presence should be enough
+			// http://bugs.jquery.com/ticket/12359
+			div.innerHTML = "<select msallowclip=''><option selected=''></option></select>";
+
+			// Support: IE8, Opera 11-12.16
+			// Nothing should be selected when empty strings follow ^= or $= or *=
+			// The test attribute must be unknown in Opera but "safe" for WinRT
+			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+			if ( div.querySelectorAll("[msallowclip^='']").length ) {
+				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+			}
+
+			// Support: IE8
+			// Boolean attributes and "value" are not treated correctly
+			if ( !div.querySelectorAll("[selected]").length ) {
+				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+			}
+
+			// Webkit/Opera - :checked should return selected option elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			// IE8 throws error here and will not see later tests
+			if ( !div.querySelectorAll(":checked").length ) {
+				rbuggyQSA.push(":checked");
+			}
+		});
+
+		assert(function( div ) {
+			// Support: Windows 8 Native Apps
+			// The type and name attributes are restricted during .innerHTML assignment
+			var input = doc.createElement("input");
+			input.setAttribute( "type", "hidden" );
+			div.appendChild( input ).setAttribute( "name", "D" );
+
+			// Support: IE8
+			// Enforce case-sensitivity of name attribute
+			if ( div.querySelectorAll("[name=d]").length ) {
+				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+			}
+
+			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+			// IE8 throws error here and will not see later tests
+			if ( !div.querySelectorAll(":enabled").length ) {
+				rbuggyQSA.push( ":enabled", ":disabled" );
+			}
+
+			// Opera 10-11 does not throw on post-comma invalid pseudos
+			div.querySelectorAll("*,:x");
+			rbuggyQSA.push(",.*:");
+		});
+	}
+
+	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+		docElem.webkitMatchesSelector ||
+		docElem.mozMatchesSelector ||
+		docElem.oMatchesSelector ||
+		docElem.msMatchesSelector) )) ) {
+
+		assert(function( div ) {
+			// Check to see if it's possible to do matchesSelector
+			// on a disconnected node (IE 9)
+			support.disconnectedMatch = matches.call( div, "div" );
+
+			// This should fail with an exception
+			// Gecko does not error, returns false instead
+			matches.call( div, "[s!='']:x" );
+			rbuggyMatches.push( "!=", pseudos );
+		});
+	}
+
+	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+	/* Contains
+	---------------------------------------------------------------------- */
+	hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+	// Element contains another
+	// Purposefully does not implement inclusive descendent
+	// As in, an element does not contain itself
+	contains = hasCompare || rnative.test( docElem.contains ) ?
+		function( a, b ) {
+			var adown = a.nodeType === 9 ? a.documentElement : a,
+				bup = b && b.parentNode;
+			return a === bup || !!( bup && bup.nodeType === 1 && (
+				adown.contains ?
+					adown.contains( bup ) :
+					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+			));
+		} :
+		function( a, b ) {
+			if ( b ) {
+				while ( (b = b.parentNode) ) {
+					if ( b === a ) {
+						return true;
+					}
+				}
+			}
+			return false;
+		};
+
+	/* Sorting
+	---------------------------------------------------------------------- */
+
+	// Document order sorting
+	sortOrder = hasCompare ?
+	function( a, b ) {
+
+		// Flag for duplicate removal
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		// Sort on method existence if only one input has compareDocumentPosition
+		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+		if ( compare ) {
+			return compare;
+		}
+
+		// Calculate position if both inputs belong to the same document
+		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+			a.compareDocumentPosition( b ) :
+
+			// Otherwise we know they are disconnected
+			1;
+
+		// Disconnected nodes
+		if ( compare & 1 ||
+			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+			// Choose the first element that is related to our preferred document
+			if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+				return -1;
+			}
+			if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+				return 1;
+			}
+
+			// Maintain original order
+			return sortInput ?
+				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
+				0;
+		}
+
+		return compare & 4 ? -1 : 1;
+	} :
+	function( a, b ) {
+		// Exit early if the nodes are identical
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		var cur,
+			i = 0,
+			aup = a.parentNode,
+			bup = b.parentNode,
+			ap = [ a ],
+			bp = [ b ];
+
+		// Parentless nodes are either documents or disconnected
+		if ( !aup || !bup ) {
+			return a === doc ? -1 :
+				b === doc ? 1 :
+				aup ? -1 :
+				bup ? 1 :
+				sortInput ?
+				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
+				0;
+
+		// If the nodes are siblings, we can do a quick check
+		} else if ( aup === bup ) {
+			return siblingCheck( a, b );
+		}
+
+		// Otherwise we need full lists of their ancestors for comparison
+		cur = a;
+		while ( (cur = cur.parentNode) ) {
+			ap.unshift( cur );
+		}
+		cur = b;
+		while ( (cur = cur.parentNode) ) {
+			bp.unshift( cur );
+		}
+
+		// Walk down the tree looking for a discrepancy
+		while ( ap[i] === bp[i] ) {
+			i++;
+		}
+
+		return i ?
+			// Do a sibling check if the nodes have a common ancestor
+			siblingCheck( ap[i], bp[i] ) :
+
+			// Otherwise nodes in our document sort first
+			ap[i] === preferredDoc ? -1 :
+			bp[i] === preferredDoc ? 1 :
+			0;
+	};
+
+	return doc;
+};
+
+Sizzle.matches = function( expr, elements ) {
+	return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	// Make sure that attribute selectors are quoted
+	expr = expr.replace( rattributeQuotes, "='$1']" );
+
+	if ( support.matchesSelector && documentIsHTML &&
+		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
+
+		try {
+			var ret = matches.call( elem, expr );
+
+			// IE 9's matchesSelector returns false on disconnected nodes
+			if ( ret || support.disconnectedMatch ||
+					// As well, disconnected nodes are said to be in a document
+					// fragment in IE 9
+					elem.document && elem.document.nodeType !== 11 ) {
+				return ret;
+			}
+		} catch(e) {}
+	}
+
+	return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+	// Set document vars if needed
+	if ( ( context.ownerDocument || context ) !== document ) {
+		setDocument( context );
+	}
+	return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	var fn = Expr.attrHandle[ name.toLowerCase() ],
+		// Don't get fooled by Object.prototype properties (jQuery #13807)
+		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+			fn( elem, name, !documentIsHTML ) :
+			undefined;
+
+	return val !== undefined ?
+		val :
+		support.attributes || !documentIsHTML ?
+			elem.getAttribute( name ) :
+			(val = elem.getAttributeNode(name)) && val.specified ?
+				val.value :
+				null;
+};
+
+Sizzle.error = function( msg ) {
+	throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+	var elem,
+		duplicates = [],
+		j = 0,
+		i = 0;
+
+	// Unless we *know* we can detect duplicates, assume their presence
+	hasDuplicate = !support.detectDuplicates;
+	sortInput = !support.sortStable && results.slice( 0 );
+	results.sort( sortOrder );
+
+	if ( hasDuplicate ) {
+		while ( (elem = results[i++]) ) {
+			if ( elem === results[ i ] ) {
+				j = duplicates.push( i );
+			}
+		}
+		while ( j-- ) {
+			results.splice( duplicates[ j ], 1 );
+		}
+	}
+
+	// Clear input after sorting to release objects
+	// See https://github.com/jquery/sizzle/pull/225
+	sortInput = null;
+
+	return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+	var node,
+		ret = "",
+		i = 0,
+		nodeType = elem.nodeType;
+
+	if ( !nodeType ) {
+		// If no nodeType, this is expected to be an array
+		while ( (node = elem[i++]) ) {
+			// Do not traverse comment nodes
+			ret += getText( node );
+		}
+	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+		// Use textContent for elements
+		// innerText usage removed for consistency of new lines (jQuery #11153)
+		if ( typeof elem.textContent === "string" ) {
+			return elem.textContent;
+		} else {
+			// Traverse its children
+			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+				ret += getText( elem );
+			}
+		}
+	} else if ( nodeType === 3 || nodeType === 4 ) {
+		return elem.nodeValue;
+	}
+	// Do not include comment or processing instruction nodes
+
+	return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+	// Can be adjusted by the user
+	cacheLength: 50,
+
+	createPseudo: markFunction,
+
+	match: matchExpr,
+
+	attrHandle: {},
+
+	find: {},
+
+	relative: {
+		">": { dir: "parentNode", first: true },
+		" ": { dir: "parentNode" },
+		"+": { dir: "previousSibling", first: true },
+		"~": { dir: "previousSibling" }
+	},
+
+	preFilter: {
+		"ATTR": function( match ) {
+			match[1] = match[1].replace( runescape, funescape );
+
+			// Move the given value to match[3] whether quoted or unquoted
+			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+			if ( match[2] === "~=" ) {
+				match[3] = " " + match[3] + " ";
+			}
+
+			return match.slice( 0, 4 );
+		},
+
+		"CHILD": function( match ) {
+			/* matches from matchExpr["CHILD"]
+				1 type (only|nth|...)
+				2 what (child|of-type)
+				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+				4 xn-component of xn+y argument ([+-]?\d*n|)
+				5 sign of xn-component
+				6 x of xn-component
+				7 sign of y-component
+				8 y of y-component
+			*/
+			match[1] = match[1].toLowerCase();
+
+			if ( match[1].slice( 0, 3 ) === "nth" ) {
+				// nth-* requires argument
+				if ( !match[3] ) {
+					Sizzle.error( match[0] );
+				}
+
+				// numeric x and y parameters for Expr.filter.CHILD
+				// remember that false/true cast respectively to 0/1
+				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+			// other types prohibit arguments
+			} else if ( match[3] ) {
+				Sizzle.error( match[0] );
+			}
+
+			return match;
+		},
+
+		"PSEUDO": function( match ) {
+			var excess,
+				unquoted = !match[6] && match[2];
+
+			if ( matchExpr["CHILD"].test( match[0] ) ) {
+				return null;
+			}
+
+			// Accept quoted arguments as-is
+			if ( match[3] ) {
+				match[2] = match[4] || match[5] || "";
+
+			// Strip excess characters from unquoted arguments
+			} else if ( unquoted && rpseudo.test( unquoted ) &&
+				// Get excess from tokenize (recursively)
+				(excess = tokenize( unquoted, true )) &&
+				// advance to the next closing parenthesis
+				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+				// excess is a negative index
+				match[0] = match[0].slice( 0, excess );
+				match[2] = unquoted.slice( 0, excess );
+			}
+
+			// Return only captures needed by the pseudo filter method (type and argument)
+			return match.slice( 0, 3 );
+		}
+	},
+
+	filter: {
+
+		"TAG": function( nodeNameSelector ) {
+			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+			return nodeNameSelector === "*" ?
+				function() { return true; } :
+				function( elem ) {
+					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+				};
+		},
+
+		"CLASS": function( className ) {
+			var pattern = classCache[ className + " " ];
+
+			return pattern ||
+				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+				classCache( className, function( elem ) {
+					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
+				});
+		},
+
+		"ATTR": function( name, operator, check ) {
+			return function( elem ) {
+				var result = Sizzle.attr( elem, name );
+
+				if ( result == null ) {
+					return operator === "!=";
+				}
+				if ( !operator ) {
+					return true;
+				}
+
+				result += "";
+
+				return operator === "=" ? result === check :
+					operator === "!=" ? result !== check :
+					operator === "^=" ? check && result.indexOf( check ) === 0 :
+					operator === "*=" ? check && result.indexOf( check ) > -1 :
+					operator === "$=" ? check && result.slice( -check.length ) === check :
+					operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
+					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+					false;
+			};
+		},
+
+		"CHILD": function( type, what, argument, first, last ) {
+			var simple = type.slice( 0, 3 ) !== "nth",
+				forward = type.slice( -4 ) !== "last",
+				ofType = what === "of-type";
+
+			return first === 1 && last === 0 ?
+
+				// Shortcut for :nth-*(n)
+				function( elem ) {
+					return !!elem.parentNode;
+				} :
+
+				function( elem, context, xml ) {
+					var cache, outerCache, node, diff, nodeIndex, start,
+						dir = simple !== forward ? "nextSibling" : "previousSibling",
+						parent = elem.parentNode,
+						name = ofType && elem.nodeName.toLowerCase(),
+						useCache = !xml && !ofType;
+
+					if ( parent ) {
+
+						// :(first|last|only)-(child|of-type)
+						if ( simple ) {
+							while ( dir ) {
+								node = elem;
+								while ( (node = node[ dir ]) ) {
+									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+										return false;
+									}
+								}
+								// Reverse direction for :only-* (if we haven't yet done so)
+								start = dir = type === "only" && !start && "nextSibling";
+							}
+							return true;
+						}
+
+						start = [ forward ? parent.firstChild : parent.lastChild ];
+
+						// non-xml :nth-child(...) stores cache data on `parent`
+						if ( forward && useCache ) {
+							// Seek `elem` from a previously-cached index
+							outerCache = parent[ expando ] || (parent[ expando ] = {});
+							cache = outerCache[ type ] || [];
+							nodeIndex = cache[0] === dirruns && cache[1];
+							diff = cache[0] === dirruns && cache[2];
+							node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+							while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+								// Fallback to seeking `elem` from the start
+								(diff = nodeIndex = 0) || start.pop()) ) {
+
+								// When found, cache indexes on `parent` and break
+								if ( node.nodeType === 1 && ++diff && node === elem ) {
+									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+									break;
+								}
+							}
+
+						// Use previously-cached element index if available
+						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+							diff = cache[1];
+
+						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+						} else {
+							// Use the same loop as above to seek `elem` from the start
+							while ( (node = ++nodeIndex && node && node[ dir ] ||
+								(diff = nodeIndex = 0) || start.pop()) ) {
+
+								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+									// Cache the index of each encountered element
+									if ( useCache ) {
+										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+									}
+
+									if ( node === elem ) {
+										break;
+									}
+								}
+							}
+						}
+
+						// Incorporate the offset, then check against cycle size
+						diff -= last;
+						return diff === first || ( diff % first === 0 && diff / first >= 0 );
+					}
+				};
+		},
+
+		"PSEUDO": function( pseudo, argument ) {
+			// pseudo-class names are case-insensitive
+			// http://www.w3.org/TR/selectors/#pseudo-classes
+			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+			// Remember that setFilters inherits from pseudos
+			var args,
+				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+					Sizzle.error( "unsupported pseudo: " + pseudo );
+
+			// The user may use createPseudo to indicate that
+			// arguments are needed to create the filter function
+			// just as Sizzle does
+			if ( fn[ expando ] ) {
+				return fn( argument );
+			}
+
+			// But maintain support for old signatures
+			if ( fn.length > 1 ) {
+				args = [ pseudo, pseudo, "", argument ];
+				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+					markFunction(function( seed, matches ) {
+						var idx,
+							matched = fn( seed, argument ),
+							i = matched.length;
+						while ( i-- ) {
+							idx = indexOf.call( seed, matched[i] );
+							seed[ idx ] = !( matches[ idx ] = matched[i] );
+						}
+					}) :
+					function( elem ) {
+						return fn( elem, 0, args );
+					};
+			}
+
+			return fn;
+		}
+	},
+
+	pseudos: {
+		// Potentially complex pseudos
+		"not": markFunction(function( selector ) {
+			// Trim the selector passed to compile
+			// to avoid treating leading and trailing
+			// spaces as combinators
+			var input = [],
+				results = [],
+				matcher = compile( selector.replace( rtrim, "$1" ) );
+
+			return matcher[ expando ] ?
+				markFunction(function( seed, matches, context, xml ) {
+					var elem,
+						unmatched = matcher( seed, null, xml, [] ),
+						i = seed.length;
+
+					// Match elements unmatched by `matcher`
+					while ( i-- ) {
+						if ( (elem = unmatched[i]) ) {
+							seed[i] = !(matches[i] = elem);
+						}
+					}
+				}) :
+				function( elem, context, xml ) {
+					input[0] = elem;
+					matcher( input, null, xml, results );
+					return !results.pop();
+				};
+		}),
+
+		"has": markFunction(function( selector ) {
+			return function( elem ) {
+				return Sizzle( selector, elem ).length > 0;
+			};
+		}),
+
+		"contains": markFunction(function( text ) {
+			return function( elem ) {
+				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+			};
+		}),
+
+		// "Whether an element is represented by a :lang() selector
+		// is based solely on the element's language value
+		// being equal to the identifier C,
+		// or beginning with the identifier C immediately followed by "-".
+		// The matching of C against the element's language value is performed case-insensitively.
+		// The identifier C does not have to be a valid language name."
+		// http://www.w3.org/TR/selectors/#lang-pseudo
+		"lang": markFunction( function( lang ) {
+			// lang value must be a valid identifier
+			if ( !ridentifier.test(lang || "") ) {
+				Sizzle.error( "unsupported lang: " + lang );
+			}
+			lang = lang.replace( runescape, funescape ).toLowerCase();
+			return function( elem ) {
+				var elemLang;
+				do {
+					if ( (elemLang = documentIsHTML ?
+						elem.lang :
+						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+						elemLang = elemLang.toLowerCase();
+						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+					}
+				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+				return false;
+			};
+		}),
+
+		// Miscellaneous
+		"target": function( elem ) {
+			var hash = window.location && window.location.hash;
+			return hash && hash.slice( 1 ) === elem.id;
+		},
+
+		"root": function( elem ) {
+			return elem === docElem;
+		},
+
+		"focus": function( elem ) {
+			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+		},
+
+		// Boolean properties
+		"enabled": function( elem ) {
+			return elem.disabled === false;
+		},
+
+		"disabled": function( elem ) {
+			return elem.disabled === true;
+		},
+
+		"checked": function( elem ) {
+			// In CSS3, :checked should return both checked and selected elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			var nodeName = elem.nodeName.toLowerCase();
+			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+		},
+
+		"selected": function( elem ) {
+			// Accessing this property makes selected-by-default
+			// options in Safari work properly
+			if ( elem.parentNode ) {
+				elem.parentNode.selectedIndex;
+			}
+
+			return elem.selected === true;
+		},
+
+		// Contents
+		"empty": function( elem ) {
+			// http://www.w3.org/TR/selectors/#empty-pseudo
+			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+			//   but not by others (comment: 8; processing instruction: 7; etc.)
+			// nodeType < 6 works because attributes (2) do not appear as children
+			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+				if ( elem.nodeType < 6 ) {
+					return false;
+				}
+			}
+			return true;
+		},
+
+		"parent": function( elem ) {
+			return !Expr.pseudos["empty"]( elem );
+		},
+
+		// Element/input types
+		"header": function( elem ) {
+			return rheader.test( elem.nodeName );
+		},
+
+		"input": function( elem ) {
+			return rinputs.test( elem.nodeName );
+		},
+
+		"button": function( elem ) {
+			var name = elem.nodeName.toLowerCase();
+			return name === "input" && elem.type === "button" || name === "button";
+		},
+
+		"text": function( elem ) {
+			var attr;
+			return elem.nodeName.toLowerCase() === "input" &&
+				elem.type === "text" &&
+
+				// Support: IE<8
+				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+		},
+
+		// Position-in-collection
+		"first": createPositionalPseudo(function() {
+			return [ 0 ];
+		}),
+
+		"last": createPositionalPseudo(function( matchIndexes, length ) {
+			return [ length - 1 ];
+		}),
+
+		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			return [ argument < 0 ? argument + length : argument ];
+		}),
+
+		"even": createPositionalPseudo(function( matchIndexes, length ) {
+			var i = 0;
+			for ( ; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"odd": createPositionalPseudo(function( matchIndexes, length ) {
+			var i = 1;
+			for ( ; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			var i = argument < 0 ? argument + length : argument;
+			for ( ; --i >= 0; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			var i = argument < 0 ? argument + length : argument;
+			for ( ; ++i < length; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		})
+	}
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+	Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+	Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+	var matched, match, tokens, type,
+		soFar, groups, preFilters,
+		cached = tokenCache[ selector + " " ];
+
+	if ( cached ) {
+		return parseOnly ? 0 : cached.slice( 0 );
+	}
+
+	soFar = selector;
+	groups = [];
+	preFilters = Expr.preFilter;
+
+	while ( soFar ) {
+
+		// Comma and first run
+		if ( !matched || (match = rcomma.exec( soFar )) ) {
+			if ( match ) {
+				// Don't consume trailing commas as valid
+				soFar = soFar.slice( match[0].length ) || soFar;
+			}
+			groups.push( (tokens = []) );
+		}
+
+		matched = false;
+
+		// Combinators
+		if ( (match = rcombinators.exec( soFar )) ) {
+			matched = match.shift();
+			tokens.push({
+				value: matched,
+				// Cast descendant combinators to space
+				type: match[0].replace( rtrim, " " )
+			});
+			soFar = soFar.slice( matched.length );
+		}
+
+		// Filters
+		for ( type in Expr.filter ) {
+			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+				(match = preFilters[ type ]( match ))) ) {
+				matched = match.shift();
+				tokens.push({
+					value: matched,
+					type: type,
+					matches: match
+				});
+				soFar = soFar.slice( matched.length );
+			}
+		}
+
+		if ( !matched ) {
+			break;
+		}
+	}
+
+	// Return the length of the invalid excess
+	// if we're just parsing
+	// Otherwise, throw an error or return tokens
+	return parseOnly ?
+		soFar.length :
+		soFar ?
+			Sizzle.error( selector ) :
+			// Cache the tokens
+			tokenCache( selector, groups ).slice( 0 );
+};
+
+function toSelector( tokens ) {
+	var i = 0,
+		len = tokens.length,
+		selector = "";
+	for ( ; i < len; i++ ) {
+		selector += tokens[i].value;
+	}
+	return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+	var dir = combinator.dir,
+		checkNonElements = base && dir === "parentNode",
+		doneName = done++;
+
+	return combinator.first ?
+		// Check against closest ancestor/preceding element
+		function( elem, context, xml ) {
+			while ( (elem = elem[ dir ]) ) {
+				if ( elem.nodeType === 1 || checkNonElements ) {
+					return matcher( elem, context, xml );
+				}
+			}
+		} :
+
+		// Check against all ancestor/preceding elements
+		function( elem, context, xml ) {
+			var oldCache, outerCache,
+				newCache = [ dirruns, doneName ];
+
+			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+			if ( xml ) {
+				while ( (elem = elem[ dir ]) ) {
+					if ( elem.nodeType === 1 || checkNonElements ) {
+						if ( matcher( elem, context, xml ) ) {
+							return true;
+						}
+					}
+				}
+			} else {
+				while ( (elem = elem[ dir ]) ) {
+					if ( elem.nodeType === 1 || checkNonElements ) {
+						outerCache = elem[ expando ] || (elem[ expando ] = {});
+						if ( (oldCache = outerCache[ dir ]) &&
+							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+							// Assign to newCache so results back-propagate to previous elements
+							return (newCache[ 2 ] = oldCache[ 2 ]);
+						} else {
+							// Reuse newcache so results back-propagate to previous elements
+							outerCache[ dir ] = newCache;
+
+							// A match means we're done; a fail means we have to keep checking
+							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+								return true;
+							}
+						}
+					}
+				}
+			}
+		};
+}
+
+function elementMatcher( matchers ) {
+	return matchers.length > 1 ?
+		function( elem, context, xml ) {
+			var i = matchers.length;
+			while ( i-- ) {
+				if ( !matchers[i]( elem, context, xml ) ) {
+					return false;
+				}
+			}
+			return true;
+		} :
+		matchers[0];
+}
+
+function multipleContexts( selector, contexts, results ) {
+	var i = 0,
+		len = contexts.length;
+	for ( ; i < len; i++ ) {
+		Sizzle( selector, contexts[i], results );
+	}
+	return results;
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+	var elem,
+		newUnmatched = [],
+		i = 0,
+		len = unmatched.length,
+		mapped = map != null;
+
+	for ( ; i < len; i++ ) {
+		if ( (elem = unmatched[i]) ) {
+			if ( !filter || filter( elem, context, xml ) ) {
+				newUnmatched.push( elem );
+				if ( mapped ) {
+					map.push( i );
+				}
+			}
+		}
+	}
+
+	return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+	if ( postFilter && !postFilter[ expando ] ) {
+		postFilter = setMatcher( postFilter );
+	}
+	if ( postFinder && !postFinder[ expando ] ) {
+		postFinder = setMatcher( postFinder, postSelector );
+	}
+	return markFunction(function( seed, results, context, xml ) {
+		var temp, i, elem,
+			preMap = [],
+			postMap = [],
+			preexisting = results.length,
+
+			// Get initial elements from seed or context
+			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+			// Prefilter to get matcher input, preserving a map for seed-results synchronization
+			matcherIn = preFilter && ( seed || !selector ) ?
+				condense( elems, preMap, preFilter, context, xml ) :
+				elems,
+
+			matcherOut = matcher ?
+				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+					// ...intermediate processing is necessary
+					[] :
+
+					// ...otherwise use results directly
+					results :
+				matcherIn;
+
+		// Find primary matches
+		if ( matcher ) {
+			matcher( matcherIn, matcherOut, context, xml );
+		}
+
+		// Apply postFilter
+		if ( postFilter ) {
+			temp = condense( matcherOut, postMap );
+			postFilter( temp, [], context, xml );
+
+			// Un-match failing elements by moving them back to matcherIn
+			i = temp.length;
+			while ( i-- ) {
+				if ( (elem = temp[i]) ) {
+					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+				}
+			}
+		}
+
+		if ( seed ) {
+			if ( postFinder || preFilter ) {
+				if ( postFinder ) {
+					// Get the final matcherOut by condensing this intermediate into postFinder contexts
+					temp = [];
+					i = matcherOut.length;
+					while ( i-- ) {
+						if ( (elem = matcherOut[i]) ) {
+							// Restore matcherIn since elem is not yet a final match
+							temp.push( (matcherIn[i] = elem) );
+						}
+					}
+					postFinder( null, (matcherOut = []), temp, xml );
+				}
+
+				// Move matched elements from seed to results to keep them synchronized
+				i = matcherOut.length;
+				while ( i-- ) {
+					if ( (elem = matcherOut[i]) &&
+						(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
+
+						seed[temp] = !(results[temp] = elem);
+					}
+				}
+			}
+
+		// Add elements to results, through postFinder if defined
+		} else {
+			matcherOut = condense(
+				matcherOut === results ?
+					matcherOut.splice( preexisting, matcherOut.length ) :
+					matcherOut
+			);
+			if ( postFinder ) {
+				postFinder( null, results, matcherOut, xml );
+			} else {
+				push.apply( results, matcherOut );
+			}
+		}
+	});
+}
+
+function matcherFromTokens( tokens ) {
+	var checkContext, matcher, j,
+		len = tokens.length,
+		leadingRelative = Expr.relative[ tokens[0].type ],
+		implicitRelative = leadingRelative || Expr.relative[" "],
+		i = leadingRelative ? 1 : 0,
+
+		// The foundational matcher ensures that elements are reachable from top-level context(s)
+		matchContext = addCombinator( function( elem ) {
+			return elem === checkContext;
+		}, implicitRelative, true ),
+		matchAnyContext = addCombinator( function( elem ) {
+			return indexOf.call( checkContext, elem ) > -1;
+		}, implicitRelative, true ),
+		matchers = [ function( elem, context, xml ) {
+			return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+				(checkContext = context).nodeType ?
+					matchContext( elem, context, xml ) :
+					matchAnyContext( elem, context, xml ) );
+		} ];
+
+	for ( ; i < len; i++ ) {
+		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+		} else {
+			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+			// Return special upon seeing a positional matcher
+			if ( matcher[ expando ] ) {
+				// Find the next relative operator (if any) for proper handling
+				j = ++i;
+				for ( ; j < len; j++ ) {
+					if ( Expr.relative[ tokens[j].type ] ) {
+						break;
+					}
+				}
+				return setMatcher(
+					i > 1 && elementMatcher( matchers ),
+					i > 1 && toSelector(
+						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
+						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+					).replace( rtrim, "$1" ),
+					matcher,
+					i < j && matcherFromTokens( tokens.slice( i, j ) ),
+					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+					j < len && toSelector( tokens )
+				);
+			}
+			matchers.push( matcher );
+		}
+	}
+
+	return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+	var bySet = setMatchers.length > 0,
+		byElement = elementMatchers.length > 0,
+		superMatcher = function( seed, context, xml, results, outermost ) {
+			var elem, j, matcher,
+				matchedCount = 0,
+				i = "0",
+				unmatched = seed && [],
+				setMatched = [],
+				contextBackup = outermostContext,
+				// We must always have either seed elements or outermost context
+				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+				// Use integer dirruns iff this is the outermost matcher
+				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+				len = elems.length;
+
+			if ( outermost ) {
+				outermostContext = context !== document && context;
+			}
+
+			// Add elements passing elementMatchers directly to results
+			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+			// Support: IE<9, Safari
+			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+				if ( byElement && elem ) {
+					j = 0;
+					while ( (matcher = elementMatchers[j++]) ) {
+						if ( matcher( elem, context, xml ) ) {
+							results.push( elem );
+							break;
+						}
+					}
+					if ( outermost ) {
+						dirruns = dirrunsUnique;
+					}
+				}
+
+				// Track unmatched elements for set filters
+				if ( bySet ) {
+					// They will have gone through all possible matchers
+					if ( (elem = !matcher && elem) ) {
+						matchedCount--;
+					}
+
+					// Lengthen the array for every element, matched or not
+					if ( seed ) {
+						unmatched.push( elem );
+					}
+				}
+			}
+
+			// Apply set filters to unmatched elements
+			matchedCount += i;
+			if ( bySet && i !== matchedCount ) {
+				j = 0;
+				while ( (matcher = setMatchers[j++]) ) {
+					matcher( unmatched, setMatched, context, xml );
+				}
+
+				if ( seed ) {
+					// Reintegrate element matches to eliminate the need for sorting
+					if ( matchedCount > 0 ) {
+						while ( i-- ) {
+							if ( !(unmatched[i] || setMatched[i]) ) {
+								setMatched[i] = pop.call( results );
+							}
+						}
+					}
+
+					// Discard index placeholder values to get only actual matches
+					setMatched = condense( setMatched );
+				}
+
+				// Add matches to results
+				push.apply( results, setMatched );
+
+				// Seedless set matches succeeding multiple successful matchers stipulate sorting
+				if ( outermost && !seed && setMatched.length > 0 &&
+					( matchedCount + setMatchers.length ) > 1 ) {
+
+					Sizzle.uniqueSort( results );
+				}
+			}
+
+			// Override manipulation of globals by nested matchers
+			if ( outermost ) {
+				dirruns = dirrunsUnique;
+				outermostContext = contextBackup;
+			}
+
+			return unmatched;
+		};
+
+	return bySet ?
+		markFunction( superMatcher ) :
+		superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+	var i,
+		setMatchers = [],
+		elementMatchers = [],
+		cached = compilerCache[ selector + " " ];
+
+	if ( !cached ) {
+		// Generate a function of recursive functions that can be used to check each element
+		if ( !match ) {
+			match = tokenize( selector );
+		}
+		i = match.length;
+		while ( i-- ) {
+			cached = matcherFromTokens( match[i] );
+			if ( cached[ expando ] ) {
+				setMatchers.push( cached );
+			} else {
+				elementMatchers.push( cached );
+			}
+		}
+
+		// Cache the compiled function
+		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+		// Save selector and tokenization
+		cached.selector = selector;
+	}
+	return cached;
+};
+
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ *  selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ *  selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+	var i, tokens, token, type, find,
+		compiled = typeof selector === "function" && selector,
+		match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+	results = results || [];
+
+	// Try to minimize operations if there is no seed and only one group
+	if ( match.length === 1 ) {
+
+		// Take a shortcut and set the context if the root selector is an ID
+		tokens = match[0] = match[0].slice( 0 );
+		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+				support.getById && context.nodeType === 9 && documentIsHTML &&
+				Expr.relative[ tokens[1].type ] ) {
+
+			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+			if ( !context ) {
+				return results;
+
+			// Precompiled matchers will still verify ancestry, so step up a level
+			} else if ( compiled ) {
+				context = context.parentNode;
+			}
+
+			selector = selector.slice( tokens.shift().value.length );
+		}
+
+		// Fetch a seed set for right-to-left matching
+		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+		while ( i-- ) {
+			token = tokens[i];
+
+			// Abort if we hit a combinator
+			if ( Expr.relative[ (type = token.type) ] ) {
+				break;
+			}
+			if ( (find = Expr.find[ type ]) ) {
+				// Search, expanding context for leading sibling combinators
+				if ( (seed = find(
+					token.matches[0].replace( runescape, funescape ),
+					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+				)) ) {
+
+					// If seed is empty or no tokens remain, we can return early
+					tokens.splice( i, 1 );
+					selector = seed.length && toSelector( tokens );
+					if ( !selector ) {
+						push.apply( results, seed );
+						return results;
+					}
+
+					break;
+				}
+			}
+		}
+	}
+
+	// Compile and execute a filtering function if one is not provided
+	// Provide `match` to avoid retokenization if we modified the selector above
+	( compiled || compile( selector, match ) )(
+		seed,
+		context,
+		!documentIsHTML,
+		results,
+		rsibling.test( selector ) && testContext( context.parentNode ) || context
+	);
+	return results;
+};
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome<14
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( div1 ) {
+	// Should return 1, but returns 4 (following)
+	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( div ) {
+	div.innerHTML = "<a href='#'></a>";
+	return div.firstChild.getAttribute("href") === "#" ;
+}) ) {
+	addHandle( "type|href|height|width", function( elem, name, isXML ) {
+		if ( !isXML ) {
+			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+		}
+	});
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( div ) {
+	div.innerHTML = "<input/>";
+	div.firstChild.setAttribute( "value", "" );
+	return div.firstChild.getAttribute( "value" ) === "";
+}) ) {
+	addHandle( "value", function( elem, name, isXML ) {
+		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+			return elem.defaultValue;
+		}
+	});
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( div ) {
+	return div.getAttribute("disabled") == null;
+}) ) {
+	addHandle( booleans, function( elem, name, isXML ) {
+		var val;
+		if ( !isXML ) {
+			return elem[ name ] === true ? name.toLowerCase() :
+					(val = elem.getAttributeNode( name )) && val.specified ?
+					val.value :
+				null;
+		}
+	});
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+	if ( jQuery.isFunction( qualifier ) ) {
+		return jQuery.grep( elements, function( elem, i ) {
+			/* jshint -W018 */
+			return !!qualifier.call( elem, i, elem ) !== not;
+		});
+
+	}
+
+	if ( qualifier.nodeType ) {
+		return jQuery.grep( elements, function( elem ) {
+			return ( elem === qualifier ) !== not;
+		});
+
+	}
+
+	if ( typeof qualifier === "string" ) {
+		if ( risSimple.test( qualifier ) ) {
+			return jQuery.filter( qualifier, elements, not );
+		}
+
+		qualifier = jQuery.filter( qualifier, elements );
+	}
+
+	return jQuery.grep( elements, function( elem ) {
+		return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
+	});
+}
+
+jQuery.filter = function( expr, elems, not ) {
+	var elem = elems[ 0 ];
+
+	if ( not ) {
+		expr = ":not(" + expr + ")";
+	}
+
+	return elems.length === 1 && elem.nodeType === 1 ?
+		jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+		jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+			return elem.nodeType === 1;
+		}));
+};
+
+jQuery.fn.extend({
+	find: function( selector ) {
+		var i,
+			ret = [],
+			self = this,
+			len = self.length;
+
+		if ( typeof selector !== "string" ) {
+			return this.pushStack( jQuery( selector ).filter(function() {
+				for ( i = 0; i < len; i++ ) {
+					if ( jQuery.contains( self[ i ], this ) ) {
+						return true;
+					}
+				}
+			}) );
+		}
+
+		for ( i = 0; i < len; i++ ) {
+			jQuery.find( selector, self[ i ], ret );
+		}
+
+		// Needed because $( selector, context ) becomes $( context ).find( selector )
+		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+		ret.selector = this.selector ? this.selector + " " + selector : selector;
+		return ret;
+	},
+	filter: function( selector ) {
+		return this.pushStack( winnow(this, selector || [], false) );
+	},
+	not: function( selector ) {
+		return this.pushStack( winnow(this, selector || [], true) );
+	},
+	is: function( selector ) {
+		return !!winnow(
+			this,
+
+			// If this is a positional/relative selector, check membership in the returned set
+			// so $("p:first").is("p:last") won't return true for a doc with two "p".
+			typeof selector === "string" && rneedsContext.test( selector ) ?
+				jQuery( selector ) :
+				selector || [],
+			false
+		).length;
+	}
+});
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+	// Use the correct document accordingly with window argument (sandbox)
+	document = window.document,
+
+	// A simple way to check for HTML strings
+	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+	// Strict HTML recognition (#11290: must start with <)
+	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+	init = jQuery.fn.init = function( selector, context ) {
+		var match, elem;
+
+		// HANDLE: $(""), $(null), $(undefined), $(false)
+		if ( !selector ) {
+			return this;
+		}
+
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+				// Assume that strings that start and end with <> are HTML and skip the regex check
+				match = [ null, selector, null ];
+
+			} else {
+				match = rquickExpr.exec( selector );
+			}
+
+			// Match html or make sure no context is specified for #id
+			if ( match && (match[1] || !context) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[1] ) {
+					context = context instanceof jQuery ? context[0] : context;
+
+					// scripts is true for back-compat
+					// Intentionally let the error be thrown if parseHTML is not present
+					jQuery.merge( this, jQuery.parseHTML(
+						match[1],
+						context && context.nodeType ? context.ownerDocument || context : document,
+						true
+					) );
+
+					// HANDLE: $(html, props)
+					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+						for ( match in context ) {
+							// Properties of context are called as methods if possible
+							if ( jQuery.isFunction( this[ match ] ) ) {
+								this[ match ]( context[ match ] );
+
+							// ...and otherwise set as attributes
+							} else {
+								this.attr( match, context[ match ] );
+							}
+						}
+					}
+
+					return this;
+
+				// HANDLE: $(#id)
+				} else {
+					elem = document.getElementById( match[2] );
+
+					// Check parentNode to catch when Blackberry 4.6 returns
+					// nodes that are no longer in the document #6963
+					if ( elem && elem.parentNode ) {
+						// Handle the case where IE and Opera return items
+						// by name instead of ID
+						if ( elem.id !== match[2] ) {
+							return rootjQuery.find( selector );
+						}
+
+						// Otherwise, we inject the element directly into the jQuery object
+						this.length = 1;
+						this[0] = elem;
+					}
+
+					this.context = document;
+					this.selector = selector;
+					return this;
+				}
+
+			// HANDLE: $(expr, $(...))
+			} else if ( !context || context.jquery ) {
+				return ( context || rootjQuery ).find( selector );
+
+			// HANDLE: $(expr, context)
+			// (which is just equivalent to: $(context).find(expr)
+			} else {
+				return this.constructor( context ).find( selector );
+			}
+
+		// HANDLE: $(DOMElement)
+		} else if ( selector.nodeType ) {
+			this.context = this[0] = selector;
+			this.length = 1;
+			return this;
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) ) {
+			return typeof rootjQuery.ready !== "undefined" ?
+				rootjQuery.ready( selector ) :
+				// Execute immediately if ready is not present
+				selector( jQuery );
+		}
+
+		if ( selector.selector !== undefined ) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return jQuery.makeArray( selector, this );
+	};
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+	// methods guaranteed to produce a unique set when starting from a unique set
+	guaranteedUnique = {
+		children: true,
+		contents: true,
+		next: true,
+		prev: true
+	};
+
+jQuery.extend({
+	dir: function( elem, dir, until ) {
+		var matched = [],
+			cur = elem[ dir ];
+
+		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+			if ( cur.nodeType === 1 ) {
+				matched.push( cur );
+			}
+			cur = cur[dir];
+		}
+		return matched;
+	},
+
+	sibling: function( n, elem ) {
+		var r = [];
+
+		for ( ; n; n = n.nextSibling ) {
+			if ( n.nodeType === 1 && n !== elem ) {
+				r.push( n );
+			}
+		}
+
+		return r;
+	}
+});
+
+jQuery.fn.extend({
+	has: function( target ) {
+		var i,
+			targets = jQuery( target, this ),
+			len = targets.length;
+
+		return this.filter(function() {
+			for ( i = 0; i < len; i++ ) {
+				if ( jQuery.contains( this, targets[i] ) ) {
+					return true;
+				}
+			}
+		});
+	},
+
+	closest: function( selectors, context ) {
+		var cur,
+			i = 0,
+			l = this.length,
+			matched = [],
+			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+				jQuery( selectors, context || this.context ) :
+				0;
+
+		for ( ; i < l; i++ ) {
+			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
+				// Always skip document fragments
+				if ( cur.nodeType < 11 && (pos ?
+					pos.index(cur) > -1 :
+
+					// Don't pass non-elements to Sizzle
+					cur.nodeType === 1 &&
+						jQuery.find.matchesSelector(cur, selectors)) ) {
+
+					matched.push( cur );
+					break;
+				}
+			}
+		}
+
+		return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
+	},
+
+	// Determine the position of an element within
+	// the matched set of elements
+	index: function( elem ) {
+
+		// No argument, return index in parent
+		if ( !elem ) {
+			return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
+		}
+
+		// index in selector
+		if ( typeof elem === "string" ) {
+			return jQuery.inArray( this[0], jQuery( elem ) );
+		}
+
+		// Locate the position of the desired element
+		return jQuery.inArray(
+			// If it receives a jQuery object, the first element is used
+			elem.jquery ? elem[0] : elem, this );
+	},
+
+	add: function( selector, context ) {
+		return this.pushStack(
+			jQuery.unique(
+				jQuery.merge( this.get(), jQuery( selector, context ) )
+			)
+		);
+	},
+
+	addBack: function( selector ) {
+		return this.add( selector == null ?
+			this.prevObject : this.prevObject.filter(selector)
+		);
+	}
+});
+
+function sibling( cur, dir ) {
+	do {
+		cur = cur[ dir ];
+	} while ( cur && cur.nodeType !== 1 );
+
+	return cur;
+}
+
+jQuery.each({
+	parent: function( elem ) {
+		var parent = elem.parentNode;
+		return parent && parent.nodeType !== 11 ? parent : null;
+	},
+	parents: function( elem ) {
+		return jQuery.dir( elem, "parentNode" );
+	},
+	parentsUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "parentNode", until );
+	},
+	next: function( elem ) {
+		return sibling( elem, "nextSibling" );
+	},
+	prev: function( elem ) {
+		return sibling( elem, "previousSibling" );
+	},
+	nextAll: function( elem ) {
+		return jQuery.dir( elem, "nextSibling" );
+	},
+	prevAll: function( elem ) {
+		return jQuery.dir( elem, "previousSibling" );
+	},
+	nextUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "nextSibling", until );
+	},
+	prevUntil: function( elem, i, until ) {
+		return jQuery.dir( elem, "previousSibling", until );
+	},
+	siblings: function( elem ) {
+		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+	},
+	children: function( elem ) {
+		return jQuery.sibling( elem.firstChild );
+	},
+	contents: function( elem ) {
+		return jQuery.nodeName( elem, "iframe" ) ?
+			elem.contentDocument || elem.contentWindow.document :
+			jQuery.merge( [], elem.childNodes );
+	}
+}, function( name, fn ) {
+	jQuery.fn[ name ] = function( until, selector ) {
+		var ret = jQuery.map( this, fn, until );
+
+		if ( name.slice( -5 ) !== "Until" ) {
+			selector = until;
+		}
+
+		if ( selector && typeof selector === "string" ) {
+			ret = jQuery.filter( selector, ret );
+		}
+
+		if ( this.length > 1 ) {
+			// Remove duplicates
+			if ( !guaranteedUnique[ name ] ) {
+				ret = jQuery.unique( ret );
+			}
+
+			// Reverse order for parents* and prev-derivatives
+			if ( rparentsprev.test( name ) ) {
+				ret = ret.reverse();
+			}
+		}
+
+		return this.pushStack( ret );
+	};
+});
+var rnotwhite = (/\S+/g);
+
+
+
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+	var object = optionsCache[ options ] = {};
+	jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+		object[ flag ] = true;
+	});
+	return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ *	options: an optional list of space-separated options that will change how
+ *			the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ *	once:			will ensure the callback list can only be fired once (like a Deferred)
+ *
+ *	memory:			will keep track of previous values and will call any callback added
+ *					after the list has been fired right away with the latest "memorized"
+ *					values (like a Deferred)
+ *
+ *	unique:			will ensure a callback can only be added once (no duplicate in the list)
+ *
+ *	stopOnFalse:	interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+	// Convert options from String-formatted to Object-formatted if needed
+	// (we check in cache first)
+	options = typeof options === "string" ?
+		( optionsCache[ options ] || createOptions( options ) ) :
+		jQuery.extend( {}, options );
+
+	var // Flag to know if list is currently firing
+		firing,
+		// Last fire value (for non-forgettable lists)
+		memory,
+		// Flag to know if list was already fired
+		fired,
+		// End of the loop when firing
+		firingLength,
+		// Index of currently firing callback (modified by remove if needed)
+		firingIndex,
+		// First callback to fire (used internally by add and fireWith)
+		firingStart,
+		// Actual callback list
+		list = [],
+		// Stack of fire calls for repeatable lists
+		stack = !options.once && [],
+		// Fire callbacks
+		fire = function( data ) {
+			memory = options.memory && data;
+			fired = true;
+			firingIndex = firingStart || 0;
+			firingStart = 0;
+			firingLength = list.length;
+			firing = true;
+			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+					memory = false; // To prevent further calls using add
+					break;
+				}
+			}
+			firing = false;
+			if ( list ) {
+				if ( stack ) {
+					if ( stack.length ) {
+						fire( stack.shift() );
+					}
+				} else if ( memory ) {
+					list = [];
+				} else {
+					self.disable();
+				}
+			}
+		},
+		// Actual Callbacks object
+		self = {
+			// Add a callback or a collection of callbacks to the list
+			add: function() {
+				if ( list ) {
+					// First, we save the current length
+					var start = list.length;
+					(function add( args ) {
+						jQuery.each( args, function( _, arg ) {
+							var type = jQuery.type( arg );
+							if ( type === "function" ) {
+								if ( !options.unique || !self.has( arg ) ) {
+									list.push( arg );
+								}
+							} else if ( arg && arg.length && type !== "string" ) {
+								// Inspect recursively
+								add( arg );
+							}
+						});
+					})( arguments );
+					// Do we need to add the callbacks to the
+					// current firing batch?
+					if ( firing ) {
+						firingLength = list.length;
+					// With memory, if we're not firing then
+					// we should call right away
+					} else if ( memory ) {
+						firingStart = start;
+						fire( memory );
+					}
+				}
+				return this;
+			},
+			// Remove a callback from the list
+			remove: function() {
+				if ( list ) {
+					jQuery.each( arguments, function( _, arg ) {
+						var index;
+						while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+							list.splice( index, 1 );
+							// Handle firing indexes
+							if ( firing ) {
+								if ( index <= firingLength ) {
+									firingLength--;
+								}
+								if ( index <= firingIndex ) {
+									firingIndex--;
+								}
+							}
+						}
+					});
+				}
+				return this;
+			},
+			// Check if a given callback is in the list.
+			// If no argument is given, return whether or not list has callbacks attached.
+			has: function( fn ) {
+				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+			},
+			// Remove all callbacks from the list
+			empty: function() {
+				list = [];
+				firingLength = 0;
+				return this;
+			},
+			// Have the list do nothing anymore
+			disable: function() {
+				list = stack = memory = undefined;
+				return this;
+			},
+			// Is it disabled?
+			disabled: function() {
+				return !list;
+			},
+			// Lock the list in its current state
+			lock: function() {
+				stack = undefined;
+				if ( !memory ) {
+					self.disable();
+				}
+				return this;
+			},
+			// Is it locked?
+			locked: function() {
+				return !stack;
+			},
+			// Call all callbacks with the given context and arguments
+			fireWith: function( context, args ) {
+				if ( list && ( !fired || stack ) ) {
+					args = args || [];
+					args = [ context, args.slice ? args.slice() : args ];
+					if ( firing ) {
+						stack.push( args );
+					} else {
+						fire( args );
+					}
+				}
+				return this;
+			},
+			// Call all the callbacks with the given arguments
+			fire: function() {
+				self.fireWith( this, arguments );
+				return this;
+			},
+			// To know if the callbacks have already been called at least once
+			fired: function() {
+				return !!fired;
+			}
+		};
+
+	return self;
+};
+
+
+jQuery.extend({
+
+	Deferred: function( func ) {
+		var tuples = [
+				// action, add listener, listener list, final state
+				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+				[ "notify", "progress", jQuery.Callbacks("memory") ]
+			],
+			state = "pending",
+			promise = {
+				state: function() {
+					return state;
+				},
+				always: function() {
+					deferred.done( arguments ).fail( arguments );
+					return this;
+				},
+				then: function( /* fnDone, fnFail, fnProgress */ ) {
+					var fns = arguments;
+					return jQuery.Deferred(function( newDefer ) {
+						jQuery.each( tuples, function( i, tuple ) {
+							var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+							// deferred[ done | fail | progress ] for forwarding actions to newDefer
+							deferred[ tuple[1] ](function() {
+								var returned = fn && fn.apply( this, arguments );
+								if ( returned && jQuery.isFunction( returned.promise ) ) {
+									returned.promise()
+										.done( newDefer.resolve )
+										.fail( newDefer.reject )
+										.progress( newDefer.notify );
+								} else {
+									newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+								}
+							});
+						});
+						fns = null;
+					}).promise();
+				},
+				// Get a promise for this deferred
+				// If obj is provided, the promise aspect is added to the object
+				promise: function( obj ) {
+					return obj != null ? jQuery.extend( obj, promise ) : promise;
+				}
+			},
+			deferred = {};
+
+		// Keep pipe for back-compat
+		promise.pipe = promise.then;
+
+		// Add list-specific methods
+		jQuery.each( tuples, function( i, tuple ) {
+			var list = tuple[ 2 ],
+				stateString = tuple[ 3 ];
+
+			// promise[ done | fail | progress ] = list.add
+			promise[ tuple[1] ] = list.add;
+
+			// Handle state
+			if ( stateString ) {
+				list.add(function() {
+					// state = [ resolved | rejected ]
+					state = stateString;
+
+				// [ reject_list | resolve_list ].disable; progress_list.lock
+				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+			}
+
+			// deferred[ resolve | reject | notify ]
+			deferred[ tuple[0] ] = function() {
+				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+				return this;
+			};
+			deferred[ tuple[0] + "With" ] = list.fireWith;
+		});
+
+		// Make the deferred a promise
+		promise.promise( deferred );
+
+		// Call given func if any
+		if ( func ) {
+			func.call( deferred, deferred );
+		}
+
+		// All done!
+		return deferred;
+	},
+
+	// Deferred helper
+	when: function( subordinate /* , ..., subordinateN */ ) {
+		var i = 0,
+			resolveValues = slice.call( arguments ),
+			length = resolveValues.length,
+
+			// the count of uncompleted subordinates
+			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+			// Update function for both resolve and progress values
+			updateFunc = function( i, contexts, values ) {
+				return function( value ) {
+					contexts[ i ] = this;
+					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+					if ( values === progressValues ) {
+						deferred.notifyWith( contexts, values );
+
+					} else if ( !(--remaining) ) {
+						deferred.resolveWith( contexts, values );
+					}
+				};
+			},
+
+			progressValues, progressContexts, resolveContexts;
+
+		// add listeners to Deferred subordinates; treat others as resolved
+		if ( length > 1 ) {
+			progressValues = new Array( length );
+			progressContexts = new Array( length );
+			resolveContexts = new Array( length );
+			for ( ; i < length; i++ ) {
+				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+					resolveValues[ i ].promise()
+						.done( updateFunc( i, resolveContexts, resolveValues ) )
+						.fail( deferred.reject )
+						.progress( updateFunc( i, progressContexts, progressValues ) );
+				} else {
+					--remaining;
+				}
+			}
+		}
+
+		// if we're not waiting on anything, resolve the master
+		if ( !remaining ) {
+			deferred.resolveWith( resolveContexts, resolveValues );
+		}
+
+		return deferred.promise();
+	}
+});
+
+
+// The deferred used on DOM ready
+var readyList;
+
+jQuery.fn.ready = function( fn ) {
+	// Add the callback
+	jQuery.ready.promise().done( fn );
+
+	return this;
+};
+
+jQuery.extend({
+	// Is the DOM ready to be used? Set to true once it occurs.
+	isReady: false,
+
+	// A counter to track how many items to wait for before
+	// the ready event fires. See #6781
+	readyWait: 1,
+
+	// Hold (or release) the ready event
+	holdReady: function( hold ) {
+		if ( hold ) {
+			jQuery.readyWait++;
+		} else {
+			jQuery.ready( true );
+		}
+	},
+
+	// Handle when the DOM is ready
+	ready: function( wait ) {
+
+		// Abort if there are pending holds or we're already ready
+		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+			return;
+		}
+
+		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+		if ( !document.body ) {
+			return setTimeout( jQuery.ready );
+		}
+
+		// Remember that the DOM is ready
+		jQuery.isReady = true;
+
+		// If a normal DOM Ready event fired, decrement, and wait if need be
+		if ( wait !== true && --jQuery.readyWait > 0 ) {
+			return;
+		}
+
+		// If there are functions bound, to execute
+		readyList.resolveWith( document, [ jQuery ] );
+
+		// Trigger any bound ready events
+		if ( jQuery.fn.triggerHandler ) {
+			jQuery( document ).triggerHandler( "ready" );
+			jQuery( document ).off( "ready" );
+		}
+	}
+});
+
+/**
+ * Clean-up method for dom ready events
+ */
+function detach() {
+	if ( document.addEventListener ) {
+		document.removeEventListener( "DOMContentLoaded", completed, false );
+		window.removeEventListener( "load", completed, false );
+
+	} else {
+		document.detachEvent( "onreadystatechange", completed );
+		window.detachEvent( "onload", completed );
+	}
+}
+
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+	// readyState === "complete" is good enough for us to call the dom ready in oldIE
+	if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
+		detach();
+		jQuery.ready();
+	}
+}
+
+jQuery.ready.promise = function( obj ) {
+	if ( !readyList ) {
+
+		readyList = jQuery.Deferred();
+
+		// Catch cases where $(document).ready() is called after the browser event has already occurred.
+		// we once tried to use readyState "interactive" here, but it caused issues like the one
+		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+		if ( document.readyState === "complete" ) {
+			// Handle it asynchronously to allow scripts the opportunity to delay ready
+			setTimeout( jQuery.ready );
+
+		// Standards-based browsers support DOMContentLoaded
+		} else if ( document.addEventListener ) {
+			// Use the handy event callback
+			document.addEventListener( "DOMContentLoaded", completed, false );
+
+			// A fallback to window.onload, that will always work
+			window.addEventListener( "load", completed, false );
+
+		// If IE event model is used
+		} else {
+			// Ensure firing before onload, maybe late but safe also for iframes
+			document.attachEvent( "onreadystatechange", completed );
+
+			// A fallback to window.onload, that will always work
+			window.attachEvent( "onload", completed );
+
+			// If IE and not a frame
+			// continually check to see if the document is ready
+			var top = false;
+
+			try {
+				top = window.frameElement == null && document.documentElement;
+			} catch(e) {}
+
+			if ( top && top.doScroll ) {
+				(function doScrollCheck() {
+					if ( !jQuery.isReady ) {
+
+						try {
+							// Use the trick by Diego Perini
+							// http://javascript.nwbox.com/IEContentLoaded/
+							top.doScroll("left");
+						} catch(e) {
+							return setTimeout( doScrollCheck, 50 );
+						}
+
+						// detach all dom ready events
+						detach();
+
+						// and execute any waiting functions
+						jQuery.ready();
+					}
+				})();
+			}
+		}
+	}
+	return readyList.promise( obj );
+};
+
+
+var strundefined = typeof undefined;
+
+
+
+// Support: IE<9
+// Iteration over object's inherited properties before its own
+var i;
+for ( i in jQuery( support ) ) {
+	break;
+}
+support.ownLast = i !== "0";
+
+// Note: most support tests are defined in their respective modules.
+// false until the test is run
+support.inlineBlockNeedsLayout = false;
+
+// Execute ASAP in case we need to set body.style.zoom
+jQuery(function() {
+	// Minified: var a,b,c,d
+	var val, div, body, container;
+
+	body = document.getElementsByTagName( "body" )[ 0 ];
+	if ( !body || !body.style ) {
+		// Return for frameset docs that don't have a body
+		return;
+	}
+
+	// Setup
+	div = document.createElement( "div" );
+	container = document.createElement( "div" );
+	container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+	body.appendChild( container ).appendChild( div );
+
+	if ( typeof div.style.zoom !== strundefined ) {
+		// Support: IE<8
+		// Check if natively block-level elements act like inline-block
+		// elements when setting their display to 'inline' and giving
+		// them layout
+		div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
+
+		support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
+		if ( val ) {
+			// Prevent IE 6 from affecting layout for positioned elements #11048
+			// Prevent IE from shrinking the body in IE 7 mode #12869
+			// Support: IE<8
+			body.style.zoom = 1;
+		}
+	}
+
+	body.removeChild( container );
+});
+
+
+
+
+(function() {
+	var div = document.createElement( "div" );
+
+	// Execute the test only if not already executed in another module.
+	if (support.deleteExpando == null) {
+		// Support: IE<9
+		support.deleteExpando = true;
+		try {
+			delete div.test;
+		} catch( e ) {
+			support.deleteExpando = false;
+		}
+	}
+
+	// Null elements to avoid leaks in IE.
+	div = null;
+})();
+
+
+/**
+ * Determines whether an object can have data
+ */
+jQuery.acceptData = function( elem ) {
+	var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
+		nodeType = +elem.nodeType || 1;
+
+	// Do not set data on non-element DOM nodes because it will not be cleared (#8335).
+	return nodeType !== 1 && nodeType !== 9 ?
+		false :
+
+		// Nodes accept data unless otherwise specified; rejection can be conditional
+		!noData || noData !== true && elem.getAttribute("classid") === noData;
+};
+
+
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+	rmultiDash = /([A-Z])/g;
+
+function dataAttr( elem, key, data ) {
+	// If nothing was found internally, try to fetch any
+	// data from the HTML5 data-* attribute
+	if ( data === undefined && elem.nodeType === 1 ) {
+
+		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+		data = elem.getAttribute( name );
+
+		if ( typeof data === "string" ) {
+			try {
+				data = data === "true" ? true :
+					data === "false" ? false :
+					data === "null" ? null :
+					// Only convert to a number if it doesn't change the string
+					+data + "" === data ? +data :
+					rbrace.test( data ) ? jQuery.parseJSON( data ) :
+					data;
+			} catch( e ) {}
+
+			// Make sure we set the data so it isn't changed later
+			jQuery.data( elem, key, data );
+
+		} else {
+			data = undefined;
+		}
+	}
+
+	return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+	var name;
+	for ( name in obj ) {
+
+		// if the public data object is empty, the private is still empty
+		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+			continue;
+		}
+		if ( name !== "toJSON" ) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
+	if ( !jQuery.acceptData( elem ) ) {
+		return;
+	}
+
+	var ret, thisCache,
+		internalKey = jQuery.expando,
+
+		// We have to handle DOM nodes and JS objects differently because IE6-7
+		// can't GC object references properly across the DOM-JS boundary
+		isNode = elem.nodeType,
+
+		// Only DOM nodes need the global jQuery cache; JS object data is
+		// attached directly to the object so GC can occur automatically
+		cache = isNode ? jQuery.cache : elem,
+
+		// Only defining an ID for JS objects if its cache already exists allows
+		// the code to shortcut on the same path as a DOM node with no cache
+		id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+	// Avoid doing any more work than we need to when trying to get data on an
+	// object that has no data at all
+	if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
+		return;
+	}
+
+	if ( !id ) {
+		// Only DOM nodes need a new unique ID for each element since their data
+		// ends up in the global cache
+		if ( isNode ) {
+			id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
+		} else {
+			id = internalKey;
+		}
+	}
+
+	if ( !cache[ id ] ) {
+		// Avoid exposing jQuery metadata on plain JS objects when the object
+		// is serialized using JSON.stringify
+		cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
+	}
+
+	// An object can be passed to jQuery.data instead of a key/value pair; this gets
+	// shallow copied over onto the existing cache
+	if ( typeof name === "object" || typeof name === "function" ) {
+		if ( pvt ) {
+			cache[ id ] = jQuery.extend( cache[ id ], name );
+		} else {
+			cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+		}
+	}
+
+	thisCache = cache[ id ];
+
+	// jQuery data() is stored in a separate object inside the object's internal data
+	// cache in order to avoid key collisions between internal data and user-defined
+	// data.
+	if ( !pvt ) {
+		if ( !thisCache.data ) {
+			thisCache.data = {};
+		}
+
+		thisCache = thisCache.data;
+	}
+
+	if ( data !== undefined ) {
+		thisCache[ jQuery.camelCase( name ) ] = data;
+	}
+
+	// Check for both converted-to-camel and non-converted data property names
+	// If a data property was specified
+	if ( typeof name === "string" ) {
+
+		// First Try to find as-is property data
+		ret = thisCache[ name ];
+
+		// Test for null|undefined property data
+		if ( ret == null ) {
+
+			// Try to find the camelCased property
+			ret = thisCache[ jQuery.camelCase( name ) ];
+		}
+	} else {
+		ret = thisCache;
+	}
+
+	return ret;
+}
+
+function internalRemoveData( elem, name, pvt ) {
+	if ( !jQuery.acceptData( elem ) ) {
+		return;
+	}
+
+	var thisCache, i,
+		isNode = elem.nodeType,
+
+		// See jQuery.data for more information
+		cache = isNode ? jQuery.cache : elem,
+		id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+	// If there is already no cache entry for this object, there is no
+	// purpose in continuing
+	if ( !cache[ id ] ) {
+		return;
+	}
+
+	if ( name ) {
+
+		thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+		if ( thisCache ) {
+
+			// Support array or space separated string names for data keys
+			if ( !jQuery.isArray( name ) ) {
+
+				// try the string as a key before any manipulation
+				if ( name in thisCache ) {
+					name = [ name ];
+				} else {
+
+					// split the camel cased version by spaces unless a key with the spaces exists
+					name = jQuery.camelCase( name );
+					if ( name in thisCache ) {
+						name = [ name ];
+					} else {
+						name = name.split(" ");
+					}
+				}
+			} else {
+				// If "name" is an array of keys...
+				// When data is initially created, via ("key", "val") signature,
+				// keys will be converted to camelCase.
+				// Since there is no way to tell _how_ a key was added, remove
+				// both plain key and camelCase key. #12786
+				// This will only penalize the array argument path.
+				name = name.concat( jQuery.map( name, jQuery.camelCase ) );
+			}
+
+			i = name.length;
+			while ( i-- ) {
+				delete thisCache[ name[i] ];
+			}
+
+			// If there is no data left in the cache, we want to continue
+			// and let the cache object itself get destroyed
+			if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
+				return;
+			}
+		}
+	}
+
+	// See jQuery.data for more information
+	if ( !pvt ) {
+		delete cache[ id ].data;
+
+		// Don't destroy the parent cache unless the internal data object
+		// had been the only thing left in it
+		if ( !isEmptyDataObject( cache[ id ] ) ) {
+			return;
+		}
+	}
+
+	// Destroy the cache
+	if ( isNode ) {
+		jQuery.cleanData( [ elem ], true );
+
+	// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+	/* jshint eqeqeq: false */
+	} else if ( support.deleteExpando || cache != cache.window ) {
+		/* jshint eqeqeq: true */
+		delete cache[ id ];
+
+	// When all else fails, null
+	} else {
+		cache[ id ] = null;
+	}
+}
+
+jQuery.extend({
+	cache: {},
+
+	// The following elements (space-suffixed to avoid Object.prototype collisions)
+	// throw uncatchable exceptions if you attempt to set expando properties
+	noData: {
+		"applet ": true,
+		"embed ": true,
+		// ...but Flash objects (which have this classid) *can* handle expandos
+		"object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
+	},
+
+	hasData: function( elem ) {
+		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+		return !!elem && !isEmptyDataObject( elem );
+	},
+
+	data: function( elem, name, data ) {
+		return internalData( elem, name, data );
+	},
+
+	removeData: function( elem, name ) {
+		return internalRemoveData( elem, name );
+	},
+
+	// For internal use only.
+	_data: function( elem, name, data ) {
+		return internalData( elem, name, data, true );
+	},
+
+	_removeData: function( elem, name ) {
+		return internalRemoveData( elem, name, true );
+	}
+});
+
+jQuery.fn.extend({
+	data: function( key, value ) {
+		var i, name, data,
+			elem = this[0],
+			attrs = elem && elem.attributes;
+
+		// Special expections of .data basically thwart jQuery.access,
+		// so implement the relevant behavior ourselves
+
+		// Gets all values
+		if ( key === undefined ) {
+			if ( this.length ) {
+				data = jQuery.data( elem );
+
+				if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+					i = attrs.length;
+					while ( i-- ) {
+
+						// Support: IE11+
+						// The attrs elements can be null (#14894)
+						if ( attrs[ i ] ) {
+							name = attrs[ i ].name;
+							if ( name.indexOf( "data-" ) === 0 ) {
+								name = jQuery.camelCase( name.slice(5) );
+								dataAttr( elem, name, data[ name ] );
+							}
+						}
+					}
+					jQuery._data( elem, "parsedAttrs", true );
+				}
+			}
+
+			return data;
+		}
+
+		// Sets multiple values
+		if ( typeof key === "object" ) {
+			return this.each(function() {
+				jQuery.data( this, key );
+			});
+		}
+
+		return arguments.length > 1 ?
+
+			// Sets one value
+			this.each(function() {
+				jQuery.data( this, key, value );
+			}) :
+
+			// Gets one value
+			// Try to fetch any internally stored data first
+			elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
+	},
+
+	removeData: function( key ) {
+		return this.each(function() {
+			jQuery.removeData( this, key );
+		});
+	}
+});
+
+
+jQuery.extend({
+	queue: function( elem, type, data ) {
+		var queue;
+
+		if ( elem ) {
+			type = ( type || "fx" ) + "queue";
+			queue = jQuery._data( elem, type );
+
+			// Speed up dequeue by getting out quickly if this is just a lookup
+			if ( data ) {
+				if ( !queue || jQuery.isArray(data) ) {
+					queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+				} else {
+					queue.push( data );
+				}
+			}
+			return queue || [];
+		}
+	},
+
+	dequeue: function( elem, type ) {
+		type = type || "fx";
+
+		var queue = jQuery.queue( elem, type ),
+			startLength = queue.length,
+			fn = queue.shift(),
+			hooks = jQuery._queueHooks( elem, type ),
+			next = function() {
+				jQuery.dequeue( elem, type );
+			};
+
+		// If the fx queue is dequeued, always remove the progress sentinel
+		if ( fn === "inprogress" ) {
+			fn = queue.shift();
+			startLength--;
+		}
+
+		if ( fn ) {
+
+			// Add a progress sentinel to prevent the fx queue from being
+			// automatically dequeued
+			if ( type === "fx" ) {
+				queue.unshift( "inprogress" );
+			}
+
+			// clear up the last queue stop function
+			delete hooks.stop;
+			fn.call( elem, next, hooks );
+		}
+
+		if ( !startLength && hooks ) {
+			hooks.empty.fire();
+		}
+	},
+
+	// not intended for public consumption - generates a queueHooks object, or returns the current one
+	_queueHooks: function( elem, type ) {
+		var key = type + "queueHooks";
+		return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+			empty: jQuery.Callbacks("once memory").add(function() {
+				jQuery._removeData( elem, type + "queue" );
+				jQuery._removeData( elem, key );
+			})
+		});
+	}
+});
+
+jQuery.fn.extend({
+	queue: function( type, data ) {
+		var setter = 2;
+
+		if ( typeof type !== "string" ) {
+			data = type;
+			type = "fx";
+			setter--;
+		}
+
+		if ( arguments.length < setter ) {
+			return jQuery.queue( this[0], type );
+		}
+
+		return data === undefined ?
+			this :
+			this.each(function() {
+				var queue = jQuery.queue( this, type, data );
+
+				// ensure a hooks for this queue
+				jQuery._queueHooks( this, type );
+
+				if ( type === "fx" && queue[0] !== "inprogress" ) {
+					jQuery.dequeue( this, type );
+				}
+			});
+	},
+	dequeue: function( type ) {
+		return this.each(function() {
+			jQuery.dequeue( this, type );
+		});
+	},
+	clearQueue: function( type ) {
+		return this.queue( type || "fx", [] );
+	},
+	// Get a promise resolved when queues of a certain type
+	// are emptied (fx is the type by default)
+	promise: function( type, obj ) {
+		var tmp,
+			count = 1,
+			defer = jQuery.Deferred(),
+			elements = this,
+			i = this.length,
+			resolve = function() {
+				if ( !( --count ) ) {
+					defer.resolveWith( elements, [ elements ] );
+				}
+			};
+
+		if ( typeof type !== "string" ) {
+			obj = type;
+			type = undefined;
+		}
+		type = type || "fx";
+
+		while ( i-- ) {
+			tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+			if ( tmp && tmp.empty ) {
+				count++;
+				tmp.empty.add( resolve );
+			}
+		}
+		resolve();
+		return defer.promise( obj );
+	}
+});
+var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
+
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+var isHidden = function( elem, el ) {
+		// isHidden might be called from jQuery#filter function;
+		// in that case, element will be second argument
+		elem = el || elem;
+		return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+	};
+
+
+
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+	var i = 0,
+		length = elems.length,
+		bulk = key == null;
+
+	// Sets many values
+	if ( jQuery.type( key ) === "object" ) {
+		chainable = true;
+		for ( i in key ) {
+			jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+		}
+
+	// Sets one value
+	} else if ( value !== undefined ) {
+		chainable = true;
+
+		if ( !jQuery.isFunction( value ) ) {
+			raw = true;
+		}
+
+		if ( bulk ) {
+			// Bulk operations run against the entire set
+			if ( raw ) {
+				fn.call( elems, value );
+				fn = null;
+
+			// ...except when executing function values
+			} else {
+				bulk = fn;
+				fn = function( elem, key, value ) {
+					return bulk.call( jQuery( elem ), value );
+				};
+			}
+		}
+
+		if ( fn ) {
+			for ( ; i < length; i++ ) {
+				fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+			}
+		}
+	}
+
+	return chainable ?
+		elems :
+
+		// Gets
+		bulk ?
+			fn.call( elems ) :
+			length ? fn( elems[0], key ) : emptyGet;
+};
+var rcheckableType = (/^(?:checkbox|radio)$/i);
+
+
+
+(function() {
+	// Minified: var a,b,c
+	var input = document.createElement( "input" ),
+		div = document.createElement( "div" ),
+		fragment = document.createDocumentFragment();
+
+	// Setup
+	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+
+	// IE strips leading whitespace when .innerHTML is used
+	support.leadingWhitespace = div.firstChild.nodeType === 3;
+
+	// Make sure that tbody elements aren't automatically inserted
+	// IE will insert them into empty tables
+	support.tbody = !div.getElementsByTagName( "tbody" ).length;
+
+	// Make sure that link elements get serialized correctly by innerHTML
+	// This requires a wrapper element in IE
+	support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
+
+	// Makes sure cloning an html5 element does not cause problems
+	// Where outerHTML is undefined, this still works
+	support.html5Clone =
+		document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
+
+	// Check if a disconnected checkbox will retain its checked
+	// value of true after appended to the DOM (IE6/7)
+	input.type = "checkbox";
+	input.checked = true;
+	fragment.appendChild( input );
+	support.appendChecked = input.checked;
+
+	// Make sure textarea (and checkbox) defaultValue is properly cloned
+	// Support: IE6-IE11+
+	div.innerHTML = "<textarea>x</textarea>";
+	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+
+	// #11217 - WebKit loses check when the name is after the checked attribute
+	fragment.appendChild( div );
+	div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
+
+	// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
+	// old WebKit doesn't clone checked state correctly in fragments
+	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+	// Support: IE<9
+	// Opera does not clone events (and typeof div.attachEvent === undefined).
+	// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
+	support.noCloneEvent = true;
+	if ( div.attachEvent ) {
+		div.attachEvent( "onclick", function() {
+			support.noCloneEvent = false;
+		});
+
+		div.cloneNode( true ).click();
+	}
+
+	// Execute the test only if not already executed in another module.
+	if (support.deleteExpando == null) {
+		// Support: IE<9
+		support.deleteExpando = true;
+		try {
+			delete div.test;
+		} catch( e ) {
+			support.deleteExpando = false;
+		}
+	}
+})();
+
+
+(function() {
+	var i, eventName,
+		div = document.createElement( "div" );
+
+	// Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
+	for ( i in { submit: true, change: true, focusin: true }) {
+		eventName = "on" + i;
+
+		if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
+			// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
+			div.setAttribute( eventName, "t" );
+			support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
+		}
+	}
+
+	// Null elements to avoid leaks in IE.
+	div = null;
+})();
+
+
+var rformElems = /^(?:input|select|textarea)$/i,
+	rkeyEvent = /^key/,
+	rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
+	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+
+function returnTrue() {
+	return true;
+}
+
+function returnFalse() {
+	return false;
+}
+
+function safeActiveElement() {
+	try {
+		return document.activeElement;
+	} catch ( err ) { }
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+	global: {},
+
+	add: function( elem, types, handler, data, selector ) {
+		var tmp, events, t, handleObjIn,
+			special, eventHandle, handleObj,
+			handlers, type, namespaces, origType,
+			elemData = jQuery._data( elem );
+
+		// Don't attach events to noData or text/comment nodes (but allow plain objects)
+		if ( !elemData ) {
+			return;
+		}
+
+		// Caller can pass in an object of custom data in lieu of the handler
+		if ( handler.handler ) {
+			handleObjIn = handler;
+			handler = handleObjIn.handler;
+			selector = handleObjIn.selector;
+		}
+
+		// Make sure that the handler has a unique ID, used to find/remove it later
+		if ( !handler.guid ) {
+			handler.guid = jQuery.guid++;
+		}
+
+		// Init the element's event structure and main handler, if this is the first
+		if ( !(events = elemData.events) ) {
+			events = elemData.events = {};
+		}
+		if ( !(eventHandle = elemData.handle) ) {
+			eventHandle = elemData.handle = function( e ) {
+				// Discard the second event of a jQuery.event.trigger() and
+				// when an event is called after a page has unloaded
+				return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
+					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+					undefined;
+			};
+			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+			eventHandle.elem = elem;
+		}
+
+		// Handle multiple events separated by a space
+		types = ( types || "" ).match( rnotwhite ) || [ "" ];
+		t = types.length;
+		while ( t-- ) {
+			tmp = rtypenamespace.exec( types[t] ) || [];
+			type = origType = tmp[1];
+			namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+			// There *must* be a type, no attaching namespace-only handlers
+			if ( !type ) {
+				continue;
+			}
+
+			// If event changes its type, use the special event handlers for the changed type
+			special = jQuery.event.special[ type ] || {};
+
+			// If selector defined, determine special event api type, otherwise given type
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+
+			// Update special based on newly reset type
+			special = jQuery.event.special[ type ] || {};
+
+			// handleObj is passed to all event handlers
+			handleObj = jQuery.extend({
+				type: type,
+				origType: origType,
+				data: data,
+				handler: handler,
+				guid: handler.guid,
+				selector: selector,
+				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+				namespace: namespaces.join(".")
+			}, handleObjIn );
+
+			// Init the event handler queue if we're the first
+			if ( !(handlers = events[ type ]) ) {
+				handlers = events[ type ] = [];
+				handlers.delegateCount = 0;
+
+				// Only use addEventListener/attachEvent if the special events handler returns false
+				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+					// Bind the global event handler to the element
+					if ( elem.addEventListener ) {
+						elem.addEventListener( type, eventHandle, false );
+
+					} else if ( elem.attachEvent ) {
+						elem.attachEvent( "on" + type, eventHandle );
+					}
+				}
+			}
+
+			if ( special.add ) {
+				special.add.call( elem, handleObj );
+
+				if ( !handleObj.handler.guid ) {
+					handleObj.handler.guid = handler.guid;
+				}
+			}
+
+			// Add to the element's handler list, delegates in front
+			if ( selector ) {
+				handlers.splice( handlers.delegateCount++, 0, handleObj );
+			} else {
+				handlers.push( handleObj );
+			}
+
+			// Keep track of which events have ever been used, for event optimization
+			jQuery.event.global[ type ] = true;
+		}
+
+		// Nullify elem to prevent memory leaks in IE
+		elem = null;
+	},
+
+	// Detach an event or set of events from an element
+	remove: function( elem, types, handler, selector, mappedTypes ) {
+		var j, handleObj, tmp,
+			origCount, t, events,
+			special, handlers, type,
+			namespaces, origType,
+			elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+		if ( !elemData || !(events = elemData.events) ) {
+			return;
+		}
+
+		// Once for each type.namespace in types; type may be omitted
+		types = ( types || "" ).match( rnotwhite ) || [ "" ];
+		t = types.length;
+		while ( t-- ) {
+			tmp = rtypenamespace.exec( types[t] ) || [];
+			type = origType = tmp[1];
+			namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+			// Unbind all events (on this namespace, if provided) for the element
+			if ( !type ) {
+				for ( type in events ) {
+					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+				}
+				continue;
+			}
+
+			special = jQuery.event.special[ type ] || {};
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+			handlers = events[ type ] || [];
+			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+			// Remove matching events
+			origCount = j = handlers.length;
+			while ( j-- ) {
+				handleObj = handlers[ j ];
+
+				if ( ( mappedTypes || origType === handleObj.origType ) &&
+					( !handler || handler.guid === handleObj.guid ) &&
+					( !tmp || tmp.test( handleObj.namespace ) ) &&
+					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+					handlers.splice( j, 1 );
+
+					if ( handleObj.selector ) {
+						handlers.delegateCount--;
+					}
+					if ( special.remove ) {
+						special.remove.call( elem, handleObj );
+					}
+				}
+			}
+
+			// Remove generic event handler if we removed something and no more handlers exist
+			// (avoids potential for endless recursion during removal of special event handlers)
+			if ( origCount && !handlers.length ) {
+				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+					jQuery.removeEvent( elem, type, elemData.handle );
+				}
+
+				delete events[ type ];
+			}
+		}
+
+		// Remove the expando if it's no longer used
+		if ( jQuery.isEmptyObject( events ) ) {
+			delete elemData.handle;
+
+			// removeData also checks for emptiness and clears the expando if empty
+			// so use it instead of delete
+			jQuery._removeData( elem, "events" );
+		}
+	},
+
+	trigger: function( event, data, elem, onlyHandlers ) {
+		var handle, ontype, cur,
+			bubbleType, special, tmp, i,
+			eventPath = [ elem || document ],
+			type = hasOwn.call( event, "type" ) ? event.type : event,
+			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
+
+		cur = tmp = elem = elem || document;
+
+		// Don't do events on text and comment nodes
+		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return;
+		}
+
+		// focus/blur morphs to focusin/out; ensure we're not firing them right now
+		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+			return;
+		}
+
+		if ( type.indexOf(".") >= 0 ) {
+			// Namespaced trigger; create a regexp to match event type in handle()
+			namespaces = type.split(".");
+			type = namespaces.shift();
+			namespaces.sort();
+		}
+		ontype = type.indexOf(":") < 0 && "on" + type;
+
+		// Caller can pass in a jQuery.Event object, Object, or just an event type string
+		event = event[ jQuery.expando ] ?
+			event :
+			new jQuery.Event( type, typeof event === "object" && event );
+
+		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+		event.isTrigger = onlyHandlers ? 2 : 3;
+		event.namespace = namespaces.join(".");
+		event.namespace_re = event.namespace ?
+			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+			null;
+
+		// Clean up the event in case it is being reused
+		event.result = undefined;
+		if ( !event.target ) {
+			event.target = elem;
+		}
+
+		// Clone any incoming data and prepend the event, creating the handler arg list
+		data = data == null ?
+			[ event ] :
+			jQuery.makeArray( data, [ event ] );
+
+		// Allow special events to draw outside the lines
+		special = jQuery.event.special[ type ] || {};
+		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+			return;
+		}
+
+		// Determine event propagation path in advance, per W3C events spec (#9951)
+		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+			bubbleType = special.delegateType || type;
+			if ( !rfocusMorph.test( bubbleType + type ) ) {
+				cur = cur.parentNode;
+			}
+			for ( ; cur; cur = cur.parentNode ) {
+				eventPath.push( cur );
+				tmp = cur;
+			}
+
+			// Only add window if we got to document (e.g., not plain obj or detached DOM)
+			if ( tmp === (elem.ownerDocument || document) ) {
+				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+			}
+		}
+
+		// Fire handlers on the event path
+		i = 0;
+		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
+
+			event.type = i > 1 ?
+				bubbleType :
+				special.bindType || type;
+
+			// jQuery handler
+			handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+			if ( handle ) {
+				handle.apply( cur, data );
+			}
+
+			// Native handler
+			handle = ontype && cur[ ontype ];
+			if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
+				event.result = handle.apply( cur, data );
+				if ( event.result === false ) {
+					event.preventDefault();
+				}
+			}
+		}
+		event.type = type;
+
+		// If nobody prevented the default action, do it now
+		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+			if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
+				jQuery.acceptData( elem ) ) {
+
+				// Call a native DOM method on the target with the same name name as the event.
+				// Can't use an .isFunction() check here because IE6/7 fails that test.
+				// Don't do default actions on window, that's where global variables be (#6170)
+				if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
+
+					// Don't re-trigger an onFOO event when we call its FOO() method
+					tmp = elem[ ontype ];
+
+					if ( tmp ) {
+						elem[ ontype ] = null;
+					}
+
+					// Prevent re-triggering of the same event, since we already bubbled it above
+					jQuery.event.triggered = type;
+					try {
+						elem[ type ]();
+					} catch ( e ) {
+						// IE<9 dies on focus/blur to hidden element (#1486,#12518)
+						// only reproducible on winXP IE8 native, not IE9 in IE8 mode
+					}
+					jQuery.event.triggered = undefined;
+
+					if ( tmp ) {
+						elem[ ontype ] = tmp;
+					}
+				}
+			}
+		}
+
+		return event.result;
+	},
+
+	dispatch: function( event ) {
+
+		// Make a writable jQuery.Event from the native event object
+		event = jQuery.event.fix( event );
+
+		var i, ret, handleObj, matched, j,
+			handlerQueue = [],
+			args = slice.call( arguments ),
+			handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
+			special = jQuery.event.special[ event.type ] || {};
+
+		// Use the fix-ed jQuery.Event rather than the (read-only) native event
+		args[0] = event;
+		event.delegateTarget = this;
+
+		// Call the preDispatch hook for the mapped type, and let it bail if desired
+		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+			return;
+		}
+
+		// Determine handlers
+		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+		// Run delegates first; they may want to stop propagation beneath us
+		i = 0;
+		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+			event.currentTarget = matched.elem;
+
+			j = 0;
+			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+
+				// Triggered event must either 1) have no namespace, or
+				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+
+					event.handleObj = handleObj;
+					event.data = handleObj.data;
+
+					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+							.apply( matched.elem, args );
+
+					if ( ret !== undefined ) {
+						if ( (event.result = ret) === false ) {
+							event.preventDefault();
+							event.stopPropagation();
+						}
+					}
+				}
+			}
+		}
+
+		// Call the postDispatch hook for the mapped type
+		if ( special.postDispatch ) {
+			special.postDispatch.call( this, event );
+		}
+
+		return event.result;
+	},
+
+	handlers: function( event, handlers ) {
+		var sel, handleObj, matches, i,
+			handlerQueue = [],
+			delegateCount = handlers.delegateCount,
+			cur = event.target;
+
+		// Find delegate handlers
+		// Black-hole SVG <use> instance trees (#13180)
+		// Avoid non-left-click bubbling in Firefox (#3861)
+		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
+
+			/* jshint eqeqeq: false */
+			for ( ; cur != this; cur = cur.parentNode || this ) {
+				/* jshint eqeqeq: true */
+
+				// Don't check non-elements (#13208)
+				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+				if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
+					matches = [];
+					for ( i = 0; i < delegateCount; i++ ) {
+						handleObj = handlers[ i ];
+
+						// Don't conflict with Object.prototype properties (#13203)
+						sel = handleObj.selector + " ";
+
+						if ( matches[ sel ] === undefined ) {
+							matches[ sel ] = handleObj.needsContext ?
+								jQuery( sel, this ).index( cur ) >= 0 :
+								jQuery.find( sel, this, null, [ cur ] ).length;
+						}
+						if ( matches[ sel ] ) {
+							matches.push( handleObj );
+						}
+					}
+					if ( matches.length ) {
+						handlerQueue.push({ elem: cur, handlers: matches });
+					}
+				}
+			}
+		}
+
+		// Add the remaining (directly-bound) handlers
+		if ( delegateCount < handlers.length ) {
+			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+		}
+
+		return handlerQueue;
+	},
+
+	fix: function( event ) {
+		if ( event[ jQuery.expando ] ) {
+			return event;
+		}
+
+		// Create a writable copy of the event object and normalize some properties
+		var i, prop, copy,
+			type = event.type,
+			originalEvent = event,
+			fixHook = this.fixHooks[ type ];
+
+		if ( !fixHook ) {
+			this.fixHooks[ type ] = fixHook =
+				rmouseEvent.test( type ) ? this.mouseHooks :
+				rkeyEvent.test( type ) ? this.keyHooks :
+				{};
+		}
+		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+		event = new jQuery.Event( originalEvent );
+
+		i = copy.length;
+		while ( i-- ) {
+			prop = copy[ i ];
+			event[ prop ] = originalEvent[ prop ];
+		}
+
+		// Support: IE<9
+		// Fix target property (#1925)
+		if ( !event.target ) {
+			event.target = originalEvent.srcElement || document;
+		}
+
+		// Support: Chrome 23+, Safari?
+		// Target should not be a text node (#504, #13143)
+		if ( event.target.nodeType === 3 ) {
+			event.target = event.target.parentNode;
+		}
+
+		// Support: IE<9
+		// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
+		event.metaKey = !!event.metaKey;
+
+		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+	},
+
+	// Includes some event props shared by KeyEvent and MouseEvent
+	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+	fixHooks: {},
+
+	keyHooks: {
+		props: "char charCode key keyCode".split(" "),
+		filter: function( event, original ) {
+
+			// Add which for key events
+			if ( event.which == null ) {
+				event.which = original.charCode != null ? original.charCode : original.keyCode;
+			}
+
+			return event;
+		}
+	},
+
+	mouseHooks: {
+		props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+		filter: function( event, original ) {
+			var body, eventDoc, doc,
+				button = original.button,
+				fromElement = original.fromElement;
+
+			// Calculate pageX/Y if missing and clientX/Y available
+			if ( event.pageX == null && original.clientX != null ) {
+				eventDoc = event.target.ownerDocument || document;
+				doc = eventDoc.documentElement;
+				body = eventDoc.body;
+
+				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
+			}
+
+			// Add relatedTarget, if necessary
+			if ( !event.relatedTarget && fromElement ) {
+				event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+			}
+
+			// Add which for click: 1 === left; 2 === middle; 3 === right
+			// Note: button is not normalized, so don't use it
+			if ( !event.which && button !== undefined ) {
+				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+			}
+
+			return event;
+		}
+	},
+
+	special: {
+		load: {
+			// Prevent triggered image.load events from bubbling to window.load
+			noBubble: true
+		},
+		focus: {
+			// Fire native event if possible so blur/focus sequence is correct
+			trigger: function() {
+				if ( this !== safeActiveElement() && this.focus ) {
+					try {
+						this.focus();
+						return false;
+					} catch ( e ) {
+						// Support: IE<9
+						// If we error on focus to hidden element (#1486, #12518),
+						// let .trigger() run the handlers
+					}
+				}
+			},
+			delegateType: "focusin"
+		},
+		blur: {
+			trigger: function() {
+				if ( this === safeActiveElement() && this.blur ) {
+					this.blur();
+					return false;
+				}
+			},
+			delegateType: "focusout"
+		},
+		click: {
+			// For checkbox, fire native event so checked state will be right
+			trigger: function() {
+				if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
+					this.click();
+					return false;
+				}
+			},
+
+			// For cross-browser consistency, don't fire native .click() on links
+			_default: function( event ) {
+				return jQuery.nodeName( event.target, "a" );
+			}
+		},
+
+		beforeunload: {
+			postDispatch: function( event ) {
+
+				// Support: Firefox 20+
+				// Firefox doesn't alert if the returnValue field is not set.
+				if ( event.result !== undefined && event.originalEvent ) {
+					event.originalEvent.returnValue = event.result;
+				}
+			}
+		}
+	},
+
+	simulate: function( type, elem, event, bubble ) {
+		// Piggyback on a donor event to simulate a different one.
+		// Fake originalEvent to avoid donor's stopPropagation, but if the
+		// simulated event prevents default then we do the same on the donor.
+		var e = jQuery.extend(
+			new jQuery.Event(),
+			event,
+			{
+				type: type,
+				isSimulated: true,
+				originalEvent: {}
+			}
+		);
+		if ( bubble ) {
+			jQuery.event.trigger( e, null, elem );
+		} else {
+			jQuery.event.dispatch.call( elem, e );
+		}
+		if ( e.isDefaultPrevented() ) {
+			event.preventDefault();
+		}
+	}
+};
+
+jQuery.removeEvent = document.removeEventListener ?
+	function( elem, type, handle ) {
+		if ( elem.removeEventListener ) {
+			elem.removeEventListener( type, handle, false );
+		}
+	} :
+	function( elem, type, handle ) {
+		var name = "on" + type;
+
+		if ( elem.detachEvent ) {
+
+			// #8545, #7054, preventing memory leaks for custom events in IE6-8
+			// detachEvent needed property on element, by name of that event, to properly expose it to GC
+			if ( typeof elem[ name ] === strundefined ) {
+				elem[ name ] = null;
+			}
+
+			elem.detachEvent( name, handle );
+		}
+	};
+
+jQuery.Event = function( src, props ) {
+	// Allow instantiation without the 'new' keyword
+	if ( !(this instanceof jQuery.Event) ) {
+		return new jQuery.Event( src, props );
+	}
+
+	// Event object
+	if ( src && src.type ) {
+		this.originalEvent = src;
+		this.type = src.type;
+
+		// Events bubbling up the document may have been marked as prevented
+		// by a handler lower down the tree; reflect the correct value.
+		this.isDefaultPrevented = src.defaultPrevented ||
+				src.defaultPrevented === undefined &&
+				// Support: IE < 9, Android < 4.0
+				src.returnValue === false ?
+			returnTrue :
+			returnFalse;
+
+	// Event type
+	} else {
+		this.type = src;
+	}
+
+	// Put explicitly provided properties onto the event object
+	if ( props ) {
+		jQuery.extend( this, props );
+	}
+
+	// Create a timestamp if incoming event doesn't have one
+	this.timeStamp = src && src.timeStamp || jQuery.now();
+
+	// Mark it as fixed
+	this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+	isDefaultPrevented: returnFalse,
+	isPropagationStopped: returnFalse,
+	isImmediatePropagationStopped: returnFalse,
+
+	preventDefault: function() {
+		var e = this.originalEvent;
+
+		this.isDefaultPrevented = returnTrue;
+		if ( !e ) {
+			return;
+		}
+
+		// If preventDefault exists, run it on the original event
+		if ( e.preventDefault ) {
+			e.preventDefault();
+
+		// Support: IE
+		// Otherwise set the returnValue property of the original event to false
+		} else {
+			e.returnValue = false;
+		}
+	},
+	stopPropagation: function() {
+		var e = this.originalEvent;
+
+		this.isPropagationStopped = returnTrue;
+		if ( !e ) {
+			return;
+		}
+		// If stopPropagation exists, run it on the original event
+		if ( e.stopPropagation ) {
+			e.stopPropagation();
+		}
+
+		// Support: IE
+		// Set the cancelBubble property of the original event to true
+		e.cancelBubble = true;
+	},
+	stopImmediatePropagation: function() {
+		var e = this.originalEvent;
+
+		this.isImmediatePropagationStopped = returnTrue;
+
+		if ( e && e.stopImmediatePropagation ) {
+			e.stopImmediatePropagation();
+		}
+
+		this.stopPropagation();
+	}
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+	mouseenter: "mouseover",
+	mouseleave: "mouseout",
+	pointerenter: "pointerover",
+	pointerleave: "pointerout"
+}, function( orig, fix ) {
+	jQuery.event.special[ orig ] = {
+		delegateType: fix,
+		bindType: fix,
+
+		handle: function( event ) {
+			var ret,
+				target = this,
+				related = event.relatedTarget,
+				handleObj = event.handleObj;
+
+			// For mousenter/leave call the handler if related is outside the target.
+			// NB: No relatedTarget if the mouse left/entered the browser window
+			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+				event.type = handleObj.origType;
+				ret = handleObj.handler.apply( this, arguments );
+				event.type = fix;
+			}
+			return ret;
+		}
+	};
+});
+
+// IE submit delegation
+if ( !support.submitBubbles ) {
+
+	jQuery.event.special.submit = {
+		setup: function() {
+			// Only need this for delegated form submit events
+			if ( jQuery.nodeName( this, "form" ) ) {
+				return false;
+			}
+
+			// Lazy-add a submit handler when a descendant form may potentially be submitted
+			jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+				// Node name check avoids a VML-related crash in IE (#9807)
+				var elem = e.target,
+					form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+				if ( form && !jQuery._data( form, "submitBubbles" ) ) {
+					jQuery.event.add( form, "submit._submit", function( event ) {
+						event._submit_bubble = true;
+					});
+					jQuery._data( form, "submitBubbles", true );
+				}
+			});
+			// return undefined since we don't need an event listener
+		},
+
+		postDispatch: function( event ) {
+			// If form was submitted by the user, bubble the event up the tree
+			if ( event._submit_bubble ) {
+				delete event._submit_bubble;
+				if ( this.parentNode && !event.isTrigger ) {
+					jQuery.event.simulate( "submit", this.parentNode, event, true );
+				}
+			}
+		},
+
+		teardown: function() {
+			// Only need this for delegated form submit events
+			if ( jQuery.nodeName( this, "form" ) ) {
+				return false;
+			}
+
+			// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+			jQuery.event.remove( this, "._submit" );
+		}
+	};
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !support.changeBubbles ) {
+
+	jQuery.event.special.change = {
+
+		setup: function() {
+
+			if ( rformElems.test( this.nodeName ) ) {
+				// IE doesn't fire change on a check/radio until blur; trigger it on click
+				// after a propertychange. Eat the blur-change in special.change.handle.
+				// This still fires onchange a second time for check/radio after blur.
+				if ( this.type === "checkbox" || this.type === "radio" ) {
+					jQuery.event.add( this, "propertychange._change", function( event ) {
+						if ( event.originalEvent.propertyName === "checked" ) {
+							this._just_changed = true;
+						}
+					});
+					jQuery.event.add( this, "click._change", function( event ) {
+						if ( this._just_changed && !event.isTrigger ) {
+							this._just_changed = false;
+						}
+						// Allow triggered, simulated change events (#11500)
+						jQuery.event.simulate( "change", this, event, true );
+					});
+				}
+				return false;
+			}
+			// Delegated event; lazy-add a change handler on descendant inputs
+			jQuery.event.add( this, "beforeactivate._change", function( e ) {
+				var elem = e.target;
+
+				if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
+					jQuery.event.add( elem, "change._change", function( event ) {
+						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+							jQuery.event.simulate( "change", this.parentNode, event, true );
+						}
+					});
+					jQuery._data( elem, "changeBubbles", true );
+				}
+			});
+		},
+
+		handle: function( event ) {
+			var elem = event.target;
+
+			// Swallow native change events from checkbox/radio, we already triggered them above
+			if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+				return event.handleObj.handler.apply( this, arguments );
+			}
+		},
+
+		teardown: function() {
+			jQuery.event.remove( this, "._change" );
+
+			return !rformElems.test( this.nodeName );
+		}
+	};
+}
+
+// Create "bubbling" focus and blur events
+if ( !support.focusinBubbles ) {
+	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+		// Attach a single capturing handler on the document while someone wants focusin/focusout
+		var handler = function( event ) {
+				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+			};
+
+		jQuery.event.special[ fix ] = {
+			setup: function() {
+				var doc = this.ownerDocument || this,
+					attaches = jQuery._data( doc, fix );
+
+				if ( !attaches ) {
+					doc.addEventListener( orig, handler, true );
+				}
+				jQuery._data( doc, fix, ( attaches || 0 ) + 1 );
+			},
+			teardown: function() {
+				var doc = this.ownerDocument || this,
+					attaches = jQuery._data( doc, fix ) - 1;
+
+				if ( !attaches ) {
+					doc.removeEventListener( orig, handler, true );
+					jQuery._removeData( doc, fix );
+				} else {
+					jQuery._data( doc, fix, attaches );
+				}
+			}
+		};
+	});
+}
+
+jQuery.fn.extend({
+
+	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+		var type, origFn;
+
+		// Types can be a map of types/handlers
+		if ( typeof types === "object" ) {
+			// ( types-Object, selector, data )
+			if ( typeof selector !== "string" ) {
+				// ( types-Object, data )
+				data = data || selector;
+				selector = undefined;
+			}
+			for ( type in types ) {
+				this.on( type, selector, data, types[ type ], one );
+			}
+			return this;
+		}
+
+		if ( data == null && fn == null ) {
+			// ( types, fn )
+			fn = selector;
+			data = selector = undefined;
+		} else if ( fn == null ) {
+			if ( typeof selector === "string" ) {
+				// ( types, selector, fn )
+				fn = data;
+				data = undefined;
+			} else {
+				// ( types, data, fn )
+				fn = data;
+				data = selector;
+				selector = undefined;
+			}
+		}
+		if ( fn === false ) {
+			fn = returnFalse;
+		} else if ( !fn ) {
+			return this;
+		}
+
+		if ( one === 1 ) {
+			origFn = fn;
+			fn = function( event ) {
+				// Can use an empty set, since event contains the info
+				jQuery().off( event );
+				return origFn.apply( this, arguments );
+			};
+			// Use same guid so caller can remove using origFn
+			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+		}
+		return this.each( function() {
+			jQuery.event.add( this, types, fn, data, selector );
+		});
+	},
+	one: function( types, selector, data, fn ) {
+		return this.on( types, selector, data, fn, 1 );
+	},
+	off: function( types, selector, fn ) {
+		var handleObj, type;
+		if ( types && types.preventDefault && types.handleObj ) {
+			// ( event )  dispatched jQuery.Event
+			handleObj = types.handleObj;
+			jQuery( types.delegateTarget ).off(
+				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+				handleObj.selector,
+				handleObj.handler
+			);
+			return this;
+		}
+		if ( typeof types === "object" ) {
+			// ( types-object [, selector] )
+			for ( type in types ) {
+				this.off( type, selector, types[ type ] );
+			}
+			return this;
+		}
+		if ( selector === false || typeof selector === "function" ) {
+			// ( types [, fn] )
+			fn = selector;
+			selector = undefined;
+		}
+		if ( fn === false ) {
+			fn = returnFalse;
+		}
+		return this.each(function() {
+			jQuery.event.remove( this, types, fn, selector );
+		});
+	},
+
+	trigger: function( type, data ) {
+		return this.each(function() {
+			jQuery.event.trigger( type, data, this );
+		});
+	},
+	triggerHandler: function( type, data ) {
+		var elem = this[0];
+		if ( elem ) {
+			return jQuery.event.trigger( type, data, elem, true );
+		}
+	}
+});
+
+
+function createSafeFragment( document ) {
+	var list = nodeNames.split( "|" ),
+		safeFrag = document.createDocumentFragment();
+
+	if ( safeFrag.createElement ) {
+		while ( list.length ) {
+			safeFrag.createElement(
+				list.pop()
+			);
+		}
+	}
+	return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+	rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
+	rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+	rleadingWhitespace = /^\s+/,
+	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+	rtagName = /<([\w:]+)/,
+	rtbody = /<tbody/i,
+	rhtml = /<|&#?\w+;/,
+	rnoInnerhtml = /<(?:script|style|link)/i,
+	// checked="checked" or checked
+	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+	rscriptType = /^$|\/(?:java|ecma)script/i,
+	rscriptTypeMasked = /^true\/(.*)/,
+	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
+
+	// We have to close these tags to support XHTML (#13200)
+	wrapMap = {
+		option: [ 1, "<select multiple='multiple'>", "</select>" ],
+		legend: [ 1, "<fieldset>", "</fieldset>" ],
+		area: [ 1, "<map>", "</map>" ],
+		param: [ 1, "<object>", "</object>" ],
+		thead: [ 1, "<table>", "</table>" ],
+		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+		// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
+		// unless wrapped in a div with non-breaking characters in front of it.
+		_default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>"  ]
+	},
+	safeFragment = createSafeFragment( document ),
+	fragmentDiv = safeFragment.appendChild( document.createElement("div") );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+function getAll( context, tag ) {
+	var elems, elem,
+		i = 0,
+		found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
+			typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
+			undefined;
+
+	if ( !found ) {
+		for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
+			if ( !tag || jQuery.nodeName( elem, tag ) ) {
+				found.push( elem );
+			} else {
+				jQuery.merge( found, getAll( elem, tag ) );
+			}
+		}
+	}
+
+	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+		jQuery.merge( [ context ], found ) :
+		found;
+}
+
+// Used in buildFragment, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+	if ( rcheckableType.test( elem.type ) ) {
+		elem.defaultChecked = elem.checked;
+	}
+}
+
+// Support: IE<8
+// Manipulating tables requires a tbody
+function manipulationTarget( elem, content ) {
+	return jQuery.nodeName( elem, "table" ) &&
+		jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
+
+		elem.getElementsByTagName("tbody")[0] ||
+			elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
+		elem;
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+	elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
+	return elem;
+}
+function restoreScript( elem ) {
+	var match = rscriptTypeMasked.exec( elem.type );
+	if ( match ) {
+		elem.type = match[1];
+	} else {
+		elem.removeAttribute("type");
+	}
+	return elem;
+}
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+	var elem,
+		i = 0;
+	for ( ; (elem = elems[i]) != null; i++ ) {
+		jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
+	}
+}
+
+function cloneCopyEvent( src, dest ) {
+
+	if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+		return;
+	}
+
+	var type, i, l,
+		oldData = jQuery._data( src ),
+		curData = jQuery._data( dest, oldData ),
+		events = oldData.events;
+
+	if ( events ) {
+		delete curData.handle;
+		curData.events = {};
+
+		for ( type in events ) {
+			for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+				jQuery.event.add( dest, type, events[ type ][ i ] );
+			}
+		}
+	}
+
+	// make the cloned public data object a copy from the original
+	if ( curData.data ) {
+		curData.data = jQuery.extend( {}, curData.data );
+	}
+}
+
+function fixCloneNodeIssues( src, dest ) {
+	var nodeName, e, data;
+
+	// We do not need to do anything for non-Elements
+	if ( dest.nodeType !== 1 ) {
+		return;
+	}
+
+	nodeName = dest.nodeName.toLowerCase();
+
+	// IE6-8 copies events bound via attachEvent when using cloneNode.
+	if ( !support.noCloneEvent && dest[ jQuery.expando ] ) {
+		data = jQuery._data( dest );
+
+		for ( e in data.events ) {
+			jQuery.removeEvent( dest, e, data.handle );
+		}
+
+		// Event data gets referenced instead of copied if the expando gets copied too
+		dest.removeAttribute( jQuery.expando );
+	}
+
+	// IE blanks contents when cloning scripts, and tries to evaluate newly-set text
+	if ( nodeName === "script" && dest.text !== src.text ) {
+		disableScript( dest ).text = src.text;
+		restoreScript( dest );
+
+	// IE6-10 improperly clones children of object elements using classid.
+	// IE10 throws NoModificationAllowedError if parent is null, #12132.
+	} else if ( nodeName === "object" ) {
+		if ( dest.parentNode ) {
+			dest.outerHTML = src.outerHTML;
+		}
+
+		// This path appears unavoidable for IE9. When cloning an object
+		// element in IE9, the outerHTML strategy above is not sufficient.
+		// If the src has innerHTML and the destination does not,
+		// copy the src.innerHTML into the dest.innerHTML. #10324
+		if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
+			dest.innerHTML = src.innerHTML;
+		}
+
+	} else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+		// IE6-8 fails to persist the checked state of a cloned checkbox
+		// or radio button. Worse, IE6-7 fail to give the cloned element
+		// a checked appearance if the defaultChecked value isn't also set
+
+		dest.defaultChecked = dest.checked = src.checked;
+
+		// IE6-7 get confused and end up setting the value of a cloned
+		// checkbox/radio button to an empty string instead of "on"
+		if ( dest.value !== src.value ) {
+			dest.value = src.value;
+		}
+
+	// IE6-8 fails to return the selected option to the default selected
+	// state when cloning options
+	} else if ( nodeName === "option" ) {
+		dest.defaultSelected = dest.selected = src.defaultSelected;
+
+	// IE6-8 fails to set the defaultValue to the correct value when
+	// cloning other types of input fields
+	} else if ( nodeName === "input" || nodeName === "textarea" ) {
+		dest.defaultValue = src.defaultValue;
+	}
+}
+
+jQuery.extend({
+	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+		var destElements, node, clone, i, srcElements,
+			inPage = jQuery.contains( elem.ownerDocument, elem );
+
+		if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
+			clone = elem.cloneNode( true );
+
+		// IE<=8 does not properly clone detached, unknown element nodes
+		} else {
+			fragmentDiv.innerHTML = elem.outerHTML;
+			fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+		}
+
+		if ( (!support.noCloneEvent || !support.noCloneChecked) &&
+				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+
+			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+			destElements = getAll( clone );
+			srcElements = getAll( elem );
+
+			// Fix all IE cloning issues
+			for ( i = 0; (node = srcElements[i]) != null; ++i ) {
+				// Ensure that the destination node is not null; Fixes #9587
+				if ( destElements[i] ) {
+					fixCloneNodeIssues( node, destElements[i] );
+				}
+			}
+		}
+
+		// Copy the events from the original to the clone
+		if ( dataAndEvents ) {
+			if ( deepDataAndEvents ) {
+				srcElements = srcElements || getAll( elem );
+				destElements = destElements || getAll( clone );
+
+				for ( i = 0; (node = srcElements[i]) != null; i++ ) {
+					cloneCopyEvent( node, destElements[i] );
+				}
+			} else {
+				cloneCopyEvent( elem, clone );
+			}
+		}
+
+		// Preserve script evaluation history
+		destElements = getAll( clone, "script" );
+		if ( destElements.length > 0 ) {
+			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+		}
+
+		destElements = srcElements = node = null;
+
+		// Return the cloned set
+		return clone;
+	},
+
+	buildFragment: function( elems, context, scripts, selection ) {
+		var j, elem, contains,
+			tmp, tag, tbody, wrap,
+			l = elems.length,
+
+			// Ensure a safe fragment
+			safe = createSafeFragment( context ),
+
+			nodes = [],
+			i = 0;
+
+		for ( ; i < l; i++ ) {
+			elem = elems[ i ];
+
+			if ( elem || elem === 0 ) {
+
+				// Add nodes directly
+				if ( jQuery.type( elem ) === "object" ) {
+					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+				// Convert non-html into a text node
+				} else if ( !rhtml.test( elem ) ) {
+					nodes.push( context.createTextNode( elem ) );
+
+				// Convert html into DOM nodes
+				} else {
+					tmp = tmp || safe.appendChild( context.createElement("div") );
+
+					// Deserialize a standard representation
+					tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
+					wrap = wrapMap[ tag ] || wrapMap._default;
+
+					tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
+
+					// Descend through wrappers to the right content
+					j = wrap[0];
+					while ( j-- ) {
+						tmp = tmp.lastChild;
+					}
+
+					// Manually add leading whitespace removed by IE
+					if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+						nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
+					}
+
+					// Remove IE's autoinserted <tbody> from table fragments
+					if ( !support.tbody ) {
+
+						// String was a <table>, *may* have spurious <tbody>
+						elem = tag === "table" && !rtbody.test( elem ) ?
+							tmp.firstChild :
+
+							// String was a bare <thead> or <tfoot>
+							wrap[1] === "<table>" && !rtbody.test( elem ) ?
+								tmp :
+								0;
+
+						j = elem && elem.childNodes.length;
+						while ( j-- ) {
+							if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
+								elem.removeChild( tbody );
+							}
+						}
+					}
+
+					jQuery.merge( nodes, tmp.childNodes );
+
+					// Fix #12392 for WebKit and IE > 9
+					tmp.textContent = "";
+
+					// Fix #12392 for oldIE
+					while ( tmp.firstChild ) {
+						tmp.removeChild( tmp.firstChild );
+					}
+
+					// Remember the top-level container for proper cleanup
+					tmp = safe.lastChild;
+				}
+			}
+		}
+
+		// Fix #11356: Clear elements from fragment
+		if ( tmp ) {
+			safe.removeChild( tmp );
+		}
+
+		// Reset defaultChecked for any radios and checkboxes
+		// about to be appended to the DOM in IE 6/7 (#8060)
+		if ( !support.appendChecked ) {
+			jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
+		}
+
+		i = 0;
+		while ( (elem = nodes[ i++ ]) ) {
+
+			// #4087 - If origin and destination elements are the same, and this is
+			// that element, do not do anything
+			if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
+				continue;
+			}
+
+			contains = jQuery.contains( elem.ownerDocument, elem );
+
+			// Append to fragment
+			tmp = getAll( safe.appendChild( elem ), "script" );
+
+			// Preserve script evaluation history
+			if ( contains ) {
+				setGlobalEval( tmp );
+			}
+
+			// Capture executables
+			if ( scripts ) {
+				j = 0;
+				while ( (elem = tmp[ j++ ]) ) {
+					if ( rscriptType.test( elem.type || "" ) ) {
+						scripts.push( elem );
+					}
+				}
+			}
+		}
+
+		tmp = null;
+
+		return safe;
+	},
+
+	cleanData: function( elems, /* internal */ acceptData ) {
+		var elem, type, id, data,
+			i = 0,
+			internalKey = jQuery.expando,
+			cache = jQuery.cache,
+			deleteExpando = support.deleteExpando,
+			special = jQuery.event.special;
+
+		for ( ; (elem = elems[i]) != null; i++ ) {
+			if ( acceptData || jQuery.acceptData( elem ) ) {
+
+				id = elem[ internalKey ];
+				data = id && cache[ id ];
+
+				if ( data ) {
+					if ( data.events ) {
+						for ( type in data.events ) {
+							if ( special[ type ] ) {
+								jQuery.event.remove( elem, type );
+
+							// This is a shortcut to avoid jQuery.event.remove's overhead
+							} else {
+								jQuery.removeEvent( elem, type, data.handle );
+							}
+						}
+					}
+
+					// Remove cache only if it was not already removed by jQuery.event.remove
+					if ( cache[ id ] ) {
+
+						delete cache[ id ];
+
+						// IE does not allow us to delete expando properties from nodes,
+						// nor does it have a removeAttribute function on Document nodes;
+						// we must handle all of these cases
+						if ( deleteExpando ) {
+							delete elem[ internalKey ];
+
+						} else if ( typeof elem.removeAttribute !== strundefined ) {
+							elem.removeAttribute( internalKey );
+
+						} else {
+							elem[ internalKey ] = null;
+						}
+
+						deletedIds.push( id );
+					}
+				}
+			}
+		}
+	}
+});
+
+jQuery.fn.extend({
+	text: function( value ) {
+		return access( this, function( value ) {
+			return value === undefined ?
+				jQuery.text( this ) :
+				this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+		}, null, value, arguments.length );
+	},
+
+	append: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+				var target = manipulationTarget( this, elem );
+				target.appendChild( elem );
+			}
+		});
+	},
+
+	prepend: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+				var target = manipulationTarget( this, elem );
+				target.insertBefore( elem, target.firstChild );
+			}
+		});
+	},
+
+	before: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.parentNode ) {
+				this.parentNode.insertBefore( elem, this );
+			}
+		});
+	},
+
+	after: function() {
+		return this.domManip( arguments, function( elem ) {
+			if ( this.parentNode ) {
+				this.parentNode.insertBefore( elem, this.nextSibling );
+			}
+		});
+	},
+
+	remove: function( selector, keepData /* Internal Use Only */ ) {
+		var elem,
+			elems = selector ? jQuery.filter( selector, this ) : this,
+			i = 0;
+
+		for ( ; (elem = elems[i]) != null; i++ ) {
+
+			if ( !keepData && elem.nodeType === 1 ) {
+				jQuery.cleanData( getAll( elem ) );
+			}
+
+			if ( elem.parentNode ) {
+				if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
+					setGlobalEval( getAll( elem, "script" ) );
+				}
+				elem.parentNode.removeChild( elem );
+			}
+		}
+
+		return this;
+	},
+
+	empty: function() {
+		var elem,
+			i = 0;
+
+		for ( ; (elem = this[i]) != null; i++ ) {
+			// Remove element nodes and prevent memory leaks
+			if ( elem.nodeType === 1 ) {
+				jQuery.cleanData( getAll( elem, false ) );
+			}
+
+			// Remove any remaining nodes
+			while ( elem.firstChild ) {
+				elem.removeChild( elem.firstChild );
+			}
+
+			// If this is a select, ensure that it displays empty (#12336)
+			// Support: IE<9
+			if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
+				elem.options.length = 0;
+			}
+		}
+
+		return this;
+	},
+
+	clone: function( dataAndEvents, deepDataAndEvents ) {
+		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+		return this.map(function() {
+			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+		});
+	},
+
+	html: function( value ) {
+		return access( this, function( value ) {
+			var elem = this[ 0 ] || {},
+				i = 0,
+				l = this.length;
+
+			if ( value === undefined ) {
+				return elem.nodeType === 1 ?
+					elem.innerHTML.replace( rinlinejQuery, "" ) :
+					undefined;
+			}
+
+			// See if we can take a shortcut and just use innerHTML
+			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+				( support.htmlSerialize || !rnoshimcache.test( value )  ) &&
+				( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+				!wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
+
+				value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+				try {
+					for (; i < l; i++ ) {
+						// Remove element nodes and prevent memory leaks
+						elem = this[i] || {};
+						if ( elem.nodeType === 1 ) {
+							jQuery.cleanData( getAll( elem, false ) );
+							elem.innerHTML = value;
+						}
+					}
+
+					elem = 0;
+
+				// If using innerHTML throws an exception, use the fallback method
+				} catch(e) {}
+			}
+
+			if ( elem ) {
+				this.empty().append( value );
+			}
+		}, null, value, arguments.length );
+	},
+
+	replaceWith: function() {
+		var arg = arguments[ 0 ];
+
+		// Make the changes, replacing each context element with the new content
+		this.domManip( arguments, function( elem ) {
+			arg = this.parentNode;
+
+			jQuery.cleanData( getAll( this ) );
+
+			if ( arg ) {
+				arg.replaceChild( elem, this );
+			}
+		});
+
+		// Force removal if there was no new content (e.g., from empty arguments)
+		return arg && (arg.length || arg.nodeType) ? this : this.remove();
+	},
+
+	detach: function( selector ) {
+		return this.remove( selector, true );
+	},
+
+	domManip: function( args, callback ) {
+
+		// Flatten any nested arrays
+		args = concat.apply( [], args );
+
+		var first, node, hasScripts,
+			scripts, doc, fragment,
+			i = 0,
+			l = this.length,
+			set = this,
+			iNoClone = l - 1,
+			value = args[0],
+			isFunction = jQuery.isFunction( value );
+
+		// We can't cloneNode fragments that contain checked, in WebKit
+		if ( isFunction ||
+				( l > 1 && typeof value === "string" &&
+					!support.checkClone && rchecked.test( value ) ) ) {
+			return this.each(function( index ) {
+				var self = set.eq( index );
+				if ( isFunction ) {
+					args[0] = value.call( this, index, self.html() );
+				}
+				self.domManip( args, callback );
+			});
+		}
+
+		if ( l ) {
+			fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
+			first = fragment.firstChild;
+
+			if ( fragment.childNodes.length === 1 ) {
+				fragment = first;
+			}
+
+			if ( first ) {
+				scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+				hasScripts = scripts.length;
+
+				// Use the original fragment for the last item instead of the first because it can end up
+				// being emptied incorrectly in certain situations (#8070).
+				for ( ; i < l; i++ ) {
+					node = fragment;
+
+					if ( i !== iNoClone ) {
+						node = jQuery.clone( node, true, true );
+
+						// Keep references to cloned scripts for later restoration
+						if ( hasScripts ) {
+							jQuery.merge( scripts, getAll( node, "script" ) );
+						}
+					}
+
+					callback.call( this[i], node, i );
+				}
+
+				if ( hasScripts ) {
+					doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+					// Reenable scripts
+					jQuery.map( scripts, restoreScript );
+
+					// Evaluate executable scripts on first document insertion
+					for ( i = 0; i < hasScripts; i++ ) {
+						node = scripts[ i ];
+						if ( rscriptType.test( node.type || "" ) &&
+							!jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
+
+							if ( node.src ) {
+								// Optional AJAX dependency, but won't run scripts if not present
+								if ( jQuery._evalUrl ) {
+									jQuery._evalUrl( node.src );
+								}
+							} else {
+								jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
+							}
+						}
+					}
+				}
+
+				// Fix #11809: Avoid leaking memory
+				fragment = first = null;
+			}
+		}
+
+		return this;
+	}
+});
+
+jQuery.each({
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function( name, original ) {
+	jQuery.fn[ name ] = function( selector ) {
+		var elems,
+			i = 0,
+			ret = [],
+			insert = jQuery( selector ),
+			last = insert.length - 1;
+
+		for ( ; i <= last; i++ ) {
+			elems = i === last ? this : this.clone(true);
+			jQuery( insert[i] )[ original ]( elems );
+
+			// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
+			push.apply( ret, elems.get() );
+		}
+
+		return this.pushStack( ret );
+	};
+});
+
+
+var iframe,
+	elemdisplay = {};
+
+/**
+ * Retrieve the actual display of a element
+ * @param {String} name nodeName of the element
+ * @param {Object} doc Document object
+ */
+// Called only from within defaultDisplay
+function actualDisplay( name, doc ) {
+	var style,
+		elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+
+		// getDefaultComputedStyle might be reliably used only on attached element
+		display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
+
+			// Use of this method is a temporary fix (more like optmization) until something better comes along,
+			// since it was removed from specification and supported only in FF
+			style.display : jQuery.css( elem[ 0 ], "display" );
+
+	// We don't have any data stored on the element,
+	// so use "detach" method as fast way to get rid of the element
+	elem.detach();
+
+	return display;
+}
+
+/**
+ * Try to determine the default display value of an element
+ * @param {String} nodeName
+ */
+function defaultDisplay( nodeName ) {
+	var doc = document,
+		display = elemdisplay[ nodeName ];
+
+	if ( !display ) {
+		display = actualDisplay( nodeName, doc );
+
+		// If the simple way fails, read from inside an iframe
+		if ( display === "none" || !display ) {
+
+			// Use the already-created iframe if possible
+			iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
+
+			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+			doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
+
+			// Support: IE
+			doc.write();
+			doc.close();
+
+			display = actualDisplay( nodeName, doc );
+			iframe.detach();
+		}
+
+		// Store the correct default display
+		elemdisplay[ nodeName ] = display;
+	}
+
+	return display;
+}
+
+
+(function() {
+	var shrinkWrapBlocksVal;
+
+	support.shrinkWrapBlocks = function() {
+		if ( shrinkWrapBlocksVal != null ) {
+			return shrinkWrapBlocksVal;
+		}
+
+		// Will be changed later if needed.
+		shrinkWrapBlocksVal = false;
+
+		// Minified: var b,c,d
+		var div, body, container;
+
+		body = document.getElementsByTagName( "body" )[ 0 ];
+		if ( !body || !body.style ) {
+			// Test fired too early or in an unsupported environment, exit.
+			return;
+		}
+
+		// Setup
+		div = document.createElement( "div" );
+		container = document.createElement( "div" );
+		container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+		body.appendChild( container ).appendChild( div );
+
+		// Support: IE6
+		// Check if elements with layout shrink-wrap their children
+		if ( typeof div.style.zoom !== strundefined ) {
+			// Reset CSS: box-sizing; display; margin; border
+			div.style.cssText =
+				// Support: Firefox<29, Android 2.3
+				// Vendor-prefix box-sizing
+				"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
+				"box-sizing:content-box;display:block;margin:0;border:0;" +
+				"padding:1px;width:1px;zoom:1";
+			div.appendChild( document.createElement( "div" ) ).style.width = "5px";
+			shrinkWrapBlocksVal = div.offsetWidth !== 3;
+		}
+
+		body.removeChild( container );
+
+		return shrinkWrapBlocksVal;
+	};
+
+})();
+var rmargin = (/^margin/);
+
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+
+
+var getStyles, curCSS,
+	rposition = /^(top|right|bottom|left)$/;
+
+if ( window.getComputedStyle ) {
+	getStyles = function( elem ) {
+		return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
+	};
+
+	curCSS = function( elem, name, computed ) {
+		var width, minWidth, maxWidth, ret,
+			style = elem.style;
+
+		computed = computed || getStyles( elem );
+
+		// getPropertyValue is only needed for .css('filter') in IE9, see #12537
+		ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
+
+		if ( computed ) {
+
+			if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+				ret = jQuery.style( elem, name );
+			}
+
+			// A tribute to the "awesome hack by Dean Edwards"
+			// Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
+			// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+			// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+			if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+				// Remember the original values
+				width = style.width;
+				minWidth = style.minWidth;
+				maxWidth = style.maxWidth;
+
+				// Put in the new values to get a computed value out
+				style.minWidth = style.maxWidth = style.width = ret;
+				ret = computed.width;
+
+				// Revert the changed values
+				style.width = width;
+				style.minWidth = minWidth;
+				style.maxWidth = maxWidth;
+			}
+		}
+
+		// Support: IE
+		// IE returns zIndex value as an integer.
+		return ret === undefined ?
+			ret :
+			ret + "";
+	};
+} else if ( document.documentElement.currentStyle ) {
+	getStyles = function( elem ) {
+		return elem.currentStyle;
+	};
+
+	curCSS = function( elem, name, computed ) {
+		var left, rs, rsLeft, ret,
+			style = elem.style;
+
+		computed = computed || getStyles( elem );
+		ret = computed ? computed[ name ] : undefined;
+
+		// Avoid setting ret to empty string here
+		// so we don't default to auto
+		if ( ret == null && style && style[ name ] ) {
+			ret = style[ name ];
+		}
+
+		// From the awesome hack by Dean Edwards
+		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+		// If we're not dealing with a regular pixel number
+		// but a number that has a weird ending, we need to convert it to pixels
+		// but not position css attributes, as those are proportional to the parent element instead
+		// and we can't measure the parent instead because it might trigger a "stacking dolls" problem
+		if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+
+			// Remember the original values
+			left = style.left;
+			rs = elem.runtimeStyle;
+			rsLeft = rs && rs.left;
+
+			// Put in the new values to get a computed value out
+			if ( rsLeft ) {
+				rs.left = elem.currentStyle.left;
+			}
+			style.left = name === "fontSize" ? "1em" : ret;
+			ret = style.pixelLeft + "px";
+
+			// Revert the changed values
+			style.left = left;
+			if ( rsLeft ) {
+				rs.left = rsLeft;
+			}
+		}
+
+		// Support: IE
+		// IE returns zIndex value as an integer.
+		return ret === undefined ?
+			ret :
+			ret + "" || "auto";
+	};
+}
+
+
+
+
+function addGetHookIf( conditionFn, hookFn ) {
+	// Define the hook, we'll check on the first run if it's really needed.
+	return {
+		get: function() {
+			var condition = conditionFn();
+
+			if ( condition == null ) {
+				// The test was not ready at this point; screw the hook this time
+				// but check again when needed next time.
+				return;
+			}
+
+			if ( condition ) {
+				// Hook not needed (or it's not possible to use it due to missing dependency),
+				// remove it.
+				// Since there are no other hooks for marginRight, remove the whole object.
+				delete this.get;
+				return;
+			}
+
+			// Hook needed; redefine it so that the support test is not executed again.
+
+			return (this.get = hookFn).apply( this, arguments );
+		}
+	};
+}
+
+
+(function() {
+	// Minified: var b,c,d,e,f,g, h,i
+	var div, style, a, pixelPositionVal, boxSizingReliableVal,
+		reliableHiddenOffsetsVal, reliableMarginRightVal;
+
+	// Setup
+	div = document.createElement( "div" );
+	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+	a = div.getElementsByTagName( "a" )[ 0 ];
+	style = a && a.style;
+
+	// Finish early in limited (non-browser) environments
+	if ( !style ) {
+		return;
+	}
+
+	style.cssText = "float:left;opacity:.5";
+
+	// Support: IE<9
+	// Make sure that element opacity exists (as opposed to filter)
+	support.opacity = style.opacity === "0.5";
+
+	// Verify style float existence
+	// (IE uses styleFloat instead of cssFloat)
+	support.cssFloat = !!style.cssFloat;
+
+	div.style.backgroundClip = "content-box";
+	div.cloneNode( true ).style.backgroundClip = "";
+	support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+	// Support: Firefox<29, Android 2.3
+	// Vendor-prefix box-sizing
+	support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" ||
+		style.WebkitBoxSizing === "";
+
+	jQuery.extend(support, {
+		reliableHiddenOffsets: function() {
+			if ( reliableHiddenOffsetsVal == null ) {
+				computeStyleTests();
+			}
+			return reliableHiddenOffsetsVal;
+		},
+
+		boxSizingReliable: function() {
+			if ( boxSizingReliableVal == null ) {
+				computeStyleTests();
+			}
+			return boxSizingReliableVal;
+		},
+
+		pixelPosition: function() {
+			if ( pixelPositionVal == null ) {
+				computeStyleTests();
+			}
+			return pixelPositionVal;
+		},
+
+		// Support: Android 2.3
+		reliableMarginRight: function() {
+			if ( reliableMarginRightVal == null ) {
+				computeStyleTests();
+			}
+			return reliableMarginRightVal;
+		}
+	});
+
+	function computeStyleTests() {
+		// Minified: var b,c,d,j
+		var div, body, container, contents;
+
+		body = document.getElementsByTagName( "body" )[ 0 ];
+		if ( !body || !body.style ) {
+			// Test fired too early or in an unsupported environment, exit.
+			return;
+		}
+
+		// Setup
+		div = document.createElement( "div" );
+		container = document.createElement( "div" );
+		container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+		body.appendChild( container ).appendChild( div );
+
+		div.style.cssText =
+			// Support: Firefox<29, Android 2.3
+			// Vendor-prefix box-sizing
+			"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
+			"box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
+			"border:1px;padding:1px;width:4px;position:absolute";
+
+		// Support: IE<9
+		// Assume reasonable values in the absence of getComputedStyle
+		pixelPositionVal = boxSizingReliableVal = false;
+		reliableMarginRightVal = true;
+
+		// Check for getComputedStyle so that this code is not run in IE<9.
+		if ( window.getComputedStyle ) {
+			pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+			boxSizingReliableVal =
+				( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+
+			// Support: Android 2.3
+			// Div with explicit width and no margin-right incorrectly
+			// gets computed margin-right based on width of container (#3333)
+			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+			contents = div.appendChild( document.createElement( "div" ) );
+
+			// Reset CSS: box-sizing; display; margin; border; padding
+			contents.style.cssText = div.style.cssText =
+				// Support: Firefox<29, Android 2.3
+				// Vendor-prefix box-sizing
+				"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
+				"box-sizing:content-box;display:block;margin:0;border:0;padding:0";
+			contents.style.marginRight = contents.style.width = "0";
+			div.style.width = "1px";
+
+			reliableMarginRightVal =
+				!parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
+		}
+
+		// Support: IE8
+		// Check if table cells still have offsetWidth/Height when they are set
+		// to display:none and there are still other visible table cells in a
+		// table row; if so, offsetWidth/Height are not reliable for use when
+		// determining if an element has been hidden directly using
+		// display:none (it is still safe to use offsets if a parent element is
+		// hidden; don safety goggles and see bug #4512 for more information).
+		div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
+		contents = div.getElementsByTagName( "td" );
+		contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
+		reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
+		if ( reliableHiddenOffsetsVal ) {
+			contents[ 0 ].style.display = "";
+			contents[ 1 ].style.display = "none";
+			reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
+		}
+
+		body.removeChild( container );
+	}
+
+})();
+
+
+// A method for quickly swapping in/out CSS properties to get correct calculations.
+jQuery.swap = function( elem, options, callback, args ) {
+	var ret, name,
+		old = {};
+
+	// Remember the old values, and insert the new ones
+	for ( name in options ) {
+		old[ name ] = elem.style[ name ];
+		elem.style[ name ] = options[ name ];
+	}
+
+	ret = callback.apply( elem, args || [] );
+
+	// Revert the old values
+	for ( name in options ) {
+		elem.style[ name ] = old[ name ];
+	}
+
+	return ret;
+};
+
+
+var
+		ralpha = /alpha\([^)]*\)/i,
+	ropacity = /opacity\s*=\s*([^)]*)/,
+
+	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
+	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
+
+	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+	cssNormalTransform = {
+		letterSpacing: "0",
+		fontWeight: "400"
+	},
+
+	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
+
+
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+	// shortcut for names that are not vendor prefixed
+	if ( name in style ) {
+		return name;
+	}
+
+	// check for vendor prefixed names
+	var capName = name.charAt(0).toUpperCase() + name.slice(1),
+		origName = name,
+		i = cssPrefixes.length;
+
+	while ( i-- ) {
+		name = cssPrefixes[ i ] + capName;
+		if ( name in style ) {
+			return name;
+		}
+	}
+
+	return origName;
+}
+
+function showHide( elements, show ) {
+	var display, elem, hidden,
+		values = [],
+		index = 0,
+		length = elements.length;
+
+	for ( ; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+
+		values[ index ] = jQuery._data( elem, "olddisplay" );
+		display = elem.style.display;
+		if ( show ) {
+			// Reset the inline display of this element to learn if it is
+			// being hidden by cascaded rules or not
+			if ( !values[ index ] && display === "none" ) {
+				elem.style.display = "";
+			}
+
+			// Set elements which have been overridden with display: none
+			// in a stylesheet to whatever the default browser style is
+			// for such an element
+			if ( elem.style.display === "" && isHidden( elem ) ) {
+				values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+			}
+		} else {
+			hidden = isHidden( elem );
+
+			if ( display && display !== "none" || !hidden ) {
+				jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
+			}
+		}
+	}
+
+	// Set the display of most of the elements in a second loop
+	// to avoid the constant reflow
+	for ( index = 0; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+			elem.style.display = show ? values[ index ] || "" : "none";
+		}
+	}
+
+	return elements;
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+	var matches = rnumsplit.exec( value );
+	return matches ?
+		// Guard against undefined "subtract", e.g., when used as in cssHooks
+		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+		value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+	var i = extra === ( isBorderBox ? "border" : "content" ) ?
+		// If we already have the right measurement, avoid augmentation
+		4 :
+		// Otherwise initialize for horizontal or vertical properties
+		name === "width" ? 1 : 0,
+
+		val = 0;
+
+	for ( ; i < 4; i += 2 ) {
+		// both box models exclude margin, so add it if we want it
+		if ( extra === "margin" ) {
+			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+		}
+
+		if ( isBorderBox ) {
+			// border-box includes padding, so remove it if we want content
+			if ( extra === "content" ) {
+				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+			}
+
+			// at this point, extra isn't border nor margin, so remove border
+			if ( extra !== "margin" ) {
+				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+			}
+		} else {
+			// at this point, extra isn't content, so add padding
+			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+			// at this point, extra isn't content nor padding, so add border
+			if ( extra !== "padding" ) {
+				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+			}
+		}
+	}
+
+	return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+	// Start with offset property, which is equivalent to the border-box value
+	var valueIsBorderBox = true,
+		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+		styles = getStyles( elem ),
+		isBorderBox = support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+	// some non-html elements return undefined for offsetWidth, so check for null/undefined
+	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+	if ( val <= 0 || val == null ) {
+		// Fall back to computed then uncomputed css if necessary
+		val = curCSS( elem, name, styles );
+		if ( val < 0 || val == null ) {
+			val = elem.style[ name ];
+		}
+
+		// Computed unit is not pixels. Stop here and return.
+		if ( rnumnonpx.test(val) ) {
+			return val;
+		}
+
+		// we need the check for style in case a browser which returns unreliable values
+		// for getComputedStyle silently falls back to the reliable elem.style
+		valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );
+
+		// Normalize "", auto, and prepare for extra
+		val = parseFloat( val ) || 0;
+	}
+
+	// use the active box-sizing model to add/subtract irrelevant styles
+	return ( val +
+		augmentWidthOrHeight(
+			elem,
+			name,
+			extra || ( isBorderBox ? "border" : "content" ),
+			valueIsBorderBox,
+			styles
+		)
+	) + "px";
+}
+
+jQuery.extend({
+	// Add in style property hooks for overriding the default
+	// behavior of getting and setting a style property
+	cssHooks: {
+		opacity: {
+			get: function( elem, computed ) {
+				if ( computed ) {
+					// We should always get a number back from opacity
+					var ret = curCSS( elem, "opacity" );
+					return ret === "" ? "1" : ret;
+				}
+			}
+		}
+	},
+
+	// Don't automatically add "px" to these possibly-unitless properties
+	cssNumber: {
+		"columnCount": true,
+		"fillOpacity": true,
+		"flexGrow": true,
+		"flexShrink": true,
+		"fontWeight": true,
+		"lineHeight": true,
+		"opacity": true,
+		"order": true,
+		"orphans": true,
+		"widows": true,
+		"zIndex": true,
+		"zoom": true
+	},
+
+	// Add in properties whose names you wish to fix before
+	// setting or getting the value
+	cssProps: {
+		// normalize float css property
+		"float": support.cssFloat ? "cssFloat" : "styleFloat"
+	},
+
+	// Get and set the style property on a DOM Node
+	style: function( elem, name, value, extra ) {
+		// Don't set styles on text and comment nodes
+		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+			return;
+		}
+
+		// Make sure that we're working with the right name
+		var ret, type, hooks,
+			origName = jQuery.camelCase( name ),
+			style = elem.style;
+
+		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+		// gets hook for the prefixed version
+		// followed by the unprefixed version
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// Check if we're setting a value
+		if ( value !== undefined ) {
+			type = typeof value;
+
+			// convert relative number strings (+= or -=) to relative numbers. #7345
+			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+				// Fixes bug #9237
+				type = "number";
+			}
+
+			// Make sure that null and NaN values aren't set. See: #7116
+			if ( value == null || value !== value ) {
+				return;
+			}
+
+			// If a number was passed in, add 'px' to the (except for certain CSS properties)
+			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+				value += "px";
+			}
+
+			// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
+			// but it would mean to define eight (for every problematic property) identical functions
+			if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
+				style[ name ] = "inherit";
+			}
+
+			// If a hook was provided, use that value, otherwise just set the specified value
+			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+
+				// Support: IE
+				// Swallow errors from 'invalid' CSS values (#5509)
+				try {
+					style[ name ] = value;
+				} catch(e) {}
+			}
+
+		} else {
+			// If a hook was provided get the non-computed value from there
+			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+				return ret;
+			}
+
+			// Otherwise just get the value from the style object
+			return style[ name ];
+		}
+	},
+
+	css: function( elem, name, extra, styles ) {
+		var num, val, hooks,
+			origName = jQuery.camelCase( name );
+
+		// Make sure that we're working with the right name
+		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+		// gets hook for the prefixed version
+		// followed by the unprefixed version
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// If a hook was provided get the computed value from there
+		if ( hooks && "get" in hooks ) {
+			val = hooks.get( elem, true, extra );
+		}
+
+		// Otherwise, if a way to get the computed value exists, use that
+		if ( val === undefined ) {
+			val = curCSS( elem, name, styles );
+		}
+
+		//convert "normal" to computed value
+		if ( val === "normal" && name in cssNormalTransform ) {
+			val = cssNormalTransform[ name ];
+		}
+
+		// Return, converting to number if forced or a qualifier was provided and val looks numeric
+		if ( extra === "" || extra ) {
+			num = parseFloat( val );
+			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
+		}
+		return val;
+	}
+});
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+	jQuery.cssHooks[ name ] = {
+		get: function( elem, computed, extra ) {
+			if ( computed ) {
+				// certain elements can have dimension info if we invisibly show them
+				// however, it must have a current display style that would benefit from this
+				return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
+					jQuery.swap( elem, cssShow, function() {
+						return getWidthOrHeight( elem, name, extra );
+					}) :
+					getWidthOrHeight( elem, name, extra );
+			}
+		},
+
+		set: function( elem, value, extra ) {
+			var styles = extra && getStyles( elem );
+			return setPositiveNumber( elem, value, extra ?
+				augmentWidthOrHeight(
+					elem,
+					name,
+					extra,
+					support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+					styles
+				) : 0
+			);
+		}
+	};
+});
+
+if ( !support.opacity ) {
+	jQuery.cssHooks.opacity = {
+		get: function( elem, computed ) {
+			// IE uses filters for opacity
+			return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+				( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
+				computed ? "1" : "";
+		},
+
+		set: function( elem, value ) {
+			var style = elem.style,
+				currentStyle = elem.currentStyle,
+				opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+				filter = currentStyle && currentStyle.filter || style.filter || "";
+
+			// IE has trouble with opacity if it does not have layout
+			// Force it by setting the zoom level
+			style.zoom = 1;
+
+			// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+			// if value === "", then remove inline opacity #12685
+			if ( ( value >= 1 || value === "" ) &&
+					jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
+					style.removeAttribute ) {
+
+				// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+				// if "filter:" is present at all, clearType is disabled, we want to avoid this
+				// style.removeAttribute is IE Only, but so apparently is this code path...
+				style.removeAttribute( "filter" );
+
+				// if there is no filter style applied in a css rule or unset inline opacity, we are done
+				if ( value === "" || currentStyle && !currentStyle.filter ) {
+					return;
+				}
+			}
+
+			// otherwise, set new filter values
+			style.filter = ralpha.test( filter ) ?
+				filter.replace( ralpha, opacity ) :
+				filter + " " + opacity;
+		}
+	};
+}
+
+jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
+	function( elem, computed ) {
+		if ( computed ) {
+			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+			// Work around by temporarily setting element display to inline-block
+			return jQuery.swap( elem, { "display": "inline-block" },
+				curCSS, [ elem, "marginRight" ] );
+		}
+	}
+);
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+	margin: "",
+	padding: "",
+	border: "Width"
+}, function( prefix, suffix ) {
+	jQuery.cssHooks[ prefix + suffix ] = {
+		expand: function( value ) {
+			var i = 0,
+				expanded = {},
+
+				// assumes a single number if not a string
+				parts = typeof value === "string" ? value.split(" ") : [ value ];
+
+			for ( ; i < 4; i++ ) {
+				expanded[ prefix + cssExpand[ i ] + suffix ] =
+					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+			}
+
+			return expanded;
+		}
+	};
+
+	if ( !rmargin.test( prefix ) ) {
+		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+	}
+});
+
+jQuery.fn.extend({
+	css: function( name, value ) {
+		return access( this, function( elem, name, value ) {
+			var styles, len,
+				map = {},
+				i = 0;
+
+			if ( jQuery.isArray( name ) ) {
+				styles = getStyles( elem );
+				len = name.length;
+
+				for ( ; i < len; i++ ) {
+					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+				}
+
+				return map;
+			}
+
+			return value !== undefined ?
+				jQuery.style( elem, name, value ) :
+				jQuery.css( elem, name );
+		}, name, value, arguments.length > 1 );
+	},
+	show: function() {
+		return showHide( this, true );
+	},
+	hide: function() {
+		return showHide( this );
+	},
+	toggle: function( state ) {
+		if ( typeof state === "boolean" ) {
+			return state ? this.show() : this.hide();
+		}
+
+		return this.each(function() {
+			if ( isHidden( this ) ) {
+				jQuery( this ).show();
+			} else {
+				jQuery( this ).hide();
+			}
+		});
+	}
+});
+
+
+function Tween( elem, options, prop, end, easing ) {
+	return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+	constructor: Tween,
+	init: function( elem, options, prop, end, easing, unit ) {
+		this.elem = elem;
+		this.prop = prop;
+		this.easing = easing || "swing";
+		this.options = options;
+		this.start = this.now = this.cur();
+		this.end = end;
+		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+	},
+	cur: function() {
+		var hooks = Tween.propHooks[ this.prop ];
+
+		return hooks && hooks.get ?
+			hooks.get( this ) :
+			Tween.propHooks._default.get( this );
+	},
+	run: function( percent ) {
+		var eased,
+			hooks = Tween.propHooks[ this.prop ];
+
+		if ( this.options.duration ) {
+			this.pos = eased = jQuery.easing[ this.easing ](
+				percent, this.options.duration * percent, 0, 1, this.options.duration
+			);
+		} else {
+			this.pos = eased = percent;
+		}
+		this.now = ( this.end - this.start ) * eased + this.start;
+
+		if ( this.options.step ) {
+			this.options.step.call( this.elem, this.now, this );
+		}
+
+		if ( hooks && hooks.set ) {
+			hooks.set( this );
+		} else {
+			Tween.propHooks._default.set( this );
+		}
+		return this;
+	}
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+	_default: {
+		get: function( tween ) {
+			var result;
+
+			if ( tween.elem[ tween.prop ] != null &&
+				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+				return tween.elem[ tween.prop ];
+			}
+
+			// passing an empty string as a 3rd parameter to .css will automatically
+			// attempt a parseFloat and fallback to a string if the parse fails
+			// so, simple values such as "10px" are parsed to Float.
+			// complex values such as "rotate(1rad)" are returned as is.
+			result = jQuery.css( tween.elem, tween.prop, "" );
+			// Empty strings, null, undefined and "auto" are converted to 0.
+			return !result || result === "auto" ? 0 : result;
+		},
+		set: function( tween ) {
+			// use step hook for back compat - use cssHook if its there - use .style if its
+			// available and use plain properties where available
+			if ( jQuery.fx.step[ tween.prop ] ) {
+				jQuery.fx.step[ tween.prop ]( tween );
+			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+			} else {
+				tween.elem[ tween.prop ] = tween.now;
+			}
+		}
+	}
+};
+
+// Support: IE <=9
+// Panic based approach to setting things on disconnected nodes
+
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+	set: function( tween ) {
+		if ( tween.elem.nodeType && tween.elem.parentNode ) {
+			tween.elem[ tween.prop ] = tween.now;
+		}
+	}
+};
+
+jQuery.easing = {
+	linear: function( p ) {
+		return p;
+	},
+	swing: function( p ) {
+		return 0.5 - Math.cos( p * Math.PI ) / 2;
+	}
+};
+
+jQuery.fx = Tween.prototype.init;
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+
+
+
+var
+	fxNow, timerId,
+	rfxtypes = /^(?:toggle|show|hide)$/,
+	rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
+	rrun = /queueHooks$/,
+	animationPrefilters = [ defaultPrefilter ],
+	tweeners = {
+		"*": [ function( prop, value ) {
+			var tween = this.createTween( prop, value ),
+				target = tween.cur(),
+				parts = rfxnum.exec( value ),
+				unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+				// Starting value computation is required for potential unit mismatches
+				start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
+					rfxnum.exec( jQuery.css( tween.elem, prop ) ),
+				scale = 1,
+				maxIterations = 20;
+
+			if ( start && start[ 3 ] !== unit ) {
+				// Trust units reported by jQuery.css
+				unit = unit || start[ 3 ];
+
+				// Make sure we update the tween properties later on
+				parts = parts || [];
+
+				// Iteratively approximate from a nonzero starting point
+				start = +target || 1;
+
+				do {
+					// If previous iteration zeroed out, double until we get *something*
+					// Use a string for doubling factor so we don't accidentally see scale as unchanged below
+					scale = scale || ".5";
+
+					// Adjust and apply
+					start = start / scale;
+					jQuery.style( tween.elem, prop, start + unit );
+
+				// Update scale, tolerating zero or NaN from tween.cur()
+				// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+			}
+
+			// Update tween properties
+			if ( parts ) {
+				start = tween.start = +start || +target || 0;
+				tween.unit = unit;
+				// If a +=/-= token was provided, we're doing a relative animation
+				tween.end = parts[ 1 ] ?
+					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
+					+parts[ 2 ];
+			}
+
+			return tween;
+		} ]
+	};
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+	setTimeout(function() {
+		fxNow = undefined;
+	});
+	return ( fxNow = jQuery.now() );
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+	var which,
+		attrs = { height: type },
+		i = 0;
+
+	// if we include width, step value is 1 to do all cssExpand values,
+	// if we don't include width, step value is 2 to skip over Left and Right
+	includeWidth = includeWidth ? 1 : 0;
+	for ( ; i < 4 ; i += 2 - includeWidth ) {
+		which = cssExpand[ i ];
+		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+	}
+
+	if ( includeWidth ) {
+		attrs.opacity = attrs.width = type;
+	}
+
+	return attrs;
+}
+
+function createTween( value, prop, animation ) {
+	var tween,
+		collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+		index = 0,
+		length = collection.length;
+	for ( ; index < length; index++ ) {
+		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
+
+			// we're done with this property
+			return tween;
+		}
+	}
+}
+
+function defaultPrefilter( elem, props, opts ) {
+	/* jshint validthis: true */
+	var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
+		anim = this,
+		orig = {},
+		style = elem.style,
+		hidden = elem.nodeType && isHidden( elem ),
+		dataShow = jQuery._data( elem, "fxshow" );
+
+	// handle queue: false promises
+	if ( !opts.queue ) {
+		hooks = jQuery._queueHooks( elem, "fx" );
+		if ( hooks.unqueued == null ) {
+			hooks.unqueued = 0;
+			oldfire = hooks.empty.fire;
+			hooks.empty.fire = function() {
+				if ( !hooks.unqueued ) {
+					oldfire();
+				}
+			};
+		}
+		hooks.unqueued++;
+
+		anim.always(function() {
+			// doing this makes sure that the complete handler will be called
+			// before this completes
+			anim.always(function() {
+				hooks.unqueued--;
+				if ( !jQuery.queue( elem, "fx" ).length ) {
+					hooks.empty.fire();
+				}
+			});
+		});
+	}
+
+	// height/width overflow pass
+	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+		// Make sure that nothing sneaks out
+		// Record all 3 overflow attributes because IE does not
+		// change the overflow attribute when overflowX and
+		// overflowY are set to the same value
+		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+		// Set display property to inline-block for height/width
+		// animations on inline elements that are having width/height animated
+		display = jQuery.css( elem, "display" );
+
+		// Test default display if display is currently "none"
+		checkDisplay = display === "none" ?
+			jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
+
+		if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
+
+			// inline-level elements accept inline-block;
+			// block-level elements need to be inline with layout
+			if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
+				style.display = "inline-block";
+			} else {
+				style.zoom = 1;
+			}
+		}
+	}
+
+	if ( opts.overflow ) {
+		style.overflow = "hidden";
+		if ( !support.shrinkWrapBlocks() ) {
+			anim.always(function() {
+				style.overflow = opts.overflow[ 0 ];
+				style.overflowX = opts.overflow[ 1 ];
+				style.overflowY = opts.overflow[ 2 ];
+			});
+		}
+	}
+
+	// show/hide pass
+	for ( prop in props ) {
+		value = props[ prop ];
+		if ( rfxtypes.exec( value ) ) {
+			delete props[ prop ];
+			toggle = toggle || value === "toggle";
+			if ( value === ( hidden ? "hide" : "show" ) ) {
+
+				// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
+				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+					hidden = true;
+				} else {
+					continue;
+				}
+			}
+			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+
+		// Any non-fx value stops us from restoring the original display value
+		} else {
+			display = undefined;
+		}
+	}
+
+	if ( !jQuery.isEmptyObject( orig ) ) {
+		if ( dataShow ) {
+			if ( "hidden" in dataShow ) {
+				hidden = dataShow.hidden;
+			}
+		} else {
+			dataShow = jQuery._data( elem, "fxshow", {} );
+		}
+
+		// store state if its toggle - enables .stop().toggle() to "reverse"
+		if ( toggle ) {
+			dataShow.hidden = !hidden;
+		}
+		if ( hidden ) {
+			jQuery( elem ).show();
+		} else {
+			anim.done(function() {
+				jQuery( elem ).hide();
+			});
+		}
+		anim.done(function() {
+			var prop;
+			jQuery._removeData( elem, "fxshow" );
+			for ( prop in orig ) {
+				jQuery.style( elem, prop, orig[ prop ] );
+			}
+		});
+		for ( prop in orig ) {
+			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+
+			if ( !( prop in dataShow ) ) {
+				dataShow[ prop ] = tween.start;
+				if ( hidden ) {
+					tween.end = tween.start;
+					tween.start = prop === "width" || prop === "height" ? 1 : 0;
+				}
+			}
+		}
+
+	// If this is a noop like .hide().hide(), restore an overwritten display value
+	} else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
+		style.display = display;
+	}
+}
+
+function propFilter( props, specialEasing ) {
+	var index, name, easing, value, hooks;
+
+	// camelCase, specialEasing and expand cssHook pass
+	for ( index in props ) {
+		name = jQuery.camelCase( index );
+		easing = specialEasing[ name ];
+		value = props[ index ];
+		if ( jQuery.isArray( value ) ) {
+			easing = value[ 1 ];
+			value = props[ index ] = value[ 0 ];
+		}
+
+		if ( index !== name ) {
+			props[ name ] = value;
+			delete props[ index ];
+		}
+
+		hooks = jQuery.cssHooks[ name ];
+		if ( hooks && "expand" in hooks ) {
+			value = hooks.expand( value );
+			delete props[ name ];
+
+			// not quite $.extend, this wont overwrite keys already present.
+			// also - reusing 'index' from above because we have the correct "name"
+			for ( index in value ) {
+				if ( !( index in props ) ) {
+					props[ index ] = value[ index ];
+					specialEasing[ index ] = easing;
+				}
+			}
+		} else {
+			specialEasing[ name ] = easing;
+		}
+	}
+}
+
+function Animation( elem, properties, options ) {
+	var result,
+		stopped,
+		index = 0,
+		length = animationPrefilters.length,
+		deferred = jQuery.Deferred().always( function() {
+			// don't match elem in the :animated selector
+			delete tick.elem;
+		}),
+		tick = function() {
+			if ( stopped ) {
+				return false;
+			}
+			var currentTime = fxNow || createFxNow(),
+				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+				// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+				temp = remaining / animation.duration || 0,
+				percent = 1 - temp,
+				index = 0,
+				length = animation.tweens.length;
+
+			for ( ; index < length ; index++ ) {
+				animation.tweens[ index ].run( percent );
+			}
+
+			deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+			if ( percent < 1 && length ) {
+				return remaining;
+			} else {
+				deferred.resolveWith( elem, [ animation ] );
+				return false;
+			}
+		},
+		animation = deferred.promise({
+			elem: elem,
+			props: jQuery.extend( {}, properties ),
+			opts: jQuery.extend( true, { specialEasing: {} }, options ),
+			originalProperties: properties,
+			originalOptions: options,
+			startTime: fxNow || createFxNow(),
+			duration: options.duration,
+			tweens: [],
+			createTween: function( prop, end ) {
+				var tween = jQuery.Tween( elem, animation.opts, prop, end,
+						animation.opts.specialEasing[ prop ] || animation.opts.easing );
+				animation.tweens.push( tween );
+				return tween;
+			},
+			stop: function( gotoEnd ) {
+				var index = 0,
+					// if we are going to the end, we want to run all the tweens
+					// otherwise we skip this part
+					length = gotoEnd ? animation.tweens.length : 0;
+				if ( stopped ) {
+					return this;
+				}
+				stopped = true;
+				for ( ; index < length ; index++ ) {
+					animation.tweens[ index ].run( 1 );
+				}
+
+				// resolve when we played the last frame
+				// otherwise, reject
+				if ( gotoEnd ) {
+					deferred.resolveWith( elem, [ animation, gotoEnd ] );
+				} else {
+					deferred.rejectWith( elem, [ animation, gotoEnd ] );
+				}
+				return this;
+			}
+		}),
+		props = animation.props;
+
+	propFilter( props, animation.opts.specialEasing );
+
+	for ( ; index < length ; index++ ) {
+		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+		if ( result ) {
+			return result;
+		}
+	}
+
+	jQuery.map( props, createTween, animation );
+
+	if ( jQuery.isFunction( animation.opts.start ) ) {
+		animation.opts.start.call( elem, animation );
+	}
+
+	jQuery.fx.timer(
+		jQuery.extend( tick, {
+			elem: elem,
+			anim: animation,
+			queue: animation.opts.queue
+		})
+	);
+
+	// attach callbacks from options
+	return animation.progress( animation.opts.progress )
+		.done( animation.opts.done, animation.opts.complete )
+		.fail( animation.opts.fail )
+		.always( animation.opts.always );
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+	tweener: function( props, callback ) {
+		if ( jQuery.isFunction( props ) ) {
+			callback = props;
+			props = [ "*" ];
+		} else {
+			props = props.split(" ");
+		}
+
+		var prop,
+			index = 0,
+			length = props.length;
+
+		for ( ; index < length ; index++ ) {
+			prop = props[ index ];
+			tweeners[ prop ] = tweeners[ prop ] || [];
+			tweeners[ prop ].unshift( callback );
+		}
+	},
+
+	prefilter: function( callback, prepend ) {
+		if ( prepend ) {
+			animationPrefilters.unshift( callback );
+		} else {
+			animationPrefilters.push( callback );
+		}
+	}
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+		complete: fn || !fn && easing ||
+			jQuery.isFunction( speed ) && speed,
+		duration: speed,
+		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+	};
+
+	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+	// normalize opt.queue - true/undefined/null -> "fx"
+	if ( opt.queue == null || opt.queue === true ) {
+		opt.queue = "fx";
+	}
+
+	// Queueing
+	opt.old = opt.complete;
+
+	opt.complete = function() {
+		if ( jQuery.isFunction( opt.old ) ) {
+			opt.old.call( this );
+		}
+
+		if ( opt.queue ) {
+			jQuery.dequeue( this, opt.queue );
+		}
+	};
+
+	return opt;
+};
+
+jQuery.fn.extend({
+	fadeTo: function( speed, to, easing, callback ) {
+
+		// show any hidden elements after setting opacity to 0
+		return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+			// animate to the value specified
+			.end().animate({ opacity: to }, speed, easing, callback );
+	},
+	animate: function( prop, speed, easing, callback ) {
+		var empty = jQuery.isEmptyObject( prop ),
+			optall = jQuery.speed( speed, easing, callback ),
+			doAnimation = function() {
+				// Operate on a copy of prop so per-property easing won't be lost
+				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+				// Empty animations, or finishing resolves immediately
+				if ( empty || jQuery._data( this, "finish" ) ) {
+					anim.stop( true );
+				}
+			};
+			doAnimation.finish = doAnimation;
+
+		return empty || optall.queue === false ?
+			this.each( doAnimation ) :
+			this.queue( optall.queue, doAnimation );
+	},
+	stop: function( type, clearQueue, gotoEnd ) {
+		var stopQueue = function( hooks ) {
+			var stop = hooks.stop;
+			delete hooks.stop;
+			stop( gotoEnd );
+		};
+
+		if ( typeof type !== "string" ) {
+			gotoEnd = clearQueue;
+			clearQueue = type;
+			type = undefined;
+		}
+		if ( clearQueue && type !== false ) {
+			this.queue( type || "fx", [] );
+		}
+
+		return this.each(function() {
+			var dequeue = true,
+				index = type != null && type + "queueHooks",
+				timers = jQuery.timers,
+				data = jQuery._data( this );
+
+			if ( index ) {
+				if ( data[ index ] && data[ index ].stop ) {
+					stopQueue( data[ index ] );
+				}
+			} else {
+				for ( index in data ) {
+					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+						stopQueue( data[ index ] );
+					}
+				}
+			}
+
+			for ( index = timers.length; index--; ) {
+				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+					timers[ index ].anim.stop( gotoEnd );
+					dequeue = false;
+					timers.splice( index, 1 );
+				}
+			}
+
+			// start the next in the queue if the last step wasn't forced
+			// timers currently will call their complete callbacks, which will dequeue
+			// but only if they were gotoEnd
+			if ( dequeue || !gotoEnd ) {
+				jQuery.dequeue( this, type );
+			}
+		});
+	},
+	finish: function( type ) {
+		if ( type !== false ) {
+			type = type || "fx";
+		}
+		return this.each(function() {
+			var index,
+				data = jQuery._data( this ),
+				queue = data[ type + "queue" ],
+				hooks = data[ type + "queueHooks" ],
+				timers = jQuery.timers,
+				length = queue ? queue.length : 0;
+
+			// enable finishing flag on private data
+			data.finish = true;
+
+			// empty the queue first
+			jQuery.queue( this, type, [] );
+
+			if ( hooks && hooks.stop ) {
+				hooks.stop.call( this, true );
+			}
+
+			// look for any active animations, and finish them
+			for ( index = timers.length; index--; ) {
+				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+					timers[ index ].anim.stop( true );
+					timers.splice( index, 1 );
+				}
+			}
+
+			// look for any animations in the old queue and finish them
+			for ( index = 0; index < length; index++ ) {
+				if ( queue[ index ] && queue[ index ].finish ) {
+					queue[ index ].finish.call( this );
+				}
+			}
+
+			// turn off finishing flag
+			delete data.finish;
+		});
+	}
+});
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+	var cssFn = jQuery.fn[ name ];
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return speed == null || typeof speed === "boolean" ?
+			cssFn.apply( this, arguments ) :
+			this.animate( genFx( name, true ), speed, easing, callback );
+	};
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+	slideDown: genFx("show"),
+	slideUp: genFx("hide"),
+	slideToggle: genFx("toggle"),
+	fadeIn: { opacity: "show" },
+	fadeOut: { opacity: "hide" },
+	fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return this.animate( props, speed, easing, callback );
+	};
+});
+
+jQuery.timers = [];
+jQuery.fx.tick = function() {
+	var timer,
+		timers = jQuery.timers,
+		i = 0;
+
+	fxNow = jQuery.now();
+
+	for ( ; i < timers.length; i++ ) {
+		timer = timers[ i ];
+		// Checks the timer has not already been removed
+		if ( !timer() && timers[ i ] === timer ) {
+			timers.splice( i--, 1 );
+		}
+	}
+
+	if ( !timers.length ) {
+		jQuery.fx.stop();
+	}
+	fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+	jQuery.timers.push( timer );
+	if ( timer() ) {
+		jQuery.fx.start();
+	} else {
+		jQuery.timers.pop();
+	}
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.start = function() {
+	if ( !timerId ) {
+		timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+	}
+};
+
+jQuery.fx.stop = function() {
+	clearInterval( timerId );
+	timerId = null;
+};
+
+jQuery.fx.speeds = {
+	slow: 600,
+	fast: 200,
+	// Default speed
+	_default: 400
+};
+
+
+// Based off of the plugin by Clint Helfers, with permission.
+// http://blindsignals.com/index.php/2009/07/jquery-delay/
+jQuery.fn.delay = function( time, type ) {
+	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+	type = type || "fx";
+
+	return this.queue( type, function( next, hooks ) {
+		var timeout = setTimeout( next, time );
+		hooks.stop = function() {
+			clearTimeout( timeout );
+		};
+	});
+};
+
+
+(function() {
+	// Minified: var a,b,c,d,e
+	var input, div, select, a, opt;
+
+	// Setup
+	div = document.createElement( "div" );
+	div.setAttribute( "className", "t" );
+	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+	a = div.getElementsByTagName("a")[ 0 ];
+
+	// First batch of tests.
+	select = document.createElement("select");
+	opt = select.appendChild( document.createElement("option") );
+	input = div.getElementsByTagName("input")[ 0 ];
+
+	a.style.cssText = "top:1px";
+
+	// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+	support.getSetAttribute = div.className !== "t";
+
+	// Get the style information from getAttribute
+	// (IE uses .cssText instead)
+	support.style = /top/.test( a.getAttribute("style") );
+
+	// Make sure that URLs aren't manipulated
+	// (IE normalizes it by default)
+	support.hrefNormalized = a.getAttribute("href") === "/a";
+
+	// Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
+	support.checkOn = !!input.value;
+
+	// Make sure that a selected-by-default option has a working selected property.
+	// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+	support.optSelected = opt.selected;
+
+	// Tests for enctype support on a form (#6743)
+	support.enctype = !!document.createElement("form").enctype;
+
+	// Make sure that the options inside disabled selects aren't marked as disabled
+	// (WebKit marks them as disabled)
+	select.disabled = true;
+	support.optDisabled = !opt.disabled;
+
+	// Support: IE8 only
+	// Check if we can trust getAttribute("value")
+	input = document.createElement( "input" );
+	input.setAttribute( "value", "" );
+	support.input = input.getAttribute( "value" ) === "";
+
+	// Check if an input maintains its value after becoming a radio
+	input.value = "t";
+	input.setAttribute( "type", "radio" );
+	support.radioValue = input.value === "t";
+})();
+
+
+var rreturn = /\r/g;
+
+jQuery.fn.extend({
+	val: function( value ) {
+		var hooks, ret, isFunction,
+			elem = this[0];
+
+		if ( !arguments.length ) {
+			if ( elem ) {
+				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+					return ret;
+				}
+
+				ret = elem.value;
+
+				return typeof ret === "string" ?
+					// handle most common string cases
+					ret.replace(rreturn, "") :
+					// handle cases where value is null/undef or number
+					ret == null ? "" : ret;
+			}
+
+			return;
+		}
+
+		isFunction = jQuery.isFunction( value );
+
+		return this.each(function( i ) {
+			var val;
+
+			if ( this.nodeType !== 1 ) {
+				return;
+			}
+
+			if ( isFunction ) {
+				val = value.call( this, i, jQuery( this ).val() );
+			} else {
+				val = value;
+			}
+
+			// Treat null/undefined as ""; convert numbers to string
+			if ( val == null ) {
+				val = "";
+			} else if ( typeof val === "number" ) {
+				val += "";
+			} else if ( jQuery.isArray( val ) ) {
+				val = jQuery.map( val, function( value ) {
+					return value == null ? "" : value + "";
+				});
+			}
+
+			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+			// If set returns undefined, fall back to normal setting
+			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+				this.value = val;
+			}
+		});
+	}
+});
+
+jQuery.extend({
+	valHooks: {
+		option: {
+			get: function( elem ) {
+				var val = jQuery.find.attr( elem, "value" );
+				return val != null ?
+					val :
+					// Support: IE10-11+
+					// option.text throws exceptions (#14686, #14858)
+					jQuery.trim( jQuery.text( elem ) );
+			}
+		},
+		select: {
+			get: function( elem ) {
+				var value, option,
+					options = elem.options,
+					index = elem.selectedIndex,
+					one = elem.type === "select-one" || index < 0,
+					values = one ? null : [],
+					max = one ? index + 1 : options.length,
+					i = index < 0 ?
+						max :
+						one ? index : 0;
+
+				// Loop through all the selected options
+				for ( ; i < max; i++ ) {
+					option = options[ i ];
+
+					// oldIE doesn't update selected after form reset (#2551)
+					if ( ( option.selected || i === index ) &&
+							// Don't return options that are disabled or in a disabled optgroup
+							( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
+							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+						// Get the specific value for the option
+						value = jQuery( option ).val();
+
+						// We don't need an array for one selects
+						if ( one ) {
+							return value;
+						}
+
+						// Multi-Selects return an array
+						values.push( value );
+					}
+				}
+
+				return values;
+			},
+
+			set: function( elem, value ) {
+				var optionSet, option,
+					options = elem.options,
+					values = jQuery.makeArray( value ),
+					i = options.length;
+
+				while ( i-- ) {
+					option = options[ i ];
+
+					if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {
+
+						// Support: IE6
+						// When new option element is added to select box we need to
+						// force reflow of newly added node in order to workaround delay
+						// of initialization properties
+						try {
+							option.selected = optionSet = true;
+
+						} catch ( _ ) {
+
+							// Will be executed only in IE6
+							option.scrollHeight;
+						}
+
+					} else {
+						option.selected = false;
+					}
+				}
+
+				// Force browsers to behave consistently when non-matching value is set
+				if ( !optionSet ) {
+					elem.selectedIndex = -1;
+				}
+
+				return options;
+			}
+		}
+	}
+});
+
+// Radios and checkboxes getter/setter
+jQuery.each([ "radio", "checkbox" ], function() {
+	jQuery.valHooks[ this ] = {
+		set: function( elem, value ) {
+			if ( jQuery.isArray( value ) ) {
+				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+			}
+		}
+	};
+	if ( !support.checkOn ) {
+		jQuery.valHooks[ this ].get = function( elem ) {
+			// Support: Webkit
+			// "" is returned instead of "on" if a value isn't specified
+			return elem.getAttribute("value") === null ? "on" : elem.value;
+		};
+	}
+});
+
+
+
+
+var nodeHook, boolHook,
+	attrHandle = jQuery.expr.attrHandle,
+	ruseDefault = /^(?:checked|selected)$/i,
+	getSetAttribute = support.getSetAttribute,
+	getSetInput = support.input;
+
+jQuery.fn.extend({
+	attr: function( name, value ) {
+		return access( this, jQuery.attr, name, value, arguments.length > 1 );
+	},
+
+	removeAttr: function( name ) {
+		return this.each(function() {
+			jQuery.removeAttr( this, name );
+		});
+	}
+});
+
+jQuery.extend({
+	attr: function( elem, name, value ) {
+		var hooks, ret,
+			nType = elem.nodeType;
+
+		// don't get/set attributes on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		// Fallback to prop when attributes are not supported
+		if ( typeof elem.getAttribute === strundefined ) {
+			return jQuery.prop( elem, name, value );
+		}
+
+		// All attributes are lowercase
+		// Grab necessary hook if one is defined
+		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+			name = name.toLowerCase();
+			hooks = jQuery.attrHooks[ name ] ||
+				( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
+		}
+
+		if ( value !== undefined ) {
+
+			if ( value === null ) {
+				jQuery.removeAttr( elem, name );
+
+			} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+				return ret;
+
+			} else {
+				elem.setAttribute( name, value + "" );
+				return value;
+			}
+
+		} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+			return ret;
+
+		} else {
+			ret = jQuery.find.attr( elem, name );
+
+			// Non-existent attributes return null, we normalize to undefined
+			return ret == null ?
+				undefined :
+				ret;
+		}
+	},
+
+	removeAttr: function( elem, value ) {
+		var name, propName,
+			i = 0,
+			attrNames = value && value.match( rnotwhite );
+
+		if ( attrNames && elem.nodeType === 1 ) {
+			while ( (name = attrNames[i++]) ) {
+				propName = jQuery.propFix[ name ] || name;
+
+				// Boolean attributes get special treatment (#10870)
+				if ( jQuery.expr.match.bool.test( name ) ) {
+					// Set corresponding property to false
+					if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+						elem[ propName ] = false;
+					// Support: IE<9
+					// Also clear defaultChecked/defaultSelected (if appropriate)
+					} else {
+						elem[ jQuery.camelCase( "default-" + name ) ] =
+							elem[ propName ] = false;
+					}
+
+				// See #9699 for explanation of this approach (setting first, then removal)
+				} else {
+					jQuery.attr( elem, name, "" );
+				}
+
+				elem.removeAttribute( getSetAttribute ? name : propName );
+			}
+		}
+	},
+
+	attrHooks: {
+		type: {
+			set: function( elem, value ) {
+				if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+					// Setting the type on a radio button after the value resets the value in IE6-9
+					// Reset value to default in case type is set after value during creation
+					var val = elem.value;
+					elem.setAttribute( "type", value );
+					if ( val ) {
+						elem.value = val;
+					}
+					return value;
+				}
+			}
+		}
+	}
+});
+
+// Hook for boolean attributes
+boolHook = {
+	set: function( elem, value, name ) {
+		if ( value === false ) {
+			// Remove boolean attributes when set to false
+			jQuery.removeAttr( elem, name );
+		} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+			// IE<8 needs the *property* name
+			elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
+
+		// Use defaultChecked and defaultSelected for oldIE
+		} else {
+			elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
+		}
+
+		return name;
+	}
+};
+
+// Retrieve booleans specially
+jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+
+	var getter = attrHandle[ name ] || jQuery.find.attr;
+
+	attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
+		function( elem, name, isXML ) {
+			var ret, handle;
+			if ( !isXML ) {
+				// Avoid an infinite loop by temporarily removing this function from the getter
+				handle = attrHandle[ name ];
+				attrHandle[ name ] = ret;
+				ret = getter( elem, name, isXML ) != null ?
+					name.toLowerCase() :
+					null;
+				attrHandle[ name ] = handle;
+			}
+			return ret;
+		} :
+		function( elem, name, isXML ) {
+			if ( !isXML ) {
+				return elem[ jQuery.camelCase( "default-" + name ) ] ?
+					name.toLowerCase() :
+					null;
+			}
+		};
+});
+
+// fix oldIE attroperties
+if ( !getSetInput || !getSetAttribute ) {
+	jQuery.attrHooks.value = {
+		set: function( elem, value, name ) {
+			if ( jQuery.nodeName( elem, "input" ) ) {
+				// Does not return so that setAttribute is also used
+				elem.defaultValue = value;
+			} else {
+				// Use nodeHook if defined (#1954); otherwise setAttribute is fine
+				return nodeHook && nodeHook.set( elem, value, name );
+			}
+		}
+	};
+}
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+	// Use this for any attribute in IE6/7
+	// This fixes almost every IE6/7 issue
+	nodeHook = {
+		set: function( elem, value, name ) {
+			// Set the existing or create a new attribute node
+			var ret = elem.getAttributeNode( name );
+			if ( !ret ) {
+				elem.setAttributeNode(
+					(ret = elem.ownerDocument.createAttribute( name ))
+				);
+			}
+
+			ret.value = value += "";
+
+			// Break association with cloned elements by also using setAttribute (#9646)
+			if ( name === "value" || value === elem.getAttribute( name ) ) {
+				return value;
+			}
+		}
+	};
+
+	// Some attributes are constructed with empty-string values when not defined
+	attrHandle.id = attrHandle.name = attrHandle.coords =
+		function( elem, name, isXML ) {
+			var ret;
+			if ( !isXML ) {
+				return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
+					ret.value :
+					null;
+			}
+		};
+
+	// Fixing value retrieval on a button requires this module
+	jQuery.valHooks.button = {
+		get: function( elem, name ) {
+			var ret = elem.getAttributeNode( name );
+			if ( ret && ret.specified ) {
+				return ret.value;
+			}
+		},
+		set: nodeHook.set
+	};
+
+	// Set contenteditable to false on removals(#10429)
+	// Setting to empty string throws an error as an invalid value
+	jQuery.attrHooks.contenteditable = {
+		set: function( elem, value, name ) {
+			nodeHook.set( elem, value === "" ? false : value, name );
+		}
+	};
+
+	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
+	// This is for removals
+	jQuery.each([ "width", "height" ], function( i, name ) {
+		jQuery.attrHooks[ name ] = {
+			set: function( elem, value ) {
+				if ( value === "" ) {
+					elem.setAttribute( name, "auto" );
+					return value;
+				}
+			}
+		};
+	});
+}
+
+if ( !support.style ) {
+	jQuery.attrHooks.style = {
+		get: function( elem ) {
+			// Return undefined in the case of empty string
+			// Note: IE uppercases css property names, but if we were to .toLowerCase()
+			// .cssText, that would destroy case senstitivity in URL's, like in "background"
+			return elem.style.cssText || undefined;
+		},
+		set: function( elem, value ) {
+			return ( elem.style.cssText = value + "" );
+		}
+	};
+}
+
+
+
+
+var rfocusable = /^(?:input|select|textarea|button|object)$/i,
+	rclickable = /^(?:a|area)$/i;
+
+jQuery.fn.extend({
+	prop: function( name, value ) {
+		return access( this, jQuery.prop, name, value, arguments.length > 1 );
+	},
+
+	removeProp: function( name ) {
+		name = jQuery.propFix[ name ] || name;
+		return this.each(function() {
+			// try/catch handles cases where IE balks (such as removing a property on window)
+			try {
+				this[ name ] = undefined;
+				delete this[ name ];
+			} catch( e ) {}
+		});
+	}
+});
+
+jQuery.extend({
+	propFix: {
+		"for": "htmlFor",
+		"class": "className"
+	},
+
+	prop: function( elem, name, value ) {
+		var ret, hooks, notxml,
+			nType = elem.nodeType;
+
+		// don't get/set properties on text, comment and attribute nodes
+		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+		if ( notxml ) {
+			// Fix name and attach hooks
+			name = jQuery.propFix[ name ] || name;
+			hooks = jQuery.propHooks[ name ];
+		}
+
+		if ( value !== undefined ) {
+			return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
+				ret :
+				( elem[ name ] = value );
+
+		} else {
+			return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
+				ret :
+				elem[ name ];
+		}
+	},
+
+	propHooks: {
+		tabIndex: {
+			get: function( elem ) {
+				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+				// Use proper attribute retrieval(#12072)
+				var tabindex = jQuery.find.attr( elem, "tabindex" );
+
+				return tabindex ?
+					parseInt( tabindex, 10 ) :
+					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+						0 :
+						-1;
+			}
+		}
+	}
+});
+
+// Some attributes require a special call on IE
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !support.hrefNormalized ) {
+	// href/src property should get the full normalized URL (#10299/#12915)
+	jQuery.each([ "href", "src" ], function( i, name ) {
+		jQuery.propHooks[ name ] = {
+			get: function( elem ) {
+				return elem.getAttribute( name, 4 );
+			}
+		};
+	});
+}
+
+// Support: Safari, IE9+
+// mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !support.optSelected ) {
+	jQuery.propHooks.selected = {
+		get: function( elem ) {
+			var parent = elem.parentNode;
+
+			if ( parent ) {
+				parent.selectedIndex;
+
+				// Make sure that it also works with optgroups, see #5701
+				if ( parent.parentNode ) {
+					parent.parentNode.selectedIndex;
+				}
+			}
+			return null;
+		}
+	};
+}
+
+jQuery.each([
+	"tabIndex",
+	"readOnly",
+	"maxLength",
+	"cellSpacing",
+	"cellPadding",
+	"rowSpan",
+	"colSpan",
+	"useMap",
+	"frameBorder",
+	"contentEditable"
+], function() {
+	jQuery.propFix[ this.toLowerCase() ] = this;
+});
+
+// IE6/7 call enctype encoding
+if ( !support.enctype ) {
+	jQuery.propFix.enctype = "encoding";
+}
+
+
+
+
+var rclass = /[\t\r\n\f]/g;
+
+jQuery.fn.extend({
+	addClass: function( value ) {
+		var classes, elem, cur, clazz, j, finalValue,
+			i = 0,
+			len = this.length,
+			proceed = typeof value === "string" && value;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).addClass( value.call( this, j, this.className ) );
+			});
+		}
+
+		if ( proceed ) {
+			// The disjunction here is for better compressibility (see removeClass)
+			classes = ( value || "" ).match( rnotwhite ) || [];
+
+			for ( ; i < len; i++ ) {
+				elem = this[ i ];
+				cur = elem.nodeType === 1 && ( elem.className ?
+					( " " + elem.className + " " ).replace( rclass, " " ) :
+					" "
+				);
+
+				if ( cur ) {
+					j = 0;
+					while ( (clazz = classes[j++]) ) {
+						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+							cur += clazz + " ";
+						}
+					}
+
+					// only assign if different to avoid unneeded rendering.
+					finalValue = jQuery.trim( cur );
+					if ( elem.className !== finalValue ) {
+						elem.className = finalValue;
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	removeClass: function( value ) {
+		var classes, elem, cur, clazz, j, finalValue,
+			i = 0,
+			len = this.length,
+			proceed = arguments.length === 0 || typeof value === "string" && value;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( j ) {
+				jQuery( this ).removeClass( value.call( this, j, this.className ) );
+			});
+		}
+		if ( proceed ) {
+			classes = ( value || "" ).match( rnotwhite ) || [];
+
+			for ( ; i < len; i++ ) {
+				elem = this[ i ];
+				// This expression is here for better compressibility (see addClass)
+				cur = elem.nodeType === 1 && ( elem.className ?
+					( " " + elem.className + " " ).replace( rclass, " " ) :
+					""
+				);
+
+				if ( cur ) {
+					j = 0;
+					while ( (clazz = classes[j++]) ) {
+						// Remove *all* instances
+						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+							cur = cur.replace( " " + clazz + " ", " " );
+						}
+					}
+
+					// only assign if different to avoid unneeded rendering.
+					finalValue = value ? jQuery.trim( cur ) : "";
+					if ( elem.className !== finalValue ) {
+						elem.className = finalValue;
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	toggleClass: function( value, stateVal ) {
+		var type = typeof value;
+
+		if ( typeof stateVal === "boolean" && type === "string" ) {
+			return stateVal ? this.addClass( value ) : this.removeClass( value );
+		}
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each(function( i ) {
+				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+			});
+		}
+
+		return this.each(function() {
+			if ( type === "string" ) {
+				// toggle individual class names
+				var className,
+					i = 0,
+					self = jQuery( this ),
+					classNames = value.match( rnotwhite ) || [];
+
+				while ( (className = classNames[ i++ ]) ) {
+					// check each className given, space separated list
+					if ( self.hasClass( className ) ) {
+						self.removeClass( className );
+					} else {
+						self.addClass( className );
+					}
+				}
+
+			// Toggle whole class name
+			} else if ( type === strundefined || type === "boolean" ) {
+				if ( this.className ) {
+					// store className if set
+					jQuery._data( this, "__className__", this.className );
+				}
+
+				// If the element has a class name or if we're passed "false",
+				// then remove the whole classname (if there was one, the above saved it).
+				// Otherwise bring back whatever was previously saved (if anything),
+				// falling back to the empty string if nothing was stored.
+				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+			}
+		});
+	},
+
+	hasClass: function( selector ) {
+		var className = " " + selector + " ",
+			i = 0,
+			l = this.length;
+		for ( ; i < l; i++ ) {
+			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+});
+
+
+
+
+// Return jQuery for attributes-only inclusion
+
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+	// Handle event binding
+	jQuery.fn[ name ] = function( data, fn ) {
+		return arguments.length > 0 ?
+			this.on( name, null, data, fn ) :
+			this.trigger( name );
+	};
+});
+
+jQuery.fn.extend({
+	hover: function( fnOver, fnOut ) {
+		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+	},
+
+	bind: function( types, data, fn ) {
+		return this.on( types, null, data, fn );
+	},
+	unbind: function( types, fn ) {
+		return this.off( types, null, fn );
+	},
+
+	delegate: function( selector, types, data, fn ) {
+		return this.on( types, selector, data, fn );
+	},
+	undelegate: function( selector, types, fn ) {
+		// ( namespace ) or ( selector, types [, fn] )
+		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+	}
+});
+
+
+var nonce = jQuery.now();
+
+var rquery = (/\?/);
+
+
+
+var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
+
+jQuery.parseJSON = function( data ) {
+	// Attempt to parse using the native JSON parser first
+	if ( window.JSON && window.JSON.parse ) {
+		// Support: Android 2.3
+		// Workaround failure to string-cast null input
+		return window.JSON.parse( data + "" );
+	}
+
+	var requireNonComma,
+		depth = null,
+		str = jQuery.trim( data + "" );
+
+	// Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
+	// after removing valid tokens
+	return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
+
+		// Force termination if we see a misplaced comma
+		if ( requireNonComma && comma ) {
+			depth = 0;
+		}
+
+		// Perform no more replacements after returning to outermost depth
+		if ( depth === 0 ) {
+			return token;
+		}
+
+		// Commas must not follow "[", "{", or ","
+		requireNonComma = open || comma;
+
+		// Determine new depth
+		// array/object open ("[" or "{"): depth += true - false (increment)
+		// array/object close ("]" or "}"): depth += false - true (decrement)
+		// other cases ("," or primitive): depth += true - true (numeric cast)
+		depth += !close - !open;
+
+		// Remove this token
+		return "";
+	}) ) ?
+		( Function( "return " + str ) )() :
+		jQuery.error( "Invalid JSON: " + data );
+};
+
+
+// Cross-browser xml parsing
+jQuery.parseXML = function( data ) {
+	var xml, tmp;
+	if ( !data || typeof data !== "string" ) {
+		return null;
+	}
+	try {
+		if ( window.DOMParser ) { // Standard
+			tmp = new DOMParser();
+			xml = tmp.parseFromString( data, "text/xml" );
+		} else { // IE
+			xml = new ActiveXObject( "Microsoft.XMLDOM" );
+			xml.async = "false";
+			xml.loadXML( data );
+		}
+	} catch( e ) {
+		xml = undefined;
+	}
+	if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+		jQuery.error( "Invalid XML: " + data );
+	}
+	return xml;
+};
+
+
+var
+	// Document location
+	ajaxLocParts,
+	ajaxLocation,
+
+	rhash = /#.*$/,
+	rts = /([?&])_=[^&]*/,
+	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+	// #7653, #8125, #8152: local protocol detection
+	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+	rnoContent = /^(?:GET|HEAD)$/,
+	rprotocol = /^\/\//,
+	rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
+
+	/* Prefilters
+	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+	 * 2) These are called:
+	 *    - BEFORE asking for a transport
+	 *    - AFTER param serialization (s.data is a string if s.processData is true)
+	 * 3) key is the dataType
+	 * 4) the catchall symbol "*" can be used
+	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+	 */
+	prefilters = {},
+
+	/* Transports bindings
+	 * 1) key is the dataType
+	 * 2) the catchall symbol "*" can be used
+	 * 3) selection will start with transport dataType and THEN go to "*" if needed
+	 */
+	transports = {},
+
+	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+	allTypes = "*/".concat("*");
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+	ajaxLocation = location.href;
+} catch( e ) {
+	// Use the href attribute of an A element
+	// since IE will modify it given document.location
+	ajaxLocation = document.createElement( "a" );
+	ajaxLocation.href = "";
+	ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+	// dataTypeExpression is optional and defaults to "*"
+	return function( dataTypeExpression, func ) {
+
+		if ( typeof dataTypeExpression !== "string" ) {
+			func = dataTypeExpression;
+			dataTypeExpression = "*";
+		}
+
+		var dataType,
+			i = 0,
+			dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
+
+		if ( jQuery.isFunction( func ) ) {
+			// For each dataType in the dataTypeExpression
+			while ( (dataType = dataTypes[i++]) ) {
+				// Prepend if requested
+				if ( dataType.charAt( 0 ) === "+" ) {
+					dataType = dataType.slice( 1 ) || "*";
+					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+
+				// Otherwise append
+				} else {
+					(structure[ dataType ] = structure[ dataType ] || []).push( func );
+				}
+			}
+		}
+	};
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+	var inspected = {},
+		seekingTransport = ( structure === transports );
+
+	function inspect( dataType ) {
+		var selected;
+		inspected[ dataType ] = true;
+		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+			if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+				options.dataTypes.unshift( dataTypeOrTransport );
+				inspect( dataTypeOrTransport );
+				return false;
+			} else if ( seekingTransport ) {
+				return !( selected = dataTypeOrTransport );
+			}
+		});
+		return selected;
+	}
+
+	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+	var deep, key,
+		flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+	for ( key in src ) {
+		if ( src[ key ] !== undefined ) {
+			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+		}
+	}
+	if ( deep ) {
+		jQuery.extend( true, target, deep );
+	}
+
+	return target;
+}
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+	var firstDataType, ct, finalDataType, type,
+		contents = s.contents,
+		dataTypes = s.dataTypes;
+
+	// Remove auto dataType and get content-type in the process
+	while ( dataTypes[ 0 ] === "*" ) {
+		dataTypes.shift();
+		if ( ct === undefined ) {
+			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+		}
+	}
+
+	// Check if we're dealing with a known content-type
+	if ( ct ) {
+		for ( type in contents ) {
+			if ( contents[ type ] && contents[ type ].test( ct ) ) {
+				dataTypes.unshift( type );
+				break;
+			}
+		}
+	}
+
+	// Check to see if we have a response for the expected dataType
+	if ( dataTypes[ 0 ] in responses ) {
+		finalDataType = dataTypes[ 0 ];
+	} else {
+		// Try convertible dataTypes
+		for ( type in responses ) {
+			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+				finalDataType = type;
+				break;
+			}
+			if ( !firstDataType ) {
+				firstDataType = type;
+			}
+		}
+		// Or just use first one
+		finalDataType = finalDataType || firstDataType;
+	}
+
+	// If we found a dataType
+	// We add the dataType to the list if needed
+	// and return the corresponding response
+	if ( finalDataType ) {
+		if ( finalDataType !== dataTypes[ 0 ] ) {
+			dataTypes.unshift( finalDataType );
+		}
+		return responses[ finalDataType ];
+	}
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+	var conv2, current, conv, tmp, prev,
+		converters = {},
+		// Work with a copy of dataTypes in case we need to modify it for conversion
+		dataTypes = s.dataTypes.slice();
+
+	// Create converters map with lowercased keys
+	if ( dataTypes[ 1 ] ) {
+		for ( conv in s.converters ) {
+			converters[ conv.toLowerCase() ] = s.converters[ conv ];
+		}
+	}
+
+	current = dataTypes.shift();
+
+	// Convert to each sequential dataType
+	while ( current ) {
+
+		if ( s.responseFields[ current ] ) {
+			jqXHR[ s.responseFields[ current ] ] = response;
+		}
+
+		// Apply the dataFilter if provided
+		if ( !prev && isSuccess && s.dataFilter ) {
+			response = s.dataFilter( response, s.dataType );
+		}
+
+		prev = current;
+		current = dataTypes.shift();
+
+		if ( current ) {
+
+			// There's only work to do if current dataType is non-auto
+			if ( current === "*" ) {
+
+				current = prev;
+
+			// Convert response if prev dataType is non-auto and differs from current
+			} else if ( prev !== "*" && prev !== current ) {
+
+				// Seek a direct converter
+				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+				// If none found, seek a pair
+				if ( !conv ) {
+					for ( conv2 in converters ) {
+
+						// If conv2 outputs current
+						tmp = conv2.split( " " );
+						if ( tmp[ 1 ] === current ) {
+
+							// If prev can be converted to accepted input
+							conv = converters[ prev + " " + tmp[ 0 ] ] ||
+								converters[ "* " + tmp[ 0 ] ];
+							if ( conv ) {
+								// Condense equivalence converters
+								if ( conv === true ) {
+									conv = converters[ conv2 ];
+
+								// Otherwise, insert the intermediate dataType
+								} else if ( converters[ conv2 ] !== true ) {
+									current = tmp[ 0 ];
+									dataTypes.unshift( tmp[ 1 ] );
+								}
+								break;
+							}
+						}
+					}
+				}
+
+				// Apply converter (if not an equivalence)
+				if ( conv !== true ) {
+
+					// Unless errors are allowed to bubble, catch and return them
+					if ( conv && s[ "throws" ] ) {
+						response = conv( response );
+					} else {
+						try {
+							response = conv( response );
+						} catch ( e ) {
+							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return { state: "success", data: response };
+}
+
+jQuery.extend({
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Last-Modified header cache for next request
+	lastModified: {},
+	etag: {},
+
+	ajaxSettings: {
+		url: ajaxLocation,
+		type: "GET",
+		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+		global: true,
+		processData: true,
+		async: true,
+		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+		/*
+		timeout: 0,
+		data: null,
+		dataType: null,
+		username: null,
+		password: null,
+		cache: null,
+		throws: false,
+		traditional: false,
+		headers: {},
+		*/
+
+		accepts: {
+			"*": allTypes,
+			text: "text/plain",
+			html: "text/html",
+			xml: "application/xml, text/xml",
+			json: "application/json, text/javascript"
+		},
+
+		contents: {
+			xml: /xml/,
+			html: /html/,
+			json: /json/
+		},
+
+		responseFields: {
+			xml: "responseXML",
+			text: "responseText",
+			json: "responseJSON"
+		},
+
+		// Data converters
+		// Keys separate source (or catchall "*") and destination types with a single space
+		converters: {
+
+			// Convert anything to text
+			"* text": String,
+
+			// Text to html (true = no transformation)
+			"text html": true,
+
+			// Evaluate text as a json expression
+			"text json": jQuery.parseJSON,
+
+			// Parse text as xml
+			"text xml": jQuery.parseXML
+		},
+
+		// For options that shouldn't be deep extended:
+		// you can add your own custom options here if
+		// and when you create one that shouldn't be
+		// deep extended (see ajaxExtend)
+		flatOptions: {
+			url: true,
+			context: true
+		}
+	},
+
+	// Creates a full fledged settings object into target
+	// with both ajaxSettings and settings fields.
+	// If target is omitted, writes into ajaxSettings.
+	ajaxSetup: function( target, settings ) {
+		return settings ?
+
+			// Building a settings object
+			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+			// Extending ajaxSettings
+			ajaxExtend( jQuery.ajaxSettings, target );
+	},
+
+	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+	ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+	// Main method
+	ajax: function( url, options ) {
+
+		// If url is an object, simulate pre-1.5 signature
+		if ( typeof url === "object" ) {
+			options = url;
+			url = undefined;
+		}
+
+		// Force options to be an object
+		options = options || {};
+
+		var // Cross-domain detection vars
+			parts,
+			// Loop variable
+			i,
+			// URL without anti-cache param
+			cacheURL,
+			// Response headers as string
+			responseHeadersString,
+			// timeout handle
+			timeoutTimer,
+
+			// To know if global events are to be dispatched
+			fireGlobals,
+
+			transport,
+			// Response headers
+			responseHeaders,
+			// Create the final options object
+			s = jQuery.ajaxSetup( {}, options ),
+			// Callbacks context
+			callbackContext = s.context || s,
+			// Context for global events is callbackContext if it is a DOM node or jQuery collection
+			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+				jQuery( callbackContext ) :
+				jQuery.event,
+			// Deferreds
+			deferred = jQuery.Deferred(),
+			completeDeferred = jQuery.Callbacks("once memory"),
+			// Status-dependent callbacks
+			statusCode = s.statusCode || {},
+			// Headers (they are sent all at once)
+			requestHeaders = {},
+			requestHeadersNames = {},
+			// The jqXHR state
+			state = 0,
+			// Default abort message
+			strAbort = "canceled",
+			// Fake xhr
+			jqXHR = {
+				readyState: 0,
+
+				// Builds headers hashtable if needed
+				getResponseHeader: function( key ) {
+					var match;
+					if ( state === 2 ) {
+						if ( !responseHeaders ) {
+							responseHeaders = {};
+							while ( (match = rheaders.exec( responseHeadersString )) ) {
+								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+							}
+						}
+						match = responseHeaders[ key.toLowerCase() ];
+					}
+					return match == null ? null : match;
+				},
+
+				// Raw string
+				getAllResponseHeaders: function() {
+					return state === 2 ? responseHeadersString : null;
+				},
+
+				// Caches the header
+				setRequestHeader: function( name, value ) {
+					var lname = name.toLowerCase();
+					if ( !state ) {
+						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+						requestHeaders[ name ] = value;
+					}
+					return this;
+				},
+
+				// Overrides response content-type header
+				overrideMimeType: function( type ) {
+					if ( !state ) {
+						s.mimeType = type;
+					}
+					return this;
+				},
+
+				// Status-dependent callbacks
+				statusCode: function( map ) {
+					var code;
+					if ( map ) {
+						if ( state < 2 ) {
+							for ( code in map ) {
+								// Lazy-add the new callback in a way that preserves old ones
+								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+							}
+						} else {
+							// Execute the appropriate callbacks
+							jqXHR.always( map[ jqXHR.status ] );
+						}
+					}
+					return this;
+				},
+
+				// Cancel the request
+				abort: function( statusText ) {
+					var finalText = statusText || strAbort;
+					if ( transport ) {
+						transport.abort( finalText );
+					}
+					done( 0, finalText );
+					return this;
+				}
+			};
+
+		// Attach deferreds
+		deferred.promise( jqXHR ).complete = completeDeferred.add;
+		jqXHR.success = jqXHR.done;
+		jqXHR.error = jqXHR.fail;
+
+		// Remove hash character (#7531: and string promotion)
+		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+		// Handle falsy url in the settings object (#10093: consistency with old signature)
+		// We also use the url parameter if available
+		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+		// Alias method option to type as per ticket #12004
+		s.type = options.method || options.type || s.method || s.type;
+
+		// Extract dataTypes list
+		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
+
+		// A cross-domain request is in order when we have a protocol:host:port mismatch
+		if ( s.crossDomain == null ) {
+			parts = rurl.exec( s.url.toLowerCase() );
+			s.crossDomain = !!( parts &&
+				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
+						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
+			);
+		}
+
+		// Convert data if not already a string
+		if ( s.data && s.processData && typeof s.data !== "string" ) {
+			s.data = jQuery.param( s.data, s.traditional );
+		}
+
+		// Apply prefilters
+		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+		// If request was aborted inside a prefilter, stop there
+		if ( state === 2 ) {
+			return jqXHR;
+		}
+
+		// We can fire global events as of now if asked to
+		fireGlobals = s.global;
+
+		// Watch for a new set of requests
+		if ( fireGlobals && jQuery.active++ === 0 ) {
+			jQuery.event.trigger("ajaxStart");
+		}
+
+		// Uppercase the type
+		s.type = s.type.toUpperCase();
+
+		// Determine if request has content
+		s.hasContent = !rnoContent.test( s.type );
+
+		// Save the URL in case we're toying with the If-Modified-Since
+		// and/or If-None-Match header later on
+		cacheURL = s.url;
+
+		// More options handling for requests with no content
+		if ( !s.hasContent ) {
+
+			// If data is available, append data to url
+			if ( s.data ) {
+				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+				// #9682: remove data so that it's not used in an eventual retry
+				delete s.data;
+			}
+
+			// Add anti-cache in url if needed
+			if ( s.cache === false ) {
+				s.url = rts.test( cacheURL ) ?
+
+					// If there is already a '_' parameter, set its value
+					cacheURL.replace( rts, "$1_=" + nonce++ ) :
+
+					// Otherwise add one to the end
+					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
+			}
+		}
+
+		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+		if ( s.ifModified ) {
+			if ( jQuery.lastModified[ cacheURL ] ) {
+				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+			}
+			if ( jQuery.etag[ cacheURL ] ) {
+				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+			}
+		}
+
+		// Set the correct header, if data is being sent
+		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+			jqXHR.setRequestHeader( "Content-Type", s.contentType );
+		}
+
+		// Set the Accepts header for the server, depending on the dataType
+		jqXHR.setRequestHeader(
+			"Accept",
+			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+				s.accepts[ "*" ]
+		);
+
+		// Check for headers option
+		for ( i in s.headers ) {
+			jqXHR.setRequestHeader( i, s.headers[ i ] );
+		}
+
+		// Allow custom headers/mimetypes and early abort
+		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+			// Abort if not done already and return
+			return jqXHR.abort();
+		}
+
+		// aborting is no longer a cancellation
+		strAbort = "abort";
+
+		// Install callbacks on deferreds
+		for ( i in { success: 1, error: 1, complete: 1 } ) {
+			jqXHR[ i ]( s[ i ] );
+		}
+
+		// Get transport
+		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+		// If no transport, we auto-abort
+		if ( !transport ) {
+			done( -1, "No Transport" );
+		} else {
+			jqXHR.readyState = 1;
+
+			// Send global event
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+			}
+			// Timeout
+			if ( s.async && s.timeout > 0 ) {
+				timeoutTimer = setTimeout(function() {
+					jqXHR.abort("timeout");
+				}, s.timeout );
+			}
+
+			try {
+				state = 1;
+				transport.send( requestHeaders, done );
+			} catch ( e ) {
+				// Propagate exception as error if not done
+				if ( state < 2 ) {
+					done( -1, e );
+				// Simply rethrow otherwise
+				} else {
+					throw e;
+				}
+			}
+		}
+
+		// Callback for when everything is done
+		function done( status, nativeStatusText, responses, headers ) {
+			var isSuccess, success, error, response, modified,
+				statusText = nativeStatusText;
+
+			// Called once
+			if ( state === 2 ) {
+				return;
+			}
+
+			// State is "done" now
+			state = 2;
+
+			// Clear timeout if it exists
+			if ( timeoutTimer ) {
+				clearTimeout( timeoutTimer );
+			}
+
+			// Dereference transport for early garbage collection
+			// (no matter how long the jqXHR object will be used)
+			transport = undefined;
+
+			// Cache response headers
+			responseHeadersString = headers || "";
+
+			// Set readyState
+			jqXHR.readyState = status > 0 ? 4 : 0;
+
+			// Determine if successful
+			isSuccess = status >= 200 && status < 300 || status === 304;
+
+			// Get response data
+			if ( responses ) {
+				response = ajaxHandleResponses( s, jqXHR, responses );
+			}
+
+			// Convert no matter what (that way responseXXX fields are always set)
+			response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+			// If successful, handle type chaining
+			if ( isSuccess ) {
+
+				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+				if ( s.ifModified ) {
+					modified = jqXHR.getResponseHeader("Last-Modified");
+					if ( modified ) {
+						jQuery.lastModified[ cacheURL ] = modified;
+					}
+					modified = jqXHR.getResponseHeader("etag");
+					if ( modified ) {
+						jQuery.etag[ cacheURL ] = modified;
+					}
+				}
+
+				// if no content
+				if ( status === 204 || s.type === "HEAD" ) {
+					statusText = "nocontent";
+
+				// if not modified
+				} else if ( status === 304 ) {
+					statusText = "notmodified";
+
+				// If we have data, let's convert it
+				} else {
+					statusText = response.state;
+					success = response.data;
+					error = response.error;
+					isSuccess = !error;
+				}
+			} else {
+				// We extract error from statusText
+				// then normalize statusText and status for non-aborts
+				error = statusText;
+				if ( status || !statusText ) {
+					statusText = "error";
+					if ( status < 0 ) {
+						status = 0;
+					}
+				}
+			}
+
+			// Set data for the fake xhr object
+			jqXHR.status = status;
+			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+			// Success/Error
+			if ( isSuccess ) {
+				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+			} else {
+				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+			}
+
+			// Status-dependent callbacks
+			jqXHR.statusCode( statusCode );
+			statusCode = undefined;
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+					[ jqXHR, s, isSuccess ? success : error ] );
+			}
+
+			// Complete
+			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+				// Handle the global AJAX counter
+				if ( !( --jQuery.active ) ) {
+					jQuery.event.trigger("ajaxStop");
+				}
+			}
+		}
+
+		return jqXHR;
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get( url, data, callback, "json" );
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get( url, undefined, callback, "script" );
+	}
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+	jQuery[ method ] = function( url, data, callback, type ) {
+		// shift arguments if data argument was omitted
+		if ( jQuery.isFunction( data ) ) {
+			type = type || callback;
+			callback = data;
+			data = undefined;
+		}
+
+		return jQuery.ajax({
+			url: url,
+			type: method,
+			dataType: type,
+			data: data,
+			success: callback
+		});
+	};
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
+	jQuery.fn[ type ] = function( fn ) {
+		return this.on( type, fn );
+	};
+});
+
+
+jQuery._evalUrl = function( url ) {
+	return jQuery.ajax({
+		url: url,
+		type: "GET",
+		dataType: "script",
+		async: false,
+		global: false,
+		"throws": true
+	});
+};
+
+
+jQuery.fn.extend({
+	wrapAll: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapAll( html.call(this, i) );
+			});
+		}
+
+		if ( this[0] ) {
+			// The elements to wrap the target around
+			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+			if ( this[0].parentNode ) {
+				wrap.insertBefore( this[0] );
+			}
+
+			wrap.map(function() {
+				var elem = this;
+
+				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+					elem = elem.firstChild;
+				}
+
+				return elem;
+			}).append( this );
+		}
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each(function(i) {
+				jQuery(this).wrapInner( html.call(this, i) );
+			});
+		}
+
+		return this.each(function() {
+			var self = jQuery( this ),
+				contents = self.contents();
+
+			if ( contents.length ) {
+				contents.wrapAll( html );
+
+			} else {
+				self.append( html );
+			}
+		});
+	},
+
+	wrap: function( html ) {
+		var isFunction = jQuery.isFunction( html );
+
+		return this.each(function(i) {
+			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+		});
+	},
+
+	unwrap: function() {
+		return this.parent().each(function() {
+			if ( !jQuery.nodeName( this, "body" ) ) {
+				jQuery( this ).replaceWith( this.childNodes );
+			}
+		}).end();
+	}
+});
+
+
+jQuery.expr.filters.hidden = function( elem ) {
+	// Support: Opera <= 12.12
+	// Opera reports offsetWidths and offsetHeights less than zero on some elements
+	return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
+		(!support.reliableHiddenOffsets() &&
+			((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+};
+
+jQuery.expr.filters.visible = function( elem ) {
+	return !jQuery.expr.filters.hidden( elem );
+};
+
+
+
+
+var r20 = /%20/g,
+	rbracket = /\[\]$/,
+	rCRLF = /\r?\n/g,
+	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+	rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+function buildParams( prefix, obj, traditional, add ) {
+	var name;
+
+	if ( jQuery.isArray( obj ) ) {
+		// Serialize array item.
+		jQuery.each( obj, function( i, v ) {
+			if ( traditional || rbracket.test( prefix ) ) {
+				// Treat each array item as a scalar.
+				add( prefix, v );
+
+			} else {
+				// Item is non-scalar (array or object), encode its numeric index.
+				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+			}
+		});
+
+	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
+		// Serialize object item.
+		for ( name in obj ) {
+			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+		}
+
+	} else {
+		// Serialize scalar item.
+		add( prefix, obj );
+	}
+}
+
+// Serialize an array of form elements or a set of
+// key/values into a query string
+jQuery.param = function( a, traditional ) {
+	var prefix,
+		s = [],
+		add = function( key, value ) {
+			// If value is a function, invoke it and return its value
+			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+		};
+
+	// Set traditional to true for jQuery <= 1.3.2 behavior.
+	if ( traditional === undefined ) {
+		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+	}
+
+	// If an array was passed in, assume that it is an array of form elements.
+	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+		// Serialize the form elements
+		jQuery.each( a, function() {
+			add( this.name, this.value );
+		});
+
+	} else {
+		// If traditional, encode the "old" way (the way 1.3.2 or older
+		// did it), otherwise encode params recursively.
+		for ( prefix in a ) {
+			buildParams( prefix, a[ prefix ], traditional, add );
+		}
+	}
+
+	// Return the resulting serialization
+	return s.join( "&" ).replace( r20, "+" );
+};
+
+jQuery.fn.extend({
+	serialize: function() {
+		return jQuery.param( this.serializeArray() );
+	},
+	serializeArray: function() {
+		return this.map(function() {
+			// Can add propHook for "elements" to filter or add form elements
+			var elements = jQuery.prop( this, "elements" );
+			return elements ? jQuery.makeArray( elements ) : this;
+		})
+		.filter(function() {
+			var type = this.type;
+			// Use .is(":disabled") so that fieldset[disabled] works
+			return this.name && !jQuery( this ).is( ":disabled" ) &&
+				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+				( this.checked || !rcheckableType.test( type ) );
+		})
+		.map(function( i, elem ) {
+			var val = jQuery( this ).val();
+
+			return val == null ?
+				null :
+				jQuery.isArray( val ) ?
+					jQuery.map( val, function( val ) {
+						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+					}) :
+					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+		}).get();
+	}
+});
+
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
+	// Support: IE6+
+	function() {
+
+		// XHR cannot access local files, always use ActiveX for that case
+		return !this.isLocal &&
+
+			// Support: IE7-8
+			// oldIE XHR does not support non-RFC2616 methods (#13240)
+			// See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
+			// and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
+			// Although this check for six methods instead of eight
+			// since IE also does not support "trace" and "connect"
+			/^(get|post|head|put|delete|options)$/i.test( this.type ) &&
+
+			createStandardXHR() || createActiveXHR();
+	} :
+	// For all other browsers, use the standard XMLHttpRequest object
+	createStandardXHR;
+
+var xhrId = 0,
+	xhrCallbacks = {},
+	xhrSupported = jQuery.ajaxSettings.xhr();
+
+// Support: IE<10
+// Open requests must be manually aborted on unload (#5280)
+if ( window.ActiveXObject ) {
+	jQuery( window ).on( "unload", function() {
+		for ( var key in xhrCallbacks ) {
+			xhrCallbacks[ key ]( undefined, true );
+		}
+	});
+}
+
+// Determine support properties
+support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+xhrSupported = support.ajax = !!xhrSupported;
+
+// Create transport if the browser can provide an xhr
+if ( xhrSupported ) {
+
+	jQuery.ajaxTransport(function( options ) {
+		// Cross domain only allowed if supported through XMLHttpRequest
+		if ( !options.crossDomain || support.cors ) {
+
+			var callback;
+
+			return {
+				send: function( headers, complete ) {
+					var i,
+						xhr = options.xhr(),
+						id = ++xhrId;
+
+					// Open the socket
+					xhr.open( options.type, options.url, options.async, options.username, options.password );
+
+					// Apply custom fields if provided
+					if ( options.xhrFields ) {
+						for ( i in options.xhrFields ) {
+							xhr[ i ] = options.xhrFields[ i ];
+						}
+					}
+
+					// Override mime type if needed
+					if ( options.mimeType && xhr.overrideMimeType ) {
+						xhr.overrideMimeType( options.mimeType );
+					}
+
+					// X-Requested-With header
+					// For cross-domain requests, seeing as conditions for a preflight are
+					// akin to a jigsaw puzzle, we simply never set it to be sure.
+					// (it can always be set on a per-request basis or even using ajaxSetup)
+					// For same-domain requests, won't change header if already provided.
+					if ( !options.crossDomain && !headers["X-Requested-With"] ) {
+						headers["X-Requested-With"] = "XMLHttpRequest";
+					}
+
+					// Set headers
+					for ( i in headers ) {
+						// Support: IE<9
+						// IE's ActiveXObject throws a 'Type Mismatch' exception when setting
+						// request header to a null-value.
+						//
+						// To keep consistent with other XHR implementations, cast the value
+						// to string and ignore `undefined`.
+						if ( headers[ i ] !== undefined ) {
+							xhr.setRequestHeader( i, headers[ i ] + "" );
+						}
+					}
+
+					// Do send the request
+					// This may raise an exception which is actually
+					// handled in jQuery.ajax (so no try/catch here)
+					xhr.send( ( options.hasContent && options.data ) || null );
+
+					// Listener
+					callback = function( _, isAbort ) {
+						var status, statusText, responses;
+
+						// Was never called and is aborted or complete
+						if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+							// Clean up
+							delete xhrCallbacks[ id ];
+							callback = undefined;
+							xhr.onreadystatechange = jQuery.noop;
+
+							// Abort manually if needed
+							if ( isAbort ) {
+								if ( xhr.readyState !== 4 ) {
+									xhr.abort();
+								}
+							} else {
+								responses = {};
+								status = xhr.status;
+
+								// Support: IE<10
+								// Accessing binary-data responseText throws an exception
+								// (#11426)
+								if ( typeof xhr.responseText === "string" ) {
+									responses.text = xhr.responseText;
+								}
+
+								// Firefox throws an exception when accessing
+								// statusText for faulty cross-domain requests
+								try {
+									statusText = xhr.statusText;
+								} catch( e ) {
+									// We normalize with Webkit giving an empty statusText
+									statusText = "";
+								}
+
+								// Filter status for non standard behaviors
+
+								// If the request is local and we have data: assume a success
+								// (success with no data won't get notified, that's the best we
+								// can do given current implementations)
+								if ( !status && options.isLocal && !options.crossDomain ) {
+									status = responses.text ? 200 : 404;
+								// IE - #1450: sometimes returns 1223 when it should be 204
+								} else if ( status === 1223 ) {
+									status = 204;
+								}
+							}
+						}
+
+						// Call complete if needed
+						if ( responses ) {
+							complete( status, statusText, responses, xhr.getAllResponseHeaders() );
+						}
+					};
+
+					if ( !options.async ) {
+						// if we're in sync mode we fire the callback
+						callback();
+					} else if ( xhr.readyState === 4 ) {
+						// (IE6 & IE7) if it's in cache and has been
+						// retrieved directly we need to fire the callback
+						setTimeout( callback );
+					} else {
+						// Add to the list of active xhr callbacks
+						xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
+					}
+				},
+
+				abort: function() {
+					if ( callback ) {
+						callback( undefined, true );
+					}
+				}
+			};
+		}
+	});
+}
+
+// Functions to create xhrs
+function createStandardXHR() {
+	try {
+		return new window.XMLHttpRequest();
+	} catch( e ) {}
+}
+
+function createActiveXHR() {
+	try {
+		return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+	} catch( e ) {}
+}
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup({
+	accepts: {
+		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+	},
+	contents: {
+		script: /(?:java|ecma)script/
+	},
+	converters: {
+		"text script": function( text ) {
+			jQuery.globalEval( text );
+			return text;
+		}
+	}
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+	if ( s.cache === undefined ) {
+		s.cache = false;
+	}
+	if ( s.crossDomain ) {
+		s.type = "GET";
+		s.global = false;
+	}
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+	// This transport only deals with cross domain requests
+	if ( s.crossDomain ) {
+
+		var script,
+			head = document.head || jQuery("head")[0] || document.documentElement;
+
+		return {
+
+			send: function( _, callback ) {
+
+				script = document.createElement("script");
+
+				script.async = true;
+
+				if ( s.scriptCharset ) {
+					script.charset = s.scriptCharset;
+				}
+
+				script.src = s.url;
+
+				// Attach handlers for all browsers
+				script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+					if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+						// Handle memory leak in IE
+						script.onload = script.onreadystatechange = null;
+
+						// Remove the script
+						if ( script.parentNode ) {
+							script.parentNode.removeChild( script );
+						}
+
+						// Dereference the script
+						script = null;
+
+						// Callback if not abort
+						if ( !isAbort ) {
+							callback( 200, "success" );
+						}
+					}
+				};
+
+				// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
+				// Use native DOM manipulation to avoid our domManip AJAX trickery
+				head.insertBefore( script, head.firstChild );
+			},
+
+			abort: function() {
+				if ( script ) {
+					script.onload( undefined, true );
+				}
+			}
+		};
+	}
+});
+
+
+
+
+var oldCallbacks = [],
+	rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+	jsonp: "callback",
+	jsonpCallback: function() {
+		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+		this[ callback ] = true;
+		return callback;
+	}
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+	var callbackName, overwritten, responseContainer,
+		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+			"url" :
+			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+		);
+
+	// Handle iff the expected data type is "jsonp" or we have a parameter to set
+	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+		// Get callback name, remembering preexisting value associated with it
+		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+			s.jsonpCallback() :
+			s.jsonpCallback;
+
+		// Insert callback into url or form data
+		if ( jsonProp ) {
+			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+		} else if ( s.jsonp !== false ) {
+			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+		}
+
+		// Use data converter to retrieve json after script execution
+		s.converters["script json"] = function() {
+			if ( !responseContainer ) {
+				jQuery.error( callbackName + " was not called" );
+			}
+			return responseContainer[ 0 ];
+		};
+
+		// force json dataType
+		s.dataTypes[ 0 ] = "json";
+
+		// Install callback
+		overwritten = window[ callbackName ];
+		window[ callbackName ] = function() {
+			responseContainer = arguments;
+		};
+
+		// Clean-up function (fires after converters)
+		jqXHR.always(function() {
+			// Restore preexisting value
+			window[ callbackName ] = overwritten;
+
+			// Save back as free
+			if ( s[ callbackName ] ) {
+				// make sure that re-using the options doesn't screw things around
+				s.jsonpCallback = originalSettings.jsonpCallback;
+
+				// save the callback name for future use
+				oldCallbacks.push( callbackName );
+			}
+
+			// Call if it was a function and we have a response
+			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+				overwritten( responseContainer[ 0 ] );
+			}
+
+			responseContainer = overwritten = undefined;
+		});
+
+		// Delegate to script
+		return "script";
+	}
+});
+
+
+
+
+// data: string of html
+// context (optional): If specified, the fragment will be created in this context, defaults to document
+// keepScripts (optional): If true, will include scripts passed in the html string
+jQuery.parseHTML = function( data, context, keepScripts ) {
+	if ( !data || typeof data !== "string" ) {
+		return null;
+	}
+	if ( typeof context === "boolean" ) {
+		keepScripts = context;
+		context = false;
+	}
+	context = context || document;
+
+	var parsed = rsingleTag.exec( data ),
+		scripts = !keepScripts && [];
+
+	// Single tag
+	if ( parsed ) {
+		return [ context.createElement( parsed[1] ) ];
+	}
+
+	parsed = jQuery.buildFragment( [ data ], context, scripts );
+
+	if ( scripts && scripts.length ) {
+		jQuery( scripts ).remove();
+	}
+
+	return jQuery.merge( [], parsed.childNodes );
+};
+
+
+// Keep a copy of the old load method
+var _load = jQuery.fn.load;
+
+/**
+ * Load a url into a page
+ */
+jQuery.fn.load = function( url, params, callback ) {
+	if ( typeof url !== "string" && _load ) {
+		return _load.apply( this, arguments );
+	}
+
+	var selector, response, type,
+		self = this,
+		off = url.indexOf(" ");
+
+	if ( off >= 0 ) {
+		selector = jQuery.trim( url.slice( off, url.length ) );
+		url = url.slice( 0, off );
+	}
+
+	// If it's a function
+	if ( jQuery.isFunction( params ) ) {
+
+		// We assume that it's the callback
+		callback = params;
+		params = undefined;
+
+	// Otherwise, build a param string
+	} else if ( params && typeof params === "object" ) {
+		type = "POST";
+	}
+
+	// If we have elements to modify, make the request
+	if ( self.length > 0 ) {
+		jQuery.ajax({
+			url: url,
+
+			// if "type" variable is undefined, then "GET" method will be used
+			type: type,
+			dataType: "html",
+			data: params
+		}).done(function( responseText ) {
+
+			// Save response for use in complete callback
+			response = arguments;
+
+			self.html( selector ?
+
+				// If a selector was specified, locate the right elements in a dummy div
+				// Exclude scripts to avoid IE 'Permission Denied' errors
+				jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+				// Otherwise use the full result
+				responseText );
+
+		}).complete( callback && function( jqXHR, status ) {
+			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+		});
+	}
+
+	return this;
+};
+
+
+
+
+jQuery.expr.filters.animated = function( elem ) {
+	return jQuery.grep(jQuery.timers, function( fn ) {
+		return elem === fn.elem;
+	}).length;
+};
+
+
+
+
+
+var docElem = window.document.documentElement;
+
+/**
+ * Gets a window from an element
+ */
+function getWindow( elem ) {
+	return jQuery.isWindow( elem ) ?
+		elem :
+		elem.nodeType === 9 ?
+			elem.defaultView || elem.parentWindow :
+			false;
+}
+
+jQuery.offset = {
+	setOffset: function( elem, options, i ) {
+		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+			position = jQuery.css( elem, "position" ),
+			curElem = jQuery( elem ),
+			props = {};
+
+		// set position first, in-case top/left are set even on static elem
+		if ( position === "static" ) {
+			elem.style.position = "relative";
+		}
+
+		curOffset = curElem.offset();
+		curCSSTop = jQuery.css( elem, "top" );
+		curCSSLeft = jQuery.css( elem, "left" );
+		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+			jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
+
+		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+		if ( calculatePosition ) {
+			curPosition = curElem.position();
+			curTop = curPosition.top;
+			curLeft = curPosition.left;
+		} else {
+			curTop = parseFloat( curCSSTop ) || 0;
+			curLeft = parseFloat( curCSSLeft ) || 0;
+		}
+
+		if ( jQuery.isFunction( options ) ) {
+			options = options.call( elem, i, curOffset );
+		}
+
+		if ( options.top != null ) {
+			props.top = ( options.top - curOffset.top ) + curTop;
+		}
+		if ( options.left != null ) {
+			props.left = ( options.left - curOffset.left ) + curLeft;
+		}
+
+		if ( "using" in options ) {
+			options.using.call( elem, props );
+		} else {
+			curElem.css( props );
+		}
+	}
+};
+
+jQuery.fn.extend({
+	offset: function( options ) {
+		if ( arguments.length ) {
+			return options === undefined ?
+				this :
+				this.each(function( i ) {
+					jQuery.offset.setOffset( this, options, i );
+				});
+		}
+
+		var docElem, win,
+			box = { top: 0, left: 0 },
+			elem = this[ 0 ],
+			doc = elem && elem.ownerDocument;
+
+		if ( !doc ) {
+			return;
+		}
+
+		docElem = doc.documentElement;
+
+		// Make sure it's not a disconnected DOM node
+		if ( !jQuery.contains( docElem, elem ) ) {
+			return box;
+		}
+
+		// If we don't have gBCR, just use 0,0 rather than error
+		// BlackBerry 5, iOS 3 (original iPhone)
+		if ( typeof elem.getBoundingClientRect !== strundefined ) {
+			box = elem.getBoundingClientRect();
+		}
+		win = getWindow( doc );
+		return {
+			top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
+			left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+		};
+	},
+
+	position: function() {
+		if ( !this[ 0 ] ) {
+			return;
+		}
+
+		var offsetParent, offset,
+			parentOffset = { top: 0, left: 0 },
+			elem = this[ 0 ];
+
+		// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
+		if ( jQuery.css( elem, "position" ) === "fixed" ) {
+			// we assume that getBoundingClientRect is available when computed position is fixed
+			offset = elem.getBoundingClientRect();
+		} else {
+			// Get *real* offsetParent
+			offsetParent = this.offsetParent();
+
+			// Get correct offsets
+			offset = this.offset();
+			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+				parentOffset = offsetParent.offset();
+			}
+
+			// Add offsetParent borders
+			parentOffset.top  += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+		}
+
+		// Subtract parent offsets and element margins
+		// note: when an element has margin: auto the offsetLeft and marginLeft
+		// are the same in Safari causing offset.left to incorrectly be 0
+		return {
+			top:  offset.top  - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
+		};
+	},
+
+	offsetParent: function() {
+		return this.map(function() {
+			var offsetParent = this.offsetParent || docElem;
+
+			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
+				offsetParent = offsetParent.offsetParent;
+			}
+			return offsetParent || docElem;
+		});
+	}
+});
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+	var top = /Y/.test( prop );
+
+	jQuery.fn[ method ] = function( val ) {
+		return access( this, function( elem, method, val ) {
+			var win = getWindow( elem );
+
+			if ( val === undefined ) {
+				return win ? (prop in win) ? win[ prop ] :
+					win.document.documentElement[ method ] :
+					elem[ method ];
+			}
+
+			if ( win ) {
+				win.scrollTo(
+					!top ? val : jQuery( win ).scrollLeft(),
+					top ? val : jQuery( win ).scrollTop()
+				);
+
+			} else {
+				elem[ method ] = val;
+			}
+		}, method, val, arguments.length, null );
+	};
+});
+
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// getComputedStyle returns percent when specified for top/left/bottom/right
+// rather than make the css module depend on the offset module, we just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+		function( elem, computed ) {
+			if ( computed ) {
+				computed = curCSS( elem, prop );
+				// if curCSS returns percentage, fallback to offset
+				return rnumnonpx.test( computed ) ?
+					jQuery( elem ).position()[ prop ] + "px" :
+					computed;
+			}
+		}
+	);
+});
+
+
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+		// margin is only for outerHeight, outerWidth
+		jQuery.fn[ funcName ] = function( margin, value ) {
+			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+			return access( this, function( elem, type, value ) {
+				var doc;
+
+				if ( jQuery.isWindow( elem ) ) {
+					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+					// isn't a whole lot we can do. See pull request at this URL for discussion:
+					// https://github.com/jquery/jquery/pull/764
+					return elem.document.documentElement[ "client" + name ];
+				}
+
+				// Get document width or height
+				if ( elem.nodeType === 9 ) {
+					doc = elem.documentElement;
+
+					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+					// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+					return Math.max(
+						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+						elem.body[ "offset" + name ], doc[ "offset" + name ],
+						doc[ "client" + name ]
+					);
+				}
+
+				return value === undefined ?
+					// Get width or height on the element, requesting but not forcing parseFloat
+					jQuery.css( elem, type, extra ) :
+
+					// Set width or height on the element
+					jQuery.style( elem, type, value, extra );
+			}, type, chainable ? margin : undefined, chainable, null );
+		};
+	});
+});
+
+
+// The number of elements contained in the matched element set
+jQuery.fn.size = function() {
+	return this.length;
+};
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+
+
+
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( typeof define === "function" && define.amd ) {
+	define( "jquery", [], function() {
+		return jQuery;
+	});
+}
+
+
+
+
+var
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+
+	// Map over the $ in case of overwrite
+	_$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+	if ( window.$ === jQuery ) {
+		window.$ = _$;
+	}
+
+	if ( deep && window.jQuery === jQuery ) {
+		window.jQuery = _jQuery;
+	}
+
+	return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in
+// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( typeof noGlobal === strundefined ) {
+	window.jQuery = window.$ = jQuery;
+}
+
+
+
+
+return jQuery;
+
+}));
+/**
+ * Copyright (c) 2007-2014 Ariel Flesler - aflesler<a>gmail<d>com | http://flesler.blogspot.com
+ * Licensed under MIT
+ * @author Ariel Flesler
+ * @version 1.4.13
+ */
+;(function(k){'use strict';k(['jquery'],function($){var j=$.scrollTo=function(a,b,c){return $(window).scrollTo(a,b,c)};j.defaults={axis:'xy',duration:parseFloat($.fn.jquery)>=1.3?0:1,limit:!0};j.window=function(a){return $(window)._scrollable()};$.fn._scrollable=function(){return this.map(function(){var a=this,isWin=!a.nodeName||$.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!isWin)return a;var b=(a.contentWindow||a).document||a.ownerDocument||a;return/webkit/i.test(navigator.userAgent)||b.compatMode=='BackCompat'?b.body:b.documentElement})};$.fn.scrollTo=function(f,g,h){if(typeof g=='object'){h=g;g=0}if(typeof h=='function')h={onAfter:h};if(f=='max')f=9e9;h=$.extend({},j.defaults,h);g=g||h.duration;h.queue=h.queue&&h.axis.length>1;if(h.queue)g/=2;h.offset=both(h.offset);h.over=both(h.over);return this._scrollable().each(function(){if(f==null)return;var d=this,$elem=$(d),targ=f,toff,attr={},win=$elem.is('html,body');switch(typeof targ){case'number':case'string':if(/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)){targ=both(targ);break}targ=win?$(targ):$(targ,this);if(!targ.length)return;case'object':if(targ.is||targ.style)toff=(targ=$(targ)).offset()}var e=$.isFunction(h.offset)&&h.offset(d,targ)||h.offset;$.each(h.axis.split(''),function(i,a){var b=a=='x'?'Left':'Top',pos=b.toLowerCase(),key='scroll'+b,old=d[key],max=j.max(d,a);if(toff){attr[key]=toff[pos]+(win?0:old-$elem.offset()[pos]);if(h.margin){attr[key]-=parseInt(targ.css('margin'+b))||0;attr[key]-=parseInt(targ.css('border'+b+'Width'))||0}attr[key]+=e[pos]||0;if(h.over[pos])attr[key]+=targ[a=='x'?'width':'height']()*h.over[pos]}else{var c=targ[pos];attr[key]=c.slice&&c.slice(-1)=='%'?parseFloat(c)/100*max:c}if(h.limit&&/^\d+$/.test(attr[key]))attr[key]=attr[key]<=0?0:Math.min(attr[key],max);if(!i&&h.queue){if(old!=attr[key])animate(h.onAfterFirst);delete attr[key]}});animate(h.onAfter);function animate(a){$elem.animate(attr,g,h.easing,a&&function(){a.call(this,targ,h)})}}).end()};j.max=function(a,b){var c=b=='x'?'Width':'Height',scroll='scroll'+c;if(!$(a).is('html,body'))return a[scroll]-$(a)[c.toLowerCase()]();var d='client'+c,html=a.ownerDocument.documentElement,body=a.ownerDocument.body;return Math.max(html[scroll],body[scroll])-Math.min(html[d],body[d])};function both(a){return $.isFunction(a)||typeof a=='object'?a:{top:a,left:a}}return j})}(typeof define==='function'&&define.amd?define:function(a,b){if(typeof module!=='undefined'&&module.exports){module.exports=b(require('jquery'))}else{b(jQuery)}}));$(function() {
+  var className = 'active';
+  var topMenu = $("#toc");
+  var menuItems = topMenu.find("a");
+  var scrollItems = menuItems.map(function() {
+    var item = $($(this).attr("href"));
+    if (item.length) { return item; }
+  });
+
+  var lastTocScroll = 0;
+  var lastTocScrollHuman = true;
+
+  // Scroll an element so that it becomes visible
+  // unless the user recently scrolled the toc div.
+  // If the user scrolls to the top or the bottom of an overflow:scroll
+  // element, the browser will scroll the main area, which will cause
+  // another element to be activated (and scrolled to) in the toc pane.
+  function scrollToView(pane, element) {
+    if (new Date().getTime() - lastTocScroll < 2000) return;
+
+    var y = element.position().top;
+    if (y < 0 || y > pane.height()) {
+      lastTocScrollHuman = false;
+      pane.scrollTo(element, { axis: 'y' });
+    }
+  }
+
+  topMenu.scroll(function() {
+    if (lastTocScrollHuman) {
+      lastTocScroll = new Date().getTime();
+    } else {
+      lastTocScrollHuman = true;
+    }
+  });
+
+  $(window).scroll(function() {
+    // Get container scroll position
+   var fromTop = $(this).scrollTop() + 40;
+
+   // Get id of current scroll item
+   var cur = scrollItems.map(function(){
+     if ($(this).offset().top < fromTop)
+       return this;
+   });
+   // Get the id of the current element
+   cur = cur[cur.length-1];
+   var id = cur && cur.length ? cur[0].id : "";
+   $('#toc a').removeClass(className);
+   var item = menuItems.filter("[href=#"+id+"]");
+   if (item.length != 0) {
+     item.addClass(className);
+     scrollToView(topMenu, item);
+   }
+ });
+});
+// Borrowed from http://asciidoctor.org/javascripts/view-result.js
+function insert_unhide_links() {
+  $('.example').each(function(idx, node) {
+    var example_block = $(node);
+    var view_example_link = $('<p><a class="view-example" href="#">Show example</a></p>');
+    example_block.before(view_example_link);
+    example_block.toggle();
+    view_example_link.on('click', function(event) {
+      event.preventDefault();
+      example_block.toggle();
+    });
+  });
+  $('.definition').each(function(idx, node) {
+    var definition_block = $(node);
+    var view_definition_link = $('<p><a class="view-definition" href="#">Show definition</a></p>');
+    definition_block.before(view_definition_link);
+    definition_block.toggle();
+    view_definition_link.on('click', function(event) {
+      event.preventDefault();
+      definition_block.toggle();
+    });
+  });
+}
+
+$(insert_unhide_links);
+</script>
+</head>
+<body class="book toc2 toc-left">
+<div id="header">
+<h1>Multi-Protocol Networking Library</h1>
+<div id="toc" class="toc2">
+<div id="toctitle">Table of Contents</div>
+<ul class="sectlevel1">
+<li><a href="#_usage_example">Usage Example</a></li>
+<li><a href="#_design_concept">Design Concept</a>
+<ul class="sectlevel2">
+<li><a href="#_memory_buffers">Memory buffers</a></li>
+<li><a href="#_event_handler_function">Event handler function</a></li>
+<li><a href="#_events">Events</a></li>
+<li><a href="#_connection_flags">Connection flags</a></li>
+</ul>
+</li>
+<li><a href="#_build_options">Build Options</a>
+<ul class="sectlevel2">
+<li><a href="#_enabling_flags">Enabling flags</a></li>
+<li><a href="#_disabling_flags">Disabling flags</a></li>
+<li><a href="#_platform_specific">Platform specific</a></li>
+<li><a href="#_tunables">Tunables</a></li>
+</ul>
+</li>
+<li><a href="#_api_reference">API Reference</a>
+<ul class="sectlevel2">
+<li><a href="#_memory_buffers_2">Memory Buffers</a></li>
+<li><a href="#_core_tcp_udp_ssl">Core: TCP/UDP/SSL</a></li>
+<li><a href="#_http_websocket">HTTP + Websocket</a></li>
+<li><a href="#_json_rpc">JSON-RPC</a></li>
+<li><a href="#_dns">DNS</a></li>
+<li><a href="#_dns_server">DNS server</a></li>
+<li><a href="#_mqtt">MQTT</a></li>
+<li><a href="#_mqtt_broker">MQTT Broker</a></li>
+<li><a href="#_coap">CoAP</a></li>
+<li><a href="#_utilities">Utilities</a></li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<div id="content">
+<div class="sect1">
+<h2 id="_usage_example">Usage Example</h2>
+<div class="sectionbody">
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Copy <code>mongoose.c</code> and <code>mongoose.h</code> to your build tree</p>
+</li>
+<li>
+<p>Write code that uses Mongoose API, e.g. in <code>my_app.c</code></p>
+</li>
+<li>
+<p>Compile application: <code>$ cc my_app.c mongoose.c</code></p>
+</li>
+</ol>
+</div>
+<div class="listingblock">
+<div class="title">my_app.c</div>
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">#include "mongoose.h"  <img src="/images/icons/callouts/1.png" alt="1">
+
+static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { <img src="/images/icons/callouts/2.png" alt="2">
+  struct mbuf *io = &amp;nc-&gt;recv_mbuf;
+
+  switch (ev) {
+    case MG_EV_RECV:
+      // This event handler implements simple TCP echo server
+      mg_send(nc, io-&gt;buf, io-&gt;len);  // Echo received data back
+      mbuf_remove(io, io-&gt;len);      // Discard data from recv buffer
+      break;
+    default:
+      break;
+  }
+}
+
+int main(void) {
+  struct mg_mgr mgr;
+
+  mg_mgr_init(&amp;mgr, NULL);  <img src="/images/icons/callouts/3.png" alt="3">
+
+  // Note that many connections can be added to a single event manager
+  // Connections can be created at any point, e.g. in event handler function
+  mg_bind(&amp;mgr, "1234", ev_handler);  <img src="/images/icons/callouts/4.png" alt="4">
+
+  for (;;) {  <img src="/images/icons/callouts/5.png" alt="5">
+    mg_mgr_poll(&amp;mgr, 1000);
+  }
+
+  mg_mgr_free(&amp;mgr);
+  return 0;
+}</code></pre>
+</div>
+</div>
+<div class="colist arabic">
+<table>
+<tr>
+<td><img src="/images/icons/callouts/1.png" alt="1"></td>
+<td>Include Mongoose API definitions</td>
+</tr>
+<tr>
+<td><img src="/images/icons/callouts/2.png" alt="2"></td>
+<td>Define an event handler function</td>
+</tr>
+<tr>
+<td><img src="/images/icons/callouts/3.png" alt="3"></td>
+<td>Initialize event manager object</td>
+</tr>
+<tr>
+<td><img src="/images/icons/callouts/4.png" alt="4"></td>
+<td>Create listening connection and add it to the event manager</td>
+</tr>
+<tr>
+<td><img src="/images/icons/callouts/5.png" alt="5"></td>
+<td>Start infinite event loop</td>
+</tr>
+</table>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_design_concept">Design Concept</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Mongoose is a multi-protocol networking library that implements non-blocking,
+asyncronous IO and provides event-based API. It has three basic data structures:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><a href="#_struct_mg_mgr"><code>struct mg_mgr</code></a> is an event manager
+that holds all active connections</p>
+</li>
+<li>
+<p><a href="#_struct_mg_connection"><code>struct mg_connection</code></a> describes a connection</p>
+</li>
+<li>
+<p><a href="#_struct_mbuf"><code>struct mbuf</code></a> describes data buffer
+(received or sent data)</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Connections could be either <strong>listening</strong>, <strong>outbound</strong> or <strong>inbound</strong>.
+Outbound connections are created by <a href="#_mg_connect"><code>mg_connect()</code></a> call.
+Listening connections are created by <a href="#_mg_bind"><code>mg_bind()</code></a> call.
+Inbound connections are those accepted by a listening connection.
+Each connection is described by
+<a href="#_struct_mg_connection"><code>struct mg_connection</code></a> structure, which has
+a number of fields like socket, event handler function, send/receive buffer,
+flags, et cetera.</p>
+</div>
+<div class="paragraph">
+<p>Mongoose usage pattern is to declare and initialize event manager, create
+connections and create an event loop by calling
+<a href="#_mg_mgr_poll"><code>mg_mgr_poll()</code></a> in a loop.
+<a href="#_mg_mgr_poll"><code>mg_mgr_poll()</code></a> iterates over all sockets,
+accepts new connections, sends and receives data, closes connections,
+and calls event handler functions for the respective events.</p>
+</div>
+<div class="sect2">
+<h3 id="_memory_buffers">Memory buffers</h3>
+<div class="paragraph">
+<p>Each connection has send and receive buffer,
+<a href="#_struct_mg_connection"><code>struct mg_connection::send_mbuf</code></a>
+and
+<a href="#_struct_mg_connection"><code>struct mg_connection::recv_mbuf</code></a> respectively.
+When data arrives,
+Mongoose appends received data to the <code>recv_mbuf</code> and
+triggers <code>MG_EV_RECV</code> event. User may send data back by calling one of the
+output functions, like <a href="#_mg_send"><code>mg_send()</code></a> or
+<a href="#_mg_printf"><code>mg_printf()</code></a>. Output functions append data to the
+<code>send_mbuf</code>. When Mongoose
+successfully writes data to the socket, it discards data from
+<a href="#_struct_mg_connection"><code>mg_connection::send_mbuf</code></a> and
+sends <code>MG_EV_SEND</code> event. When connection is closed, <code>MG_EV_CLOSE</code> event is sent.</p>
+</div>
+<div class="imageblock" style="text-align: center">
+<div class="content">
+<img src="/images/mongoose/mbuf.png" alt="mbuf" width="600">
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_event_handler_function">Event handler function</h3>
+<div class="paragraph">
+<p>Each connection has an event handler function associated with it. That
+function must be implemented by user. Event handler is the key element of
+the Mongoose application, since it defines application&#8217;s behavior. This is how
+an event handler function looks like:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
+  switch (ev) {
+    /* Event handler code that defines behavior of the connection */
+    ...
+  }
+}</code></pre>
+</div>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">struct mg_connection *nc</dt>
+<dd>
+<p>Connection that has received an event.</p>
+</dd>
+<dt class="hdlist1">int ev</dt>
+<dd>
+<p>Event number, defined in <code>mongoose.h</code>. For example, when data arrives
+on inbound connection <code>ev</code> would be <code>MG_EV_RECV</code>.</p>
+</dd>
+<dt class="hdlist1">void *ev_data</dt>
+<dd>
+<p>This pointer points to the event-specific data, and it has different
+meaning for different events. For example, for <code>MG_EV_RECV</code> event,
+<code>ev_data</code> is an <code>int *</code> pointer, pointing to the number of bytes received
+from the remote peer and saved into the receive IO buffer. Exact meaning
+of <code>ev_data</code> is described for each event. Protocol-specific events usually
+have <code>ev_data</code> pointing to structures that hold protocol-specific information.</p>
+</dd>
+</dl>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<img src="/images/icons/note.png" alt="Note">
+</td>
+<td class="content">
+<a href="#_struct_mg_connection"><code>struct mg_connection</code></a> has <code>void *user_data</code>
+which is a placeholder for a application-specific data. Mongoose does not use
+that pointer. Event handler can store any kind of information there.
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_events">Events</h3>
+<div class="paragraph">
+<p>Mongoose accepts incoming connections, reads and writes data, and
+calls specified event handler for each connection when appropriate. Typical
+event sequence is this:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>For outbound connection: <code>MG_EV_CONNECT</code> &#8594; (<code>MG_EV_RECV</code>, <code>MG_EV_SEND</code>, <code>MG_EV_POLL</code> &#8230;&#8203;) &#8594; <code>MG_EV_CLOSE</code></p>
+</li>
+<li>
+<p>For inbound connection: <code>MG_EV_ACCEPT</code> &#8594;  (<code>MG_EV_RECV</code>, <code>MG_EV_SEND</code>, <code>MG_EV_POLL</code> &#8230;&#8203;) &#8594; <code>MG_EV_CLOSE</code></p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Below is a list
+of core events triggered by Mongoose (note that each protocol triggers
+protocol-specific events in addition to the core ones):</p>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">MG_EV_ACCEPT</dt>
+<dd>
+<p>sent when new server connection is accepted by a
+listening connection. <code>void *ev_data</code> is <code>union socket_address</code>
+of the remote peer.</p>
+</dd>
+<dt class="hdlist1">MG_EV_CONNECT</dt>
+<dd>
+<p>sent when a new outbound connection created by
+<a href="#_mg_connect"><code>mg_connect()</code></a>
+either failed or succeeded. <code>void *ev_data</code> is <code>int *success</code>.
+If <code>success</code> is 0, then connection has been established,
+otherwise it contains error code. See
+<a href="#_mg_connect_opt"><code>mg_connect_opt()</code></a> function for code example.</p>
+</dd>
+<dt class="hdlist1">MG_EV_RECV</dt>
+<dd>
+<p>New data is received and appended to the end of <code>recv_mbuf</code>.
+<code>void *ev_data</code> is <code>int *num_received_bytes</code>. Typically, event handler
+should check received data in <code>nc&#8594;recv_mbuf</code>,
+discard processed data by calling <a href="#_mbuf_remove"><code>mbuf_remove()</code></a>,
+set connection flags <code>nc&#8594;flags</code> if necessary
+(see <a href="#_struct_mg_connection"><code>struct mg_connection</code></a>), and write
+data the remote peer by output functions like <a href="#_mg_send"><code>mg_send()</code></a>.</p>
+</dd>
+</dl>
+</div>
+<div class="admonitionblock warning">
+<table>
+<tr>
+<td class="icon">
+<img src="/images/icons/warning.png" alt="Warning">
+</td>
+<td class="content">
+Mongoose uses <code>realloc()</code> to expand receive buffer.
+It is user&#8217;s responsibility to discard processed
+data from the beginning of receive buffer, note the <code>mbuf_remove()</code>
+call in the example above.
+</td>
+</tr>
+</table>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">MG_EV_SEND</dt>
+<dd>
+<p>Mongoose has written data to the remote peer and discarded
+written data from the
+<a href="#_struct_mg_connection"><code>mg_connection::send_mbuf</code></a>. <code>void *ev_data</code>
+is <code>int *num_sent_bytes</code>.</p>
+</dd>
+</dl>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<img src="/images/icons/note.png" alt="Note">
+</td>
+<td class="content">
+Mongoose output functions only append
+data to the <code>mg_connection::send_mbuf</code>, they do not do any socket writes.
+An actual IO is done by <a href="#_mg_mgr_poll"><code>mg_mgr_poll()</code></a>. <code>MG_EV_SEND</code> event
+is just a notification about an IO has been done.
+</td>
+</tr>
+</table>
+</div>
+<div class="dlist">
+<dl>
+<dt class="hdlist1">MG_EV_POLL</dt>
+<dd>
+<p>Sent to all connections on each invocation of
+<a href="#_mg_mgr_poll"><code>mg_mgr_poll()</code></a>.
+This event could be used to do any housekeeping, for example check whether
+certain timeout has expired and close the connection, or send heartbeet
+message, et cetera.</p>
+</dd>
+<dt class="hdlist1">MG_EV_TIMER</dt>
+<dd>
+<p>Sent to the connection if
+<a href="#_mg_set_timer"><code>mg_set_timer()</code></a> was called.</p>
+</dd>
+</dl>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_connection_flags">Connection flags</h3>
+<div class="paragraph">
+<p>Each connection has a <code>flags</code> bit field. Some flags are set by Mongoose, for
+example if a user creates an outbound UDP connection using <code>udp://1.2.3.4:5678</code>
+address, Mongoose is going to set <code>MG_F_UDP</code> flag for that connection. Other flags
+are meant to be set only by user event handler to tell Mongoose how to behave.
+Below is a list of connection flags that are meant to be set by event handlers:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>MG_F_FINISHED_SENDING_DATA</code> tells Mongoose that all data has been
+appended to the <code>send_mbuf</code>. As soon as Mongoose sends it to the
+socket, the connection will be closed.</p>
+</li>
+<li>
+<p><code>MG_F_BUFFER_BUT_DONT_SEND</code> tells Mongoose to append data to the
+<code>send_mbuf</code> but hold on sending it, because the data will be modified
+later and then will be sent by clearing <code>MG_F_BUFFER_BUT_DONT_SEND</code> flag.</p>
+</li>
+<li>
+<p><code>MG_F_CLOSE_IMMEDIATELY</code> tells Mongoose to close the connection
+immediately, usually after some error</p>
+</li>
+<li>
+<p><code>MG_F_USER_1</code>, <code>MG_F_USER_2</code>, <code>MG_F_USER_3</code>, <code>MG_F_USER_4</code> could be
+used by a developer to store application-specific state</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Flags below are set by Mongoose:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>MG_F_SSL_HANDSHAKE_DONE</code> SSL only, set when SSL handshake is done.</p>
+</li>
+<li>
+<p><code>MG_F_CONNECTING</code> set when connection is in connecting state after
+<code>mg_connect()</code> call but connect did not finish yet.</p>
+</li>
+<li>
+<p><code>MG_F_LISTENING</code> set for all listening connections</p>
+</li>
+<li>
+<p><code>MG_F_UDP</code> set if connection is UDP</p>
+</li>
+<li>
+<p><code>MG_F_IS_WEBSOCKET</code> set if connection is a Websocket connection</p>
+</li>
+<li>
+<p><code>MG_F_WEBSOCKET_NO_DEFRAG</code> should be set by a user if user wants to switch
+off automatic Websocket frame defragmentation</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_build_options">Build Options</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Mongoose source code ships in a single .c file that contains functionality
+for all supported protocols (modules). Modules can be disabled at compile
+time which reduces executable size. That can be done by setting preprocessor
+flags. Also, some preprocessor flags can be used to tune internal Mongoose
+parameters.</p>
+</div>
+<div class="paragraph">
+<p>To set a preprocessor flag during compile time, use <code>-D &lt;PREPROCESSOR_FLAG&gt;</code>
+compiler option. For example, to disable both MQTT and JSON-RPC,
+compile the application <code>my_app.c</code> like this (assumed UNIX system):</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code>  $ cc my_app.c mongoose.c -D MG_DISABLE_MQTT -D MG_DISABLE_JSON_RPC</code></pre>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_enabling_flags">Enabling flags</h3>
+<div class="ulist">
+<ul>
+<li>
+<p><code>MG_ENABLE_SSL</code> Enable OpenSSL support</p>
+</li>
+<li>
+<p><code>MG_ENABLE_IPV6</code> Enable IPV6 support</p>
+</li>
+<li>
+<p><code>MG_ENABLE_THREADS</code> enable <code>mg_start_thread()</code> API</p>
+</li>
+<li>
+<p><code>MG_ENABLE_MQTT_BROKER</code> enable MQTT broker</p>
+</li>
+<li>
+<p><code>MG_ENABLE_DNS_SERVER</code> enable DNS server</p>
+</li>
+<li>
+<p><code>MG_ENABLE_COAP</code> enable CoAP protocol</p>
+</li>
+<li>
+<p><code>MG_ENABLE_GETADDRINFO</code> enable <code>getaddrinfo()</code> in <code>mg_resolve2()</code></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_disabling_flags">Disabling flags</h3>
+<div class="ulist">
+<ul>
+<li>
+<p><code>MG_DISABLE_HTTP_WEBSOCKET</code> disable HTTP + Websocket protocol support</p>
+</li>
+<li>
+<p><code>MG_DISABLE_HTTP_DIGEST_AUTH</code> disable HTTP Digest (MD5) authorization support</p>
+</li>
+<li>
+<p><code>MG_DISABLE_MQTT</code> disable MQTT support</p>
+</li>
+<li>
+<p><code>MG_DISABLE_SHA1</code> disable SHA1 support (used by Websocket)</p>
+</li>
+<li>
+<p><code>MG_DISABLE_MD5</code> disable MD5 support (used by HTTP auth)</p>
+</li>
+<li>
+<p><code>MG_DISABLE_JSON_RPC</code> disable JSON-RPC support</p>
+</li>
+<li>
+<p><code>MG_DISABLE_SOCKETPAIR</code> disable <code>mg_broadcast()</code> API</p>
+</li>
+<li>
+<p><code>MG_DISABLE_HTTP_KEEP_ALIVE</code> useful for embedded systems to save resources</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_platform_specific">Platform specific</h3>
+<div class="paragraph">
+<p>Mongoose tries to detect the target platform whenever possible, but in some cases you have
+to explicitly declare some peculiarities of your target, such as:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>MG_LWIP</code>: use LWIP networking stack</p>
+</li>
+<li>
+<p><code>MG_CC3200</code>: enable workarounds for the TI CC3200 target.</p>
+</li>
+<li>
+<p><code>MG_ESP8266</code>: enable workarounds for the ESP8266 target, add <code>RTOS_SDK</code> to specify the RTOS SDK flavour.</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_tunables">Tunables</h3>
+<div class="ulist">
+<ul>
+<li>
+<p><code>MG_MALLOC</code>, <code>MG_CALLOC</code>, <code>MG_REALLOC</code>, <code>MG_FREE</code> allow to use custom
+memory allocator, e.g. <code>-DMG_MALLOC=my_malloc</code></p>
+</li>
+<li>
+<p><code>MG_USE_READ_WRITE</code> when set replaces calls to <code>recv</code> with <code>read</code> and <code>send</code> with <code>write</code>,
+thus enabling to add any kind of file descriptor (files, serial devices) to an event manager.</p>
+</li>
+<li>
+<p><code>MG_SSL_CRYPTO_MODERN</code>, <code>MG_SSL_CRYPTO_OLD</code> - choose either "Modern" or "Old" ciphers
+instead of the default "Intermediate" setting.
+See [this article](<a href="https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations" class="bare">https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations</a>) for details.</p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_api_reference">API Reference</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_memory_buffers_2">Memory Buffers</h3>
+<div class="paragraph">
+<p>Mbufs are mutable/growing memory buffers, like C++ strings.
+Mbuf can append data to the end of a buffer, or insert data into arbitrary
+position in the middle of a buffer. The buffer grows automatically when
+needed.</p>
+</div>
+<div class="sect3">
+<h4 id="_struct_mbuf">struct mbuf</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mbuf {
+  char *buf;   /* Buffer pointer */
+  size_t len;  /* Data length. Data is located between offset 0 and len. */
+  size_t size; /* Buffer size allocated by realloc(1). Must be &gt;= len */
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Memory buffer descriptor</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mbuf_init">mbuf_init()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mbuf_init(struct mbuf *, size_t initial_capacity);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Initialize an Mbuf.
+<code>initial_capacity</code> specifies the initial capacity of the mbuf.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mbuf_free">mbuf_free()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mbuf_free(struct mbuf *);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Free the space allocated for the mbuffer and resets the mbuf structure.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mbuf_append">mbuf_append()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">size_t mbuf_append(struct mbuf *, const void *data, size_t data_size);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Appends data to the Mbuf.</p>
+</div>
+<div class="paragraph">
+<p>Return the number of bytes appended, or 0 if out of memory.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mbuf_insert">mbuf_insert()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">size_t mbuf_insert(struct mbuf *, size_t, const void *, size_t);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Insert data at a specified offset in the Mbuf.</p>
+</div>
+<div class="paragraph">
+<p>Existing data will be shifted forwards and the buffer will
+be grown if necessary.
+Return the number of bytes inserted.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mbuf_remove">mbuf_remove()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mbuf_remove(struct mbuf *, size_t data_size);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Remove <code>data_size</code> bytes from the beginning of the buffer.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mbuf_resize">mbuf_resize()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mbuf_resize(struct mbuf *, size_t new_size);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Resize an Mbuf.</p>
+</div>
+<div class="paragraph">
+<p>If <code>new_size</code> is smaller than buffer&#8217;s <code>len</code>, the
+resize is not performed.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mbuf_trim">mbuf_trim()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mbuf_trim(struct mbuf *);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Shrink an Mbuf by resizing its <code>size</code> to <code>len</code>.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_core_tcp_udp_ssl">Core: TCP/UDP/SSL</h3>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<img src="/images/icons/note.png" alt="Note">
+</td>
+<td class="content">
+Mongoose manager is single threaded. It does not protect
+its data structures by mutexes, therefore all functions that are dealing
+with particular event manager should be called from the same thread,
+with exception of <code>mg_broadcast()</code> function. It is fine to have different
+event managers handled by different threads.
+</td>
+</tr>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_str">struct mg_str</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_str {
+  const char *p; /* Memory chunk pointer */
+  size_t len;    /* Memory chunk length */
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Describes chunk of memory</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_mgr">struct mg_mgr</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_mgr {
+  struct mg_connection *active_connections;
+  const char *hexdump_file; /* Debug hexdump file path */
+#ifndef MG_DISABLE_SOCKETPAIR
+  sock_t ctl[2]; /* Socketpair for mg_wakeup() */
+#endif
+  void *user_data; /* User data */
+  void *mgr_data;  /* Implementation-specific event manager's data. */
+#ifdef MG_ENABLE_JAVASCRIPT
+  struct v7 *v7;
+#endif
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Mongoose event manager.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_connection">struct mg_connection</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_connection {
+  struct mg_connection *next, *prev; /* mg_mgr::active_connections linkage */
+  struct mg_connection *listener;    /* Set only for accept()-ed connections */
+  struct mg_mgr *mgr;                /* Pointer to containing manager */
+
+  sock_t sock; /* Socket to the remote peer */
+  int err;
+  union socket_address sa; /* Remote peer address */
+  size_t recv_mbuf_limit;  /* Max size of recv buffer */
+  struct mbuf recv_mbuf;   /* Received data */
+  struct mbuf send_mbuf;   /* Data scheduled for sending */
+  SSL *ssl;
+  SSL_CTX *ssl_ctx;
+  time_t last_io_time;              /* Timestamp of the last socket IO */
+  double ev_timer_time;             /* Timestamp of the future MG_EV_TIMER */
+  mg_event_handler_t proto_handler; /* Protocol-specific event handler */
+  void *proto_data;                 /* Protocol-specific data */
+  void (*proto_data_destructor)(void *proto_data);
+  mg_event_handler_t handler; /* Event handler function */
+  void *user_data;            /* User-specific data */
+  union {
+    void *v;
+    /*
+     * the C standard is fussy about fitting function pointers into
+     * void pointers, since some archs might have fat pointers for functions.
+     */
+    mg_event_handler_t f;
+  } priv_1;       /* Used by mg_enable_multithreading() */
+  void *priv_2;   /* Used by mg_enable_multithreading() */
+  void *mgr_data; /* Implementation-specific event manager's data. */
+  unsigned long flags;
+/* Flags set by Mongoose */
+#define MG_F_LISTENING (1 &lt;&lt; 0)          /* This connection is listening */
+#define MG_F_UDP (1 &lt;&lt; 1)                /* This connection is UDP */
+#define MG_F_RESOLVING (1 &lt;&lt; 2)          /* Waiting for async resolver */
+#define MG_F_CONNECTING (1 &lt;&lt; 3)         /* connect() call in progress */
+#define MG_F_SSL_HANDSHAKE_DONE (1 &lt;&lt; 4) /* SSL specific */
+#define MG_F_WANT_READ (1 &lt;&lt; 5)          /* SSL specific */
+#define MG_F_WANT_WRITE (1 &lt;&lt; 6)         /* SSL specific */
+#define MG_F_IS_WEBSOCKET (1 &lt;&lt; 7)       /* Websocket specific */
+
+/* Flags that are settable by user */
+#define MG_F_SEND_AND_CLOSE (1 &lt;&lt; 10)      /* Push remaining data and close  */
+#define MG_F_CLOSE_IMMEDIATELY (1 &lt;&lt; 11)   /* Disconnect */
+#define MG_F_WEBSOCKET_NO_DEFRAG (1 &lt;&lt; 12) /* Websocket specific */
+#define MG_F_DELETE_CHUNK (1 &lt;&lt; 13)        /* HTTP specific */
+
+#define MG_F_USER_1 (1 &lt;&lt; 20) /* Flags left for application */
+#define MG_F_USER_2 (1 &lt;&lt; 21)
+#define MG_F_USER_3 (1 &lt;&lt; 22)
+#define MG_F_USER_4 (1 &lt;&lt; 23)
+#define MG_F_USER_5 (1 &lt;&lt; 24)
+#define MG_F_USER_6 (1 &lt;&lt; 25)
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Mongoose connection.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_add_sock_opts">struct mg_add_sock_opts</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_add_sock_opts {
+  void *user_data;           /* Initial value for connection's user_data */
+  unsigned int flags;        /* Initial connection flags */
+  const char **error_string; /* Placeholder for the error string */
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Optional parameters to <code>mg_add_sock_opt()</code>.</p>
+</div>
+<div class="paragraph">
+<p><code>flags</code> is an initial <code>struct mg_connection::flags</code> bitmask to set,
+see <code>MG_F_*</code> flags definitions.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_bind_opts">struct mg_bind_opts</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_bind_opts {
+  void *user_data;           /* Initial value for connection's user_data */
+  unsigned int flags;        /* Extra connection flags */
+  const char **error_string; /* Placeholder for the error string */
+#ifdef MG_ENABLE_SSL
+  /* SSL settings. */
+  const char *ssl_cert;    /* Server certificate to present to clients */
+  const char *ssl_ca_cert; /* Verify client certificates with this CA bundle */
+#endif
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Optional parameters to <code>mg_bind_opt()</code>.</p>
+</div>
+<div class="paragraph">
+<p><code>flags</code> is an initial <code>struct mg_connection::flags</code> bitmask to set,
+see <code>MG_F_*</code> flags definitions.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_connect_opts">struct mg_connect_opts</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_connect_opts {
+  void *user_data;           /* Initial value for connection's user_data */
+  unsigned int flags;        /* Extra connection flags */
+  const char **error_string; /* Placeholder for the error string */
+#ifdef MG_ENABLE_SSL
+  /* SSL settings. */
+  const char *ssl_cert;    /* Client certificate to present to the server */
+  const char *ssl_ca_cert; /* Verify server certificate using this CA bundle */
+
+  /*
+   * Server name verification. If ssl_ca_cert is set and the certificate has
+   * passed verification, its subject will be verified against this string.
+   * By default (if ssl_server_name is NULL) hostname part of the address will
+   * be used. Wildcard matching is supported. A special value of "*" disables
+   * name verification.
+   */
+  const char *ssl_server_name;
+#endif
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Optional parameters to <code>mg_connect_opt()</code></p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mgr_init">mg_mgr_init()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mgr_init(struct mg_mgr *mgr, void *user_data);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Initialize Mongoose manager. Side effect: ignores SIGPIPE signal.
+<code>mgr&#8594;user_data</code> field will be initialized with <code>user_data</code> parameter.
+That is an arbitrary pointer, where user code can associate some data
+with the particular Mongoose manager. For example, a C++ wrapper class
+could be written, in which case <code>user_data</code> can hold a pointer to the
+class instance.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mgr_free">mg_mgr_free()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mgr_free(struct mg_mgr *);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>De-initializes Mongoose manager.</p>
+</div>
+<div class="paragraph">
+<p>Close and deallocate all active connections.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mgr_poll">mg_mgr_poll()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">time_t mg_mgr_poll(struct mg_mgr *, int milli);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This function performs the actual IO, and must be called in a loop
+(an event loop). Returns the current timestamp.
+<code>milli</code> is the maximum number of milliseconds to sleep.
+<code>mg_mgr_poll()</code> checks all connection for IO readiness. If at least one
+of the connections is IO-ready, <code>mg_mgr_poll()</code> triggers respective
+event handlers and returns.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_broadcast">mg_broadcast()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Pass a message of a given length to all connections.</p>
+</div>
+<div class="paragraph">
+<p>Must be called from a thread that does NOT call <code>mg_mgr_poll()</code>.
+Note that <code>mg_broadcast()</code> is the only function
+that can be, and must be, called from a different (non-IO) thread.</p>
+</div>
+<div class="paragraph">
+<p><code>func</code> callback function will be called by the IO thread for each
+connection. When called, event would be <code>MG_EV_POLL</code>, and message will
+be passed as <code>ev_data</code> pointer. Maximum message size is capped
+by <code>MG_CTL_MSG_MESSAGE_SIZE</code> which is set to 8192 bytes.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_next">mg_next()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_connection *mg_next(struct mg_mgr *, struct mg_connection *);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Iterate over all active connections.</p>
+</div>
+<div class="paragraph">
+<p>Returns next connection from the list
+of active connections, or <code>NULL</code> if there is no more connections. Below
+is the iteration idiom:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">for (c = mg_next(srv, NULL); c != NULL; c = mg_next(srv, c)) {
+  // Do something with connection `c`
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_add_sock">mg_add_sock()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_connection *mg_add_sock(struct mg_mgr *, sock_t, mg_event_handler_t);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Create a connection, associate it with the given socket and event handler,
+and add it to the manager.</p>
+</div>
+<div class="paragraph">
+<p>For more options see the <code>mg_add_sock_opt</code> variant.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_add_sock_opt">mg_add_sock_opt()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_connection *mg_add_sock_opt(struct mg_mgr *, sock_t,
+                                      mg_event_handler_t,
+                                      struct mg_add_sock_opts);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Create a connection, associate it with the given socket and event handler,
+and add to the manager.</p>
+</div>
+<div class="paragraph">
+<p>See the <code>mg_add_sock_opts</code> structure for a description of the options.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_bind">mg_bind()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_connection *mg_bind(struct mg_mgr *, const char *,
+                              mg_event_handler_t);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Create listening connection.</p>
+</div>
+<div class="paragraph">
+<p>See <code>mg_bind_opt</code> for full documentation.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_bind_opt">mg_bind_opt()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address,
+                                  mg_event_handler_t handler,
+                                  struct mg_bind_opts opts);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Create listening connection.</p>
+</div>
+<div class="paragraph">
+<p><code>address</code> parameter tells which address to bind to. It&#8217;s format is the same
+as for the <code>mg_connect()</code> call, where <code>HOST</code> part is optional. <code>address</code>
+can be just a port number, e.g. <code>:8000</code>. To bind to a specific interface,
+an IP address can be specified, e.g. <code>1.2.3.4:8000</code>. By default, a TCP
+connection is created. To create UDP connection, prepend <code>udp://</code> prefix,
+e.g. <code>udp://:8000</code>. To summarize, <code>address</code> paramer has following format:
+<code>[PROTO://][IP_ADDRESS]:PORT</code>, where <code>PROTO</code> could be <code>tcp</code> or <code>udp</code>.</p>
+</div>
+<div class="paragraph">
+<p>See the <code>mg_bind_opts</code> structure for a description of the optional
+parameters.</p>
+</div>
+<div class="paragraph">
+<p>Return a new listening connection, or <code>NULL</code> on error.
+NOTE: Connection remains owned by the manager, do not free().</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_connect">mg_connect()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address,
+                                 mg_event_handler_t handler);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Connect to a remote host.</p>
+</div>
+<div class="paragraph">
+<p>See <code>mg_connect_opt()</code> for full documentation.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_connect_opt">mg_connect_opt()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address,
+                                     mg_event_handler_t handler,
+                                     struct mg_connect_opts opts);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Connect to a remote host.</p>
+</div>
+<div class="paragraph">
+<p><code>address</code> format is <code>[PROTO://]HOST:PORT</code>. <code>PROTO</code> could be <code>tcp</code> or <code>udp</code>.
+<code>HOST</code> could be an IP address,
+IPv6 address (if Mongoose is compiled with <code>-DMG_ENABLE_IPV6</code>), or a host
+name. If <code>HOST</code> is a name, Mongoose will resolve it asynchronously. Examples
+of valid addresses: <code>google.com:80</code>, <code>udp://1.2.3.4:53</code>, <code>10.0.0.1:443</code>,
+<code>[::1]:80</code></p>
+</div>
+<div class="paragraph">
+<p>See the <code>mg_connect_opts</code> structure for a description of the optional
+parameters.</p>
+</div>
+<div class="paragraph">
+<p>Returns a new outbound connection, or <code>NULL</code> on error.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<img src="/images/icons/note.png" alt="Note">
+</td>
+<td class="content">
+Connection remains owned by the manager, do not free().
+</td>
+</tr>
+</table>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<img src="/images/icons/note.png" alt="Note">
+</td>
+<td class="content">
+To enable IPv6 addresses, <code>-DMG_ENABLE_IPV6</code> should be specified
+in the compilation flags.
+</td>
+</tr>
+</table>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<img src="/images/icons/note.png" alt="Note">
+</td>
+<td class="content">
+New connection will receive <code>MG_EV_CONNECT</code> as it&#8217;s first event
+which will report connect success status.
+If asynchronous resolution fail, or <code>connect()</code> syscall fail for whatever
+reason (e.g. with <code>ECONNREFUSED</code> or <code>ENETUNREACH</code>), then <code>MG_EV_CONNECT</code>
+event report failure. Code example below:
+</td>
+</tr>
+</table>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
+  int connect_status;
+
+  switch (ev) {
+    case MG_EV_CONNECT:
+      connect_status = * (int *) ev_data;
+      if (connect_status == 0) {
+        // Success
+      } else  {
+        // Error
+        printf("connect() error: %s\n", strerror(connect_status));
+      }
+      break;
+    ...
+  }
+}
+
+  ...
+  mg_connect(mgr, "my_site.com:80", ev_handler);</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_set_ssl">mg_set_ssl()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">const char *mg_set_ssl(struct mg_connection *nc, const char *cert,
+                       const char *ca_cert);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Enable SSL for a given connection.
+<code>cert</code> is a server certificate file name for a listening connection,
+or a client certificate file name for an outgoing connection.
+Certificate files must be in PEM format. Server certificate file
+must contain a certificate, concatenated with a private key, optionally
+concatenated with parameters.
+<code>ca_cert</code> is a CA certificate, or NULL if peer verification is not
+required.
+Return: NULL on success, or error message on error.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_send">mg_send()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_send(struct mg_connection *, const void *buf, int len);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send data to the connection.</p>
+</div>
+<div class="paragraph">
+<p>Note that sending functions do not actually push data to the socket.
+They just append data to the output buffer. MG_EV_SEND will be delivered when
+the data has actually been pushed out.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_printf">mg_printf()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_printf(struct mg_connection *, const char *fmt, ...);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send <code>printf</code>-style formatted data to the connection.</p>
+</div>
+<div class="paragraph">
+<p>See <code>mg_send</code> for more details on send semantics.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_vprintf">mg_vprintf()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Same as <code>mg_printf()</code>, but takes <code>va_list ap</code> as an argument.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_socketpair">mg_socketpair()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_socketpair(sock_t[2], int sock_type);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Create a socket pair.
+<code>sock_type</code> can be either <code>SOCK_STREAM</code> or <code>SOCK_DGRAM</code>.
+Return 0 on failure, 1 on success.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_check_ip_acl">mg_check_ip_acl()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_check_ip_acl(const char *acl, uint32_t remote_ip);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Verify given IP address against the ACL.</p>
+</div>
+<div class="paragraph">
+<p><code>remote_ip</code> - an IPv4 address to check, in host byte order
+<code>acl</code> - a comma separated list of IP subnets: <code>x.x.x.x/x</code> or <code>x.x.x.x</code>.
+Each subnet is
+prepended by either a - or a + sign. A plus sign means allow, where a
+minus sign means deny. If a subnet mask is omitted, such as <code>-1.2.3.4</code>,
+this means to deny only that single IP address.
+Subnet masks may vary from 0 to 32, inclusive. The default setting
+is to allow all accesses. On each request the full list is traversed,
+and the last match wins. Example:</p>
+</div>
+<div class="paragraph">
+<p><code>-0.0.0.0/0,+192.168/16</code> - deny all acccesses, only allow 192.168/16 subnet</p>
+</div>
+<div class="paragraph">
+<p>To learn more about subnet masks, see the
+<a href="https://en.wikipedia.org/wiki/Subnetwork">Wikipedia page on Subnetwork</a></p>
+</div>
+<div class="paragraph">
+<p>Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_enable_multithreading">mg_enable_multithreading()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_enable_multithreading(struct mg_connection *nc);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Enable multi-threaded handling for the given listening connection <code>nc</code>.
+For each accepted connection, Mongoose will create a separate thread
+and run event handler in that thread. Thus, if an event hanler is doing
+a blocking call or some long computation, that will not slow down
+other connections.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_enable_javascript">mg_enable_javascript()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">enum v7_err mg_enable_javascript(struct mg_mgr *m, struct v7 *v7,
+                                 const char *init_js_file_name);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Enable server-side JavaScript scripting.
+Requires <code>-DMG_ENABLE_JAVASCRIPT</code> compilation flag, and V7 engine sources.
+v7 instance must not be destroyed during manager&#8217;s lifetime.
+Return V7 error.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_set_timer">mg_set_timer()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">double mg_set_timer(struct mg_connection *c, double timestamp);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Schedule MG_EV_TIMER event to be delivered at <code>timestamp</code> time.
+<code>timestamp</code> is a UNIX time (a number of seconds since Epoch). It is
+<code>double</code> instead of <code>time_t</code> to allow for sub-second precision.
+Return the old timer value.</p>
+</div>
+<div class="paragraph">
+<p>Example: set connect timeout to 1.5 seconds:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code> c = mg_connect(&amp;mgr, "cesanta.com", ev_handler);
+ mg_set_timer(c, mg_time() + 1.5);
+ ...
+
+ void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
+ switch (ev) {
+   case MG_EV_CONNECT:
+     mg_set_timer(c, 0);  // Clear connect timer
+     break;
+   case MG_EV_TIMER:
+     log("Connect timeout");
+     c-&gt;flags |= MG_F_CLOSE_IMMEDIATELY;
+     break;</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_time">mg_time()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">double mg_time();</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>A sub-second precision version of time().</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_http_websocket">HTTP + Websocket</h3>
+<div class="sect3">
+<h4 id="_struct_http_message">struct http_message</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct http_message {
+  struct mg_str message; /* Whole message: request line + headers + body */
+
+  /* HTTP Request line (or HTTP response line) */
+  struct mg_str method; /* "GET" */
+  struct mg_str uri;    /* "/my_file.html" */
+  struct mg_str proto;  /* "HTTP/1.1" -- for both request and response */
+
+  /* For responses, code and response status message are set */
+  int resp_code;
+  struct mg_str resp_status_msg;
+
+  /*
+   * Query-string part of the URI. For example, for HTTP request
+   *    GET /foo/bar?param1=val1&amp;param2=val2
+   *    |    uri    |     query_string     |
+   *
+   * Note that question mark character doesn't belong neither to the uri,
+   * nor to the query_string
+   */
+  struct mg_str query_string;
+
+  /* Headers */
+  struct mg_str header_names[MG_MAX_HTTP_HEADERS];
+  struct mg_str header_values[MG_MAX_HTTP_HEADERS];
+
+  /* Message body */
+  struct mg_str body; /* Zero-length for requests with no body */
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>HTTP message</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_websocket_message">struct websocket_message</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct websocket_message {
+  unsigned char *data;
+  size_t size;
+  unsigned char flags;
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>WebSocket message</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_http_multipart_part">struct mg_http_multipart_part</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_http_multipart_part {
+  const char *file_name;
+  const char *var_name;
+  struct mg_str data;
+  int status; /* &lt;0 on error */
+  void *user_data;
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>HTTP multipart part</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_serve_http_opts">struct mg_serve_http_opts</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_serve_http_opts {
+  /* Path to web root directory */
+  const char *document_root;
+
+  /* List of index files. Default is "" */
+  const char *index_files;
+
+  /*
+   * Leave as NULL to disable authentication.
+   * To enable directory protection with authentication, set this to ".htpasswd"
+   * Then, creating ".htpasswd" file in any directory automatically protects
+   * it with digest authentication.
+   * Use `mongoose` web server binary, or `htdigest` Apache utility to
+   * create/manipulate passwords file.
+   * Make sure `auth_domain` is set to a valid domain name.
+   */
+  const char *per_directory_auth_file;
+
+  /* Authorization domain (domain name of this web server) */
+  const char *auth_domain;
+
+  /*
+   * Leave as NULL to disable authentication.
+   * Normally, only selected directories in the document root are protected.
+   * If absolutely every access to the web server needs to be authenticated,
+   * regardless of the URI, set this option to the path to the passwords file.
+   * Format of that file is the same as ".htpasswd" file. Make sure that file
+   * is located outside document root to prevent people fetching it.
+   */
+  const char *global_auth_file;
+
+  /* Set to "no" to disable directory listing. Enabled by default. */
+  const char *enable_directory_listing;
+
+  /* SSI files pattern. If not set, "**.shtml$|**.shtm$" is used. */
+  const char *ssi_pattern;
+
+  /* IP ACL. By default, NULL, meaning all IPs are allowed to connect */
+  const char *ip_acl;
+
+  /* URL rewrites.
+   *
+   * Comma-separated list of `uri_pattern=file_or_directory_path` rewrites.
+   * When HTTP request is received, Mongoose constructs a file name from the
+   * requested URI by combining `document_root` and the URI. However, if the
+   * rewrite option is used and `uri_pattern` matches requested URI, then
+   * `document_root` is ignored. Instead, `file_or_directory_path` is used,
+   * which should be a full path name or a path relative to the web server's
+   * current working directory. Note that `uri_pattern`, as all Mongoose
+   * patterns, is a prefix pattern.
+   *
+   * If uri_pattern starts with `@` symbol, then Mongoose compares it with the
+   * HOST header of the request. If they are equal, Mongoose sets document root
+   * to `file_or_directory_path`, implementing virtual hosts support.
+   * Example: `@foo.com=/document/root/for/foo.com`
+   *
+   * If `uri_pattern` starts with `%` symbol, then Mongoose compares it with
+   * the listening port. If they match, then Mongoose issues a 301 redirect.
+   * For example, to redirect all HTTP requests to the
+   * HTTPS port, do `%80=https://my.site.com`. Note that the request URI is
+   * automatically appended to the redirect location.
+   */
+  const char *url_rewrites;
+
+  /* DAV document root. If NULL, DAV requests are going to fail. */
+  const char *dav_document_root;
+
+  /*
+   * DAV passwords file. If NULL, DAV requests are going to fail.
+   * If passwords file is set to "-", then DAV auth is disabled.
+   */
+  const char *dav_auth_file;
+
+  /* Glob pattern for the files to hide. */
+  const char *hidden_file_pattern;
+
+  /* Set to non-NULL to enable CGI, e.g. **.cgi$|**.php$" */
+  const char *cgi_file_pattern;
+
+  /* If not NULL, ignore CGI script hashbang and use this interpreter */
+  const char *cgi_interpreter;
+
+  /*
+   * Comma-separated list of Content-Type overrides for path suffixes, e.g.
+   * ".txt=text/plain; charset=utf-8,.c=text/plain"
+   */
+  const char *custom_mime_types;
+
+  /*
+   * Extra HTTP headers to add to each server response.
+   * Example: to enable CORS, set this to "Access-Control-Allow-Origin: *".
+   */
+  const char *extra_headers;
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This structure defines how <code>mg_serve_http()</code> works.
+Best practice is to set only required settings, and leave the rest as NULL.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_set_protocol_http_websocket">mg_set_protocol_http_websocket()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_set_protocol_http_websocket(struct mg_connection *nc);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Attach built-in HTTP event handler to the given connection.
+User-defined event handler will receive following extra events:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>MG_EV_HTTP_REQUEST: HTTP request has arrived. Parsed HTTP request
+is passed as
+ <code>struct http_message</code> through the handler&#8217;s <code>void *ev_data</code> pointer.</p>
+</li>
+<li>
+<p>MG_EV_HTTP_MULTIPART_REQUEST: A multipart POST request has received.
+This event is sent before body is parsed. After this user
+should expect a sequence of MG_EV_HTTP_PART_BEGIN/DATA/END requests.
+This is also the last time when headers and other request fields are
+accessible.</p>
+</li>
+<li>
+<p>MG_EV_HTTP_REPLY: HTTP reply has arrived. Parsed HTTP reply is passed as
+<code>struct http_message</code> through the handler&#8217;s <code>void *ev_data</code> pointer.</p>
+</li>
+<li>
+<p>MG_EV_HTTP_CHUNK: HTTP chunked-encoding chunk has arrived.
+Parsed HTTP reply is passed as <code>struct http_message</code> through the
+handler&#8217;s <code>void *ev_data</code> pointer. <code>http_message::body</code> would contain
+incomplete, reassembled HTTP body.
+It will grow with every new chunk arrived, and
+potentially can consume a lot of memory. An event handler may process
+the body as chunks are coming, and signal Mongoose to delete processed
+body by setting <code>MG_F_DELETE_CHUNK</code> in <code>mg_connection::flags</code>. When
+the last zero chunk is received,
+Mongoose sends <code>MG_EV_HTTP_REPLY</code> event with
+full reassembled body (if handler did not signal to delete chunks) or
+with empty body (if handler did signal to delete chunks).</p>
+</li>
+<li>
+<p>MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: server has received websocket handshake
+request. <code>ev_data</code> contains parsed HTTP request.</p>
+</li>
+<li>
+<p>MG_EV_WEBSOCKET_HANDSHAKE_DONE: server has completed Websocket handshake.
+<code>ev_data</code> is <code>NULL</code>.</p>
+</li>
+<li>
+<p>MG_EV_WEBSOCKET_FRAME: new websocket frame has arrived. <code>ev_data</code> is
+<code>struct websocket_message *</code></p>
+</li>
+<li>
+<p>MG_EV_HTTP_PART_BEGIN: new part of multipart message is started,
+extra parameters are passed in mg_http_multipart_part</p>
+</li>
+<li>
+<p>MG_EV_HTTP_PART_DATA: new portion of data from multiparted message
+no additional headers are available, only data and data size</p>
+</li>
+<li>
+<p>MG_EV_HTTP_PART_END: final boundary received, analogue to maybe used to
+find the end of packet
+Note: Mongoose should be compiled with MG_ENABLE_HTTP_STREAMING_MULTIPART
+to enable MG_EV_HTTP_MULTIPART_REQUEST, MG_EV_HTTP_REQUEST_END,
+MG_EV_HTTP_REQUEST_CANCEL, MG_EV_HTTP_PART_BEGIN, MG_EV_HTTP_PART_DATA,
+MG_EV_HTTP_PART_END constants</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_send_websocket_handshake">mg_send_websocket_handshake()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_send_websocket_handshake(struct mg_connection *nc, const char *uri,
+                                 const char *extra_headers);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send websocket handshake to the server.</p>
+</div>
+<div class="paragraph">
+<p><code>nc</code> must be a valid connection, connected to a server. <code>uri</code> is an URI
+to fetch, extra_headers` is extra HTTP headers to send or <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p>This function is intended to be used by websocket client.</p>
+</div>
+<div class="paragraph">
+<p>Note that the Host header is mandatory in HTTP/1.1 and must be
+included in <code>extra_headers</code>. <code>mg_send_websocket_handshake2</code> offers
+a better API for that.</p>
+</div>
+<div class="paragraph">
+<p>Deprecated in favour of <code>mg_send_websocket_handshake2</code></p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_send_websocket_handshake2">mg_send_websocket_handshake2()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_send_websocket_handshake2(struct mg_connection *nc, const char *path,
+                                  const char *host, const char *protocol,
+                                  const char *extra_headers);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send websocket handshake to the server.</p>
+</div>
+<div class="paragraph">
+<p><code>nc</code> must be a valid connection, connected to a server. <code>uri</code> is an URI
+to fetch, <code>host</code> goes into the <code>Host</code> header, <code>protocol</code> goes into the
+<code>Sec-WebSocket-Proto</code> header (NULL to omit), extra_headers` is extra HTTP
+headers to send or <code>NULL</code>.</p>
+</div>
+<div class="paragraph">
+<p>This function is intended to be used by websocket client.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_connect_ws">mg_connect_ws()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_connection *mg_connect_ws(struct mg_mgr *mgr,
+                                    mg_event_handler_t event_handler,
+                                    const char *url, const char *protocol,
+                                    const char *extra_headers);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Helper function that creates an outbound WebSocket connection.</p>
+</div>
+<div class="paragraph">
+<p><code>url</code> is a URL to connect to. It must be properly URL-encoded, e.g. have
+no spaces, etc. By default, <code>mg_connect_ws()</code> sends Connection and
+Host headers. <code>extra_headers</code> is an extra HTTP headers to send, e.g.
+<code>"User-Agent: my-app\r\n"</code>.
+If <code>protocol</code> is not NULL, then a <code>Sec-WebSocket-Protocol</code> header is sent.</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">  nc1 = mg_connect_ws(mgr, ev_handler_1, "ws://echo.websocket.org", NULL,
+                      NULL);
+  nc2 = mg_connect_ws(mgr, ev_handler_1, "wss://echo.websocket.org", NULL,
+                      NULL);
+  nc3 = mg_connect_ws(mgr, ev_handler_1, "ws://api.cesanta.com",
+                      "clubby.cesanta.com", NULL);</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_connect_ws_opt">mg_connect_ws_opt()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_connection *mg_connect_ws_opt(struct mg_mgr *mgr,
+                                        mg_event_handler_t ev_handler,
+                                        struct mg_connect_opts opts,
+                                        const char *url, const char *protocol,
+                                        const char *extra_headers);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Helper function that creates an outbound WebSocket connection</p>
+</div>
+<div class="paragraph">
+<p>Mostly identical to mg_connect_ws, but allows to provide extra parameters
+(for example, SSL parameters</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_send_websocket_frame">mg_send_websocket_frame()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_send_websocket_frame(struct mg_connection *nc, int op_and_flags,
+                             const void *data, size_t data_len);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send websocket frame to the remote end.</p>
+</div>
+<div class="paragraph">
+<p><code>op_and_flags</code> specifies frame&#8217;s type, one of:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>WEBSOCKET_OP_CONTINUE</p>
+</li>
+<li>
+<p>WEBSOCKET_OP_TEXT</p>
+</li>
+<li>
+<p>WEBSOCKET_OP_BINARY</p>
+</li>
+<li>
+<p>WEBSOCKET_OP_CLOSE</p>
+</li>
+<li>
+<p>WEBSOCKET_OP_PING</p>
+</li>
+<li>
+<p>WEBSOCKET_OP_PONG</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Orred with one of the flags:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>WEBSOCKET_DONT_FIN: Don&#8217;t set the FIN flag on the frame to be sent.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p><code>data</code> and <code>data_len</code> contain frame data.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_send_websocket_framev">mg_send_websocket_framev()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_send_websocket_framev(struct mg_connection *nc, int op_and_flags,
+                              const struct mg_str *strings, int num_strings);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send multiple websocket frames.</p>
+</div>
+<div class="paragraph">
+<p>Like <code>mg_send_websocket_frame()</code>, but composes a frame from multiple buffers.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_printf_websocket_frame">mg_printf_websocket_frame()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_printf_websocket_frame(struct mg_connection *nc, int op_and_flags,
+                               const char *fmt, ...);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send websocket frame to the remote end.</p>
+</div>
+<div class="paragraph">
+<p>Like <code>mg_send_websocket_frame()</code>, but allows to create formatted message
+with <code>printf()</code>-like semantics.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_send_http_chunk">mg_send_http_chunk()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_send_http_chunk(struct mg_connection *nc, const char *buf, size_t len);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send buffer <code>buf</code> of size <code>len</code> to the client using chunked HTTP encoding.
+This function first sends buffer size as hex number + newline, then
+buffer itself, then newline. For example,
+  <code>mg_send_http_chunk(nc, "foo", 3)</code> whill append <code>3\r\nfoo\r\n</code> string to
+the <code>nc&#8594;send_mbuf</code> output IO buffer.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<img src="/images/icons/note.png" alt="Note">
+</td>
+<td class="content">
+HTTP header "Transfer-Encoding: chunked" should be sent prior to
+using this function.
+</td>
+</tr>
+</table>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<img src="/images/icons/note.png" alt="Note">
+</td>
+<td class="content">
+do not forget to send empty chunk at the end of the response,
+to tell the client that everything was sent. Example:
+</td>
+</tr>
+</table>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code>  mg_printf_http_chunk(nc, "%s", "my response!");
+  mg_send_http_chunk(nc, "", 0); // Tell the client we're finished</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_printf_http_chunk">mg_printf_http_chunk()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_printf_http_chunk(struct mg_connection *nc, const char *fmt, ...);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send printf-formatted HTTP chunk.
+Functionality is similar to <code>mg_send_http_chunk()</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_send_response_line">mg_send_response_line()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_send_response_line(struct mg_connection *c, int status_code,
+                           const char *extra_headers);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send response status line.
+If <code>extra_headers</code> is not NULL, then <code>extra_headers</code> are also sent
+after the reponse line. <code>extra_headers</code> must NOT end end with new line.
+Example:</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *");</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Will result in:</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>HTTP/1.1 200 OK\r\n
+Access-Control-Allow-Origin: *\r\n</pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_send_head">mg_send_head()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_send_head(struct mg_connection *n, int status_code,
+                  int64_t content_length, const char *extra_headers);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send response line and headers.
+This function sends response line with the <code>status_code</code>, and automatically
+sends one header: either "Content-Length", or "Transfer-Encoding".
+If <code>content_length</code> is negative, then "Transfer-Encoding: chunked" header
+is sent, otherwise, "Content-Length" header is sent.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<img src="/images/icons/note.png" alt="Note">
+</td>
+<td class="content">
+If <code>Transfer-Encoding</code> is <code>chunked</code>, then message body must be sent
+using <code>mg_send_http_chunk()</code> or <code>mg_printf_http_chunk()</code> functions.
+Otherwise, <code>mg_send()</code> or <code>mg_printf()</code> must be used.
+Extra headers could be set through <code>extra_headers</code> - and note <code>extra_headers</code>
+must NOT be terminated by a new line.
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_printf_html_escape">mg_printf_html_escape()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_printf_html_escape(struct mg_connection *nc, const char *fmt, ...);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send printf-formatted HTTP chunk, escaping HTML tags.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_parse_http">mg_parse_http()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_parse_http(const char *s, int n, struct http_message *hm, int is_req);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Parse a HTTP message.</p>
+</div>
+<div class="paragraph">
+<p><code>is_req</code> should be set to 1 if parsing request, 0 if reply.</p>
+</div>
+<div class="paragraph">
+<p>Return number of bytes parsed. If HTTP message is
+incomplete, <code>0</code> is returned. On parse error, negative number is returned.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_get_http_header">mg_get_http_header()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_str *mg_get_http_header(struct http_message *hm, const char *name);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Search and return header <code>name</code> in parsed HTTP message <code>hm</code>.
+If header is not found, NULL is returned. Example:</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>struct mg_str *host_hdr = mg_get_http_header(hm, "Host");</pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_http_parse_header">mg_http_parse_header()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_http_parse_header(struct mg_str *hdr, const char *var_name, char *buf,
+                         size_t buf_size);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Parse HTTP header <code>hdr</code>. Find variable <code>var_name</code> and store it&#8217;s value
+in the buffer <code>buf</code>, <code>buf_size</code>. Return 0 if variable not found, non-zero
+otherwise.</p>
+</div>
+<div class="paragraph">
+<p>This function is supposed to parse
+cookies, authentication headers, etcetera. Example (error handling omitted):</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>char user[20];
+struct mg_str *hdr = mg_get_http_header(hm, "Authorization");
+mg_http_parse_header(hdr, "username", user, sizeof(user));</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return length of the variable&#8217;s value. If buffer is not large enough,
+or variable not found, 0 is returned.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_parse_multipart">mg_parse_multipart()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">size_t mg_parse_multipart(const char *buf, size_t buf_len, char *var_name,
+                          size_t var_name_len, char *file_name,
+                          size_t file_name_len, const char **chunk,
+                          size_t *chunk_len);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Parse buffer <code>buf</code>, <code>buf_len</code> that contains multipart form data chunks.
+Store chunk name in a <code>var_name</code>, <code>var_name_len</code> buffer.
+If a chunk is an uploaded file, then <code>file_name</code>, <code>file_name_len</code> is
+filled with an uploaded file name. <code>chunk</code>, <code>chunk_len</code>
+points to the chunk data.</p>
+</div>
+<div class="paragraph">
+<p>Return: number of bytes to skip to the next chunk, or 0 if there are
+        no more chunks.</p>
+</div>
+<div class="paragraph">
+<p>Usage example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">   static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
+     switch(ev) {
+       case MG_EV_HTTP_REQUEST: {
+         struct http_message *hm = (struct http_message *) ev_data;
+         char var_name[100], file_name[100];
+         const char *chunk;
+         size_t chunk_len, n1, n2;
+
+         n1 = n2 = 0;
+         while ((n2 = mg_parse_multipart(hm-&gt;body.p + n1,
+                                         hm-&gt;body.len - n1,
+                                         var_name, sizeof(var_name),
+                                         file_name, sizeof(file_name),
+                                         &amp;chunk, &amp;chunk_len)) &gt; 0) {
+           printf("var: %s, file_name: %s, size: %d, chunk: [%.*s]\n",
+                  var_name, file_name, (int) chunk_len,
+                  (int) chunk_len, chunk);
+           n1 += n2;
+         }
+       }
+       break;</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_get_http_var">mg_get_http_var()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_get_http_var(const struct mg_str *buf, const char *name, char *dst,
+                    size_t dst_len);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Fetch an HTTP form variable.</p>
+</div>
+<div class="paragraph">
+<p>Fetch a variable <code>name</code> from a <code>buf</code> into a buffer specified by
+<code>dst</code>, <code>dst_len</code>. Destination is always zero-terminated. Return length
+of a fetched variable. If not found, 0 is returned. <code>buf</code> must be
+valid url-encoded buffer. If destination is too small, <code>-1</code> is returned.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_url_decode">mg_url_decode()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_url_decode(const char *src, int src_len, char *dst, int dst_len,
+                  int is_form_url_encoded);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Decode URL-encoded string.</p>
+</div>
+<div class="paragraph">
+<p>Source string is specified by (<code>src</code>, <code>src_len</code>), and destination is
+(<code>dst</code>, <code>dst_len</code>). If <code>is_form_url_encoded</code> is non-zero, then
+<code>+</code> character is decoded as a blank space character. This function
+guarantees to <code>\0</code>-terminate the destination. If destination is too small,
+then source string is partially decoded and <code>-1</code> is returned. Otherwise,
+a length of decoded string is returned, not counting final <code>\0</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_http_create_digest_auth_header">mg_http_create_digest_auth_header()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_http_create_digest_auth_header(char *buf, size_t buf_len,
+                                      const char *method, const char *uri,
+                                      const char *auth_domain, const char *user,
+                                      const char *passwd);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Create Digest authentication header for client request.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_connect_http">mg_connect_http()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_connection *mg_connect_http(struct mg_mgr *mgr,
+                                      mg_event_handler_t event_handler,
+                                      const char *url,
+                                      const char *extra_headers,
+                                      const char *post_data);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Helper function that creates outbound HTTP connection.</p>
+</div>
+<div class="paragraph">
+<p><code>url</code> is a URL to fetch. It must be properly URL-encoded, e.g. have
+no spaces, etc. By default, <code>mg_connect_http()</code> sends Connection and
+Host headers. <code>extra_headers</code> is an extra HTTP headers to send, e.g.
+<code>"User-Agent: my-app\r\n"</code>.
+If <code>post_data</code> is NULL, then GET request is created. Otherwise, POST request
+is created with the specified POST data. Note that if the data being posted
+is a form submission, the <code>Content-Type</code> header should be set accordingly
+(see example below).</p>
+</div>
+<div class="paragraph">
+<p>Examples:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">  nc1 = mg_connect_http(mgr, ev_handler_1, "http://www.google.com", NULL,
+                        NULL);
+  nc2 = mg_connect_http(mgr, ev_handler_1, "https://github.com", NULL, NULL);
+  nc3 = mg_connect_http(
+      mgr, ev_handler_1, "my_server:8000/form_submit/",
+      "Content-Type: application/x-www-form-urlencoded\r\n",
+      "var_1=value_1&amp;var_2=value_2");</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_connect_http_opt">mg_connect_http_opt()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_connection *mg_connect_http_opt(struct mg_mgr *mgr,
+                                          mg_event_handler_t ev_handler,
+                                          struct mg_connect_opts opts,
+                                          const char *url,
+                                          const char *extra_headers,
+                                          const char *post_data);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Helper function that creates outbound HTTP connection.</p>
+</div>
+<div class="paragraph">
+<p>Mostly identical to mg_connect_http, but allows to provide extra parameters
+(for example, SSL parameters</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_serve_http">mg_serve_http()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_serve_http(struct mg_connection *nc, struct http_message *hm,
+                   struct mg_serve_http_opts opts);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Serve given HTTP request according to the <code>options</code>.</p>
+</div>
+<div class="paragraph">
+<p>Example code snippet:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
+  struct http_message *hm = (struct http_message *) ev_data;
+  struct mg_serve_http_opts opts = { .document_root = "/var/www" };  // C99
+
+  switch (ev) {
+    case MG_EV_HTTP_REQUEST:
+      mg_serve_http(nc, hm, opts);
+      break;
+    default:
+      break;
+  }
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_register_http_endpoint">mg_register_http_endpoint()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_register_http_endpoint(struct mg_connection *nc, const char *uri_path,
+                               mg_event_handler_t handler);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Register callback for specified http endpoint
+Note: if callback is registered it is called instead of
+callback provided in mg_bind</p>
+</div>
+<div class="paragraph">
+<p>Example code snippet:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
+  (void) ev; (void) ev_data;
+  mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello1]");
+ nc-&gt;flags |= MG_F_SEND_AND_CLOSE;
+}
+
+static void handle_hello1(struct mg_connection *nc, int ev, void *ev_data) {
+ (void) ev; (void) ev_data;
+  mg_printf(nc, "HTTP/1.0 200 OK\r\n\r\n[I am Hello2]");
+ nc-&gt;flags |= MG_F_SEND_AND_CLOSE;
+}
+
+void init() {
+  nc = mg_bind(&amp;mgr, local_addr, cb1);
+  mg_register_http_endpoint(nc, "/hello1", handle_hello1);
+  mg_register_http_endpoint(nc, "/hello1/hello2", handle_hello2);
+}</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_file_upload_handler">mg_file_upload_handler()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_file_upload_handler(struct mg_connection *nc, int ev, void *ev_data,
+                            mg_fu_fname_fn local_name_fn);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>File upload handler.
+This handler can be used to implement file uploads with minimum code.
+This handler will process MG_EV_HTTP_PART_* events and store file data into
+a local file.
+<code>local_name_fn</code> will be invoked with whatever name was provided by the client
+and will expect the name of the local file to open. Return value of NULL will
+abort file upload (client will get a "403 Forbidden" response). If non-null,
+the returned string must be heap-allocated and will be freed by the caller.
+Exception: it is ok to return the same string verbatim.</p>
+</div>
+<div class="paragraph">
+<p>Example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_str upload_fname(struct mg_connection *nc, struct mg_str fname) {
+  // Just return the same filename. Do not actually do this except in test!
+  // fname is user-controlled and needs to be sanitized.
+  return fname;
+}
+void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
+  switch (ev) {
+    ...
+    case MG_EV_HTTP_PART_BEGIN:
+    case MG_EV_HTTP_PART_DATA:
+    case MG_EV_HTTP_PART_END:
+      mg_file_upload_handler(nc, ev, ev_data, upload_fname);
+      break;
+  }
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_json_rpc">JSON-RPC</h3>
+<div class="sect3">
+<h4 id="_struct_mg_rpc_request">struct mg_rpc_request</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_rpc_request {
+  struct json_token *message; /* Whole RPC message */
+  struct json_token *id;      /* Message ID */
+  struct json_token *method;  /* Method name */
+  struct json_token *params;  /* Method params */
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>JSON-RPC request</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_rpc_reply">struct mg_rpc_reply</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_rpc_reply {
+  struct json_token *message; /* Whole RPC message */
+  struct json_token *id;      /* Message ID */
+  struct json_token *result;  /* Remote call result */
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>JSON-RPC response</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_rpc_error">struct mg_rpc_error</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_rpc_error {
+  struct json_token *message;       /* Whole RPC message */
+  struct json_token *id;            /* Message ID */
+  struct json_token *error_code;    /* error.code */
+  struct json_token *error_message; /* error.message */
+  struct json_token *error_data;    /* error.data, can be NULL */
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>JSON-RPC error</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_rpc_parse_reply">mg_rpc_parse_reply()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_rpc_parse_reply(const char *buf, int len, struct json_token *toks,
+                       int max_toks, struct mg_rpc_reply *,
+                       struct mg_rpc_error *);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Parse JSON-RPC reply contained in <code>buf</code>, <code>len</code> into JSON tokens array
+<code>toks</code>, <code>max_toks</code>. If buffer contains valid reply, <code>reply</code> structure is
+populated. The result of RPC call is located in <code>reply.result</code>. On error,
+<code>error</code> structure is populated. Returns: the result of calling
+<code>parse_json(buf, len, toks, max_toks)</code>:</p>
+</div>
+<div class="paragraph">
+<p>On success, an offset inside <code>json_string</code> is returned
+where parsing has finished. On failure, a negative number is
+returned, one of:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>#define JSON_STRING_INVALID           -1</code></p>
+</li>
+<li>
+<p><code>#define JSON_STRING_INCOMPLETE        -2</code></p>
+</li>
+<li>
+<p><code>#define JSON_TOKEN_ARRAY_TOO_SMALL    -3</code></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_rpc_create_request">mg_rpc_create_request()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_rpc_create_request(char *buf, int len, const char *method,
+                          const char *id, const char *params_fmt, ...);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Create JSON-RPC request in a given buffer.</p>
+</div>
+<div class="paragraph">
+<p>Return length of the request, which
+can be larger then <code>len</code> that indicates an overflow.
+<code>params_fmt</code> format string should conform to <code>json_emit()</code> API,
+see <a href="https://github.com/cesanta/frozen" class="bare">https://github.com/cesanta/frozen</a></p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_rpc_create_reply">mg_rpc_create_reply()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_rpc_create_reply(char *buf, int len, const struct mg_rpc_request *req,
+                        const char *result_fmt, ...);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Create JSON-RPC reply in a given buffer.</p>
+</div>
+<div class="paragraph">
+<p>Return length of the reply, which
+can be larger then <code>len</code> that indicates an overflow.
+<code>result_fmt</code> format string should conform to <code>json_emit()</code> API,
+see <a href="https://github.com/cesanta/frozen" class="bare">https://github.com/cesanta/frozen</a></p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_rpc_create_error">mg_rpc_create_error()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_rpc_create_error(char *buf, int len, struct mg_rpc_request *req,
+                        int code, const char *message, const char *fmt, ...);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Create JSON-RPC error reply in a given buffer.</p>
+</div>
+<div class="paragraph">
+<p>Return length of the error, which
+can be larger then <code>len</code> that indicates an overflow.
+<code>fmt</code> format string should conform to <code>json_emit()</code> API,
+see <a href="https://github.com/cesanta/frozen" class="bare">https://github.com/cesanta/frozen</a></p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_rpc_create_std_error">mg_rpc_create_std_error()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_rpc_create_std_error(char *buf, int len, struct mg_rpc_request *req,
+                            int code);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Create JSON-RPC error in a given buffer.</p>
+</div>
+<div class="paragraph">
+<p>Return length of the error, which
+can be larger then <code>len</code> that indicates an overflow. See
+JSON_RPC_*_ERROR definitions for standard error values:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>#define JSON_RPC_PARSE_ERROR (-32700)</code></p>
+</li>
+<li>
+<p><code>#define JSON_RPC_INVALID_REQUEST_ERROR (-32600)</code></p>
+</li>
+<li>
+<p><code>#define JSON_RPC_METHOD_NOT_FOUND_ERROR (-32601)</code></p>
+</li>
+<li>
+<p><code>#define JSON_RPC_INVALID_PARAMS_ERROR (-32602)</code></p>
+</li>
+<li>
+<p><code>#define JSON_RPC_INTERNAL_ERROR (-32603)</code></p>
+</li>
+<li>
+<p><code>#define JSON_RPC_SERVER_ERROR (-32000)</code></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_rpc_dispatch">mg_rpc_dispatch()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_rpc_dispatch(const char *buf, int, char *dst, int dst_len,
+                    const char **methods, mg_rpc_handler_t *handlers);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Dispatches a JSON-RPC request.</p>
+</div>
+<div class="paragraph">
+<p>Parses JSON-RPC request contained in <code>buf</code>, <code>len</code>.
+Then, dispatches the request to the correct handler method.
+Valid method names should be specified in NULL
+terminated array <code>methods</code>, and corresponding handlers in <code>handlers</code>.
+Result is put in <code>dst</code>, <code>dst_len</code>. Return: length of the result, which
+can be larger then <code>dst_len</code> that indicates an overflow.
+Overflown bytes are not written to the buffer.
+If method is not found, an error is automatically generated.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_dns">DNS</h3>
+<div class="sect3">
+<h4 id="_struct_mg_dns_resource_record">struct mg_dns_resource_record</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_dns_resource_record {
+  struct mg_str name; /* buffer with compressed name */
+  int rtype;
+  int rclass;
+  int ttl;
+  enum mg_dns_resource_record_kind kind;
+  struct mg_str rdata; /* protocol data (can be a compressed name) */
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>DNS resource record.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_dns_message">struct mg_dns_message</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_dns_message {
+  struct mg_str pkt; /* packet body */
+  uint16_t flags;
+  uint16_t transaction_id;
+  int num_questions;
+  int num_answers;
+  struct mg_dns_resource_record questions[MG_MAX_DNS_QUESTIONS];
+  struct mg_dns_resource_record answers[MG_MAX_DNS_ANSWERS];
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>DNS message (request and response).</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_dns_parse_record_data">mg_dns_parse_record_data()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_dns_parse_record_data(struct mg_dns_message *msg,
+                             struct mg_dns_resource_record *rr, void *data,
+                             size_t data_len);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Parse the record data from a DNS resource record.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>A:     struct in_addr *ina</p>
+</li>
+<li>
+<p>AAAA:  struct in6_addr *ina</p>
+</li>
+<li>
+<p>CNAME: char buffer</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Returns -1 on error.</p>
+</div>
+<div class="paragraph">
+<p>TODO(mkm): MX</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_send_dns_query">mg_send_dns_query()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_send_dns_query(struct mg_connection *nc, const char *name,
+                       int query_type);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send a DNS query to the remote end.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_dns_insert_header">mg_dns_insert_header()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_dns_insert_header(struct mbuf *io, size_t pos,
+                         struct mg_dns_message *msg);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Insert a DNS header to an IO buffer.</p>
+</div>
+<div class="paragraph">
+<p>Return number of bytes inserted.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_dns_copy_questions">mg_dns_copy_questions()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_dns_copy_questions(struct mbuf *io, struct mg_dns_message *msg);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Append already encoded questions from an existing message.</p>
+</div>
+<div class="paragraph">
+<p>This is useful when generating a DNS reply message which includes
+all question records.</p>
+</div>
+<div class="paragraph">
+<p>Return number of appened bytes.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_dns_encode_record">mg_dns_encode_record()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_dns_encode_record(struct mbuf *io, struct mg_dns_resource_record *rr,
+                         const char *name, size_t nlen, const void *rdata,
+                         size_t rlen);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Encode and append a DNS resource record to an IO buffer.</p>
+</div>
+<div class="paragraph">
+<p>The record metadata is taken from the <code>rr</code> parameter, while the name and data
+are taken from the parameters, encoded in the appropriate format depending on
+record type, and stored in the IO buffer. The encoded values might contain
+offsets within the IO buffer. It&#8217;s thus important that the IO buffer doesn&#8217;t
+get trimmed while a sequence of records are encoded while preparing a DNS
+*reply.</p>
+</div>
+<div class="paragraph">
+<p>This function doesn&#8217;t update the <code>name</code> and <code>rdata</code> pointers in the <code>rr</code>
+*struct
+because they might be invalidated as soon as the IO buffer grows again.</p>
+</div>
+<div class="paragraph">
+<p>Return the number of bytes appened or -1 in case of error.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_parse_dns">mg_parse_dns()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_parse_dns(const char *buf, int len, struct mg_dns_message *msg);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Low-level: parses a DNS response.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_dns_uncompress_name">mg_dns_uncompress_name()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">size_t mg_dns_uncompress_name(struct mg_dns_message *msg, struct mg_str *name,
+                              char *dst, int dst_len);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Uncompress a DNS compressed name.</p>
+</div>
+<div class="paragraph">
+<p>The containing dns message is required because the compressed encoding
+and reference suffixes present elsewhere in the packet.</p>
+</div>
+<div class="paragraph">
+<p>If name is less than <code>dst_len</code> characters long, the remainder
+of <code>dst</code> is terminated with <code>\0' characters. Otherwise, `dst</code> is not
+*terminated.</p>
+</div>
+<div class="paragraph">
+<p>If <code>dst_len</code> is 0 <code>dst</code> can be NULL.
+Return the uncompressed name length.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_set_protocol_dns">mg_set_protocol_dns()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_set_protocol_dns(struct mg_connection *nc);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Attach built-in DNS event handler to the given listening connection.</p>
+</div>
+<div class="paragraph">
+<p>DNS event handler parses incoming UDP packets, treating them as DNS
+requests. If incoming packet gets successfully parsed by the DNS event
+handler, a user event handler will receive <code>MG_DNS_REQUEST</code> event, with
+<code>ev_data</code> pointing to the parsed <code>struct mg_dns_message</code>.</p>
+</div>
+<div class="paragraph">
+<p>See
+[captive_dns_server](<a href="https://github.com/cesanta/mongoose/tree/master/examples/captive_dns_server" class="bare">https://github.com/cesanta/mongoose/tree/master/examples/captive_dns_server</a>)
+example on how to handle DNS request and send DNS reply.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_dns_server">DNS server</h3>
+<div class="paragraph">
+<p>Disabled by default; enable with <code>-DMG_ENABLE_DNS_SERVER</code>.</p>
+</div>
+<div class="sect3">
+<h4 id="_mg_dns_create_reply">mg_dns_create_reply()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_dns_reply mg_dns_create_reply(struct mbuf *io,
+                                        struct mg_dns_message *msg);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Create a DNS reply.</p>
+</div>
+<div class="paragraph">
+<p>The reply will be based on an existing query message <code>msg</code>.
+The query body will be appended to the output buffer.
+"reply + recursion allowed" will be added to the message flags and
+message&#8217;s num_answers will be set to 0.</p>
+</div>
+<div class="paragraph">
+<p>Answer records can be appended with <code>mg_dns_send_reply</code> or by lower
+level function defined in the DNS API.</p>
+</div>
+<div class="paragraph">
+<p>In order to send the reply use <code>mg_dns_send_reply</code>.
+It&#8217;s possible to use a connection&#8217;s send buffer as reply buffers,
+and it will work for both UDP and TCP connections.</p>
+</div>
+<div class="paragraph">
+<p>Example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">reply = mg_dns_create_reply(&amp;nc-&gt;send_mbuf, msg);
+for (i = 0; i &lt; msg-&gt;num_questions; i++) {
+  rr = &amp;msg-&gt;questions[i];
+  if (rr-&gt;rtype == MG_DNS_A_RECORD) {
+    mg_dns_reply_record(&amp;reply, rr, 3600, &amp;dummy_ip_addr, 4);
+  }
+}
+mg_dns_send_reply(nc, &amp;reply);</code></pre>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_dns_reply_record">mg_dns_reply_record()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_dns_reply_record(struct mg_dns_reply *reply,
+                        struct mg_dns_resource_record *question,
+                        const char *name, int rtype, int ttl, const void *rdata,
+                        size_t rdata_len);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Append a DNS reply record to the IO buffer and to the DNS message.</p>
+</div>
+<div class="paragraph">
+<p>The message num_answers field will be incremented. It&#8217;s caller&#8217;s duty
+to ensure num_answers is propertly initialized.</p>
+</div>
+<div class="paragraph">
+<p>Returns -1 on error.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_dns_send_reply">mg_dns_send_reply()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_dns_send_reply(struct mg_connection *nc, struct mg_dns_reply *r);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send a DNS reply through a connection.</p>
+</div>
+<div class="paragraph">
+<p>The DNS data is stored in an IO buffer pointed by reply structure in <code>r</code>.
+This function mutates the content of that buffer in order to ensure that
+the DNS header reflects size and flags of the mssage, that might have been
+updated either with <code>mg_dns_reply_record</code> or by direct manipulation of
+<code>r&#8594;message</code>.</p>
+</div>
+<div class="paragraph">
+<p>Once sent, the IO buffer will be trimmed unless the reply IO buffer
+is the connection&#8217;s send buffer and the connection is not in UDP mode.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_mqtt">MQTT</h3>
+<div class="sect3">
+<h4 id="_mg_set_protocol_mqtt">mg_set_protocol_mqtt()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_set_protocol_mqtt(struct mg_connection *nc);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Attach built-in MQTT event handler to the given connection.</p>
+</div>
+<div class="paragraph">
+<p>The user-defined event handler will receive following extra events:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>MG_EV_MQTT_CONNACK</p>
+</li>
+<li>
+<p>MG_EV_MQTT_PUBLISH</p>
+</li>
+<li>
+<p>MG_EV_MQTT_PUBACK</p>
+</li>
+<li>
+<p>MG_EV_MQTT_PUBREC</p>
+</li>
+<li>
+<p>MG_EV_MQTT_PUBREL</p>
+</li>
+<li>
+<p>MG_EV_MQTT_PUBCOMP</p>
+</li>
+<li>
+<p>MG_EV_MQTT_SUBACK</p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_send_mqtt_handshake">mg_send_mqtt_handshake()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_send_mqtt_handshake(struct mg_connection *nc, const char *client_id);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send MQTT handshake.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_send_mqtt_handshake_opt">mg_send_mqtt_handshake_opt()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_send_mqtt_handshake_opt(struct mg_connection *nc, const char *client_id,
+                                struct mg_send_mqtt_handshake_opts);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send MQTT handshake with optional parameters.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_publish">mg_mqtt_publish()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_publish(struct mg_connection *nc, const char *topic,
+                     uint16_t message_id, int flags, const void *data,
+                     size_t len);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Publish a message to a given topic.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_subscribe">mg_mqtt_subscribe()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_subscribe(struct mg_connection *nc,
+                       const struct mg_mqtt_topic_expression *topics,
+                       size_t topics_len, uint16_t message_id);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Subscribe to a bunch of topics.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_unsubscribe">mg_mqtt_unsubscribe()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_unsubscribe(struct mg_connection *nc, char **topics,
+                         size_t topics_len, uint16_t message_id);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Unsubscribe from a bunch of topics.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_disconnect">mg_mqtt_disconnect()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_disconnect(struct mg_connection *nc);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send a DISCONNECT command.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_connack">mg_mqtt_connack()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_connack(struct mg_connection *nc, uint8_t return_code);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send a CONNACK command with a given <code>return_code</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_puback">mg_mqtt_puback()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_puback(struct mg_connection *nc, uint16_t message_id);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send a PUBACK command with a given <code>message_id</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_pubrec">mg_mqtt_pubrec()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_pubrec(struct mg_connection *nc, uint16_t message_id);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send a PUBREC command with a given <code>message_id</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_pubrel">mg_mqtt_pubrel()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_pubrel(struct mg_connection *nc, uint16_t message_id);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send a PUBREL command with a given <code>message_id</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_pubcomp">mg_mqtt_pubcomp()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_pubcomp(struct mg_connection *nc, uint16_t message_id);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send a PUBCOMP command with a given <code>message_id</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_suback">mg_mqtt_suback()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_suback(struct mg_connection *nc, uint8_t *qoss, size_t qoss_len,
+                    uint16_t message_id);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send a SUBACK command with a given <code>message_id</code>
+and a sequence of granted QoSs.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_unsuback">mg_mqtt_unsuback()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_unsuback(struct mg_connection *nc, uint16_t message_id);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send a UNSUBACK command with a given <code>message_id</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_ping">mg_mqtt_ping()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_ping(struct mg_connection *nc);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send a PINGREQ command.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_pong">mg_mqtt_pong()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_pong(struct mg_connection *nc);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Send a PINGRESP command.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_next_subscribe_topic">mg_mqtt_next_subscribe_topic()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg,
+                                 struct mg_str *topic, uint8_t *qos, int pos);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Extract the next topic expression from a SUBSCRIBE command payload.</p>
+</div>
+<div class="paragraph">
+<p>Topic expression name will point to a string in the payload buffer.
+Return the pos of the next topic expression or -1 when the list
+of topics is exhausted.</p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_mqtt_broker">MQTT Broker</h3>
+<div class="sect3">
+<h4 id="_struct_mg_mqtt_session">struct mg_mqtt_session</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_mqtt_session {
+  struct mg_mqtt_broker *brk;          /* Broker */
+  struct mg_mqtt_session *next, *prev; /* mg_mqtt_broker::sessions linkage */
+  struct mg_connection *nc;            /* Connection with the client */
+  size_t num_subscriptions;            /* Size of `subscriptions` array */
+  struct mg_mqtt_topic_expression *subscriptions;
+  void *user_data; /* User data */
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>MQTT session (Broker side).</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_mqtt_broker">struct mg_mqtt_broker</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_mqtt_broker {
+  struct mg_mqtt_session *sessions; /* Session list */
+  void *user_data;                  /* User data */
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>MQTT broker.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_broker_init">mg_mqtt_broker_init()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_broker_init(struct mg_mqtt_broker *brk, void *user_data);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Initialize a MQTT broker.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_broker">mg_mqtt_broker()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_mqtt_broker(struct mg_connection *brk, int ev, void *data);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Process a MQTT broker message.</p>
+</div>
+<div class="paragraph">
+<p>Listening connection expects a pointer to an initialized <code>mg_mqtt_broker</code>
+structure in the <code>user_data</code> field.</p>
+</div>
+<div class="paragraph">
+<p>Basic usage:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">mg_mqtt_broker_init(&amp;brk, NULL);
+
+if ((nc = mg_bind(&amp;mgr, address, mg_mqtt_broker)) == NULL) {
+  // fail;
+}
+nc-&gt;user_data = &amp;brk;</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>New incoming connections will receive a <code>mg_mqtt_session</code> structure
+in the connection <code>user_data</code>. The original <code>user_data</code> will be stored
+in the <code>user_data</code> field of the session structure. This allows the user
+handler to store user data before <code>mg_mqtt_broker</code> creates the session.</p>
+</div>
+<div class="paragraph">
+<p>Since only the MG_EV_ACCEPT message is processed by the listening socket,
+for most events the <code>user_data</code> will thus point to a <code>mg_mqtt_session</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mqtt_next">mg_mqtt_next()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_mqtt_session *mg_mqtt_next(struct mg_mqtt_broker *brk,
+                                     struct mg_mqtt_session *s);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Iterate over all mqtt sessions connections. Example:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_mqtt_session *s;
+for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) {
+  // Do something
+}</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_coap">CoAP</h3>
+<div class="paragraph">
+<p>CoAP message format:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code>+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+|Ver| T | TKL | Code | Message ID | Token (if any, TKL bytes) ...
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+| Options (if any) ...            |1 1 1 1 1 1 1 1| Payload (if any) ...
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-</code></pre>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_coap_option">struct mg_coap_option</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_coap_option {
+  struct mg_coap_option *next;
+  uint32_t number;
+  struct mg_str value;
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>CoAP options.
+Use mg_coap_add_option and mg_coap_free_options
+for creation and destruction.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_struct_mg_coap_message">struct mg_coap_message</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_coap_message {
+  uint32_t flags;
+  uint8_t msg_type;
+  uint8_t code_class;
+  uint8_t code_detail;
+  uint16_t msg_id;
+  struct mg_str token;
+  struct mg_coap_option *options;
+  struct mg_str payload;
+  struct mg_coap_option *optiomg_tail;
+};</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>CoAP message. See RFC 7252 for details.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_set_protocol_coap">mg_set_protocol_coap()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_set_protocol_coap(struct mg_connection *nc);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Set CoAP protocol handler - trigger CoAP specific events</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_coap_add_option">mg_coap_add_option()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_coap_option *mg_coap_add_option(struct mg_coap_message *cm,
+                                          uint32_t number, char *value,
+                                          size_t len);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Add new option to mg_coap_message structure.
+Returns pointer to the newly created option.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_coap_free_options">mg_coap_free_options()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_coap_free_options(struct mg_coap_message *cm);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Free the memory allocated for options,
+if cm paramater doesn&#8217;t contain any option does nothing.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_coap_send_message">mg_coap_send_message()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">uint32_t mg_coap_send_message(struct mg_connection *nc,
+                              struct mg_coap_message *cm);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compose CoAP message from <code>mg_coap_message</code>
+and send it into <code>nc</code> connection.
+Return 0 on success. On error, it is a bitmask:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><code>#define MG_COAP_ERROR 0x10000</code></p>
+</li>
+<li>
+<p><code>#define MG_COAP_FORMAT_ERROR (MG_COAP_ERROR | 0x20000)</code></p>
+</li>
+<li>
+<p><code>#define MG_COAP_IGNORE (MG_COAP_ERROR | 0x40000)</code></p>
+</li>
+<li>
+<p><code>#define MG_COAP_NOT_ENOUGH_DATA (MG_COAP_ERROR | 0x80000)</code></p>
+</li>
+<li>
+<p><code>#define MG_COAP_NETWORK_ERROR (MG_COAP_ERROR | 0x100000)</code></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_coap_send_ack">mg_coap_send_ack()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">uint32_t mg_coap_send_ack(struct mg_connection *nc, uint16_t msg_id);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Compose CoAP acknowledgement from <code>mg_coap_message</code>
+and send it into <code>nc</code> connection.
+Return value: see <code>mg_coap_send_message()</code></p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_coap_parse">mg_coap_parse()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">uint32_t mg_coap_parse(struct mbuf *io, struct mg_coap_message *cm);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Parse COAP message and fills mg_coap_message and returns cm&#8594;flags.
+This is a helper function.</p>
+</div>
+<div class="admonitionblock note">
+<table>
+<tr>
+<td class="icon">
+<img src="/images/icons/note.png" alt="Note">
+</td>
+<td class="content">
+usually CoAP work over UDP, so lack of data means format error,
+but in theory it is possible to use CoAP over TCP (according to RFC)
+</td>
+</tr>
+</table>
+</div>
+<div class="paragraph">
+<p>The caller have to check results and treat COAP_NOT_ENOUGH_DATA according to
+underlying protocol:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>in case of UDP COAP_NOT_ENOUGH_DATA means COAP_FORMAT_ERROR,</p>
+</li>
+<li>
+<p>in case of TCP client can try to receive more data</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Return value: see <code>mg_coap_send_message()</code></p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_coap_compose">mg_coap_compose()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">uint32_t mg_coap_compose(struct mg_coap_message *cm, struct mbuf *io);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Composes CoAP message from mg_coap_message structure.
+This is a helper function.
+Return value: see <code>mg_coap_send_message()</code></p>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_utilities">Utilities</h3>
+<div class="sect3">
+<h4 id="_mg_skip">mg_skip()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">const char *mg_skip(const char *s, const char *end_string,
+                    const char *delimiters, struct mg_str *v);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Fetch substring from input string <code>s</code>, <code>end</code> into <code>v</code>.
+Skips initial delimiter characters. Records first non-delimiter character
+as the beginning of substring <code>v</code>. Then scans the rest of the string
+until a delimiter character or end-of-string is found.
+<code>delimiters</code> is a 0-terminated string containing delimiter characters.
+Either one of <code>delimiters</code> or <code>end_string</code> terminates the search.
+Return an <code>s</code> pointer, advanced forward where parsing stopped.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_ncasecmp">mg_ncasecmp()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_ncasecmp(const char *s1, const char *s2, size_t len);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Cross-platform version of <code>strncasecmp()</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_casecmp">mg_casecmp()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_casecmp(const char *s1, const char *s2);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Cross-platform version of <code>strcasecmp()</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_vcmp">mg_vcmp()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_vcmp(const struct mg_str *str2, const char *str1);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Cross-platform version of <code>strcmp()</code> where where first string is
+specified by <code>struct mg_str</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_vcasecmp">mg_vcasecmp()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_vcasecmp(const struct mg_str *str2, const char *str1);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Cross-platform version of <code>strncasecmp()</code> where first string is
+specified by <code>struct mg_str</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_base64_decode">mg_base64_decode()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_base64_decode(const unsigned char *s, int len, char *dst);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Decode base64-encoded string <code>s</code>, <code>len</code> into the destination <code>dst</code>.
+Destination has to have enough space to hold decoded buffer.
+Decoding stops either when all string has been decoded, or invalid
+character appeared.
+Destination is '\0'-terminated.
+Return number of decoded characters. On success, that should be equal to
+<code>len</code>. On error (invalid character) the return value is smaller then <code>len</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_base64_encode">mg_base64_encode()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_base64_encode(const unsigned char *src, int src_len, char *dst);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Base64-encode chunk of memory <code>src</code>, <code>src_len</code> into the destination <code>dst</code>.
+Destination has to have enough space to hold encoded buffer.
+Destination is '\0'-terminated.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_stat">mg_stat()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_stat(const char *path, cs_stat_t *st);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Perform a 64-bit <code>stat()</code> call against given file.</p>
+</div>
+<div class="paragraph">
+<p><code>path</code> should be UTF8 encoded.</p>
+</div>
+<div class="paragraph">
+<p>Return value is the same as for <code>stat()</code> syscall.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_fopen">mg_fopen()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">FILE *mg_fopen(const char *path, const char *mode);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Open the given file and return a file stream.</p>
+</div>
+<div class="paragraph">
+<p><code>path</code> and <code>mode</code> should be UTF8 encoded.</p>
+</div>
+<div class="paragraph">
+<p>Return value is the same as for the <code>fopen()</code> call.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_open">mg_open()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_open(const char *path, int flag, int mode);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Open the given file and return a file stream.</p>
+</div>
+<div class="paragraph">
+<p><code>path</code> should be UTF8 encoded.</p>
+</div>
+<div class="paragraph">
+<p>Return value is the same as for the <code>open()</code> syscall.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_start_thread">mg_start_thread()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void *mg_start_thread(void *(*thread_func);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Start a new detached thread.
+Arguments and semantic is the same as pthead&#8217;s <code>pthread_create()</code>.
+<code>thread_func</code> is a thread function, <code>thread_func_param</code> is a parameter
+that is passed to the thread function.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_conn_addr_to_str">mg_conn_addr_to_str()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len,
+                         int flags);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Convert connection&#8217;s local or remote address into string.</p>
+</div>
+<div class="paragraph">
+<p>The <code>flags</code> parameter is a bit mask that controls the behavior,
+see <code>MG_SOCK_STRINGIFY_*</code> definitions.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>MG_SOCK_STRINGIFY_IP - print IP address</p>
+</li>
+<li>
+<p>MG_SOCK_STRINGIFY_PORT - print port number</p>
+</li>
+<li>
+<p>MG_SOCK_STRINGIFY_REMOTE - print remote peer&#8217;s IP/port, not local address</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>If both port number and IP address are printed, they are separated by <code>:</code>.
+If compiled with <code>-DMG_ENABLE_IPV6</code>, IPv6 addresses are supported.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_sock_to_str">mg_sock_to_str()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_sock_to_str(sock_t sock, char *buf, size_t len, int flags);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Legacy interface.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_sock_addr_to_str">mg_sock_addr_to_str()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len,
+                         int flags);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Convert socket&#8217;s address into string.</p>
+</div>
+<div class="paragraph">
+<p><code>flags</code> is MG_SOCK_STRINGIFY_IP and/or MG_SOCK_STRINGIFY_PORT.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_hexdump">mg_hexdump()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_hexdump(const void *buf, int len, char *dst, int dst_len);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Generates human-readable hexdump of memory chunk.</p>
+</div>
+<div class="paragraph">
+<p>Takes a memory buffer <code>buf</code> of length <code>len</code> and creates a hex dump of that
+buffer in <code>dst</code>. Generated output is a-la hexdump(1).
+Return length of generated string, excluding terminating <code>\0</code>. If returned
+length is bigger than <code>dst_len</code>, overflow bytes are discarded.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_hexdump_connection">mg_hexdump_connection()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">void mg_hexdump_connection(struct mg_connection *nc, const char *path,
+                           const void *buf, int num_bytes, int ev);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Generates human-readable hexdump of the data sent or received by connection.
+<code>path</code> is a file name where hexdump should be written. <code>num_bytes</code> is
+a number of bytes sent/received. <code>ev</code> is one of the <code>MG_*</code> events sent to
+an event handler. This function is supposed to be called from the
+event handler.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_avprintf">mg_avprintf()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Print message to buffer. If buffer is large enough to hold the message,
+return buffer. If buffer is to small, allocate large enough buffer on heap,
+and return allocated buffer.
+This is a supposed use case:</p>
+</div>
+<div class="literalblock">
+<div class="content">
+<pre>char buf[5], *p = buf;
+p = mg_avprintf(&amp;p, sizeof(buf), "%s", "hi there");
+use_p_somehow(p);
+if (p != buf) {
+  free(p);
+}</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The purpose of this is to avoid malloc-ing if generated strings are small.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_is_big_endian">mg_is_big_endian()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_is_big_endian(void);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Return true if target platform is big endian.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_next_comma_list_entry">mg_next_comma_list_entry()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
+                                     struct mg_str *eq_val);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>A helper function for traversing a comma separated list of values.
+It returns a list pointer shifted to the next value, or NULL if the end
+of the list found.
+Value is stored in val vector. If value has form "x=y", then eq_val
+vector is initialized to point to the "y" part, and val vector length
+is adjusted to point only to "x".
+If list is just a comma separated list of entries, like "aa,bb,cc" then
+<code>eq_val</code> will contain zero-length string.</p>
+</div>
+<div class="paragraph">
+<p>The purpose of this function is to parse comma separated string without
+any copying/memory allocation.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_match_prefix">mg_match_prefix()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">int mg_match_prefix(const char *pattern, int pattern_len, const char *str);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Match 0-terminated string (mg_match_prefix) or string with given length
+mg_match_prefix_n against a glob pattern.
+Match is case-insensitive. Return number of bytes matched, or -1 if no match.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mk_str">mg_mk_str()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">struct mg_str mg_mk_str(const char *s);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>A helper function for creating mg_str struct from plain C string.
+<code>NULL</code> is allowed and becomes <code>{NULL, 0}</code>.</p>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_mg_mk_str_2">MG_MK_STR()</h4>
+<div class="listingblock">
+<div class="content">
+<pre class="pygments highlight"><code data-lang="c">#define MG_MK_STR(str_literal);</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Macro for initializing mg_str.</p>
+</div>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2016-05-15 22:07:02 EEST
+</div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/internal.adoc b/docs/internal.adoc
new file mode 100644
index 000000000..a0c86672b
--- /dev/null
+++ b/docs/internal.adoc
@@ -0,0 +1,36 @@
+==== mg_do_connect()
+
+[source,c]
+----
+MG_INTERNAL struct mg_connection *mg_do_connect(struct mg_connection *nc,
+                                                int proto,
+                                                union socket_address *sa);
+----
+internals that need to be accessible in unit tests 
+
+==== to_wchar()
+
+[source,c]
+----
+int to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len);
+----
+Retur value is the same as for MultiByteToWideChar. 
+
+==== mg_handle_chunked()
+
+[source,c]
+----
+MG_INTERNAL size_t mg_handle_chunked(struct mg_connection *nc,
+                                     struct http_message *hm, char *buf,
+                                     size_t blen);
+----
+Reassemble the content of the buffer (buf, blen) which should be
+in the HTTP chunked encoding, by collapsing data chunks to the
+beginning of the buffer.
+
+If chunks get reassembled, modify hm->body to point to the reassembled
+body and fire MG_EV_HTTP_CHUNK event. If handler sets MG_F_DELETE_CHUNK
+in nc->flags, delete reassembled body from the mbuf.
+
+Return reassembled body size. 
+
diff --git a/docs/items.json b/docs/items.json
deleted file mode 100644
index 7360d0150..000000000
--- a/docs/items.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "items": [
-    { "type": "section", "name": "usage-example" },
-    { "type": "section", "name": "design-concept" },
-    { "type": "section", "name": "build-options" },
-    { "type": "flat_sections_set", "name": "c-api" }
-  ]
-}
diff --git a/docs/json-rpc.adoc b/docs/json-rpc.adoc
new file mode 100644
index 000000000..e3604b6bc
--- /dev/null
+++ b/docs/json-rpc.adoc
@@ -0,0 +1,143 @@
+=== JSON-RPC 
+
+==== struct mg_rpc_request
+
+[source,c]
+----
+struct mg_rpc_request {
+  struct json_token *message; /* Whole RPC message */
+  struct json_token *id;      /* Message ID */
+  struct json_token *method;  /* Method name */
+  struct json_token *params;  /* Method params */
+};
+----
+JSON-RPC request 
+
+==== struct mg_rpc_reply
+
+[source,c]
+----
+struct mg_rpc_reply {
+  struct json_token *message; /* Whole RPC message */
+  struct json_token *id;      /* Message ID */
+  struct json_token *result;  /* Remote call result */
+};
+----
+JSON-RPC response 
+
+==== struct mg_rpc_error
+
+[source,c]
+----
+struct mg_rpc_error {
+  struct json_token *message;       /* Whole RPC message */
+  struct json_token *id;            /* Message ID */
+  struct json_token *error_code;    /* error.code */
+  struct json_token *error_message; /* error.message */
+  struct json_token *error_data;    /* error.data, can be NULL */
+};
+----
+JSON-RPC error 
+
+==== mg_rpc_parse_reply()
+
+[source,c]
+----
+int mg_rpc_parse_reply(const char *buf, int len, struct json_token *toks,
+                       int max_toks, struct mg_rpc_reply *,
+                       struct mg_rpc_error *);
+----
+Parse JSON-RPC reply contained in `buf`, `len` into JSON tokens array
+`toks`, `max_toks`. If buffer contains valid reply, `reply` structure is
+populated. The result of RPC call is located in `reply.result`. On error,
+`error` structure is populated. Returns: the result of calling
+`parse_json(buf, len, toks, max_toks)`:
+
+On success, an offset inside `json_string` is returned
+where parsing has finished. On failure, a negative number is
+returned, one of:
+
+- `#define JSON_STRING_INVALID           -1`
+- `#define JSON_STRING_INCOMPLETE        -2`
+- `#define JSON_TOKEN_ARRAY_TOO_SMALL    -3` 
+
+==== mg_rpc_create_request()
+
+[source,c]
+----
+int mg_rpc_create_request(char *buf, int len, const char *method,
+                          const char *id, const char *params_fmt, ...);
+----
+Create JSON-RPC request in a given buffer.
+
+Return length of the request, which
+can be larger then `len` that indicates an overflow.
+`params_fmt` format string should conform to `json_emit()` API,
+see https://github.com/cesanta/frozen 
+
+==== mg_rpc_create_reply()
+
+[source,c]
+----
+int mg_rpc_create_reply(char *buf, int len, const struct mg_rpc_request *req,
+                        const char *result_fmt, ...);
+----
+Create JSON-RPC reply in a given buffer.
+
+Return length of the reply, which
+can be larger then `len` that indicates an overflow.
+`result_fmt` format string should conform to `json_emit()` API,
+see https://github.com/cesanta/frozen 
+
+==== mg_rpc_create_error()
+
+[source,c]
+----
+int mg_rpc_create_error(char *buf, int len, struct mg_rpc_request *req,
+                        int code, const char *message, const char *fmt, ...);
+----
+Create JSON-RPC error reply in a given buffer.
+
+Return length of the error, which
+can be larger then `len` that indicates an overflow.
+`fmt` format string should conform to `json_emit()` API,
+see https://github.com/cesanta/frozen 
+
+==== mg_rpc_create_std_error()
+
+[source,c]
+----
+int mg_rpc_create_std_error(char *buf, int len, struct mg_rpc_request *req,
+                            int code);
+----
+Create JSON-RPC error in a given buffer.
+
+Return length of the error, which
+can be larger then `len` that indicates an overflow. See
+JSON_RPC_*_ERROR definitions for standard error values:
+
+- `#define JSON_RPC_PARSE_ERROR (-32700)`
+- `#define JSON_RPC_INVALID_REQUEST_ERROR (-32600)`
+- `#define JSON_RPC_METHOD_NOT_FOUND_ERROR (-32601)`
+- `#define JSON_RPC_INVALID_PARAMS_ERROR (-32602)`
+- `#define JSON_RPC_INTERNAL_ERROR (-32603)`
+- `#define JSON_RPC_SERVER_ERROR (-32000)` 
+
+==== mg_rpc_dispatch()
+
+[source,c]
+----
+int mg_rpc_dispatch(const char *buf, int, char *dst, int dst_len,
+                    const char **methods, mg_rpc_handler_t *handlers);
+----
+Dispatches a JSON-RPC request.
+
+Parses JSON-RPC request contained in `buf`, `len`.
+Then, dispatches the request to the correct handler method.
+Valid method names should be specified in NULL
+terminated array `methods`, and corresponding handlers in `handlers`.
+Result is put in `dst`, `dst_len`. Return: length of the result, which
+can be larger then `dst_len` that indicates an overflow.
+Overflown bytes are not written to the buffer.
+If method is not found, an error is automatically generated. 
+
diff --git a/docs/mbuf.adoc b/docs/mbuf.adoc
new file mode 100644
index 000000000..58ef00acc
--- /dev/null
+++ b/docs/mbuf.adoc
@@ -0,0 +1,85 @@
+=== Memory Buffers
+
+Mbufs are mutable/growing memory buffers, like C++ strings.
+Mbuf can append data to the end of a buffer, or insert data into arbitrary
+position in the middle of a buffer. The buffer grows automatically when
+needed. 
+
+==== struct mbuf
+
+[source,c]
+----
+struct mbuf {
+  char *buf;   /* Buffer pointer */
+  size_t len;  /* Data length. Data is located between offset 0 and len. */
+  size_t size; /* Buffer size allocated by realloc(1). Must be >= len */
+};
+----
+Memory buffer descriptor 
+
+==== mbuf_init()
+
+[source,c]
+----
+void mbuf_init(struct mbuf *, size_t initial_capacity);
+----
+Initialize an Mbuf.
+`initial_capacity` specifies the initial capacity of the mbuf. 
+
+==== mbuf_free()
+
+[source,c]
+----
+void mbuf_free(struct mbuf *);
+----
+Free the space allocated for the mbuffer and resets the mbuf structure. 
+
+==== mbuf_append()
+
+[source,c]
+----
+size_t mbuf_append(struct mbuf *, const void *data, size_t data_size);
+----
+Appends data to the Mbuf.
+
+Return the number of bytes appended, or 0 if out of memory. 
+
+==== mbuf_insert()
+
+[source,c]
+----
+size_t mbuf_insert(struct mbuf *, size_t, const void *, size_t);
+----
+Insert data at a specified offset in the Mbuf.
+
+Existing data will be shifted forwards and the buffer will
+be grown if necessary.
+Return the number of bytes inserted. 
+
+==== mbuf_remove()
+
+[source,c]
+----
+void mbuf_remove(struct mbuf *, size_t data_size);
+----
+Remove `data_size` bytes from the beginning of the buffer. 
+
+==== mbuf_resize()
+
+[source,c]
+----
+void mbuf_resize(struct mbuf *, size_t new_size);
+----
+Resize an Mbuf.
+
+If `new_size` is smaller than buffer's `len`, the
+resize is not performed. 
+
+==== mbuf_trim()
+
+[source,c]
+----
+void mbuf_trim(struct mbuf *);
+----
+Shrink an Mbuf by resizing its `size` to `len`. 
+
diff --git a/docs/mqtt-broker.adoc b/docs/mqtt-broker.adoc
new file mode 100644
index 000000000..122540751
--- /dev/null
+++ b/docs/mqtt-broker.adoc
@@ -0,0 +1,82 @@
+=== MQTT Broker 
+
+==== struct mg_mqtt_session
+
+[source,c]
+----
+struct mg_mqtt_session {
+  struct mg_mqtt_broker *brk;          /* Broker */
+  struct mg_mqtt_session *next, *prev; /* mg_mqtt_broker::sessions linkage */
+  struct mg_connection *nc;            /* Connection with the client */
+  size_t num_subscriptions;            /* Size of `subscriptions` array */
+  struct mg_mqtt_topic_expression *subscriptions;
+  void *user_data; /* User data */
+};
+----
+MQTT session (Broker side). 
+
+==== struct mg_mqtt_broker
+
+[source,c]
+----
+struct mg_mqtt_broker {
+  struct mg_mqtt_session *sessions; /* Session list */
+  void *user_data;                  /* User data */
+};
+----
+MQTT broker. 
+
+==== mg_mqtt_broker_init()
+
+[source,c]
+----
+void mg_mqtt_broker_init(struct mg_mqtt_broker *brk, void *user_data);
+----
+Initialize a MQTT broker. 
+
+==== mg_mqtt_broker()
+
+[source,c]
+----
+void mg_mqtt_broker(struct mg_connection *brk, int ev, void *data);
+----
+Process a MQTT broker message.
+
+Listening connection expects a pointer to an initialized `mg_mqtt_broker`
+structure in the `user_data` field.
+
+Basic usage:
+
+```c
+mg_mqtt_broker_init(&brk, NULL);
+
+if ((nc = mg_bind(&mgr, address, mg_mqtt_broker)) == NULL) {
+  // fail;
+}
+nc->user_data = &brk;
+```
+
+New incoming connections will receive a `mg_mqtt_session` structure
+in the connection `user_data`. The original `user_data` will be stored
+in the `user_data` field of the session structure. This allows the user
+handler to store user data before `mg_mqtt_broker` creates the session.
+
+Since only the MG_EV_ACCEPT message is processed by the listening socket,
+for most events the `user_data` will thus point to a `mg_mqtt_session`. 
+
+==== mg_mqtt_next()
+
+[source,c]
+----
+struct mg_mqtt_session *mg_mqtt_next(struct mg_mqtt_broker *brk,
+                                     struct mg_mqtt_session *s);
+----
+Iterate over all mqtt sessions connections. Example:
+
+```c
+struct mg_mqtt_session *s;
+for (s = mg_mqtt_next(brk, NULL); s != NULL; s = mg_mqtt_next(brk, s)) {
+  // Do something
+}
+``` 
+
diff --git a/docs/mqtt.adoc b/docs/mqtt.adoc
new file mode 100644
index 000000000..466e034dd
--- /dev/null
+++ b/docs/mqtt.adoc
@@ -0,0 +1,161 @@
+=== MQTT 
+
+==== mg_set_protocol_mqtt()
+
+[source,c]
+----
+void mg_set_protocol_mqtt(struct mg_connection *nc);
+----
+Attach built-in MQTT event handler to the given connection.
+
+The user-defined event handler will receive following extra events:
+
+- MG_EV_MQTT_CONNACK
+- MG_EV_MQTT_PUBLISH
+- MG_EV_MQTT_PUBACK
+- MG_EV_MQTT_PUBREC
+- MG_EV_MQTT_PUBREL
+- MG_EV_MQTT_PUBCOMP
+- MG_EV_MQTT_SUBACK 
+
+==== mg_send_mqtt_handshake()
+
+[source,c]
+----
+void mg_send_mqtt_handshake(struct mg_connection *nc, const char *client_id);
+----
+Send MQTT handshake. 
+
+==== mg_send_mqtt_handshake_opt()
+
+[source,c]
+----
+void mg_send_mqtt_handshake_opt(struct mg_connection *nc, const char *client_id,
+                                struct mg_send_mqtt_handshake_opts);
+----
+Send MQTT handshake with optional parameters. 
+
+==== mg_mqtt_publish()
+
+[source,c]
+----
+void mg_mqtt_publish(struct mg_connection *nc, const char *topic,
+                     uint16_t message_id, int flags, const void *data,
+                     size_t len);
+----
+Publish a message to a given topic. 
+
+==== mg_mqtt_subscribe()
+
+[source,c]
+----
+void mg_mqtt_subscribe(struct mg_connection *nc,
+                       const struct mg_mqtt_topic_expression *topics,
+                       size_t topics_len, uint16_t message_id);
+----
+Subscribe to a bunch of topics. 
+
+==== mg_mqtt_unsubscribe()
+
+[source,c]
+----
+void mg_mqtt_unsubscribe(struct mg_connection *nc, char **topics,
+                         size_t topics_len, uint16_t message_id);
+----
+Unsubscribe from a bunch of topics. 
+
+==== mg_mqtt_disconnect()
+
+[source,c]
+----
+void mg_mqtt_disconnect(struct mg_connection *nc);
+----
+Send a DISCONNECT command. 
+
+==== mg_mqtt_connack()
+
+[source,c]
+----
+void mg_mqtt_connack(struct mg_connection *nc, uint8_t return_code);
+----
+Send a CONNACK command with a given `return_code`. 
+
+==== mg_mqtt_puback()
+
+[source,c]
+----
+void mg_mqtt_puback(struct mg_connection *nc, uint16_t message_id);
+----
+Send a PUBACK command with a given `message_id`. 
+
+==== mg_mqtt_pubrec()
+
+[source,c]
+----
+void mg_mqtt_pubrec(struct mg_connection *nc, uint16_t message_id);
+----
+Send a PUBREC command with a given `message_id`. 
+
+==== mg_mqtt_pubrel()
+
+[source,c]
+----
+void mg_mqtt_pubrel(struct mg_connection *nc, uint16_t message_id);
+----
+Send a PUBREL command with a given `message_id`. 
+
+==== mg_mqtt_pubcomp()
+
+[source,c]
+----
+void mg_mqtt_pubcomp(struct mg_connection *nc, uint16_t message_id);
+----
+Send a PUBCOMP command with a given `message_id`. 
+
+==== mg_mqtt_suback()
+
+[source,c]
+----
+void mg_mqtt_suback(struct mg_connection *nc, uint8_t *qoss, size_t qoss_len,
+                    uint16_t message_id);
+----
+Send a SUBACK command with a given `message_id`
+and a sequence of granted QoSs. 
+
+==== mg_mqtt_unsuback()
+
+[source,c]
+----
+void mg_mqtt_unsuback(struct mg_connection *nc, uint16_t message_id);
+----
+Send a UNSUBACK command with a given `message_id`. 
+
+==== mg_mqtt_ping()
+
+[source,c]
+----
+void mg_mqtt_ping(struct mg_connection *nc);
+----
+Send a PINGREQ command. 
+
+==== mg_mqtt_pong()
+
+[source,c]
+----
+void mg_mqtt_pong(struct mg_connection *nc);
+----
+Send a PINGRESP command. 
+
+==== mg_mqtt_next_subscribe_topic()
+
+[source,c]
+----
+int mg_mqtt_next_subscribe_topic(struct mg_mqtt_message *msg,
+                                 struct mg_str *topic, uint8_t *qos, int pos);
+----
+Extract the next topic expression from a SUBSCRIBE command payload.
+
+Topic expression name will point to a string in the payload buffer.
+Return the pos of the next topic expression or -1 when the list
+of topics is exhausted. 
+
diff --git a/docs/net.adoc b/docs/net.adoc
new file mode 100644
index 000000000..ed9b4ca50
--- /dev/null
+++ b/docs/net.adoc
@@ -0,0 +1,499 @@
+=== Core: TCP/UDP/SSL
+
+NOTE: Mongoose manager is single threaded. It does not protect
+its data structures by mutexes, therefore all functions that are dealing
+with particular event manager should be called from the same thread,
+with exception of `mg_broadcast()` function. It is fine to have different
+event managers handled by different threads. 
+
+==== struct mg_str
+
+[source,c]
+----
+struct mg_str {
+  const char *p; /* Memory chunk pointer */
+  size_t len;    /* Memory chunk length */
+};
+----
+Describes chunk of memory 
+
+==== struct mg_mgr
+
+[source,c]
+----
+struct mg_mgr {
+  struct mg_connection *active_connections;
+  const char *hexdump_file; /* Debug hexdump file path */
+#ifndef MG_DISABLE_SOCKETPAIR
+  sock_t ctl[2]; /* Socketpair for mg_wakeup() */
+#endif
+  void *user_data; /* User data */
+  void *mgr_data;  /* Implementation-specific event manager's data. */
+#ifdef MG_ENABLE_JAVASCRIPT
+  struct v7 *v7;
+#endif
+};
+----
+Mongoose event manager. 
+
+==== struct mg_connection
+
+[source,c]
+----
+struct mg_connection {
+  struct mg_connection *next, *prev; /* mg_mgr::active_connections linkage */
+  struct mg_connection *listener;    /* Set only for accept()-ed connections */
+  struct mg_mgr *mgr;                /* Pointer to containing manager */
+
+  sock_t sock; /* Socket to the remote peer */
+  int err;
+  union socket_address sa; /* Remote peer address */
+  size_t recv_mbuf_limit;  /* Max size of recv buffer */
+  struct mbuf recv_mbuf;   /* Received data */
+  struct mbuf send_mbuf;   /* Data scheduled for sending */
+  SSL *ssl;
+  SSL_CTX *ssl_ctx;
+  time_t last_io_time;              /* Timestamp of the last socket IO */
+  double ev_timer_time;             /* Timestamp of the future MG_EV_TIMER */
+  mg_event_handler_t proto_handler; /* Protocol-specific event handler */
+  void *proto_data;                 /* Protocol-specific data */
+  void (*proto_data_destructor)(void *proto_data);
+  mg_event_handler_t handler; /* Event handler function */
+  void *user_data;            /* User-specific data */
+  union {
+    void *v;
+    /*
+     * the C standard is fussy about fitting function pointers into
+     * void pointers, since some archs might have fat pointers for functions.
+     */
+    mg_event_handler_t f;
+  } priv_1;       /* Used by mg_enable_multithreading() */
+  void *priv_2;   /* Used by mg_enable_multithreading() */
+  void *mgr_data; /* Implementation-specific event manager's data. */
+  unsigned long flags;
+/* Flags set by Mongoose */
+#define MG_F_LISTENING (1 << 0)          /* This connection is listening */
+#define MG_F_UDP (1 << 1)                /* This connection is UDP */
+#define MG_F_RESOLVING (1 << 2)          /* Waiting for async resolver */
+#define MG_F_CONNECTING (1 << 3)         /* connect() call in progress */
+#define MG_F_SSL_HANDSHAKE_DONE (1 << 4) /* SSL specific */
+#define MG_F_WANT_READ (1 << 5)          /* SSL specific */
+#define MG_F_WANT_WRITE (1 << 6)         /* SSL specific */
+#define MG_F_IS_WEBSOCKET (1 << 7)       /* Websocket specific */
+
+/* Flags that are settable by user */
+#define MG_F_SEND_AND_CLOSE (1 << 10)      /* Push remaining data and close  */
+#define MG_F_CLOSE_IMMEDIATELY (1 << 11)   /* Disconnect */
+#define MG_F_WEBSOCKET_NO_DEFRAG (1 << 12) /* Websocket specific */
+#define MG_F_DELETE_CHUNK (1 << 13)        /* HTTP specific */
+
+#define MG_F_USER_1 (1 << 20) /* Flags left for application */
+#define MG_F_USER_2 (1 << 21)
+#define MG_F_USER_3 (1 << 22)
+#define MG_F_USER_4 (1 << 23)
+#define MG_F_USER_5 (1 << 24)
+#define MG_F_USER_6 (1 << 25)
+};
+----
+Mongoose connection. 
+
+==== struct mg_add_sock_opts
+
+[source,c]
+----
+struct mg_add_sock_opts {
+  void *user_data;           /* Initial value for connection's user_data */
+  unsigned int flags;        /* Initial connection flags */
+  const char **error_string; /* Placeholder for the error string */
+};
+----
+Optional parameters to `mg_add_sock_opt()`.
+
+`flags` is an initial `struct mg_connection::flags` bitmask to set,
+see `MG_F_*` flags definitions. 
+
+==== struct mg_bind_opts
+
+[source,c]
+----
+struct mg_bind_opts {
+  void *user_data;           /* Initial value for connection's user_data */
+  unsigned int flags;        /* Extra connection flags */
+  const char **error_string; /* Placeholder for the error string */
+#ifdef MG_ENABLE_SSL
+  /* SSL settings. */
+  const char *ssl_cert;    /* Server certificate to present to clients */
+  const char *ssl_ca_cert; /* Verify client certificates with this CA bundle */
+#endif
+};
+----
+Optional parameters to `mg_bind_opt()`.
+
+`flags` is an initial `struct mg_connection::flags` bitmask to set,
+see `MG_F_*` flags definitions. 
+
+==== struct mg_connect_opts
+
+[source,c]
+----
+struct mg_connect_opts {
+  void *user_data;           /* Initial value for connection's user_data */
+  unsigned int flags;        /* Extra connection flags */
+  const char **error_string; /* Placeholder for the error string */
+#ifdef MG_ENABLE_SSL
+  /* SSL settings. */
+  const char *ssl_cert;    /* Client certificate to present to the server */
+  const char *ssl_ca_cert; /* Verify server certificate using this CA bundle */
+
+  /*
+   * Server name verification. If ssl_ca_cert is set and the certificate has
+   * passed verification, its subject will be verified against this string.
+   * By default (if ssl_server_name is NULL) hostname part of the address will
+   * be used. Wildcard matching is supported. A special value of "*" disables
+   * name verification.
+   */
+  const char *ssl_server_name;
+#endif
+};
+----
+Optional parameters to `mg_connect_opt()` 
+
+==== mg_mgr_init()
+
+[source,c]
+----
+void mg_mgr_init(struct mg_mgr *mgr, void *user_data);
+----
+Initialize Mongoose manager. Side effect: ignores SIGPIPE signal.
+`mgr->user_data` field will be initialized with `user_data` parameter.
+That is an arbitrary pointer, where user code can associate some data
+with the particular Mongoose manager. For example, a C++ wrapper class
+could be written, in which case `user_data` can hold a pointer to the
+class instance. 
+
+==== mg_mgr_free()
+
+[source,c]
+----
+void mg_mgr_free(struct mg_mgr *);
+----
+De-initializes Mongoose manager.
+
+Close and deallocate all active connections. 
+
+==== mg_mgr_poll()
+
+[source,c]
+----
+time_t mg_mgr_poll(struct mg_mgr *, int milli);
+----
+This function performs the actual IO, and must be called in a loop
+(an event loop). Returns the current timestamp.
+`milli` is the maximum number of milliseconds to sleep.
+`mg_mgr_poll()` checks all connection for IO readiness. If at least one
+of the connections is IO-ready, `mg_mgr_poll()` triggers respective
+event handlers and returns. 
+
+==== mg_broadcast()
+
+[source,c]
+----
+void mg_broadcast(struct mg_mgr *, mg_event_handler_t func, void *, size_t);
+----
+Pass a message of a given length to all connections.
+
+Must be called from a thread that does NOT call `mg_mgr_poll()`.
+Note that `mg_broadcast()` is the only function
+that can be, and must be, called from a different (non-IO) thread.
+
+`func` callback function will be called by the IO thread for each
+connection. When called, event would be `MG_EV_POLL`, and message will
+be passed as `ev_data` pointer. Maximum message size is capped
+by `MG_CTL_MSG_MESSAGE_SIZE` which is set to 8192 bytes. 
+
+==== mg_next()
+
+[source,c]
+----
+struct mg_connection *mg_next(struct mg_mgr *, struct mg_connection *);
+----
+Iterate over all active connections.
+
+Returns next connection from the list
+of active connections, or `NULL` if there is no more connections. Below
+is the iteration idiom:
+
+```c
+for (c = mg_next(srv, NULL); c != NULL; c = mg_next(srv, c)) {
+  // Do something with connection `c`
+}
+``` 
+
+==== mg_add_sock()
+
+[source,c]
+----
+struct mg_connection *mg_add_sock(struct mg_mgr *, sock_t, mg_event_handler_t);
+----
+Create a connection, associate it with the given socket and event handler,
+and add it to the manager.
+
+For more options see the `mg_add_sock_opt` variant. 
+
+==== mg_add_sock_opt()
+
+[source,c]
+----
+struct mg_connection *mg_add_sock_opt(struct mg_mgr *, sock_t,
+                                      mg_event_handler_t,
+                                      struct mg_add_sock_opts);
+----
+Create a connection, associate it with the given socket and event handler,
+and add to the manager.
+
+See the `mg_add_sock_opts` structure for a description of the options. 
+
+==== mg_bind()
+
+[source,c]
+----
+struct mg_connection *mg_bind(struct mg_mgr *, const char *,
+                              mg_event_handler_t);
+----
+Create listening connection.
+
+See `mg_bind_opt` for full documentation. 
+
+==== mg_bind_opt()
+
+[source,c]
+----
+struct mg_connection *mg_bind_opt(struct mg_mgr *mgr, const char *address,
+                                  mg_event_handler_t handler,
+                                  struct mg_bind_opts opts);
+----
+Create listening connection.
+
+`address` parameter tells which address to bind to. It's format is the same
+as for the `mg_connect()` call, where `HOST` part is optional. `address`
+can be just a port number, e.g. `:8000`. To bind to a specific interface,
+an IP address can be specified, e.g. `1.2.3.4:8000`. By default, a TCP
+connection is created. To create UDP connection, prepend `udp://` prefix,
+e.g. `udp://:8000`. To summarize, `address` paramer has following format:
+`[PROTO://][IP_ADDRESS]:PORT`, where `PROTO` could be `tcp` or `udp`.
+
+See the `mg_bind_opts` structure for a description of the optional
+parameters.
+
+Return a new listening connection, or `NULL` on error.
+NOTE: Connection remains owned by the manager, do not free(). 
+
+==== mg_connect()
+
+[source,c]
+----
+struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *address,
+                                 mg_event_handler_t handler);
+----
+Connect to a remote host.
+
+See `mg_connect_opt()` for full documentation. 
+
+==== mg_connect_opt()
+
+[source,c]
+----
+struct mg_connection *mg_connect_opt(struct mg_mgr *mgr, const char *address,
+                                     mg_event_handler_t handler,
+                                     struct mg_connect_opts opts);
+----
+Connect to a remote host.
+
+`address` format is `[PROTO://]HOST:PORT`. `PROTO` could be `tcp` or `udp`.
+`HOST` could be an IP address,
+IPv6 address (if Mongoose is compiled with `-DMG_ENABLE_IPV6`), or a host
+name. If `HOST` is a name, Mongoose will resolve it asynchronously. Examples
+of valid addresses: `google.com:80`, `udp://1.2.3.4:53`, `10.0.0.1:443`,
+`[::1]:80`
+
+See the `mg_connect_opts` structure for a description of the optional
+parameters.
+
+Returns a new outbound connection, or `NULL` on error.
+
+NOTE: Connection remains owned by the manager, do not free().
+
+NOTE: To enable IPv6 addresses, `-DMG_ENABLE_IPV6` should be specified
+in the compilation flags.
+
+NOTE: New connection will receive `MG_EV_CONNECT` as it's first event
+which will report connect success status.
+If asynchronous resolution fail, or `connect()` syscall fail for whatever
+reason (e.g. with `ECONNREFUSED` or `ENETUNREACH`), then `MG_EV_CONNECT`
+event report failure. Code example below:
+
+```c
+static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
+  int connect_status;
+
+  switch (ev) {
+    case MG_EV_CONNECT:
+      connect_status = * (int *) ev_data;
+      if (connect_status == 0) {
+        // Success
+      } else  {
+        // Error
+        printf("connect() error: %s\n", strerror(connect_status));
+      }
+      break;
+    ...
+  }
+}
+
+  ...
+  mg_connect(mgr, "my_site.com:80", ev_handler);
+``` 
+
+==== mg_set_ssl()
+
+[source,c]
+----
+const char *mg_set_ssl(struct mg_connection *nc, const char *cert,
+                       const char *ca_cert);
+----
+Enable SSL for a given connection.
+`cert` is a server certificate file name for a listening connection,
+or a client certificate file name for an outgoing connection.
+Certificate files must be in PEM format. Server certificate file
+must contain a certificate, concatenated with a private key, optionally
+concatenated with parameters.
+`ca_cert` is a CA certificate, or NULL if peer verification is not
+required.
+Return: NULL on success, or error message on error. 
+
+==== mg_send()
+
+[source,c]
+----
+void mg_send(struct mg_connection *, const void *buf, int len);
+----
+Send data to the connection.
+
+Note that sending functions do not actually push data to the socket.
+They just append data to the output buffer. MG_EV_SEND will be delivered when
+the data has actually been pushed out. 
+
+==== mg_printf()
+
+[source,c]
+----
+int mg_printf(struct mg_connection *, const char *fmt, ...);
+----
+Send `printf`-style formatted data to the connection.
+
+See `mg_send` for more details on send semantics. 
+
+==== mg_vprintf()
+
+[source,c]
+----
+int mg_vprintf(struct mg_connection *, const char *fmt, va_list ap);
+----
+Same as `mg_printf()`, but takes `va_list ap` as an argument. 
+
+==== mg_socketpair()
+
+[source,c]
+----
+int mg_socketpair(sock_t[2], int sock_type);
+----
+Create a socket pair.
+`sock_type` can be either `SOCK_STREAM` or `SOCK_DGRAM`.
+Return 0 on failure, 1 on success. 
+
+==== mg_check_ip_acl()
+
+[source,c]
+----
+int mg_check_ip_acl(const char *acl, uint32_t remote_ip);
+----
+Verify given IP address against the ACL.
+
+`remote_ip` - an IPv4 address to check, in host byte order
+`acl` - a comma separated list of IP subnets: `x.x.x.x/x` or `x.x.x.x`.
+Each subnet is
+prepended by either a - or a + sign. A plus sign means allow, where a
+minus sign means deny. If a subnet mask is omitted, such as `-1.2.3.4`,
+this means to deny only that single IP address.
+Subnet masks may vary from 0 to 32, inclusive. The default setting
+is to allow all accesses. On each request the full list is traversed,
+and the last match wins. Example:
+
+`-0.0.0.0/0,+192.168/16` - deny all acccesses, only allow 192.168/16 subnet
+
+To learn more about subnet masks, see the
+link:https://en.wikipedia.org/wiki/Subnetwork[Wikipedia page on Subnetwork]
+
+Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed. 
+
+==== mg_enable_multithreading()
+
+[source,c]
+----
+void mg_enable_multithreading(struct mg_connection *nc);
+----
+Enable multi-threaded handling for the given listening connection `nc`.
+For each accepted connection, Mongoose will create a separate thread
+and run event handler in that thread. Thus, if an event hanler is doing
+a blocking call or some long computation, that will not slow down
+other connections. 
+
+==== mg_enable_javascript()
+
+[source,c]
+----
+enum v7_err mg_enable_javascript(struct mg_mgr *m, struct v7 *v7,
+                                 const char *init_js_file_name);
+----
+Enable server-side JavaScript scripting.
+Requires `-DMG_ENABLE_JAVASCRIPT` compilation flag, and V7 engine sources.
+v7 instance must not be destroyed during manager's lifetime.
+Return V7 error. 
+
+==== mg_set_timer()
+
+[source,c]
+----
+double mg_set_timer(struct mg_connection *c, double timestamp);
+----
+Schedule MG_EV_TIMER event to be delivered at `timestamp` time.
+`timestamp` is a UNIX time (a number of seconds since Epoch). It is
+`double` instead of `time_t` to allow for sub-second precision.
+Return the old timer value.
+
+Example: set connect timeout to 1.5 seconds:
+
+```
+ c = mg_connect(&mgr, "cesanta.com", ev_handler);
+ mg_set_timer(c, mg_time() + 1.5);
+ ...
+
+ void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
+ switch (ev) {
+   case MG_EV_CONNECT:
+     mg_set_timer(c, 0);  // Clear connect timer
+     break;
+   case MG_EV_TIMER:
+     log("Connect timeout");
+     c->flags |= MG_F_CLOSE_IMMEDIATELY;
+     break;
+``` 
+
+==== mg_time()
+
+[source,c]
+----
+double mg_time();
+----
+A sub-second precision version of time(). 
+
diff --git a/docs/net_if.adoc b/docs/net_if.adoc
new file mode 100644
index 000000000..7666aa2ae
--- /dev/null
+++ b/docs/net_if.adoc
@@ -0,0 +1,127 @@
+==== mg_if_connect_tcp()
+
+[source,c]
+----
+void mg_if_connect_tcp(struct mg_connection *nc,
+                       const union socket_address *sa);
+----
+Request that a TCP connection is made to the specified address. 
+
+==== mg_if_connect_udp()
+
+[source,c]
+----
+void mg_if_connect_udp(struct mg_connection *nc);
+----
+Open a UDP socket. Doesn't actually connect anything. 
+
+==== mg_if_connect_cb()
+
+[source,c]
+----
+void mg_if_connect_cb(struct mg_connection *nc, int err);
+----
+Callback invoked by connect methods. err = 0 -> ok, != 0 -> error. 
+
+==== mg_if_listen_tcp()
+
+[source,c]
+----
+int mg_if_listen_tcp(struct mg_connection *nc, union socket_address *sa);
+----
+Set up a listening TCP socket on a given address. rv = 0 -> ok. 
+
+==== mg_if_accept_new_conn()
+
+[source,c]
+----
+struct mg_connection *mg_if_accept_new_conn(struct mg_connection *lc);
+----
+Deliver a new TCP connection. Returns NULL in case on error (unable to
+create connection, in which case interface state should be discarded.
+This is phase 1 of the two-phase process - MG_EV_ACCEPT will be delivered
+when mg_if_accept_tcp_cb is invoked. 
+
+==== mg_if_listen_udp()
+
+[source,c]
+----
+int mg_if_listen_udp(struct mg_connection *nc, union socket_address *sa);
+----
+Request that a "listening" UDP socket be created. 
+
+==== mg_if_tcp_send()
+
+[source,c]
+----
+void mg_if_tcp_send(struct mg_connection *nc, const void *buf, size_t len);
+----
+Send functions for TCP and UDP. Sent data is copied before return. 
+
+==== mg_if_sent_cb()
+
+[source,c]
+----
+void mg_if_sent_cb(struct mg_connection *nc, int num_sent);
+----
+Callback that reports that data has been put on the wire. 
+
+==== mg_if_recv_tcp_cb()
+
+[source,c]
+----
+void mg_if_recv_tcp_cb(struct mg_connection *nc, void *buf, int len);
+----
+Receive callback.
+buf must be heap-allocated and ownership is transferred to the core.
+Core will acknowledge consumption by calling mg_if_recved. 
+
+==== mg_if_poll()
+
+[source,c]
+----
+void mg_if_poll(struct mg_connection *nc, time_t now);
+----
+Deliver a POLL event to the connection. 
+
+==== mg_if_timer()
+
+[source,c]
+----
+void mg_if_timer(struct mg_connection *c, double now);
+----
+Deliver a TIMER event to the connection. 
+
+==== mg_if_create_conn()
+
+[source,c]
+----
+int mg_if_create_conn(struct mg_connection *nc);
+----
+Perform interface-related connection initialization. Return 1 on success. 
+
+==== mg_if_destroy_conn()
+
+[source,c]
+----
+void mg_if_destroy_conn(struct mg_connection *nc);
+----
+Perform interface-related cleanup on connection before destruction. 
+
+==== mg_if_get_conn_addr()
+
+[source,c]
+----
+void mg_if_get_conn_addr(struct mg_connection *nc, int remote,
+                         union socket_address *sa);
+----
+Put connection's address into *sa, local (remote = 0) or remote. 
+
+==== mg_sock_set()
+
+[source,c]
+----
+void mg_sock_set(struct mg_connection *nc, sock_t sock);
+----
+Associate a socket to a connection. 
+
diff --git a/docs/resolv.adoc b/docs/resolv.adoc
new file mode 100644
index 000000000..ba70bf7aa
--- /dev/null
+++ b/docs/resolv.adoc
@@ -0,0 +1,64 @@
+=== Asynchronouns DNS resolver 
+
+==== struct mg_resolve_async_opts
+
+[source,c]
+----
+struct mg_resolve_async_opts {
+  const char *nameserver_url;
+  int max_retries;    /* defaults to 2 if zero */
+  int timeout;        /* in seconds; defaults to 5 if zero */
+  int accept_literal; /* pseudo-resolve literal ipv4 and ipv6 addrs */
+  int only_literal;   /* only resolves literal addrs; sync cb invocation */
+  struct mg_connection **dns_conn; /* return DNS connection */
+};
+----
+Options for `mg_resolve_async_opt`. 
+
+==== mg_resolve_async()
+
+[source,c]
+----
+int mg_resolve_async(struct mg_mgr *mgr, const char *name, int query,
+                     mg_resolve_callback_t cb, void *data);
+----
+See `mg_resolve_async_opt()` 
+
+==== mg_resolve_async_opt()
+
+[source,c]
+----
+int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query,
+                         mg_resolve_callback_t cb, void *data,
+                         struct mg_resolve_async_opts opts);
+----
+Resolved a DNS name asynchronously.
+
+Upon successful resolution, the user callback will be invoked
+with the full DNS response message and a pointer to the user's
+context `data`.
+
+In case of timeout while performing the resolution the callback
+will receive a NULL `msg`.
+
+The DNS answers can be extracted with `mg_next_record` and
+`mg_dns_parse_record_data`:
+
+[source,c]
+----
+struct in_addr ina;
+struct mg_dns_resource_record *rr = mg_next_record(msg, MG_DNS_A_RECORD,
+  NULL);
+mg_dns_parse_record_data(msg, rr, &ina, sizeof(ina));
+---- 
+
+==== mg_resolve_from_hosts_file()
+
+[source,c]
+----
+int mg_resolve_from_hosts_file(const char *host, union socket_address *usa);
+----
+Resolve a name from `/etc/hosts`.
+
+Returns 0 on success, -1 on failure. 
+
diff --git a/docs/usage-example/intro.md b/docs/tutorial.adoc
similarity index 53%
rename from docs/usage-example/intro.md
rename to docs/tutorial.adoc
index 410e0657a..9ade7b6a2 100644
--- a/docs/usage-example/intro.md
+++ b/docs/tutorial.adoc
@@ -1,16 +1,16 @@
----
-title: Usage Example
----
 
-- Copy `mongoose.c` and `mongoose.h` to your build tree
-- Write code that uses Mongoose API, e.g. in `my_app.c`
-- Compile application: `$ cc my_app.c mongoose.c`
+== Usage Example
 
-```c
-#include "mongoose.h"  // Include Mongoose API definitions
+1. Copy `mongoose.c` and `mongoose.h` to your build tree
+2. Write code that uses Mongoose API, e.g. in `my_app.c`
+3. Compile application: `$ cc my_app.c mongoose.c`
 
-// Define an event handler function
-static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
+[source,c]
+.my_app.c
+----
+#include "mongoose.h"  // <1>
+
+static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { // <2>
   struct mbuf *io = &nc->recv_mbuf;
 
   switch (ev) {
@@ -27,18 +27,23 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
 int main(void) {
   struct mg_mgr mgr;
 
-  mg_mgr_init(&mgr, NULL);  // Initialize event manager object
+  mg_mgr_init(&mgr, NULL);  // <3>
 
   // Note that many connections can be added to a single event manager
   // Connections can be created at any point, e.g. in event handler function
-  mg_bind(&mgr, "1234", ev_handler);  // Create listening connection and add it to the event manager
+  mg_bind(&mgr, "1234", ev_handler);  // <4>
 
-  for (;;) {  // Start infinite event loop
+  for (;;) {  // <5>
     mg_mgr_poll(&mgr, 1000);
   }
 
   mg_mgr_free(&mgr);
   return 0;
 }
-```
+----
 
+<1> Include Mongoose API definitions
+<2> Define an event handler function
+<3> Initialize event manager object
+<4> Create listening connection and add it to the event manager
+<5> Start infinite event loop
diff --git a/docs/uri.adoc b/docs/uri.adoc
new file mode 100644
index 000000000..c7173cad2
--- /dev/null
+++ b/docs/uri.adoc
@@ -0,0 +1,33 @@
+=== URI 
+
+==== mg_parse_uri()
+
+[source,c]
+----
+int mg_parse_uri(struct mg_str uri, struct mg_str *scheme,
+                 struct mg_str *user_info, struct mg_str *host,
+                 unsigned int *port, struct mg_str *path, struct mg_str *query,
+                 struct mg_str *fragment);
+----
+Parses an URI and fills string chunks with locations of the respective
+uri components within the input uri string. NULL pointers will be
+ignored.
+
+General syntax:
+
+    [scheme://[user_info@]]host[:port][/path][?query][#fragment]
+
+Example:
+
+    foo.com:80
+    tcp://foo.com:1234
+    http://foo.com:80/bar?baz=1
+    https://user:pw@foo.com:443/blah
+
+`path` will include the leading slash. `query` won't include the leading `?`.
+`host` can contain embedded colons if surrounded by square brackets in order
+to support IPv6 literal addresses.
+
+
+Returns 0 on success, -1 on error. 
+
diff --git a/docs/usage-example/items.json b/docs/usage-example/items.json
deleted file mode 100644
index bc7e70d8d..000000000
--- a/docs/usage-example/items.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "items": [
-    { "type": "markdown", "name": "intro.md" }
-  ]
-}
diff --git a/docs/util.adoc b/docs/util.adoc
new file mode 100644
index 000000000..24e75c62b
--- /dev/null
+++ b/docs/util.adoc
@@ -0,0 +1,260 @@
+=== Utilities 
+
+==== mg_skip()
+
+[source,c]
+----
+const char *mg_skip(const char *s, const char *end_string,
+                    const char *delimiters, struct mg_str *v);
+----
+Fetch substring from input string `s`, `end` into `v`.
+Skips initial delimiter characters. Records first non-delimiter character
+as the beginning of substring `v`. Then scans the rest of the string
+until a delimiter character or end-of-string is found.
+`delimiters` is a 0-terminated string containing delimiter characters.
+Either one of `delimiters` or `end_string` terminates the search.
+Return an `s` pointer, advanced forward where parsing stopped. 
+
+==== mg_ncasecmp()
+
+[source,c]
+----
+int mg_ncasecmp(const char *s1, const char *s2, size_t len);
+----
+Cross-platform version of `strncasecmp()`. 
+
+==== mg_casecmp()
+
+[source,c]
+----
+int mg_casecmp(const char *s1, const char *s2);
+----
+Cross-platform version of `strcasecmp()`. 
+
+==== mg_vcmp()
+
+[source,c]
+----
+int mg_vcmp(const struct mg_str *str2, const char *str1);
+----
+Cross-platform version of `strcmp()` where where first string is
+specified by `struct mg_str`. 
+
+==== mg_vcasecmp()
+
+[source,c]
+----
+int mg_vcasecmp(const struct mg_str *str2, const char *str1);
+----
+Cross-platform version of `strncasecmp()` where first string is
+specified by `struct mg_str`. 
+
+==== mg_base64_decode()
+
+[source,c]
+----
+int mg_base64_decode(const unsigned char *s, int len, char *dst);
+----
+Decode base64-encoded string `s`, `len` into the destination `dst`.
+Destination has to have enough space to hold decoded buffer.
+Decoding stops either when all string has been decoded, or invalid
+character appeared.
+Destination is '\0'-terminated.
+Return number of decoded characters. On success, that should be equal to
+`len`. On error (invalid character) the return value is smaller then `len`. 
+
+==== mg_base64_encode()
+
+[source,c]
+----
+void mg_base64_encode(const unsigned char *src, int src_len, char *dst);
+----
+Base64-encode chunk of memory `src`, `src_len` into the destination `dst`.
+Destination has to have enough space to hold encoded buffer.
+Destination is '\0'-terminated. 
+
+==== mg_stat()
+
+[source,c]
+----
+int mg_stat(const char *path, cs_stat_t *st);
+----
+Perform a 64-bit `stat()` call against given file.
+
+`path` should be UTF8 encoded.
+
+Return value is the same as for `stat()` syscall. 
+
+==== mg_fopen()
+
+[source,c]
+----
+FILE *mg_fopen(const char *path, const char *mode);
+----
+Open the given file and return a file stream.
+
+`path` and `mode` should be UTF8 encoded.
+
+Return value is the same as for the `fopen()` call. 
+
+==== mg_open()
+
+[source,c]
+----
+int mg_open(const char *path, int flag, int mode);
+----
+Open the given file and return a file stream.
+
+`path` should be UTF8 encoded.
+
+Return value is the same as for the `open()` syscall. 
+
+==== mg_start_thread()
+
+[source,c]
+----
+void *mg_start_thread(void *(*thread_func);
+----
+Start a new detached thread.
+Arguments and semantic is the same as pthead's `pthread_create()`.
+`thread_func` is a thread function, `thread_func_param` is a parameter
+that is passed to the thread function. 
+
+==== mg_conn_addr_to_str()
+
+[source,c]
+----
+void mg_conn_addr_to_str(struct mg_connection *nc, char *buf, size_t len,
+                         int flags);
+----
+Convert connection's local or remote address into string.
+
+The `flags` parameter is a bit mask that controls the behavior,
+see `MG_SOCK_STRINGIFY_*` definitions.
+
+- MG_SOCK_STRINGIFY_IP - print IP address
+- MG_SOCK_STRINGIFY_PORT - print port number
+- MG_SOCK_STRINGIFY_REMOTE - print remote peer's IP/port, not local address
+
+If both port number and IP address are printed, they are separated by `:`.
+If compiled with `-DMG_ENABLE_IPV6`, IPv6 addresses are supported. 
+
+==== mg_sock_to_str()
+
+[source,c]
+----
+void mg_sock_to_str(sock_t sock, char *buf, size_t len, int flags);
+----
+Legacy interface. 
+
+==== mg_sock_addr_to_str()
+
+[source,c]
+----
+void mg_sock_addr_to_str(const union socket_address *sa, char *buf, size_t len,
+                         int flags);
+----
+Convert socket's address into string.
+
+`flags` is MG_SOCK_STRINGIFY_IP and/or MG_SOCK_STRINGIFY_PORT. 
+
+==== mg_hexdump()
+
+[source,c]
+----
+int mg_hexdump(const void *buf, int len, char *dst, int dst_len);
+----
+Generates human-readable hexdump of memory chunk.
+
+Takes a memory buffer `buf` of length `len` and creates a hex dump of that
+buffer in `dst`. Generated output is a-la hexdump(1).
+Return length of generated string, excluding terminating `\0`. If returned
+length is bigger than `dst_len`, overflow bytes are discarded. 
+
+==== mg_hexdump_connection()
+
+[source,c]
+----
+void mg_hexdump_connection(struct mg_connection *nc, const char *path,
+                           const void *buf, int num_bytes, int ev);
+----
+Generates human-readable hexdump of the data sent or received by connection.
+`path` is a file name where hexdump should be written. `num_bytes` is
+a number of bytes sent/received. `ev` is one of the `MG_*` events sent to
+an event handler. This function is supposed to be called from the
+event handler. 
+
+==== mg_avprintf()
+
+[source,c]
+----
+int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
+----
+Print message to buffer. If buffer is large enough to hold the message,
+return buffer. If buffer is to small, allocate large enough buffer on heap,
+and return allocated buffer.
+This is a supposed use case:
+
+   char buf[5], *p = buf;
+   p = mg_avprintf(&p, sizeof(buf), "%s", "hi there");
+   use_p_somehow(p);
+   if (p != buf) {
+     free(p);
+   }
+
+The purpose of this is to avoid malloc-ing if generated strings are small. 
+
+==== mg_is_big_endian()
+
+[source,c]
+----
+int mg_is_big_endian(void);
+----
+Return true if target platform is big endian. 
+
+==== mg_next_comma_list_entry()
+
+[source,c]
+----
+const char *mg_next_comma_list_entry(const char *list, struct mg_str *val,
+                                     struct mg_str *eq_val);
+----
+A helper function for traversing a comma separated list of values.
+It returns a list pointer shifted to the next value, or NULL if the end
+of the list found.
+Value is stored in val vector. If value has form "x=y", then eq_val
+vector is initialized to point to the "y" part, and val vector length
+is adjusted to point only to "x".
+If list is just a comma separated list of entries, like "aa,bb,cc" then
+`eq_val` will contain zero-length string.
+
+The purpose of this function is to parse comma separated string without
+any copying/memory allocation. 
+
+==== mg_match_prefix()
+
+[source,c]
+----
+int mg_match_prefix(const char *pattern, int pattern_len, const char *str);
+----
+Match 0-terminated string (mg_match_prefix) or string with given length
+mg_match_prefix_n against a glob pattern.
+Match is case-insensitive. Return number of bytes matched, or -1 if no match. 
+
+==== mg_mk_str()
+
+[source,c]
+----
+struct mg_str mg_mk_str(const char *s);
+----
+A helper function for creating mg_str struct from plain C string.
+`NULL` is allowed and becomes `{NULL, 0}`. 
+
+==== MG_MK_STR()
+
+[source,c]
+----
+#define MG_MK_STR(str_literal);
+----
+Macro for initializing mg_str. 
+
-- 
GitLab