From 5385e266cc3d79709a7afdfbb0b0a435df43a73c Mon Sep 17 00:00:00 2001 From: Jaikinator Date: Mon, 18 Sep 2023 15:29:09 +0200 Subject: [PATCH 01/18] renamed module --- app.py | 6 +- app2.py | 317 ++++++++++++++++++ autotranscript/.pyannotetoken | 0 scraibe/.pyannotetoken | 1 + {autotranscript => scraibe}/__init__.py | 0 .../app/Logo_KIDA_bmel_green.svg | 0 {autotranscript => scraibe}/app/__init__.py | 0 {autotranscript => scraibe}/app/gradio_app.py | 2 +- {autotranscript => scraibe}/app/header.html | 0 .../app/qtfaststart.py | 0 {autotranscript => scraibe}/audio.py | 0 {autotranscript => scraibe}/autotranscript.py | 3 - {autotranscript => scraibe}/cli.py | 0 {autotranscript => scraibe}/diarisation.py | 0 {autotranscript => scraibe}/misc.py | 0 {autotranscript => scraibe}/transcriber.py | 0 .../transcript_exporter.py | 0 {autotranscript => scraibe}/version.py | 138 ++++---- setup.py | 6 +- test_autotranscript.py | 6 +- transcribe.py | 6 +- 21 files changed, 399 insertions(+), 86 deletions(-) create mode 100644 app2.py delete mode 100644 autotranscript/.pyannotetoken create mode 100644 scraibe/.pyannotetoken rename {autotranscript => scraibe}/__init__.py (100%) rename {autotranscript => scraibe}/app/Logo_KIDA_bmel_green.svg (100%) rename {autotranscript => scraibe}/app/__init__.py (100%) rename {autotranscript => scraibe}/app/gradio_app.py (99%) rename {autotranscript => scraibe}/app/header.html (100%) rename {autotranscript => scraibe}/app/qtfaststart.py (100%) rename {autotranscript => scraibe}/audio.py (100%) rename {autotranscript => scraibe}/autotranscript.py (99%) rename {autotranscript => scraibe}/cli.py (100%) rename {autotranscript => scraibe}/diarisation.py (100%) rename {autotranscript => scraibe}/misc.py (100%) rename {autotranscript => scraibe}/transcriber.py (100%) rename {autotranscript => scraibe}/transcript_exporter.py (100%) rename {autotranscript => scraibe}/version.py (95%) diff --git a/app.py b/app.py index 3645d79..c9beffe 100644 --- a/app.py +++ b/app.py @@ -1,12 +1,12 @@ from dash import Dash, dcc, html, dash_table, Input, Output, State, callback import base64 -from autotranscript.app.qtfaststart import process -from autotranscript import AutoTranscribe +from scraibe.app.qtfaststart import process +from scraibe import AutoTranscribe import io import subprocess as sp import numpy as np -from autotranscript.audio import SAMPLE_RATE +from scraibe.audio import SAMPLE_RATE # Setup auto-transcript autot = AutoTranscribe() # whisper_model="tiny", whisper_kwargs={"local" : False} diff --git a/app2.py b/app2.py new file mode 100644 index 0000000..55cb11b --- /dev/null +++ b/app2.py @@ -0,0 +1,317 @@ +""" +Gradio Audio Transcription App. +-------------------------------- + +This module provides an interface to transcribe audio files using the +AutoTranscribe model. Users can either upload an audio file or record their speech +live for transcription. The application supports multiple languages and provides +options to specify the number of speakers and the language of the audio. + +Attributes: + LANGUAGES (list): A list of supported languages for transcription. + +Usage: + Run this script to start the Gradio web interface for audio transcription. + +""" + + +import json + +import gradio as gr +from scraibe import AutoTranscribe, Transcript + + + +theme = gr.themes.Soft( + primary_hue="green", + secondary_hue='orange', + neutral_hue="gray", + +) +LANGUAGES = [ + "Afrikaans", "Arabic", "Armenian", "Azerbaijani", "Belarusian", + "Bosnian", "Bulgarian", "Catalan", "Chinese", "Croatian", + "Czech", "Danish", "Dutch", "English", "Estonian", + "Finnish", "French", "Galician", "German", "Greek", + "Hebrew", "Hindi", "Hungarian", "Icelandic", "Indonesian", + "Italian", "Japanese", "Kannada", "Kazakh", "Korean", + "Latvian", "Lithuanian", "Macedonian", "Malay", "Marathi", + "Maori", "Nepali", "Norwegian", "Persian", "Polish", + "Portuguese", "Romanian", "Russian", "Serbian", "Slovak", + "Slovenian", "Spanish", "Swahili", "Swedish", "Tagalog", + "Tamil", "Thai", "Turkish", "Ukrainian", "Urdu", + "Vietnamese", "Welsh" +] + +class GradioTranscriptionInterface: + """ + Interface handling the interaction between Gradio UI and the Audio Transcription system. + """ + + def __init__(self, model: AutoTranscribe = AutoTranscribe()): + """ + Initializes the GradioTranscriptionInterface with a transcription model. + + Args: + model (AutoTranscribe): Model responsible for audio transcription tasks. + """ + self.model = model + + def auto_transcribe(self, source, + num_speakers : int, + translation : bool, + language : str): + """ + Shortcut method for the AutoTranscribe task. + + Returns: + tuple: Transcribed text (str), JSON output (dict) + """ + + kwargs = { + "num_speakers": num_speakers if num_speakers != 0 else None, + "language": language if language != "None" else None, + "task": 'translate' if translation else None + } + + try: + result = self.model.autotranscribe(source, **kwargs) + except ValueError: + raise gr.Error("Couldn't detect any speech in the provided audio. \ + Please try again!") + return str(result), result.get_json() + + + def transcribe(self, source, translation, language): + """ + Shortcut method for the Transcribe task. + + Returns: + str: Transcribed text. + """ + kwargs = { + "language": language if language != "None" else None, + "task": 'translate' if translation == "Yes" else None + } + + result = self.model.transcribe(source, **kwargs) + return str(result) + + def perform_diarisation(self, source, num_speakers): + """ + Shortcut method for the Diarisation task. + + Returns: + str: JSON output of diarisation result. + """ + kwargs = { + "num_speakers": num_speakers if num_speakers != 0 else None, + } + + + try: + result = self.model.diarization(source, **kwargs) + except ValueError: + raise gr.Error("Couldn't detect any speech in the provided audio. \ + Please try again!") + return json.dumps(result, indent=2) + +#### +# Gradio Interface +#### + +pipe = GradioTranscriptionInterface() + + +def select_task(choice): + if choice == 'Auto Transcribe': + + return (gr.update(visible = True), + gr.update(visible = True), + gr.update(visible = True)) + + + elif choice == 'Transcribe': + + return (gr.update(visible = False), + gr.update(visible = True), + gr.update(visible = True)) + + + elif choice == 'Diarisation': + + return (gr.update(visible = True), + gr.update(visible = False), + gr.update(visible = False)) + +def select_origin(choice): + if choice == "Upload Audio": + + return (gr.update(visible = True), + gr.update(visible = False, value = None), + gr.update(visible = False, value = None), + gr.update(visible = False, value = None), + gr.update(visible = False, value = None)) + + elif choice == "Record Audio": + + return (gr.update(visible = False, value = None), + gr.update(visible = True), + gr.update(visible = False, value = None), + gr.update(visible = False, value = None), + gr.update(visible = False, value = None)) + + elif choice == "Upload Video": + + return (gr.update(visible = False, value = None), + gr.update(visible = False, value = None), + gr.update(visible = True), + gr.update(visible = False, value = None), + gr.update(visible = False, value = None)) + + elif choice == "Record Video": + + return (gr.update(visible = False, value = None), + gr.update(visible = False, value = None), + gr.update(visible = False, value = None), + gr.update(visible = True), + gr.update(visible = False, value = None)) + + elif choice == "File": + + return (gr.update(visible = False, value = None), + gr.update(visible = False, value = None), + gr.update(visible = False, value = None), + gr.update(visible = False, value = None), + gr.update(visible = True)) + +def run_scribe(task, num_speakers, translate, language, audio1, audio2, video1, video2, file_in, progress = gr.Progress(track_tqdm= True)): + # get *args which are not None + progress(0, desc='Starting task...') + source = audio1 or audio2 or video1 or video2 or file_in + + if task == 'Auto Transcribe': + + out_str , out_json = pipe.auto_transcribe(source = source, + num_speakers = num_speakers, + translation = translate, + language = language) + + return (gr.update(value = out_str, visible = True), + gr.update(value = out_json, visible = True), + gr.update(visible = True), + gr.update(visible = True)) + + elif task == 'Transcribe': + + out = pipe.transcribe(source = source, + translation = translate, + language = language) + + return (gr.update(value = out, visible = True), + gr.update(value = None, visible = False), + gr.update(visible = False), + gr.update(visible = False)) + + elif task == 'Diarisation': + + out = pipe.perform_diarisation(source = source, + num_speakers = num_speakers) + + return (gr.update(value = None, visible = False), + gr.update(value = out, visible = True), + gr.update(visible = False), + gr.update(visible = False)) + +def annotate_output(annoation : str, out_json : dict): + # get *args which are not None + + trans = Transcript.from_json(out_json) + trans = trans.annotate(*annoation.split(",")) + + return gr.update(value = str(trans)),gr.update(value = trans.get_json()) + + +with gr.Blocks(theme=theme,title='ScrAIbe: Automatic Audio Transcription') as demo: + + # Define components + header = open("header.html", "r").read() + gr.HTML(header, visible= True, show_label=False) + + with gr.Row(): + + with gr.Column(): + + task = gr.Radio(["Auto Transcribe", "Transcribe", "Diarisation"], label="Task", + value= 'Auto Transcribe') + + num_speakers = gr.Number(value=0, label= "Number of speakers (optional)", + info = "Number of speakers in the audio file. If you don't know,\ + leave it at 0.", visible= True) + + translate = gr.Checkbox(label="Translation", choices=[True, False], value = False, + info="Select 'Yes' to have the output translated into English.", + visible= True) + + language = gr.Dropdown(LANGUAGES, + label="Language (optional)", value = "None", + info="Language of the audio file. If you don't know,\ + leave it at None.", visible= True) + + input = gr.Radio(["Upload Audio", "Record Audio", "Upload Video","Record Video" + ,"File"], label="Input Type", value="Upload Audio") + + audio1 = gr.Audio(source="upload", type="filepath", label="Upload Audio", + interactive= True, visible= True) + audio2 = gr.Audio(source="microphone", label="Record Audio", type="filepath", + interactive= True, visible= False) + video1 = gr.Video(source="upload", type="filepath", label="Upload Video", + interactive= True, visible= False) + video2 = gr.Video(source="webcam", label="Record Video", type="filepath", + interactive= True, visible= False) + file_in = gr.File(label="Upload File", interactive= True, visible= False) + + submit = gr.Button() + + with gr.Column(): + + out_txt = gr.Textbox(label="Output", + visible= True, show_copy_button=True) + + out_json = gr.JSON(label="JSON Output", + visible= False, show_copy_button=True) + + annoation = gr.Textbox(label="Name your speaker's", + info= "Please provide a list of the speakers arranged \ + in the order in which they appear in the input. Use comma ',' \ + as a seperator. Be aware that the first name is given \ + to SPEAKER_00 the second to SPEAKER_01 and so on.", + visible= False, interactive= True) + + annotate = gr.Button(value="Annotate", visible= False, interactive= True) + + # Define usage of components + input.change(fn=select_origin, inputs=[input], + outputs=[audio1, audio2, video1, video2, file_in]) + + task.change(fn=select_task, inputs=[task], + outputs=[num_speakers, translate, language]) + + translate.change(fn= lambda x : gr.update(value = x), + inputs=[translate], outputs=[translate]) + num_speakers.change(fn= lambda x : gr.update(value = x), + inputs=[num_speakers], outputs=[num_speakers]) + language.change(fn= lambda x : gr.update(value = x), + inputs=[language], outputs=[language]) + + submit.click(fn = run_scribe, + inputs=[task, num_speakers, translate, language, audio1, + audio2, video1, video2, file_in], + outputs=[out_txt, out_json, annoation, annotate]) + + annotate.click(fn = annotate_output, inputs=[annoation, out_json], + outputs=[out_txt, out_json]) + + +demo.queue().launch() \ No newline at end of file diff --git a/autotranscript/.pyannotetoken b/autotranscript/.pyannotetoken deleted file mode 100644 index e69de29..0000000 diff --git a/scraibe/.pyannotetoken b/scraibe/.pyannotetoken new file mode 100644 index 0000000..42ba269 --- /dev/null +++ b/scraibe/.pyannotetoken @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/autotranscript/__init__.py b/scraibe/__init__.py similarity index 100% rename from autotranscript/__init__.py rename to scraibe/__init__.py diff --git a/autotranscript/app/Logo_KIDA_bmel_green.svg b/scraibe/app/Logo_KIDA_bmel_green.svg similarity index 100% rename from autotranscript/app/Logo_KIDA_bmel_green.svg rename to scraibe/app/Logo_KIDA_bmel_green.svg diff --git a/autotranscript/app/__init__.py b/scraibe/app/__init__.py similarity index 100% rename from autotranscript/app/__init__.py rename to scraibe/app/__init__.py diff --git a/autotranscript/app/gradio_app.py b/scraibe/app/gradio_app.py similarity index 99% rename from autotranscript/app/gradio_app.py rename to scraibe/app/gradio_app.py index 13a6ee1..6f09506 100644 --- a/autotranscript/app/gradio_app.py +++ b/scraibe/app/gradio_app.py @@ -35,7 +35,7 @@ Usage: import json import gradio as gr -from autotranscript import AutoTranscribe, Transcript +from scraibe import AutoTranscribe, Transcript theme = gr.themes.Soft( diff --git a/autotranscript/app/header.html b/scraibe/app/header.html similarity index 100% rename from autotranscript/app/header.html rename to scraibe/app/header.html diff --git a/autotranscript/app/qtfaststart.py b/scraibe/app/qtfaststart.py similarity index 100% rename from autotranscript/app/qtfaststart.py rename to scraibe/app/qtfaststart.py diff --git a/autotranscript/audio.py b/scraibe/audio.py similarity index 100% rename from autotranscript/audio.py rename to scraibe/audio.py diff --git a/autotranscript/autotranscript.py b/scraibe/autotranscript.py similarity index 99% rename from autotranscript/autotranscript.py rename to scraibe/autotranscript.py index d27dba8..f588e42 100644 --- a/autotranscript/autotranscript.py +++ b/scraibe/autotranscript.py @@ -126,7 +126,6 @@ class AutoTranscribe: diarisation = self.diariser.diarization(dia_audio, **kwargs) - if not diarisation["segments"]: print("No segments found. Try to run transcription without diarisation.") @@ -145,8 +144,6 @@ class AutoTranscribe: # Transcribe each segment and store the results final_transcript = dict() - - for i in trange(len(diarisation["segments"]), desc= "Transcribing"): seg = diarisation["segments"][i] diff --git a/autotranscript/cli.py b/scraibe/cli.py similarity index 100% rename from autotranscript/cli.py rename to scraibe/cli.py diff --git a/autotranscript/diarisation.py b/scraibe/diarisation.py similarity index 100% rename from autotranscript/diarisation.py rename to scraibe/diarisation.py diff --git a/autotranscript/misc.py b/scraibe/misc.py similarity index 100% rename from autotranscript/misc.py rename to scraibe/misc.py diff --git a/autotranscript/transcriber.py b/scraibe/transcriber.py similarity index 100% rename from autotranscript/transcriber.py rename to scraibe/transcriber.py diff --git a/autotranscript/transcript_exporter.py b/scraibe/transcript_exporter.py similarity index 100% rename from autotranscript/transcript_exporter.py rename to scraibe/transcript_exporter.py diff --git a/autotranscript/version.py b/scraibe/version.py similarity index 95% rename from autotranscript/version.py rename to scraibe/version.py index 0a3730e..b3cf626 100644 --- a/autotranscript/version.py +++ b/scraibe/version.py @@ -1,69 +1,69 @@ -import os -import subprocess as sp - -MAJOR = 0 -MINOR = 1 -MICRO = 0 -MICRO_POST = 0 -ISRELEASED = False -VERSION = '%d.%d.%d.%d' % (MAJOR, MINOR, MICRO, MICRO_POST) - -# Return the git revision as a string -# taken from numpy/numpy -def git_version(): - def _minimal_ext_cmd(cmd): - # construct minimal environment - env = {} - for k in ['SYSTEMROOT', 'PATH', 'HOME']: - v = os.environ.get(k) - if v is not None: - env[k] = v - - # LANGUAGE is used on win32 - env['LANGUAGE'] = 'C' - env['LANG'] = 'C' - env['LC_ALL'] = 'C' - - out = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE, env=env).communicate()[0] - return out - - try: - out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD']) - GIT_REVISION = out.strip().decode('ascii') - except OSError: - GIT_REVISION = "Unknown" - - return GIT_REVISION - -def _get_git_version(): - cwd = os.getcwd() - - # go to the main directory - fdir = os.path.dirname(os.path.abspath(__file__)) - maindir = os.path.abspath(os.path.join(fdir, "..")) - # maindir = fdir # os.path.join(fdir, "..") - os.chdir(maindir) - - # get git version - res = git_version() - - # restore the cwd - os.chdir(cwd) - return res - -def get_version(build_version=False): - if ISRELEASED: - return VERSION - - # unreleased version - GIT_REVISION = _get_git_version() - - if build_version: - import datetime as dt - date = dt.date.strftime(dt.datetime.now(), "%Y%m%d%H%M%S") - return VERSION + ".dev" + date - else: - return VERSION + ".dev0+" + GIT_REVISION[:7] - - - +import os +import subprocess as sp + +MAJOR = 0 +MINOR = 1 +MICRO = 0 +MICRO_POST = 0 +ISRELEASED = False +VERSION = '%d.%d.%d.%d' % (MAJOR, MINOR, MICRO, MICRO_POST) + +# Return the git revision as a string +# taken from numpy/numpy +def git_version(): + def _minimal_ext_cmd(cmd): + # construct minimal environment + env = {} + for k in ['SYSTEMROOT', 'PATH', 'HOME']: + v = os.environ.get(k) + if v is not None: + env[k] = v + + # LANGUAGE is used on win32 + env['LANGUAGE'] = 'C' + env['LANG'] = 'C' + env['LC_ALL'] = 'C' + + out = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE, env=env).communicate()[0] + return out + + try: + out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD']) + GIT_REVISION = out.strip().decode('ascii') + except OSError: + GIT_REVISION = "Unknown" + + return GIT_REVISION + +def _get_git_version(): + cwd = os.getcwd() + + # go to the main directory + fdir = os.path.dirname(os.path.abspath(__file__)) + maindir = os.path.abspath(os.path.join(fdir, "..")) + # maindir = fdir # os.path.join(fdir, "..") + os.chdir(maindir) + + # get git version + res = git_version() + + # restore the cwd + os.chdir(cwd) + return res + +def get_version(build_version=False): + if ISRELEASED: + return VERSION + + # unreleased version + GIT_REVISION = _get_git_version() + + if build_version: + import datetime as dt + date = dt.date.strftime(dt.datetime.now(), "%Y%m%d%H%M%S") + return VERSION + ".dev" + date + else: + return VERSION + ".dev0+" + GIT_REVISION[:7] + + + diff --git a/setup.py b/setup.py index 05a7f77..6efaf3b 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ import pkg_resources import os from setuptools import setup, find_packages -module_name = "autotranscript" +module_name = "scraibe" github_url = "https://github.com/JSchmie/autotranscript" file_dir = os.path.dirname(os.path.realpath(__file__)) @@ -18,7 +18,7 @@ with open(verfile, "r") as fp: ############### setup ############### -build_version = "AUTOTRANSCRIPT_BUILD" in os.environ +build_version = "SCRAIBE_BUILD" in os.environ if __name__ == "__main__": @@ -42,5 +42,5 @@ if __name__ == "__main__": description='Transcription tool for audio files based on Whisper and Pyannote', package_data={ "header" : ["app/header.html"], "logo" : ["app/Logo_KIDA_bmel_green.svg"]}, entry_points={'console_scripts': - ['autotranscript = autotranscript.cli:cli']} + ['scraibe = scraibe.cli:cli']} ) diff --git a/test_autotranscript.py b/test_autotranscript.py index 8f745a0..475f4de 100644 --- a/test_autotranscript.py +++ b/test_autotranscript.py @@ -1,5 +1,5 @@ import pytest -from autotranscript import Transcriber +from scraibe import Transcriber from unittest.mock import patch, mock_open import os @@ -55,7 +55,7 @@ def test_save_transcript_to_file(transcriber): # Test Diaraization class -from autotranscript import Diariser +from scraibe import Diariser @pytest.fixture def diarisation(): @@ -83,7 +83,7 @@ def test_diarisation(diarisation): # Test AudioProcessor -from autotranscript import AudioProcessor , TorchAudioProcessor +from scraibe import AudioProcessor , TorchAudioProcessor def test_AudioProcessor_init(): diff --git a/transcribe.py b/transcribe.py index 73d8838..094dcfe 100644 --- a/transcribe.py +++ b/transcribe.py @@ -18,16 +18,14 @@ # os.environ['HF_HOME'] = os.path.expanduser("~/PycharmProjects/autotranscript/autotranscript/models") -from autotranscript import AutoTranscribe - +from scraibe import AutoTranscribe model = AutoTranscribe() -text = model.transcribe("test.mp4") +text = model.autotranscribe('kida.mp4', num_speakers=2) print("Transcription:\n") print(text) - # from autotranscript.misc import * # import os From 8019ce43b06680065bbd7e25c31563d3f277fb2a Mon Sep 17 00:00:00 2001 From: Jaikinator Date: Mon, 18 Sep 2023 15:56:45 +0200 Subject: [PATCH 02/18] fixed bug that language cant be choosen --- scraibe/transcriber.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scraibe/transcriber.py b/scraibe/transcriber.py index 63174a4..d4c6344 100644 --- a/scraibe/transcriber.py +++ b/scraibe/transcriber.py @@ -173,6 +173,9 @@ class Transcriber: if (task := kwargs.get("task")): whisper_kwargs["task"] = task + if (language := kwargs.get("language")): + whisper_kwargs["language"] = language + return whisper_kwargs def __repr__(self) -> str: From bc1dd9d541ec89558c19969e79694995479e9e9c Mon Sep 17 00:00:00 2001 From: Jaikinator Date: Fri, 22 Sep 2023 12:42:58 +0200 Subject: [PATCH 03/18] added support for multiple file uploads --- scraibe/app/gradio_app.py | 141 +++++++++++++++++++++++++++++++------- 1 file changed, 117 insertions(+), 24 deletions(-) diff --git a/scraibe/app/gradio_app.py b/scraibe/app/gradio_app.py index 6f09506..6d70097 100644 --- a/scraibe/app/gradio_app.py +++ b/scraibe/app/gradio_app.py @@ -35,8 +35,9 @@ Usage: import json import gradio as gr -from scraibe import AutoTranscribe, Transcript +from tqdm import tqdm +from scraibe import AutoTranscribe, Transcript theme = gr.themes.Soft( primary_hue="green", @@ -89,13 +90,43 @@ class GradioTranscriptionInterface: "language": language if language != "None" else None, "task": 'translate' if translation else None } + if isinstance(source, str): + try: + result = self.model.autotranscribe(source, **kwargs) + except ValueError: + raise gr.Error("Couldn't detect any speech in the provided audio. \ + Please try again!") + + return str(result), result.get_json() - try: - result = self.model.autotranscribe(source, **kwargs) - except ValueError: - raise gr.Error("Couldn't detect any speech in the provided audio. \ - Please try again!") - return str(result), result.get_json() + elif isinstance(source, list): + source_names = [s.split("/")[-1] for s in source] + result = [] + for s in tqdm(source, total=len(source),desc = "Transcribing audio files"): + try: + res = self.model.autotranscribe(s, **kwargs) + except ValueError: + _name = s.split("/")[-1] + res = f"NO TRANSCRIPT FOUND FOR {_name}" + gr.Warning(f"Couldn't detect any speech in {_name} will skip this file.") + result.append(res) + + out = '' + out_dict = {} + for i, r in enumerate(result): + out += f"TRANSCRIPT {i} FOR ({source_names[i]}):\n\n" + out += str(r) + out += "\n\n" + + if isinstance(r, str): + out_dict[source_names[i]] = r + else: + out_dict[source_names[i]] = r.get_dict() + + return out, json.dumps(out_dict, indent=4) + + else: + raise gr.Error("Please provide a valid audio file.") def transcribe(self, source, translation, language): @@ -110,8 +141,28 @@ class GradioTranscriptionInterface: "task": 'translate' if translation == "Yes" else None } - result = self.model.transcribe(source, **kwargs) - return str(result) + if isinstance(source, str): + result = self.model.transcribe(source, **kwargs) + + return str(result) + + elif isinstance(source, list): + source_names = [s.split("/")[-1] for s in source] + result = [] + for s in tqdm(source, total=len(source),desc = "Transcribing audio files"): + res = self.model.transcribe(s, **kwargs) + result.append(res) + + out = '' + for i, res in enumerate(result): + out += f"TRANSCRIPT {i} FOR ({source_names[i]}):\n\n" + out += str(res) + out += "\n\n" + + return out + + else: + raise gr.Error("Please provide a valid audio file.") def perform_diarisation(self, source, num_speakers): """ @@ -124,13 +175,35 @@ class GradioTranscriptionInterface: "num_speakers": num_speakers if num_speakers != 0 else None, } + if isinstance(source, str): + try: + result = self.model.diarization(source, **kwargs) + except ValueError: + raise gr.Error("Couldn't detect any speech in the provided audio. \ + Please try again!") - try: - result = self.model.diarization(source, **kwargs) - except ValueError: - raise gr.Error("Couldn't detect any speech in the provided audio. \ - Please try again!") - return json.dumps(result, indent=2) + return json.dumps(result, indent=2) + elif isinstance(source, list): + source_names = [s.split("/")[-1] for s in source] + result = [] + for s in tqdm(source, total=len(source),desc = "Performing diarisation"): + try: + res = self.model.diarization(s, **kwargs) + except ValueError: + res = f"NO DIARISATION FOUND FOR {s}" + gr.Warning(f"Couldn't detect any speech in {s} will skip this file.") + result.append(res) + + out = {} + + for i, res in enumerate(result): + out[source_names[i]] = res + + return json.dumps(out, indent=4) + + else: + gr.Error("Please provide a valid audio file.") + #### # Gradio Interface @@ -197,7 +270,7 @@ def gradio_Interface(model : AutoTranscribe = None): gr.update(visible = True), gr.update(visible = False, value = None)) - elif choice == "File": + elif choice == "File or Files": return (gr.update(visible = False, value = None), gr.update(visible = False, value = None), @@ -205,22 +278,42 @@ def gradio_Interface(model : AutoTranscribe = None): gr.update(visible = False, value = None), gr.update(visible = True)) - def run_scribe(task, num_speakers, translate, language, audio1, audio2, video1, video2, file_in, progress = gr.Progress(track_tqdm= True)): + def run_scribe(task, + num_speakers, + translate, + language, + audio1, + audio2, + video1, + video2, + file_in, + progress = gr.Progress(track_tqdm= True)): # get *args which are not None progress(0, desc='Starting task...') source = audio1 or audio2 or video1 or video2 or file_in + if isinstance(source, list): + source = [s.name for s in source] + if len(source) == 1: + source = source[0] + if task == 'Auto Transcribe': - + out_str , out_json = pipe.auto_transcribe(source = source, num_speakers = num_speakers, translation = translate, language = language) - return (gr.update(value = out_str, visible = True), - gr.update(value = out_json, visible = True), - gr.update(visible = True), - gr.update(visible = True)) + if isinstance(source, str): + return (gr.update(value = out_str, visible = True), + gr.update(value = out_json, visible = True), + gr.update(visible = True), + gr.update(visible = True)) + else: + return (gr.update(value = out_str, visible = True), + gr.update(value = out_json, visible = True), + gr.update(visible = False), + gr.update(visible = False)) elif task == 'Transcribe': @@ -279,7 +372,7 @@ def gradio_Interface(model : AutoTranscribe = None): leave it at None.", visible= True) input = gr.Radio(["Upload Audio", "Record Audio", "Upload Video","Record Video" - ,"File"], label="Input Type", value="Upload Audio") + ,"File or Files"], label="Input Type", value="Upload Audio") audio1 = gr.Audio(source="upload", type="filepath", label="Upload Audio", interactive= True, visible= True) @@ -289,7 +382,7 @@ def gradio_Interface(model : AutoTranscribe = None): interactive= True, visible= False) video2 = gr.Video(source="webcam", label="Record Video", type="filepath", interactive= True, visible= False) - file_in = gr.File(label="Upload File", interactive= True, visible= False) + file_in = gr.Files(label="Upload File or Files", interactive= True, visible= False) submit = gr.Button() From 1707777c64bfad86806f72ded8aa49dd52c7d32a Mon Sep 17 00:00:00 2001 From: Jaikinator Date: Fri, 22 Sep 2023 13:32:55 +0200 Subject: [PATCH 04/18] change class name vom AutoTranscribe to Scraibe --- scraibe/app/gradio_app.py | 16 ++++++++-------- scraibe/autotranscript.py | 39 +++++++++++++++++++++++---------------- scraibe/cli.py | 12 +++++------- scraibe/misc.py | 1 - scraibe/transcriber.py | 4 ++-- transcribe.py | 34 +++------------------------------- 6 files changed, 41 insertions(+), 65 deletions(-) diff --git a/scraibe/app/gradio_app.py b/scraibe/app/gradio_app.py index 6d70097..f5126c7 100644 --- a/scraibe/app/gradio_app.py +++ b/scraibe/app/gradio_app.py @@ -3,7 +3,7 @@ Gradio Audio Transcription App. -------------------------------- This module provides an interface to transcribe audio files using the -AutoTranscribe model. Users can either upload an audio file or record their speech +Scraibe model. Users can either upload an audio file or record their speech live for transcription. The application supports multiple languages and provides options to specify the number of speakers and the language of the audio. @@ -20,7 +20,7 @@ Gradio Audio Transcription App. -------------------------------- This module provides an interface to transcribe audio files using the -AutoTranscribe model. Users can either upload an audio file or record their speech +Scraibe model. Users can either upload an audio file or record their speech live for transcription. The application supports multiple languages and provides options to specify the number of speakers and the language of the audio. @@ -37,7 +37,7 @@ import json import gradio as gr from tqdm import tqdm -from scraibe import AutoTranscribe, Transcript +from scraibe import Scraibe, Transcript theme = gr.themes.Soft( primary_hue="green", @@ -65,12 +65,12 @@ class GradioTranscriptionInterface: Interface handling the interaction between Gradio UI and the Audio Transcription system. """ - def __init__(self, model: AutoTranscribe): + def __init__(self, model: Scraibe): """ Initializes the GradioTranscriptionInterface with a transcription model. Args: - model (AutoTranscribe): Model responsible for audio transcription tasks. + model (Scraibe): Model responsible for audio transcription tasks. """ self.model = model @@ -79,7 +79,7 @@ class GradioTranscriptionInterface: translation : bool, language : str): """ - Shortcut method for the AutoTranscribe task. + Shortcut method for the Scraibe task. Returns: tuple: Transcribed text (str), JSON output (dict) @@ -209,10 +209,10 @@ class GradioTranscriptionInterface: # Gradio Interface #### -def gradio_Interface(model : AutoTranscribe = None): +def gradio_Interface(model : Scraibe = None): if model is None: - model = AutoTranscribe() + model = Scraibe() pipe = GradioTranscriptionInterface(model) diff --git a/scraibe/autotranscript.py b/scraibe/autotranscript.py index f588e42..b3545e4 100644 --- a/scraibe/autotranscript.py +++ b/scraibe/autotranscript.py @@ -1,5 +1,5 @@ """ -AutoTranscribe Class +Scraibe Class -------------------- This class serves as the core of the transcription system, responsible for handling @@ -12,15 +12,15 @@ By encapsulating the complexities of underlying models, it allows for straightfo integration into various applications, ranging from transcription services to voice assistants. Available Classes: -- AutoTranscribe: Main class for performing transcription and diarization. +- Scraibe: Main class for performing transcription and diarization. Includes methods for loading models, processing audio files, and formatting the transcription output. Usage: - from .autotranscribe import AutoTranscribe + from scraibe import Scraibe - model = AutoTranscribe(whisper_model="path/to/whisper/model", dia_model="path/to/diarisation/model") - transcript = model.transcribe("path/to/audiofile.wav") + model = Scraibe() + transcript = model.autotranscribe("path/to/audiofile.wav") """ # Standard Library Imports @@ -45,9 +45,9 @@ from .transcript_exporter import Transcript DiarisationType = TypeVar('DiarisationType') -class AutoTranscribe: +class Scraibe: """ - AutoTranscribe is a class responsible for managing the transcription and diarization of audio files. + Scraibe is a class responsible for managing the transcription and diarization of audio files. It serves as the core of the transcription system, incorporating pretrained models for speech-to-text (such as Whisper) and speaker diarization (such as pyannote.audio), allowing for comprehensive audio processing. @@ -57,7 +57,7 @@ class AutoTranscribe: diariser (Diariser): The diariser object to handle diarization. Methods: - __init__: Initializes the AutoTranscribe class with appropriate models. + __init__: Initializes the Scraibe class with appropriate models. transcribe: Transcribes an audio file using the whisper model and pyannote diarization model. remove_audio_file: Removes the original audio file to avoid disk space issues or ensure data privacy. get_audio_file: Gets an audio file as an AudioProcessor object. @@ -66,7 +66,7 @@ class AutoTranscribe: whisper_model: Union[bool, str, whisper] = None, dia_model : Union[bool, str, DiarisationType] = None, **kwargs) -> None: - """Initializes the AutoTranscribe class. + """Initializes the Scraibe class. Args: whisper_model (Union[bool, str, whisper], optional): @@ -92,7 +92,11 @@ class AutoTranscribe: else: self.diariser = dia_model - print("AutoTranscribe initialized all models successfully loaded.") + if kwargs.get("verbose"): + print("Scraibe initialized all models successfully loaded.") + self.verbose = True + else: + self.verbose = False def autotranscribe(self, audio_file : Union[str, torch.Tensor, ndarray], remove_original : bool = False, @@ -112,7 +116,8 @@ class AutoTranscribe: Transcript: A Transcript object containing the transcription, which can be exported to different formats. """ - + if kwargs.get("verbose"): + self.verbose = kwargs.get("verbose") # Get audio file as an AudioProcessor object audio_file = self.get_audio_file(audio_file) @@ -121,8 +126,9 @@ class AutoTranscribe: "waveform" : audio_file.waveform.reshape(1,len(audio_file.waveform)), "sample_rate": audio_file.sr } - - print("Starting diarisation.") + + if self.verbose: + print("Starting diarisation.") diarisation = self.diariser.diarization(dia_audio, **kwargs) @@ -137,14 +143,15 @@ class AutoTranscribe: return Transcript(final_transcript) - print("Diarisation finished. Starting transcription.") + if self.verbose: + print("Diarisation finished. Starting transcription.") audio_file.sr = torch.Tensor([audio_file.sr]).to(audio_file.waveform.device) # Transcribe each segment and store the results final_transcript = dict() - for i in trange(len(diarisation["segments"]), desc= "Transcribing"): + for i in trange(len(diarisation["segments"]), desc= "Transcribing", disable = not self.verbose): seg = diarisation["segments"][i] @@ -280,4 +287,4 @@ class AutoTranscribe: return audio_file def __repr__(self): - return f"AutoTranscribe(transcriber={self.transcriber}, diariser={self.diariser})" + return f"Scraibe(transcriber={self.transcriber}, diariser={self.diariser})" diff --git a/scraibe/cli.py b/scraibe/cli.py index b9da56d..b05da92 100644 --- a/scraibe/cli.py +++ b/scraibe/cli.py @@ -1,5 +1,5 @@ """ -Command-Line Interface (CLI) for the AutoTranscribe class, +Command-Line Interface (CLI) for the Scraibe class, allowing for user interaction to transcribe and diarize audio files. The function includes arguments for specifying the audio files, model paths, output formats, and other options necessary for transcription. @@ -8,9 +8,7 @@ import os from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter import json -from sympy import use - -from .autotranscript import AutoTranscribe +from .autotranscript import Scraibe from .app.gradio_app import gradio_Interface from whisper.tokenizer import LANGUAGES , TO_LANGUAGE_CODE @@ -20,12 +18,12 @@ from torch import set_num_threads def cli(): """ - Command-Line Interface (CLI) for the AutoTranscribe class, allowing for user interaction to transcribe + Command-Line Interface (CLI) for the Scraibe class, allowing for user interaction to transcribe and diarize audio files. The function includes arguments for specifying the audio files, model paths, output formats, and other options necessary for transcription. This function can be executed from the command line to perform transcription tasks, providing a - user-friendly way to access the AutoTranscribe class functionalities. + user-friendly way to access the Scraibe class functionalities. """ def str2bool(string): @@ -115,7 +113,7 @@ def cli(): if arg_dict["whisper_model_directory"]: class_kwargs["download_root"] = arg_dict.pop("whisper_model_directory") - model = AutoTranscribe(**class_kwargs) + model = Scraibe(**class_kwargs) if arg_dict["audio_files"]: diff --git a/scraibe/misc.py b/scraibe/misc.py index 399fcbb..b1afeea 100644 --- a/scraibe/misc.py +++ b/scraibe/misc.py @@ -14,7 +14,6 @@ WHISPER_DEFAULT_PATH = os.path.join(CACHE_DIR, "whisper") PYANNOTE_DEFAULT_PATH = os.path.join(CACHE_DIR, "pyannote") PYANNOTE_DEFAULT_CONFIG = os.path.join(PYANNOTE_DEFAULT_PATH, "config.yaml") - def config_diarization_yaml(file_path: str, path_to_segmentation: str = None) -> None: """Configure diarization pipeline from a YAML file. diff --git a/scraibe/transcriber.py b/scraibe/transcriber.py index d4c6344..dbb290e 100644 --- a/scraibe/transcriber.py +++ b/scraibe/transcriber.py @@ -90,8 +90,8 @@ class Transcriber: kwargs = self._get_whisper_kwargs(**kwargs) - if "verbose" not in kwargs: - kwargs["verbose"] = False + if not kwargs.get("verbose"): + kwargs["verbose"] = None result = self.model.transcribe(audio, *args, **kwargs) return result["text"] diff --git a/transcribe.py b/transcribe.py index 094dcfe..5a22ff3 100644 --- a/transcribe.py +++ b/transcribe.py @@ -1,36 +1,8 @@ -# import os -# import sys -# import traceback -# class TracePrints(object): -# def __init__(self): -# self.stdout = sys.stdout -# def write(self, s): -# self.stdout.write("Writing %r\n" % s) -# traceback.print_stack(file=self.stdout) +from scraibe import Scraibe +model = Scraibe() -# sys.stdout = TracePrints() - -# os.environ["PYANNOTE_CACHE"] = os.path.expanduser("~/PycharmProjects/autotranscript/autotranscript/models/pyannote") -# import os - -# os.environ['TRANSFORMERS_CACHE'] = os.path.expanduser("~/PycharmProjects/autotranscript/autotranscript/models") -# os.environ['HF_HOME'] = os.path.expanduser("~/PycharmProjects/autotranscript/autotranscript/models") - - -from scraibe import AutoTranscribe -model = AutoTranscribe() - -text = model.autotranscribe('kida.mp4', num_speakers=2) +text = model.autotranscocribe('kida.mp4', num_speakers=2) print("Transcription:\n") print(text) - -# from autotranscript.misc import * -# import os - -# print(os.path.exists(CACHE_DIR)) -# print(os.path.exists(WHISPER_DEFAULT_PATH)) -# print(os.path.exists(PYANNOTE_DEFAULT_PATH)) - -# print(os.path.exists(PYANNOTE_DEFAULT_CONFIG)) From dc2b7b706feb7a270fd7a47f95e3affa17a317b1 Mon Sep 17 00:00:00 2001 From: Jaikinator Date: Fri, 22 Sep 2023 13:34:18 +0200 Subject: [PATCH 05/18] removed shpinx fomr dependency list --- requirements.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index dbd1bc3..ef74c29 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,8 +9,6 @@ pyannote.pipeline~=2.3 setuptools~=65.6.3 setuptools-rust~=1.5.2 -sphinx~=5.0.2 - tqdm>=4.65.0 gradio~=3.36.1 @@ -22,6 +20,6 @@ torch~=1.11.0 torchvision~=0.12.0 torchaudio~=0.11.0 #optional: -#dash~=2.10.2 +#sphinx~=5.0.2 From 73ae41091689cd904ff2e16bbdc40a53b5a01bff Mon Sep 17 00:00:00 2001 From: ortizcruz Date: Fri, 22 Sep 2023 14:21:28 +0200 Subject: [PATCH 06/18] update --- README.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 635d32b..33cd38c 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,10 @@ The following command will pull and install the latest commit from this reposito pip install git+https://github.com/JSchmie/autotranscript.git -- **Python version**: Python 3.9 +- **Python version**: Python 3.8 - **PyTorch version**: Python 1.11.0 +- **CUDA version**: Cuda-toolkit 11.3.1 + Important: For the `Pyannote` model you need to be granted access in Hugging Face. Check the [Pyannote model page](https://huggingface.co/pyannote/speaker-diarization) to get access to the model. @@ -41,6 +43,10 @@ We've developed ScrAIbe with several access points to cater to diverse user need It enables full control over the functionalities as well as process customization. +Some usage examples: + +- Usage of `AutoTranscribe`, core of the transcription system, for performing trancription and diarization of audio files. + ```python from scraibe import AutoTranscribe @@ -79,15 +85,26 @@ Run the following to view all available options: After you have installed Docker, you can execute the following commands in the terminal. ``` -sudo docker build . --build-arg="hf_token=[enter your HuggingFace token] " --no-cache -t [image name] +sudo docker build . --build-arg="hf_token=[enter your HuggingFace token] " -t [image name] -sudo docker run --rm -it -p 7860:7860 --name [container name][image name] --hf_token [enter your HuggingFace token] --start_server +sudo docker run -it -p 7860:7860 --name [container name][image name] --hf_token [enter your HuggingFace token] --start_server ``` +- `-p`: Flag for connecting the container interal port to the port on your local machine. +- `--hf_token`: Flag for entering your personal HuggingFace token in the container. +- `--start_server`: Command to start the Gradio App. + Then click the following link to run the app: http://0.0.0.0:7860 +- Enabling GPU usage + +``` +sudo docker run -it -p 7860:7860 --gpus 'all,capabilities=utility' --name [container name][image name] --hf_token [enter your HuggingFace token] --start_server +``` +For further guidance check: https://blog.roboflow.com/use-the-gpu-in-docker/ + ## Documentation From 358bbe4962f0b12a3e1c64de2fb24e3e6d3adbc5 Mon Sep 17 00:00:00 2001 From: ortizcruz Date: Fri, 22 Sep 2023 14:25:12 +0200 Subject: [PATCH 07/18] update --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 33cd38c..d41108f 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,6 @@ sudo docker run -it -p 7860:7860 --gpus 'all,capabilities=utility' --name [con ``` For further guidance check: https://blog.roboflow.com/use-the-gpu-in-docker/ - ## Documentation For further insights check the [documentation page](https://cristinaortizcruz.github.io/Test/). From 438d0a9ab8ab00533511c5d3915fee041c6b892c Mon Sep 17 00:00:00 2001 From: ortizcruz Date: Fri, 22 Sep 2023 14:35:00 +0200 Subject: [PATCH 08/18] update --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d41108f..5c86a1b 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,7 @@ http://0.0.0.0:7860 ``` sudo docker run -it -p 7860:7860 --gpus 'all,capabilities=utility' --name [container name][image name] --hf_token [enter your HuggingFace token] --start_server ``` + For further guidance check: https://blog.roboflow.com/use-the-gpu-in-docker/ ## Documentation From 4cad14ac3e09243d0110220af7bac779e48ed3ea Mon Sep 17 00:00:00 2001 From: Jaikinator Date: Fri, 22 Sep 2023 15:04:15 +0200 Subject: [PATCH 09/18] changed position of tests --- tests/test_autotranscript.py | 120 +++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 tests/test_autotranscript.py diff --git a/tests/test_autotranscript.py b/tests/test_autotranscript.py new file mode 100644 index 0000000..475f4de --- /dev/null +++ b/tests/test_autotranscript.py @@ -0,0 +1,120 @@ +import pytest +from scraibe import Transcriber +from unittest.mock import patch, mock_open +import os + +def test_load_pyannote_model(): + """ + Test load_pyannote_test + """ + from pyannote.audio.pipelines.speaker_diarization import SpeakerDiarization + from pyannote.audio import Pipeline + + pipeline = Pipeline.from_pretrained("models/pyannote/speaker_diarization/config.yaml") + assert isinstance(pipeline, SpeakerDiarization) + +# Test Transcribtion class + + +@pytest.fixture +def transcriber(): + """ + Prepare Transcriber for testing + Returns: Transcriber Object + """ + + return Transcriber.load_model("medium", local=True) + + +def test_Transcriber_init(transcriber): + """ + Test Transcriber initialization with a whisper model + """ + + assert isinstance(transcriber, Transcriber) + +def test_transcription(transcriber): + """ + Test transcription + """ + + transcript = transcriber.transcribe("tests/test.wav") + assert isinstance(transcript, str) + +def test_save_transcript_to_file(transcriber): + """ + Test save_transcript_to_file + """ + transcript = transcriber.transcribe("tests/test.wav") + + Transcriber.save_transcript(transcript, "tests/output.txt") + + assert os.path.exists("tests/output.txt") + + os.remove("tests/output.txt") + +# Test Diaraization class + +from scraibe import Diariser + +@pytest.fixture +def diarisation(): + """ + Prepare Diarisation for testing + Returns: Diarisation Object + """ + + return Diariser.load_model("models/pyannote/speaker_diarization/config.yaml", local=True) + +def test_Diarisation_init(diarisation): + """ + Test Diarisation initialization with a pyannote model + """ + + assert isinstance(diarisation, Diariser) + +def test_diarisation(diarisation): + """ + Test diarisation + """ + + diarisation = diarisation.diarization("tests/test.wav") + assert isinstance(diarisation, dict) + +# Test AudioProcessor + +from scraibe import AudioProcessor , TorchAudioProcessor + + +def test_AudioProcessor_init(): + """ + Test AudioProcessor initialization + """ + audio = AudioProcessor("tests/test.wav") + assert isinstance(audio, AudioProcessor) + +def test_AudioProcessor_convert(): + """ + Test AudioProcessor convert + """ + audio = AudioProcessor("tests/test.wav") + audio.convert_audio("tests/test.mp3", format="mp3") + assert os.path.exists("tests/test.mp3") + +def test_TorchAudioProcessor_from_file(): + """ + Test TorchAudioProcessor initialization + """ + audio = TorchAudioProcessor.from_file("tests/test.wav") + + assert isinstance(audio, TorchAudioProcessor) + + os.remove("tests/test.mp3") + + +def test_TorchAudioProcessor_from_ffmpeg(): + """ + Test TorchAudioProcessor initialization + """ + audio = TorchAudioProcessor.from_ffmpeg("tests/test.wav") + assert isinstance(audio, TorchAudioProcessor) From a0d7f2f46e25d5f09b9d8c741400d7e060363738 Mon Sep 17 00:00:00 2001 From: Jacob Schmieder Date: Fri, 22 Sep 2023 15:17:11 +0200 Subject: [PATCH 10/18] Delete docs directory we do later --- docs/Makefile | 20 - docs/_build/doctrees/app.doctree | Bin 5672 -> 0 bytes .../doctrees/autotranscript.app.doctree | Bin 34589 -> 0 bytes docs/_build/doctrees/autotranscript.doctree | Bin 231190 -> 0 bytes docs/_build/doctrees/environment.pickle | Bin 40760 -> 0 bytes docs/_build/doctrees/gradio_app.doctree | Bin 2405 -> 0 bytes docs/_build/doctrees/index.doctree | Bin 5900 -> 0 bytes docs/_build/doctrees/modules.doctree | Bin 2812 -> 0 bytes docs/_build/doctrees/setup.doctree | Bin 2378 -> 0 bytes .../doctrees/test_autotranscript.doctree | Bin 2450 -> 0 bytes docs/_build/doctrees/transcribe.doctree | Bin 2403 -> 0 bytes docs/_build/html/.buildinfo | 4 - docs/_build/html/_sources/app.rst.txt | 7 - .../html/_sources/autotranscript.app.rst.txt | 21 - .../html/_sources/autotranscript.rst.txt | 77 - docs/_build/html/_sources/gradio_app.rst.txt | 7 - docs/_build/html/_sources/index.rst.txt | 27 - docs/_build/html/_sources/modules.rst.txt | 12 - docs/_build/html/_sources/setup.rst.txt | 7 - .../html/_sources/test_autotranscript.rst.txt | 7 - docs/_build/html/_sources/transcribe.rst.txt | 7 - .../_sphinx_javascript_frameworks_compat.js | 134 - docs/_build/html/_static/alabaster.css | 701 - docs/_build/html/_static/basic.css | 930 -- docs/_build/html/_static/custom.css | 1 - docs/_build/html/_static/doctools.js | 264 - .../html/_static/documentation_options.js | 14 - docs/_build/html/_static/file.png | Bin 286 -> 0 bytes docs/_build/html/_static/jquery-3.6.0.js | 10881 ---------------- docs/_build/html/_static/jquery.js | 2 - docs/_build/html/_static/language_data.js | 199 - docs/_build/html/_static/minus.png | Bin 90 -> 0 bytes docs/_build/html/_static/plus.png | Bin 90 -> 0 bytes docs/_build/html/_static/pygments.css | 83 - docs/_build/html/_static/searchtools.js | 531 - docs/_build/html/_static/underscore-1.13.1.js | 2042 --- docs/_build/html/_static/underscore.js | 6 - docs/_build/html/app.html | 112 - docs/_build/html/autotranscript.app.html | 234 - docs/_build/html/autotranscript.html | 833 -- docs/_build/html/genindex.html | 459 - docs/_build/html/gradio_app.html | 120 - docs/_build/html/index.html | 132 - docs/_build/html/modules.html | 160 - docs/_build/html/objects.inv | Bin 940 -> 0 bytes docs/_build/html/py-modindex.html | 170 - docs/_build/html/search.html | 124 - docs/_build/html/searchindex.js | 1 - docs/_build/html/setup.html | 120 - docs/_build/html/test_autotranscript.html | 120 - docs/_build/html/transcribe.html | 118 - docs/app.rst | 7 - docs/autotranscript.app.rst | 21 - docs/autotranscript.rst | 77 - docs/conf.py | 69 - docs/gradio_app.rst | 7 - docs/index.rst | 27 - docs/make.bat | 35 - docs/modules.rst | 12 - docs/setup.rst | 7 - docs/test_autotranscript.rst | 7 - docs/transcribe.rst | 7 - 62 files changed, 18963 deletions(-) delete mode 100644 docs/Makefile delete mode 100644 docs/_build/doctrees/app.doctree delete mode 100644 docs/_build/doctrees/autotranscript.app.doctree delete mode 100644 docs/_build/doctrees/autotranscript.doctree delete mode 100644 docs/_build/doctrees/environment.pickle delete mode 100644 docs/_build/doctrees/gradio_app.doctree delete mode 100644 docs/_build/doctrees/index.doctree delete mode 100644 docs/_build/doctrees/modules.doctree delete mode 100644 docs/_build/doctrees/setup.doctree delete mode 100644 docs/_build/doctrees/test_autotranscript.doctree delete mode 100644 docs/_build/doctrees/transcribe.doctree delete mode 100644 docs/_build/html/.buildinfo delete mode 100644 docs/_build/html/_sources/app.rst.txt delete mode 100644 docs/_build/html/_sources/autotranscript.app.rst.txt delete mode 100644 docs/_build/html/_sources/autotranscript.rst.txt delete mode 100644 docs/_build/html/_sources/gradio_app.rst.txt delete mode 100644 docs/_build/html/_sources/index.rst.txt delete mode 100644 docs/_build/html/_sources/modules.rst.txt delete mode 100644 docs/_build/html/_sources/setup.rst.txt delete mode 100644 docs/_build/html/_sources/test_autotranscript.rst.txt delete mode 100644 docs/_build/html/_sources/transcribe.rst.txt delete mode 100644 docs/_build/html/_static/_sphinx_javascript_frameworks_compat.js delete mode 100644 docs/_build/html/_static/alabaster.css delete mode 100644 docs/_build/html/_static/basic.css delete mode 100644 docs/_build/html/_static/custom.css delete mode 100644 docs/_build/html/_static/doctools.js delete mode 100644 docs/_build/html/_static/documentation_options.js delete mode 100644 docs/_build/html/_static/file.png delete mode 100644 docs/_build/html/_static/jquery-3.6.0.js delete mode 100644 docs/_build/html/_static/jquery.js delete mode 100644 docs/_build/html/_static/language_data.js delete mode 100644 docs/_build/html/_static/minus.png delete mode 100644 docs/_build/html/_static/plus.png delete mode 100644 docs/_build/html/_static/pygments.css delete mode 100644 docs/_build/html/_static/searchtools.js delete mode 100644 docs/_build/html/_static/underscore-1.13.1.js delete mode 100644 docs/_build/html/_static/underscore.js delete mode 100644 docs/_build/html/app.html delete mode 100644 docs/_build/html/autotranscript.app.html delete mode 100644 docs/_build/html/autotranscript.html delete mode 100644 docs/_build/html/genindex.html delete mode 100644 docs/_build/html/gradio_app.html delete mode 100644 docs/_build/html/index.html delete mode 100644 docs/_build/html/modules.html delete mode 100644 docs/_build/html/objects.inv delete mode 100644 docs/_build/html/py-modindex.html delete mode 100644 docs/_build/html/search.html delete mode 100644 docs/_build/html/searchindex.js delete mode 100644 docs/_build/html/setup.html delete mode 100644 docs/_build/html/test_autotranscript.html delete mode 100644 docs/_build/html/transcribe.html delete mode 100644 docs/app.rst delete mode 100644 docs/autotranscript.app.rst delete mode 100644 docs/autotranscript.rst delete mode 100644 docs/conf.py delete mode 100644 docs/gradio_app.rst delete mode 100644 docs/index.rst delete mode 100644 docs/make.bat delete mode 100644 docs/modules.rst delete mode 100644 docs/setup.rst delete mode 100644 docs/test_autotranscript.rst delete mode 100644 docs/transcribe.rst diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index d4bb2cb..0000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/_build/doctrees/app.doctree b/docs/_build/doctrees/app.doctree deleted file mode 100644 index aa46bd293affaf1795d135638030895fe3d7db79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5672 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 X(DgHqa6Tc(ZFrQRi(F=}MuYzXUCVXF diff --git a/docs/_build/doctrees/autotranscript.app.doctree b/docs/_build/doctrees/autotranscript.app.doctree deleted file mode 100644 index b575367f1692602c844a6e29d64262121be74ef7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34589 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 z 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 Pr0ra4=Myp6ni&6IS5BjB diff --git a/docs/_build/doctrees/environment.pickle b/docs/_build/doctrees/environment.pickle deleted file mode 100644 index 9e37e4b0b4dadcf81dc63636b3c2b8d972458aac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40760 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 diff --git a/docs/_build/doctrees/modules.doctree b/docs/_build/doctrees/modules.doctree deleted file mode 100644 index 387e742c8a498cc1938da6df7eddbf9c30c8e315..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2812 zcmZuzTW=gS6i$=uHG4@?ijdlXDpZ<^B#RIa2nmTxg@A}WAjDhcdS|?AD;|5WJVB~rb?&G2H#C} zQe;fI@HRa8E4&KFzGvu_)rCn|@LSMGxR9w~Dm)8*6xE%O_N+eNu`F>ytL8Xw@iy-~ z3&*_YTTVF1R<`_z7EU`ul}(JuU5J`c-2II$Vg&E(zYbMQ?VKV4=pXnVX+q{ZzFkLp z;diA_EL;>*>ig6=Bc_EzhB2cZk=hu2Cy~@z2=U!gG^@V4X_4P9rZl-UY!-D2-*I#v zw*nvY`+UG3@Ev~Szn*ZNv57WLyi82-GMPNpmnDd7a{klPZzoq=*qoU%&cP-9%@(E>yaLPz4^}f@_^P!&cF&_dY^O{2_4r7{5pOJ;v_|e)oN+ z_JdS`mJwxw#}|Hw=6U!#T)cyCl=bI^rb3gYPRlY^RO)wupd%YKE6*%zIAyTQ{6MHg z7AczvWC`ew`8WJK{*?c~f8;+i-_7VEWx32)qc}W@6Y%cXQ-1s&ZX$pqj_+f3R z5p-3NO_^b7IN$R9l2BGFc@5n@h^tQ^;4#>nB6YpS0mj(Erow_8^W*;_pD&~~2q4w)>tp?HXnV-b7cl;%y&DX_Z!jKib&YFu`y9s4{vR!1CyW^^J{_em^E)ff5Hk z5(x!AlvK?NI%j}8#d;g<_<7v2|&RVQb`HeAWEhbvB%EvA8_Y#`_*Iuu|3PL9oOni zoB1U8dr`9t0Ght7K z;VzSK)^l`<7E0rs?fN4SG9yiIHVF`$M~2+^eS57OT@WtjT;d1v?n)hbKd>1^m;F(o zsV#uITdu1mkvgH(l=nvor-%oIubK@gmk{FgC9V(<8qt+AyB-1<@Q?^K0|%B<;V{k# zTTD0fL>9>_HSVSuQoPK=an#HiW)q$W2M7w(a(M87Hn`m4Yr-F{Nvnqg z#IQDN7VX$VcymDBiNfleC;Ykfy(ni?cyeR;L;Qcv2i6Z)i&dT;CITgo?qRW# z#M^kOSB1GMsq_#$iknTfZ0cXCzPBN4w0mn7drPn7p~E%%n61XeVSaDZR=tB;8WSVI zy9TrfelO8d0$AjLE2Hy$Eq{yTUx#18e!T3^M|g`_)Vp%n430JNUL!6`wpYItK#_T@ RRzHoitsVpMzAdI_{{b*QWV8SP diff --git a/docs/_build/doctrees/setup.doctree b/docs/_build/doctrees/setup.doctree deleted file mode 100644 index 7ea34fd73b1e5ceb064d8e5d44ef17b1ce435380..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2378 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 diff --git a/docs/_build/html/.buildinfo b/docs/_build/html/.buildinfo deleted file mode 100644 index 1d381b6..0000000 --- a/docs/_build/html/.buildinfo +++ /dev/null @@ -1,4 +0,0 @@ -# Sphinx build info version 1 -# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 4f1b6219de23d2354e00a9f0fdc6a82f -tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/_build/html/_sources/app.rst.txt b/docs/_build/html/_sources/app.rst.txt deleted file mode 100644 index ceb7f40..0000000 --- a/docs/_build/html/_sources/app.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -app module -========== - -.. automodule:: app - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/_build/html/_sources/autotranscript.app.rst.txt b/docs/_build/html/_sources/autotranscript.app.rst.txt deleted file mode 100644 index ee68a6f..0000000 --- a/docs/_build/html/_sources/autotranscript.app.rst.txt +++ /dev/null @@ -1,21 +0,0 @@ -autotranscript.app package -========================== - -Submodules ----------- - -autotranscript.app.qtfaststart module -------------------------------------- - -.. automodule:: autotranscript.app.qtfaststart - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: autotranscript.app - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/_build/html/_sources/autotranscript.rst.txt b/docs/_build/html/_sources/autotranscript.rst.txt deleted file mode 100644 index 5ba3195..0000000 --- a/docs/_build/html/_sources/autotranscript.rst.txt +++ /dev/null @@ -1,77 +0,0 @@ -autotranscript package -====================== - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - autotranscript.app - -Submodules ----------- - -autotranscript.audio module ---------------------------- - -.. automodule:: autotranscript.audio - :members: - :undoc-members: - :show-inheritance: - -autotranscript.autotranscript module ------------------------------------- - -.. automodule:: autotranscript.autotranscript - :members: - :undoc-members: - :show-inheritance: - -autotranscript.diarisation module ---------------------------------- - -.. automodule:: autotranscript.diarisation - :members: - :undoc-members: - :show-inheritance: - -autotranscript.misc module --------------------------- - -.. automodule:: autotranscript.misc - :members: - :undoc-members: - :show-inheritance: - -autotranscript.transcriber module ---------------------------------- - -.. automodule:: autotranscript.transcriber - :members: - :undoc-members: - :show-inheritance: - -autotranscript.transcript\_exporter module ------------------------------------------- - -.. automodule:: autotranscript.transcript_exporter - :members: - :undoc-members: - :show-inheritance: - -autotranscript.version module ------------------------------ - -.. automodule:: autotranscript.version - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: autotranscript - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/_build/html/_sources/gradio_app.rst.txt b/docs/_build/html/_sources/gradio_app.rst.txt deleted file mode 100644 index bafaed0..0000000 --- a/docs/_build/html/_sources/gradio_app.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -gradio\_app module -================== - -.. automodule:: gradio_app - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/_build/html/_sources/index.rst.txt b/docs/_build/html/_sources/index.rst.txt deleted file mode 100644 index 0033a97..0000000 --- a/docs/_build/html/_sources/index.rst.txt +++ /dev/null @@ -1,27 +0,0 @@ -.. AutoTranscript documentation master file, created by - sphinx-quickstart on Thu Aug 31 08:17:31 2023. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to AutoTranscript's documentation! -========================================== - -`AutoTranscript`: Fully Automated Transcription using AI - -`AutoTranscript` is a PyTorch based interface speech-to-text tool to generate fully automated transcriptions. AutoTranscript uses AI models containing speaker diarization models: - - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - modules - - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/_build/html/_sources/modules.rst.txt b/docs/_build/html/_sources/modules.rst.txt deleted file mode 100644 index b1fd70c..0000000 --- a/docs/_build/html/_sources/modules.rst.txt +++ /dev/null @@ -1,12 +0,0 @@ -autotranscript -============== - -.. toctree:: - :maxdepth: 4 - - app - autotranscript - gradio_app - setup - test_autotranscript - transcribe diff --git a/docs/_build/html/_sources/setup.rst.txt b/docs/_build/html/_sources/setup.rst.txt deleted file mode 100644 index 552eb49..0000000 --- a/docs/_build/html/_sources/setup.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -setup module -============ - -.. automodule:: setup - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/_build/html/_sources/test_autotranscript.rst.txt b/docs/_build/html/_sources/test_autotranscript.rst.txt deleted file mode 100644 index 6bf3220..0000000 --- a/docs/_build/html/_sources/test_autotranscript.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -test\_autotranscript module -=========================== - -.. automodule:: test_autotranscript - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/_build/html/_sources/transcribe.rst.txt b/docs/_build/html/_sources/transcribe.rst.txt deleted file mode 100644 index d03031f..0000000 --- a/docs/_build/html/_sources/transcribe.rst.txt +++ /dev/null @@ -1,7 +0,0 @@ -transcribe module -================= - -.. automodule:: transcribe - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/_build/html/_static/_sphinx_javascript_frameworks_compat.js b/docs/_build/html/_static/_sphinx_javascript_frameworks_compat.js deleted file mode 100644 index 8549469..0000000 --- a/docs/_build/html/_static/_sphinx_javascript_frameworks_compat.js +++ /dev/null @@ -1,134 +0,0 @@ -/* - * _sphinx_javascript_frameworks_compat.js - * ~~~~~~~~~~ - * - * Compatability shim for jQuery and underscores.js. - * - * WILL BE REMOVED IN Sphinx 6.0 - * xref RemovedInSphinx60Warning - * - */ - -/** - * select a different prefix for underscore - */ -$u = _.noConflict(); - - -/** - * small helper function to urldecode strings - * - * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL - */ -jQuery.urldecode = function(x) { - if (!x) { - return x - } - return decodeURIComponent(x.replace(/\+/g, ' ')); -}; - -/** - * small helper function to urlencode strings - */ -jQuery.urlencode = encodeURIComponent; - -/** - * This function returns the parsed url parameters of the - * current request. Multiple values per key are supported, - * it will always return arrays of strings for the value parts. - */ -jQuery.getQueryParameters = function(s) { - if (typeof s === 'undefined') - s = document.location.search; - var parts = s.substr(s.indexOf('?') + 1).split('&'); - var result = {}; - for (var i = 0; i < parts.length; i++) { - var tmp = parts[i].split('=', 2); - var key = jQuery.urldecode(tmp[0]); - var value = jQuery.urldecode(tmp[1]); - if (key in result) - result[key].push(value); - else - result[key] = [value]; - } - return result; -}; - -/** - * highlight a given string on a jquery object by wrapping it in - * span elements with the given class name. - */ -jQuery.fn.highlightText = function(text, className) { - function highlight(node, addItems) { - if (node.nodeType === 3) { - var val = node.nodeValue; - var pos = val.toLowerCase().indexOf(text); - if (pos >= 0 && - !jQuery(node.parentNode).hasClass(className) && - !jQuery(node.parentNode).hasClass("nohighlight")) { - var span; - var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.className = className; - } - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - node.parentNode.insertBefore(span, node.parentNode.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling)); - node.nodeValue = val.substr(0, pos); - if (isInSVG) { - var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); - var bbox = node.parentElement.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute('class', className); - addItems.push({ - "parent": node.parentNode, - "target": rect}); - } - } - } - else if (!jQuery(node).is("button, select, textarea")) { - jQuery.each(node.childNodes, function() { - highlight(this, addItems); - }); - } - } - var addItems = []; - var result = this.each(function() { - highlight(this, addItems); - }); - for (var i = 0; i < addItems.length; ++i) { - jQuery(addItems[i].parent).before(addItems[i].target); - } - return result; -}; - -/* - * backward compatibility for jQuery.browser - * This will be supported until firefox bug is fixed. - */ -if (!jQuery.browser) { - jQuery.uaMatch = function(ua) { - ua = ua.toLowerCase(); - - var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || - /(webkit)[ \/]([\w.]+)/.exec(ua) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || - /(msie) ([\w.]+)/.exec(ua) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || - []; - - return { - browser: match[ 1 ] || "", - version: match[ 2 ] || "0" - }; - }; - jQuery.browser = {}; - jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; -} diff --git a/docs/_build/html/_static/alabaster.css b/docs/_build/html/_static/alabaster.css deleted file mode 100644 index 0eddaeb..0000000 --- a/docs/_build/html/_static/alabaster.css +++ /dev/null @@ -1,701 +0,0 @@ -@import url("basic.css"); - -/* -- page layout ----------------------------------------------------------- */ - -body { - font-family: Georgia, serif; - font-size: 17px; - background-color: #fff; - color: #000; - margin: 0; - padding: 0; -} - - -div.document { - width: 940px; - margin: 30px auto 0 auto; -} - -div.documentwrapper { - float: left; - width: 100%; -} - -div.bodywrapper { - margin: 0 0 0 220px; -} - -div.sphinxsidebar { - width: 220px; - font-size: 14px; - line-height: 1.5; -} - -hr { - border: 1px solid #B1B4B6; -} - -div.body { - background-color: #fff; - color: #3E4349; - padding: 0 30px 0 30px; -} - -div.body > .section { - text-align: left; -} - -div.footer { - width: 940px; - margin: 20px auto 30px auto; - font-size: 14px; - color: #888; - text-align: right; -} - -div.footer a { - color: #888; -} - -p.caption { - font-family: inherit; - font-size: inherit; -} - - -div.relations { - display: none; -} - - -div.sphinxsidebar a { - color: #444; - text-decoration: none; - border-bottom: 1px dotted #999; -} - -div.sphinxsidebar a:hover { - border-bottom: 1px solid #999; -} - -div.sphinxsidebarwrapper { - padding: 18px 10px; -} - -div.sphinxsidebarwrapper p.logo { - padding: 0; - margin: -10px 0 0 0px; - text-align: center; -} - -div.sphinxsidebarwrapper h1.logo { - margin-top: -10px; - text-align: center; - margin-bottom: 5px; - text-align: left; -} - -div.sphinxsidebarwrapper h1.logo-name { - margin-top: 0px; -} - -div.sphinxsidebarwrapper p.blurb { - margin-top: 0; - font-style: normal; -} - -div.sphinxsidebar h3, -div.sphinxsidebar h4 { - font-family: Georgia, serif; - color: #444; - font-size: 24px; - font-weight: normal; - margin: 0 0 5px 0; - padding: 0; -} - -div.sphinxsidebar h4 { - font-size: 20px; -} - -div.sphinxsidebar h3 a { - color: #444; -} - -div.sphinxsidebar p.logo a, -div.sphinxsidebar h3 a, -div.sphinxsidebar p.logo a:hover, -div.sphinxsidebar h3 a:hover { - border: none; -} - -div.sphinxsidebar p { - color: #555; - margin: 10px 0; -} - -div.sphinxsidebar ul { - margin: 10px 0; - padding: 0; - color: #000; -} - -div.sphinxsidebar ul li.toctree-l1 > a { - font-size: 120%; -} - -div.sphinxsidebar ul li.toctree-l2 > a { - font-size: 110%; -} - -div.sphinxsidebar input { - border: 1px solid #CCC; - font-family: Georgia, serif; - font-size: 1em; -} - -div.sphinxsidebar hr { - border: none; - height: 1px; - color: #AAA; - background: #AAA; - - text-align: left; - margin-left: 0; - width: 50%; -} - -div.sphinxsidebar .badge { - border-bottom: none; -} - -div.sphinxsidebar .badge:hover { - border-bottom: none; -} - -/* To address an issue with donation coming after search */ -div.sphinxsidebar h3.donation { - margin-top: 10px; -} - -/* -- body styles ----------------------------------------------------------- */ - -a { - color: #004B6B; - text-decoration: underline; -} - -a:hover { - color: #6D4100; - text-decoration: underline; -} - -div.body h1, -div.body h2, -div.body h3, -div.body h4, -div.body h5, -div.body h6 { - font-family: Georgia, serif; - font-weight: normal; - margin: 30px 0px 10px 0px; - padding: 0; -} - -div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } -div.body h2 { font-size: 180%; } -div.body h3 { font-size: 150%; } -div.body h4 { font-size: 130%; } -div.body h5 { font-size: 100%; } -div.body h6 { font-size: 100%; } - -a.headerlink { - color: #DDD; - padding: 0 4px; - text-decoration: none; -} - -a.headerlink:hover { - color: #444; - background: #EAEAEA; -} - -div.body p, div.body dd, div.body li { - line-height: 1.4em; -} - -div.admonition { - margin: 20px 0px; - padding: 10px 30px; - background-color: #EEE; - border: 1px solid #CCC; -} - -div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { - background-color: #FBFBFB; - border-bottom: 1px solid #fafafa; -} - -div.admonition p.admonition-title { - font-family: Georgia, serif; - font-weight: normal; - font-size: 24px; - margin: 0 0 10px 0; - padding: 0; - line-height: 1; -} - -div.admonition p.last { - margin-bottom: 0; -} - -div.highlight { - background-color: #fff; -} - -dt:target, .highlight { - background: #FAF3E8; -} - -div.warning { - background-color: #FCC; - border: 1px solid #FAA; -} - -div.danger { - background-color: #FCC; - border: 1px solid #FAA; - -moz-box-shadow: 2px 2px 4px #D52C2C; - -webkit-box-shadow: 2px 2px 4px #D52C2C; - box-shadow: 2px 2px 4px #D52C2C; -} - -div.error { - background-color: #FCC; - border: 1px solid #FAA; - -moz-box-shadow: 2px 2px 4px #D52C2C; - -webkit-box-shadow: 2px 2px 4px #D52C2C; - box-shadow: 2px 2px 4px #D52C2C; -} - -div.caution { - background-color: #FCC; - border: 1px solid #FAA; -} - -div.attention { - background-color: #FCC; - border: 1px solid #FAA; -} - -div.important { - background-color: #EEE; - border: 1px solid #CCC; -} - -div.note { - background-color: #EEE; - border: 1px solid #CCC; -} - -div.tip { - background-color: #EEE; - border: 1px solid #CCC; -} - -div.hint { - background-color: #EEE; - border: 1px solid #CCC; -} - -div.seealso { - background-color: #EEE; - border: 1px solid #CCC; -} - -div.topic { - background-color: #EEE; -} - -p.admonition-title { - display: inline; -} - -p.admonition-title:after { - content: ":"; -} - -pre, tt, code { - font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; - font-size: 0.9em; -} - -.hll { - background-color: #FFC; - margin: 0 -12px; - padding: 0 12px; - display: block; -} - -img.screenshot { -} - -tt.descname, tt.descclassname, code.descname, code.descclassname { - font-size: 0.95em; -} - -tt.descname, code.descname { - padding-right: 0.08em; -} - -img.screenshot { - -moz-box-shadow: 2px 2px 4px #EEE; - -webkit-box-shadow: 2px 2px 4px #EEE; - box-shadow: 2px 2px 4px #EEE; -} - -table.docutils { - border: 1px solid #888; - -moz-box-shadow: 2px 2px 4px #EEE; - -webkit-box-shadow: 2px 2px 4px #EEE; - box-shadow: 2px 2px 4px #EEE; -} - -table.docutils td, table.docutils th { - border: 1px solid #888; - padding: 0.25em 0.7em; -} - -table.field-list, table.footnote { - border: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; -} - -table.footnote { - margin: 15px 0; - width: 100%; - border: 1px solid #EEE; - background: #FDFDFD; - font-size: 0.9em; -} - -table.footnote + table.footnote { - margin-top: -15px; - border-top: none; -} - -table.field-list th { - padding: 0 0.8em 0 0; -} - -table.field-list td { - padding: 0; -} - -table.field-list p { - margin-bottom: 0.8em; -} - -/* Cloned from - * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 - */ -.field-name { - -moz-hyphens: manual; - -ms-hyphens: manual; - -webkit-hyphens: manual; - hyphens: manual; -} - -table.footnote td.label { - width: .1px; - padding: 0.3em 0 0.3em 0.5em; -} - -table.footnote td { - padding: 0.3em 0.5em; -} - -dl { - margin: 0; - padding: 0; -} - -dl dd { - margin-left: 30px; -} - -blockquote { - margin: 0 0 0 30px; - padding: 0; -} - -ul, ol { - /* Matches the 30px from the narrow-screen "li > ul" selector below */ - margin: 10px 0 10px 30px; - padding: 0; -} - -pre { - background: #EEE; - padding: 7px 30px; - margin: 15px 0px; - line-height: 1.3em; -} - -div.viewcode-block:target { - background: #ffd; -} - -dl pre, blockquote pre, li pre { - margin-left: 0; - padding-left: 30px; -} - -tt, code { - background-color: #ecf0f3; - color: #222; - /* padding: 1px 2px; */ -} - -tt.xref, code.xref, a tt { - background-color: #FBFBFB; - border-bottom: 1px solid #fff; -} - -a.reference { - text-decoration: none; - border-bottom: 1px dotted #004B6B; -} - -/* Don't put an underline on images */ -a.image-reference, a.image-reference:hover { - border-bottom: none; -} - -a.reference:hover { - border-bottom: 1px solid #6D4100; -} - -a.footnote-reference { - text-decoration: none; - font-size: 0.7em; - vertical-align: top; - border-bottom: 1px dotted #004B6B; -} - -a.footnote-reference:hover { - border-bottom: 1px solid #6D4100; -} - -a:hover tt, a:hover code { - background: #EEE; -} - - -@media screen and (max-width: 870px) { - - div.sphinxsidebar { - display: none; - } - - div.document { - width: 100%; - - } - - div.documentwrapper { - margin-left: 0; - margin-top: 0; - margin-right: 0; - margin-bottom: 0; - } - - div.bodywrapper { - margin-top: 0; - margin-right: 0; - margin-bottom: 0; - margin-left: 0; - } - - ul { - margin-left: 0; - } - - li > ul { - /* Matches the 30px from the "ul, ol" selector above */ - margin-left: 30px; - } - - .document { - width: auto; - } - - .footer { - width: auto; - } - - .bodywrapper { - margin: 0; - } - - .footer { - width: auto; - } - - .github { - display: none; - } - - - -} - - - -@media screen and (max-width: 875px) { - - body { - margin: 0; - padding: 20px 30px; - } - - div.documentwrapper { - float: none; - background: #fff; - } - - div.sphinxsidebar { - display: block; - float: none; - width: 102.5%; - margin: 50px -30px -20px -30px; - padding: 10px 20px; - background: #333; - color: #FFF; - } - - div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, - div.sphinxsidebar h3 a { - color: #fff; - } - - div.sphinxsidebar a { - color: #AAA; - } - - div.sphinxsidebar p.logo { - display: none; - } - - div.document { - width: 100%; - margin: 0; - } - - div.footer { - display: none; - } - - div.bodywrapper { - margin: 0; - } - - div.body { - min-height: 0; - padding: 0; - } - - .rtd_doc_footer { - display: none; - } - - .document { - width: auto; - } - - .footer { - width: auto; - } - - .footer { - width: auto; - } - - .github { - display: none; - } -} - - -/* misc. */ - -.revsys-inline { - display: none!important; -} - -/* Make nested-list/multi-paragraph items look better in Releases changelog - * pages. Without this, docutils' magical list fuckery causes inconsistent - * formatting between different release sub-lists. - */ -div#changelog > div.section > ul > li > p:only-child { - margin-bottom: 0; -} - -/* Hide fugly table cell borders in ..bibliography:: directive output */ -table.docutils.citation, table.docutils.citation td, table.docutils.citation th { - border: none; - /* Below needed in some edge cases; if not applied, bottom shadows appear */ - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; -} - - -/* relbar */ - -.related { - line-height: 30px; - width: 100%; - font-size: 0.9rem; -} - -.related.top { - border-bottom: 1px solid #EEE; - margin-bottom: 20px; -} - -.related.bottom { - border-top: 1px solid #EEE; -} - -.related ul { - padding: 0; - margin: 0; - list-style: none; -} - -.related li { - display: inline; -} - -nav#rellinks { - float: right; -} - -nav#rellinks li+li:before { - content: "|"; -} - -nav#breadcrumbs li+li:before { - content: "\00BB"; -} - -/* Hide certain items when printing */ -@media print { - div.related { - display: none; - } -} \ No newline at end of file diff --git a/docs/_build/html/_static/basic.css b/docs/_build/html/_static/basic.css deleted file mode 100644 index 0889677..0000000 --- a/docs/_build/html/_static/basic.css +++ /dev/null @@ -1,930 +0,0 @@ -/* - * basic.css - * ~~~~~~~~~ - * - * Sphinx stylesheet -- basic theme. - * - * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -/* -- main layout ----------------------------------------------------------- */ - -div.clearer { - clear: both; -} - -div.section::after { - display: block; - content: ''; - clear: left; -} - -/* -- relbar ---------------------------------------------------------------- */ - -div.related { - width: 100%; - font-size: 90%; -} - -div.related h3 { - display: none; -} - -div.related ul { - margin: 0; - padding: 0 0 0 10px; - list-style: none; -} - -div.related li { - display: inline; -} - -div.related li.right { - float: right; - margin-right: 5px; -} - -/* -- sidebar --------------------------------------------------------------- */ - -div.sphinxsidebarwrapper { - padding: 10px 5px 0 10px; -} - -div.sphinxsidebar { - float: left; - width: 230px; - margin-left: -100%; - font-size: 90%; - word-wrap: break-word; - overflow-wrap : break-word; -} - -div.sphinxsidebar ul { - list-style: none; -} - -div.sphinxsidebar ul ul, -div.sphinxsidebar ul.want-points { - margin-left: 20px; - list-style: square; -} - -div.sphinxsidebar ul ul { - margin-top: 0; - margin-bottom: 0; -} - -div.sphinxsidebar form { - margin-top: 10px; -} - -div.sphinxsidebar input { - border: 1px solid #98dbcc; - font-family: sans-serif; - font-size: 1em; -} - -div.sphinxsidebar #searchbox form.search { - overflow: hidden; -} - -div.sphinxsidebar #searchbox input[type="text"] { - float: left; - width: 80%; - padding: 0.25em; - box-sizing: border-box; -} - -div.sphinxsidebar #searchbox input[type="submit"] { - float: left; - width: 20%; - border-left: none; - padding: 0.25em; - box-sizing: border-box; -} - - -img { - border: 0; - max-width: 100%; -} - -/* -- search page ----------------------------------------------------------- */ - -ul.search { - margin: 10px 0 0 20px; - padding: 0; -} - -ul.search li { - padding: 5px 0 5px 20px; - background-image: url(file.png); - background-repeat: no-repeat; - background-position: 0 7px; -} - -ul.search li a { - font-weight: bold; -} - -ul.search li p.context { - color: #888; - margin: 2px 0 0 30px; - text-align: left; -} - -ul.keywordmatches li.goodmatch a { - font-weight: bold; -} - -/* -- index page ------------------------------------------------------------ */ - -table.contentstable { - width: 90%; - margin-left: auto; - margin-right: auto; -} - -table.contentstable p.biglink { - line-height: 150%; -} - -a.biglink { - font-size: 1.3em; -} - -span.linkdescr { - font-style: italic; - padding-top: 5px; - font-size: 90%; -} - -/* -- general index --------------------------------------------------------- */ - -table.indextable { - width: 100%; -} - -table.indextable td { - text-align: left; - vertical-align: top; -} - -table.indextable ul { - margin-top: 0; - margin-bottom: 0; - list-style-type: none; -} - -table.indextable > tbody > tr > td > ul { - padding-left: 0em; -} - -table.indextable tr.pcap { - height: 10px; -} - -table.indextable tr.cap { - margin-top: 10px; - background-color: #f2f2f2; -} - -img.toggler { - margin-right: 3px; - margin-top: 3px; - cursor: pointer; -} - -div.modindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -div.genindex-jumpbox { - border-top: 1px solid #ddd; - border-bottom: 1px solid #ddd; - margin: 1em 0 1em 0; - padding: 0.4em; -} - -/* -- domain module index --------------------------------------------------- */ - -table.modindextable td { - padding: 2px; - border-collapse: collapse; -} - -/* -- general body styles --------------------------------------------------- */ - -div.body { - min-width: 360px; - max-width: 800px; -} - -div.body p, div.body dd, div.body li, div.body blockquote { - -moz-hyphens: auto; - -ms-hyphens: auto; - -webkit-hyphens: auto; - hyphens: auto; -} - -a.headerlink { - visibility: hidden; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink, -caption:hover > a.headerlink, -p.caption:hover > a.headerlink, -div.code-block-caption:hover > a.headerlink { - visibility: visible; -} - -div.body p.caption { - text-align: inherit; -} - -div.body td { - text-align: left; -} - -.first { - margin-top: 0 !important; -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -img.align-left, figure.align-left, .figure.align-left, object.align-left { - clear: left; - float: left; - margin-right: 1em; -} - -img.align-right, figure.align-right, .figure.align-right, object.align-right { - clear: right; - float: right; - margin-left: 1em; -} - -img.align-center, figure.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -img.align-default, figure.align-default, .figure.align-default { - display: block; - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left; -} - -.align-center { - text-align: center; -} - -.align-default { - text-align: center; -} - -.align-right { - text-align: right; -} - -/* -- sidebars -------------------------------------------------------------- */ - -div.sidebar, -aside.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 7px; - background-color: #ffe; - width: 40%; - float: right; - clear: right; - overflow-x: auto; -} - -p.sidebar-title { - font-weight: bold; -} -nav.contents, -aside.topic, - -div.admonition, div.topic, blockquote { - clear: left; -} - -/* -- topics ---------------------------------------------------------------- */ -nav.contents, -aside.topic, - -div.topic { - border: 1px solid #ccc; - padding: 7px; - margin: 10px 0 10px 0; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- admonitions ----------------------------------------------------------- */ - -div.admonition { - margin-top: 10px; - margin-bottom: 10px; - padding: 7px; -} - -div.admonition dt { - font-weight: bold; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -/* -- content of sidebars/topics/admonitions -------------------------------- */ - -div.sidebar > :last-child, -aside.sidebar > :last-child, -nav.contents > :last-child, -aside.topic > :last-child, - -div.topic > :last-child, -div.admonition > :last-child { - margin-bottom: 0; -} - -div.sidebar::after, -aside.sidebar::after, -nav.contents::after, -aside.topic::after, - -div.topic::after, -div.admonition::after, -blockquote::after { - display: block; - content: ''; - clear: both; -} - -/* -- tables ---------------------------------------------------------------- */ - -table.docutils { - margin-top: 10px; - margin-bottom: 10px; - border: 0; - border-collapse: collapse; -} - -table.align-center { - margin-left: auto; - margin-right: auto; -} - -table.align-default { - margin-left: auto; - margin-right: auto; -} - -table caption span.caption-number { - font-style: italic; -} - -table caption span.caption-text { -} - -table.docutils td, table.docutils th { - padding: 1px 8px 1px 5px; - border-top: 0; - border-left: 0; - border-right: 0; - border-bottom: 1px solid #aaa; -} - -th { - text-align: left; - padding-right: 5px; -} - -table.citation { - border-left: solid 1px gray; - margin-left: 1px; -} - -table.citation td { - border-bottom: none; -} - -th > :first-child, -td > :first-child { - margin-top: 0px; -} - -th > :last-child, -td > :last-child { - margin-bottom: 0px; -} - -/* -- figures --------------------------------------------------------------- */ - -div.figure, figure { - margin: 0.5em; - padding: 0.5em; -} - -div.figure p.caption, figcaption { - padding: 0.3em; -} - -div.figure p.caption span.caption-number, -figcaption span.caption-number { - font-style: italic; -} - -div.figure p.caption span.caption-text, -figcaption span.caption-text { -} - -/* -- field list styles ----------------------------------------------------- */ - -table.field-list td, table.field-list th { - border: 0 !important; -} - -.field-list ul { - margin: 0; - padding-left: 1em; -} - -.field-list p { - margin: 0; -} - -.field-name { - -moz-hyphens: manual; - -ms-hyphens: manual; - -webkit-hyphens: manual; - hyphens: manual; -} - -/* -- hlist styles ---------------------------------------------------------- */ - -table.hlist { - margin: 1em 0; -} - -table.hlist td { - vertical-align: top; -} - -/* -- object description styles --------------------------------------------- */ - -.sig { - font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; -} - -.sig-name, code.descname { - background-color: transparent; - font-weight: bold; -} - -.sig-name { - font-size: 1.1em; -} - -code.descname { - font-size: 1.2em; -} - -.sig-prename, code.descclassname { - background-color: transparent; -} - -.optional { - font-size: 1.3em; -} - -.sig-paren { - font-size: larger; -} - -.sig-param.n { - font-style: italic; -} - -/* C++ specific styling */ - -.sig-inline.c-texpr, -.sig-inline.cpp-texpr { - font-family: unset; -} - -.sig.c .k, .sig.c .kt, -.sig.cpp .k, .sig.cpp .kt { - color: #0033B3; -} - -.sig.c .m, -.sig.cpp .m { - color: #1750EB; -} - -.sig.c .s, .sig.c .sc, -.sig.cpp .s, .sig.cpp .sc { - color: #067D17; -} - - -/* -- other body styles ----------------------------------------------------- */ - -ol.arabic { - list-style: decimal; -} - -ol.loweralpha { - list-style: lower-alpha; -} - -ol.upperalpha { - list-style: upper-alpha; -} - -ol.lowerroman { - list-style: lower-roman; -} - -ol.upperroman { - list-style: upper-roman; -} - -:not(li) > ol > li:first-child > :first-child, -:not(li) > ul > li:first-child > :first-child { - margin-top: 0px; -} - -:not(li) > ol > li:last-child > :last-child, -:not(li) > ul > li:last-child > :last-child { - margin-bottom: 0px; -} - -ol.simple ol p, -ol.simple ul p, -ul.simple ol p, -ul.simple ul p { - margin-top: 0; -} - -ol.simple > li:not(:first-child) > p, -ul.simple > li:not(:first-child) > p { - margin-top: 0; -} - -ol.simple p, -ul.simple p { - margin-bottom: 0; -} - -/* Docutils 0.17 and older (footnotes & citations) */ -dl.footnote > dt, -dl.citation > dt { - float: left; - margin-right: 0.5em; -} - -dl.footnote > dd, -dl.citation > dd { - margin-bottom: 0em; -} - -dl.footnote > dd:after, -dl.citation > dd:after { - content: ""; - clear: both; -} - -/* Docutils 0.18+ (footnotes & citations) */ -aside.footnote > span, -div.citation > span { - float: left; -} -aside.footnote > span:last-of-type, -div.citation > span:last-of-type { - padding-right: 0.5em; -} -aside.footnote > p { - margin-left: 2em; -} -div.citation > p { - margin-left: 4em; -} -aside.footnote > p:last-of-type, -div.citation > p:last-of-type { - margin-bottom: 0em; -} -aside.footnote > p:last-of-type:after, -div.citation > p:last-of-type:after { - content: ""; - clear: both; -} - -/* Footnotes & citations ends */ - -dl.field-list { - display: grid; - grid-template-columns: fit-content(30%) auto; -} - -dl.field-list > dt { - font-weight: bold; - word-break: break-word; - padding-left: 0.5em; - padding-right: 5px; -} - -dl.field-list > dt:after { - content: ":"; -} - -dl.field-list > dd { - padding-left: 0.5em; - margin-top: 0em; - margin-left: 0em; - margin-bottom: 0em; -} - -dl { - margin-bottom: 15px; -} - -dd > :first-child { - margin-top: 0px; -} - -dd ul, dd table { - margin-bottom: 10px; -} - -dd { - margin-top: 3px; - margin-bottom: 10px; - margin-left: 30px; -} - -dl > dd:last-child, -dl > dd:last-child > :last-child { - margin-bottom: 0; -} - -dt:target, span.highlighted { - background-color: #fbe54e; -} - -rect.highlighted { - fill: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 1.1em; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa; -} - -.line-block { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} - -.line-block .line-block { - margin-top: 0; - margin-bottom: 0; - margin-left: 1.5em; -} - -.guilabel, .menuselection { - font-family: sans-serif; -} - -.accelerator { - text-decoration: underline; -} - -.classifier { - font-style: oblique; -} - -.classifier:before { - font-style: normal; - margin: 0 0.5em; - content: ":"; - display: inline-block; -} - -abbr, acronym { - border-bottom: dotted 1px; - cursor: help; -} - -/* -- code displays --------------------------------------------------------- */ - -pre { - overflow: auto; - overflow-y: hidden; /* fixes display issues on Chrome browsers */ -} - -pre, div[class*="highlight-"] { - clear: both; -} - -span.pre { - -moz-hyphens: none; - -ms-hyphens: none; - -webkit-hyphens: none; - hyphens: none; - white-space: nowrap; -} - -div[class*="highlight-"] { - margin: 1em 0; -} - -td.linenos pre { - border: 0; - background-color: transparent; - color: #aaa; -} - -table.highlighttable { - display: block; -} - -table.highlighttable tbody { - display: block; -} - -table.highlighttable tr { - display: flex; -} - -table.highlighttable td { - margin: 0; - padding: 0; -} - -table.highlighttable td.linenos { - padding-right: 0.5em; -} - -table.highlighttable td.code { - flex: 1; - overflow: hidden; -} - -.highlight .hll { - display: block; -} - -div.highlight pre, -table.highlighttable pre { - margin: 0; -} - -div.code-block-caption + div { - margin-top: 0; -} - -div.code-block-caption { - margin-top: 1em; - padding: 2px 5px; - font-size: small; -} - -div.code-block-caption code { - background-color: transparent; -} - -table.highlighttable td.linenos, -span.linenos, -div.highlight span.gp { /* gp: Generic.Prompt */ - user-select: none; - -webkit-user-select: text; /* Safari fallback only */ - -webkit-user-select: none; /* Chrome/Safari */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* IE10+ */ -} - -div.code-block-caption span.caption-number { - padding: 0.1em 0.3em; - font-style: italic; -} - -div.code-block-caption span.caption-text { -} - -div.literal-block-wrapper { - margin: 1em 0; -} - -code.xref, a code { - background-color: transparent; - font-weight: bold; -} - -h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { - background-color: transparent; -} - -.viewcode-link { - float: right; -} - -.viewcode-back { - float: right; - font-family: sans-serif; -} - -div.viewcode-block:target { - margin: -1px -10px; - padding: 0 10px; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -span.eqno a.headerlink { - position: absolute; - z-index: 1; -} - -div.math:hover a.headerlink { - visibility: visible; -} - -/* -- printout stylesheet --------------------------------------------------- */ - -@media print { - div.document, - div.documentwrapper, - div.bodywrapper { - margin: 0 !important; - width: 100%; - } - - div.sphinxsidebar, - div.related, - div.footer, - #top-link { - display: none; - } -} \ No newline at end of file diff --git a/docs/_build/html/_static/custom.css b/docs/_build/html/_static/custom.css deleted file mode 100644 index 2a924f1..0000000 --- a/docs/_build/html/_static/custom.css +++ /dev/null @@ -1 +0,0 @@ -/* This file intentionally left blank. */ diff --git a/docs/_build/html/_static/doctools.js b/docs/_build/html/_static/doctools.js deleted file mode 100644 index c3db08d..0000000 --- a/docs/_build/html/_static/doctools.js +++ /dev/null @@ -1,264 +0,0 @@ -/* - * doctools.js - * ~~~~~~~~~~~ - * - * Base JavaScript utilities for all Sphinx HTML documentation. - * - * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ -"use strict"; - -const _ready = (callback) => { - if (document.readyState !== "loading") { - callback(); - } else { - document.addEventListener("DOMContentLoaded", callback); - } -}; - -/** - * highlight a given string on a node by wrapping it in - * span elements with the given class name. - */ -const _highlight = (node, addItems, text, className) => { - if (node.nodeType === Node.TEXT_NODE) { - const val = node.nodeValue; - const parent = node.parentNode; - const pos = val.toLowerCase().indexOf(text); - if ( - pos >= 0 && - !parent.classList.contains(className) && - !parent.classList.contains("nohighlight") - ) { - let span; - - const closestNode = parent.closest("body, svg, foreignObject"); - const isInSVG = closestNode && closestNode.matches("svg"); - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.classList.add(className); - } - - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - parent.insertBefore( - span, - parent.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling - ) - ); - node.nodeValue = val.substr(0, pos); - - if (isInSVG) { - const rect = document.createElementNS( - "http://www.w3.org/2000/svg", - "rect" - ); - const bbox = parent.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute("class", className); - addItems.push({ parent: parent, target: rect }); - } - } - } else if (node.matches && !node.matches("button, select, textarea")) { - node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); - } -}; -const _highlightText = (thisNode, text, className) => { - let addItems = []; - _highlight(thisNode, addItems, text, className); - addItems.forEach((obj) => - obj.parent.insertAdjacentElement("beforebegin", obj.target) - ); -}; - -/** - * Small JavaScript module for the documentation. - */ -const Documentation = { - init: () => { - Documentation.highlightSearchWords(); - Documentation.initDomainIndexTable(); - Documentation.initOnKeyListeners(); - }, - - /** - * i18n support - */ - TRANSLATIONS: {}, - PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), - LOCALE: "unknown", - - // gettext and ngettext don't access this so that the functions - // can safely bound to a different name (_ = Documentation.gettext) - gettext: (string) => { - const translated = Documentation.TRANSLATIONS[string]; - switch (typeof translated) { - case "undefined": - return string; // no translation - case "string": - return translated; // translation exists - default: - return translated[0]; // (singular, plural) translation tuple exists - } - }, - - ngettext: (singular, plural, n) => { - const translated = Documentation.TRANSLATIONS[singular]; - if (typeof translated !== "undefined") - return translated[Documentation.PLURAL_EXPR(n)]; - return n === 1 ? singular : plural; - }, - - addTranslations: (catalog) => { - Object.assign(Documentation.TRANSLATIONS, catalog.messages); - Documentation.PLURAL_EXPR = new Function( - "n", - `return (${catalog.plural_expr})` - ); - Documentation.LOCALE = catalog.locale; - }, - - /** - * highlight the search words provided in the url in the text - */ - highlightSearchWords: () => { - const highlight = - new URLSearchParams(window.location.search).get("highlight") || ""; - const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); - if (terms.length === 0) return; // nothing to do - - // There should never be more than one element matching "div.body" - const divBody = document.querySelectorAll("div.body"); - const body = divBody.length ? divBody[0] : document.querySelector("body"); - window.setTimeout(() => { - terms.forEach((term) => _highlightText(body, term, "highlighted")); - }, 10); - - const searchBox = document.getElementById("searchbox"); - if (searchBox === null) return; - searchBox.appendChild( - document - .createRange() - .createContextualFragment( - '" - ) - ); - }, - - /** - * helper function to hide the search marks again - */ - hideSearchWords: () => { - document - .querySelectorAll("#searchbox .highlight-link") - .forEach((el) => el.remove()); - document - .querySelectorAll("span.highlighted") - .forEach((el) => el.classList.remove("highlighted")); - const url = new URL(window.location); - url.searchParams.delete("highlight"); - window.history.replaceState({}, "", url); - }, - - /** - * helper function to focus on search bar - */ - focusSearchBar: () => { - document.querySelectorAll("input[name=q]")[0]?.focus(); - }, - - /** - * Initialise the domain index toggle buttons - */ - initDomainIndexTable: () => { - const toggler = (el) => { - const idNumber = el.id.substr(7); - const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); - if (el.src.substr(-9) === "minus.png") { - el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; - toggledRows.forEach((el) => (el.style.display = "none")); - } else { - el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; - toggledRows.forEach((el) => (el.style.display = "")); - } - }; - - const togglerElements = document.querySelectorAll("img.toggler"); - togglerElements.forEach((el) => - el.addEventListener("click", (event) => toggler(event.currentTarget)) - ); - togglerElements.forEach((el) => (el.style.display = "")); - if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); - }, - - initOnKeyListeners: () => { - // only install a listener if it is really needed - if ( - !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && - !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS - ) - return; - - const blacklistedElements = new Set([ - "TEXTAREA", - "INPUT", - "SELECT", - "BUTTON", - ]); - document.addEventListener("keydown", (event) => { - if (blacklistedElements.has(document.activeElement.tagName)) return; // bail for input elements - if (event.altKey || event.ctrlKey || event.metaKey) return; // bail with special keys - - if (!event.shiftKey) { - switch (event.key) { - case "ArrowLeft": - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; - - const prevLink = document.querySelector('link[rel="prev"]'); - if (prevLink && prevLink.href) { - window.location.href = prevLink.href; - event.preventDefault(); - } - break; - case "ArrowRight": - if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; - - const nextLink = document.querySelector('link[rel="next"]'); - if (nextLink && nextLink.href) { - window.location.href = nextLink.href; - event.preventDefault(); - } - break; - case "Escape": - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; - Documentation.hideSearchWords(); - event.preventDefault(); - } - } - - // some keyboard layouts may need Shift to get / - switch (event.key) { - case "/": - if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; - Documentation.focusSearchBar(); - event.preventDefault(); - } - }); - }, -}; - -// quick alias for translations -const _ = Documentation.gettext; - -_ready(Documentation.init); diff --git a/docs/_build/html/_static/documentation_options.js b/docs/_build/html/_static/documentation_options.js deleted file mode 100644 index a750e4d..0000000 --- a/docs/_build/html/_static/documentation_options.js +++ /dev/null @@ -1,14 +0,0 @@ -var DOCUMENTATION_OPTIONS = { - URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), - VERSION: '', - LANGUAGE: 'en', - COLLAPSE_INDEX: false, - BUILDER: 'html', - FILE_SUFFIX: '.html', - LINK_SUFFIX: '.html', - HAS_SOURCE: true, - SOURCELINK_SUFFIX: '.txt', - NAVIGATION_WITH_KEYS: false, - SHOW_SEARCH_SUMMARY: true, - ENABLE_SEARCH_SHORTCUTS: false, -}; \ No newline at end of file diff --git a/docs/_build/html/_static/file.png b/docs/_build/html/_static/file.png deleted file mode 100644 index a858a410e4faa62ce324d814e4b816fff83a6fb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( diff --git a/docs/_build/html/_static/jquery-3.6.0.js b/docs/_build/html/_static/jquery-3.6.0.js deleted file mode 100644 index fc6c299..0000000 --- a/docs/_build/html/_static/jquery-3.6.0.js +++ /dev/null @@ -1,10881 +0,0 @@ -/*! - * jQuery JavaScript Library v3.6.0 - * https://jquery.com/ - * - * Includes Sizzle.js - * https://sizzlejs.com/ - * - * Copyright OpenJS Foundation and other contributors - * Released under the MIT license - * https://jquery.org/license - * - * Date: 2021-03-02T17:08Z - */ -( function( global, factory ) { - - "use strict"; - - if ( typeof module === "object" && typeof module.exports === "object" ) { - - // For CommonJS and CommonJS-like environments where a proper `window` - // is present, execute the factory and get jQuery. - // For environments that do not have a `window` with a `document` - // (such as Node.js), expose a factory as module.exports. - // This accentuates the need for the creation of a real `window`. - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info. - module.exports = global.document ? - factory( global, true ) : - function( w ) { - if ( !w.document ) { - throw new Error( "jQuery requires a window with a document" ); - } - return factory( w ); - }; - } else { - factory( global ); - } - -// Pass this if window is not defined yet -} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { - -// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 -// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode -// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common -// enough that all such attempts are guarded in a try block. -"use strict"; - -var arr = []; - -var getProto = Object.getPrototypeOf; - -var slice = arr.slice; - -var flat = arr.flat ? function( array ) { - return arr.flat.call( array ); -} : function( array ) { - return arr.concat.apply( [], array ); -}; - - -var push = arr.push; - -var indexOf = arr.indexOf; - -var class2type = {}; - -var toString = class2type.toString; - -var hasOwn = class2type.hasOwnProperty; - -var fnToString = hasOwn.toString; - -var ObjectFunctionString = fnToString.call( Object ); - -var support = {}; - -var isFunction = function isFunction( obj ) { - - // Support: Chrome <=57, Firefox <=52 - // In some browsers, typeof returns "function" for HTML elements - // (i.e., `typeof document.createElement( "object" ) === "function"`). - // We don't want to classify *any* DOM node as a function. - // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 - // Plus for old WebKit, typeof returns "function" for HTML collections - // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) - return typeof obj === "function" && typeof obj.nodeType !== "number" && - typeof obj.item !== "function"; - }; - - -var isWindow = function isWindow( obj ) { - return obj != null && obj === obj.window; - }; - - -var document = window.document; - - - - var preservedScriptAttributes = { - type: true, - src: true, - nonce: true, - noModule: true - }; - - function DOMEval( code, node, doc ) { - doc = doc || document; - - var i, val, - script = doc.createElement( "script" ); - - script.text = code; - if ( node ) { - for ( i in preservedScriptAttributes ) { - - // Support: Firefox 64+, Edge 18+ - // Some browsers don't support the "nonce" property on scripts. - // On the other hand, just using `getAttribute` is not enough as - // the `nonce` attribute is reset to an empty string whenever it - // becomes browsing-context connected. - // See https://github.com/whatwg/html/issues/2369 - // See https://html.spec.whatwg.org/#nonce-attributes - // The `node.getAttribute` check was added for the sake of - // `jQuery.globalEval` so that it can fake a nonce-containing node - // via an object. - val = node[ i ] || node.getAttribute && node.getAttribute( i ); - if ( val ) { - script.setAttribute( i, val ); - } - } - } - doc.head.appendChild( script ).parentNode.removeChild( script ); - } - - -function toType( obj ) { - if ( obj == null ) { - return obj + ""; - } - - // Support: Android <=2.3 only (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call( obj ) ] || "object" : - typeof obj; -} -/* global Symbol */ -// Defining this global in .eslintrc.json would create a danger of using the global -// unguarded in another place, it seems safer to define global only for this module - - - -var - version = "3.6.0", - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }; - -jQuery.fn = jQuery.prototype = { - - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - - // Return all the elements in a clean array - if ( num == null ) { - return slice.call( this ); - } - - // Return just the one element from the set - return num < 0 ? this[ num + this.length ] : this[ num ]; - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - each: function( callback ) { - return jQuery.each( this, callback ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map( this, function( elem, i ) { - return callback.call( elem, i, elem ); - } ) ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - even: function() { - return this.pushStack( jQuery.grep( this, function( _elem, i ) { - return ( i + 1 ) % 2; - } ) ); - }, - - odd: function() { - return this.pushStack( jQuery.grep( this, function( _elem, i ) { - return i % 2; - } ) ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice -}; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[ 0 ] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // Skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !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 ) { - copy = options[ name ]; - - // Prevent Object.prototype pollution - // Prevent never-ending loop - if ( name === "__proto__" || target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject( copy ) || - ( copyIsArray = Array.isArray( copy ) ) ) ) { - src = target[ name ]; - - // Ensure proper type for the source value - if ( copyIsArray && !Array.isArray( src ) ) { - clone = []; - } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { - clone = {}; - } else { - clone = src; - } - copyIsArray = false; - - // 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() {}, - - isPlainObject: function( obj ) { - var proto, Ctor; - - // Detect obvious negatives - // Use toString instead of jQuery.type to catch host objects - if ( !obj || toString.call( obj ) !== "[object Object]" ) { - return false; - } - - proto = getProto( obj ); - - // Objects with no prototype (e.g., `Object.create( null )`) are plain - if ( !proto ) { - return true; - } - - // Objects with prototype are plain iff they were constructed by a global Object function - Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; - return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; - }, - - isEmptyObject: function( obj ) { - var name; - - for ( name in obj ) { - return false; - } - return true; - }, - - // Evaluates a script in a provided context; falls back to the global one - // if not specified. - globalEval: function( code, options, doc ) { - DOMEval( code, { nonce: options && options.nonce }, doc ); - }, - - each: function( obj, callback ) { - var length, i = 0; - - if ( isArrayLike( obj ) ) { - length = obj.length; - for ( ; i < length; i++ ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } else { - for ( i in obj ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } - - return obj; - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArrayLike( Object( arr ) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var length, value, - i = 0, - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArrayLike( elems ) ) { - length = elems.length; - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return flat( ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -} ); - -if ( typeof Symbol === "function" ) { - jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; -} - -// Populate the class2type map -jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), - function( _i, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); - } ); - -function isArrayLike( obj ) { - - // Support: real iOS 8.2 only (not reproducible in simulator) - // `in` check used to prevent JIT error (gh-2145) - // hasOwn isn't used here due to false negatives - // regarding Nodelist length in IE - var length = !!obj && "length" in obj && obj.length, - type = toType( obj ); - - if ( isFunction( obj ) || isWindow( obj ) ) { - return false; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} -var Sizzle = -/*! - * Sizzle CSS Selector Engine v2.3.6 - * https://sizzlejs.com/ - * - * Copyright JS Foundation and other contributors - * Released under the MIT license - * https://js.foundation/ - * - * Date: 2021-02-16 - */ -( function( window ) { -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - nonnativeSelectorCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // Instance methods - hasOwn = ( {} ).hasOwnProperty, - arr = [], - pop = arr.pop, - pushNative = arr.push, - push = arr.push, - slice = arr.slice, - - // Use a stripped-down indexOf as it's faster than native - // https://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[ i ] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + - "ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - - // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram - identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + - "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + - - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - - // "Attribute values must be CSS identifiers [capture 5] - // or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + - whitespace + "*\\]", - - pseudos = ":(" + identifier + ")(?:\\((" + - - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + - whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + - "*" ), - rdescend = new RegExp( whitespace + "|>" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + identifier + ")" ), - "CLASS": new RegExp( "^\\.(" + identifier + ")" ), - "TAG": new RegExp( "^(" + identifier + "|[*])" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + - whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + - whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + - "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + - "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rhtml = /HTML$/i, - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - - // CSS escapes - // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), - funescape = function( escape, nonHex ) { - var high = "0x" + escape.slice( 1 ) - 0x10000; - - return nonHex ? - - // Strip the backslash prefix from a non-hex escape sequence - nonHex : - - // Replace a hexadecimal escape sequence with the encoded Unicode code point - // Support: IE <=11+ - // For values outside the Basic Multilingual Plane (BMP), manually construct a - // surrogate pair - high < 0 ? - String.fromCharCode( high + 0x10000 ) : - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // CSS string/identifier serialization - // https://drafts.csswg.org/cssom/#common-serializing-idioms - rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, - fcssescape = function( ch, asCodePoint ) { - if ( asCodePoint ) { - - // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER - if ( ch === "\0" ) { - return "\uFFFD"; - } - - // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + - ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; - } - - // Other potentially-special ASCII characters get backslash-escaped - return "\\" + ch; - }, - - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }, - - inDisabledFieldset = addCombinator( - function( elem ) { - return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; - }, - { dir: "parentNode", next: "legend" } - ); - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - ( arr = slice.call( preferredDoc.childNodes ) ), - preferredDoc.childNodes - ); - - // Support: Android<4.0 - // Detect silently failing push.apply - // eslint-disable-next-line no-unused-expressions - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - pushNative.apply( target, slice.call( els ) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - - // Can't trust NodeList.length - while ( ( target[ j++ ] = els[ i++ ] ) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var m, i, elem, nid, match, groups, newSelector, - newContext = context && context.ownerDocument, - - // nodeType defaults to 9, since context defaults to document - nodeType = context ? context.nodeType : 9; - - results = results || []; - - // Return early from calls with invalid selector or context - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - - return results; - } - - // Try to shortcut find operations (as opposed to filters) in HTML documents - if ( !seed ) { - setDocument( context ); - context = context || document; - - if ( documentIsHTML ) { - - // If the selector is sufficiently simple, try using a "get*By*" DOM method - // (excepting DocumentFragment context, where the methods don't exist) - if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { - - // ID selector - if ( ( m = match[ 1 ] ) ) { - - // Document context - if ( nodeType === 9 ) { - if ( ( elem = context.getElementById( m ) ) ) { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - - // Element context - } else { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( newContext && ( elem = newContext.getElementById( m ) ) && - contains( context, elem ) && - elem.id === m ) { - - results.push( elem ); - return results; - } - } - - // Type selector - } else if ( match[ 2 ] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Class selector - } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && - context.getElementsByClassName ) { - - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // Take advantage of querySelectorAll - if ( support.qsa && - !nonnativeSelectorCache[ selector + " " ] && - ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && - - // Support: IE 8 only - // Exclude object elements - ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { - - newSelector = selector; - newContext = context; - - // qSA considers elements outside a scoping root when evaluating child or - // descendant combinators, which is not what we want. - // In such cases, we work around the behavior by prefixing every selector in the - // list with an ID selector referencing the scope context. - // The technique has to be used as well when a leading combinator is used - // as such selectors are not recognized by querySelectorAll. - // Thanks to Andrew Dupont for this technique. - if ( nodeType === 1 && - ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { - - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; - - // We can use :scope instead of the ID hack if the browser - // supports it & if we're not changing the context. - if ( newContext !== context || !support.scope ) { - - // Capture the context ID, setting it first if necessary - if ( ( nid = context.getAttribute( "id" ) ) ) { - nid = nid.replace( rcssescape, fcssescape ); - } else { - context.setAttribute( "id", ( nid = expando ) ); - } - } - - // Prefix every selector in the list - groups = tokenize( selector ); - i = groups.length; - while ( i-- ) { - groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + - toSelector( groups[ i ] ); - } - newSelector = groups.join( "," ); - } - - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch ( qsaError ) { - nonnativeSelectorCache( selector, true ); - } finally { - if ( nid === expando ) { - context.removeAttribute( "id" ); - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {function(string, object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return ( cache[ key + " " ] = value ); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created element and returns a boolean result - */ -function assert( fn ) { - var el = document.createElement( "fieldset" ); - - try { - return !!fn( el ); - } catch ( e ) { - return false; - } finally { - - // Remove from its parent by default - if ( el.parentNode ) { - el.parentNode.removeChild( el ); - } - - // release memory in IE - el = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split( "|" ), - i = arr.length; - - while ( i-- ) { - Expr.attrHandle[ arr[ i ] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - a.sourceIndex - b.sourceIndex; - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( ( cur = cur.nextSibling ) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return ( name === "input" || name === "button" ) && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for :enabled/:disabled - * @param {Boolean} disabled true for :disabled; false for :enabled - */ -function createDisabledPseudo( disabled ) { - - // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable - return function( elem ) { - - // Only certain elements can match :enabled or :disabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled - if ( "form" in elem ) { - - // Check for inherited disabledness on relevant non-disabled elements: - // * listed form-associated elements in a disabled fieldset - // https://html.spec.whatwg.org/multipage/forms.html#category-listed - // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled - // * option elements in a disabled optgroup - // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled - // All such elements have a "form" property. - if ( elem.parentNode && elem.disabled === false ) { - - // Option elements defer to a parent optgroup if present - if ( "label" in elem ) { - if ( "label" in elem.parentNode ) { - return elem.parentNode.disabled === disabled; - } else { - return elem.disabled === disabled; - } - } - - // Support: IE 6 - 11 - // Use the isDisabled shortcut property to check for disabled fieldset ancestors - return elem.isDisabled === disabled || - - // Where there is no isDisabled, check manually - /* jshint -W018 */ - elem.isDisabled !== !disabled && - inDisabledFieldset( elem ) === disabled; - } - - return elem.disabled === disabled; - - // Try to winnow out elements that can't be disabled before trusting the disabled property. - // Some victims get caught in our net (label, legend, menu, track), but it shouldn't - // even exist on them, let alone have a boolean value. - } else if ( "label" in elem ) { - return elem.disabled === disabled; - } - - // Remaining elements are neither :enabled nor :disabled - return false; - }; -} - -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction( function( argument ) { - argument = +argument; - return markFunction( function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ ( j = matchIndexes[ i ] ) ] ) { - seed[ j ] = !( matches[ j ] = seed[ j ] ); - } - } - } ); - } ); -} - -/** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ -function testContext( context ) { - return context && typeof context.getElementsByTagName !== "undefined" && context; -} - -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - var namespace = elem && elem.namespaceURI, - docElem = elem && ( elem.ownerDocument || elem ).documentElement; - - // Support: IE <=8 - // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes - // https://bugs.jquery.com/ticket/4833 - return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); -}; - -/** - * 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, subWindow, - doc = node ? node.ownerDocument || node : preferredDoc; - - // Return early if doc is invalid or already selected - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Update global variables - document = doc; - docElem = document.documentElement; - documentIsHTML = !isXML( document ); - - // Support: IE 9 - 11+, Edge 12 - 18+ - // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( preferredDoc != document && - ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { - - // Support: IE 11, Edge - if ( subWindow.addEventListener ) { - subWindow.addEventListener( "unload", unloadHandler, false ); - - // Support: IE 9 - 10 only - } else if ( subWindow.attachEvent ) { - subWindow.attachEvent( "onunload", unloadHandler ); - } - } - - // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, - // Safari 4 - 5 only, Opera <=11.6 - 12.x only - // IE/Edge & older browsers don't support the :scope pseudo-class. - // Support: Safari 6.0 only - // Safari 6.0 supports :scope but it's an alias of :root there. - support.scope = assert( function( el ) { - docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); - return typeof el.querySelectorAll !== "undefined" && - !el.querySelectorAll( ":scope fieldset div" ).length; - } ); - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties - // (excepting IE8 booleans) - support.attributes = assert( function( el ) { - el.className = "i"; - return !el.getAttribute( "className" ); - } ); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert( function( el ) { - el.appendChild( document.createComment( "" ) ); - return !el.getElementsByTagName( "*" ).length; - } ); - - // Support: IE<9 - support.getElementsByClassName = rnative.test( document.getElementsByClassName ); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programmatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert( function( el ) { - docElem.appendChild( el ).id = expando; - return !document.getElementsByName || !document.getElementsByName( expando ).length; - } ); - - // ID filter and find - if ( support.getById ) { - Expr.filter[ "ID" ] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute( "id" ) === attrId; - }; - }; - Expr.find[ "ID" ] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var elem = context.getElementById( id ); - return elem ? [ elem ] : []; - } - }; - } else { - Expr.filter[ "ID" ] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== "undefined" && - elem.getAttributeNode( "id" ); - return node && node.value === attrId; - }; - }; - - // Support: IE 6 - 7 only - // getElementById is not reliable as a find shortcut - Expr.find[ "ID" ] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var node, i, elems, - elem = context.getElementById( id ); - - if ( elem ) { - - // Verify the id attribute - node = elem.getAttributeNode( "id" ); - if ( node && node.value === id ) { - return [ elem ]; - } - - // Fall back on getElementsByName - elems = context.getElementsByName( id ); - i = 0; - while ( ( elem = elems[ i++ ] ) ) { - node = elem.getAttributeNode( "id" ); - if ( node && node.value === id ) { - return [ elem ]; - } - } - } - - return []; - } - }; - } - - // Tag - Expr.find[ "TAG" ] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( tag ); - - // DocumentFragment nodes don't have gEBTN - } else if ( support.qsa ) { - return context.querySelectorAll( tag ); - } - } : - - function( tag, context ) { - var elem, - tmp = [], - i = 0, - - // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( ( elem = results[ i++ ] ) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See https://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { - - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert( function( el ) { - - var input; - - // 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 - // https://bugs.jquery.com/ticket/12359 - docElem.appendChild( el ).innerHTML = "" + - ""; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !el.querySelectorAll( "[selected]" ).length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ - if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push( "~=" ); - } - - // Support: IE 11+, Edge 15 - 18+ - // IE 11/Edge don't find elements on a `[name='']` query in some cases. - // Adding a temporary attribute to the document before the selection works - // around the issue. - // Interestingly, IE 10 & older don't seem to have the issue. - input = document.createElement( "input" ); - input.setAttribute( "name", "" ); - el.appendChild( input ); - if ( !el.querySelectorAll( "[name='']" ).length ) { - rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + - whitespace + "*(?:''|\"\")" ); - } - - // 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 ( !el.querySelectorAll( ":checked" ).length ) { - rbuggyQSA.push( ":checked" ); - } - - // Support: Safari 8+, iOS 8+ - // https://bugs.webkit.org/show_bug.cgi?id=136851 - // In-page `selector#id sibling-combinator selector` fails - if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push( ".#.+[+~]" ); - } - - // Support: Firefox <=3.6 - 5 only - // Old Firefox doesn't throw on a badly-escaped identifier. - el.querySelectorAll( "\\\f" ); - rbuggyQSA.push( "[\\r\\n\\f]" ); - } ); - - assert( function( el ) { - el.innerHTML = "" + - ""; - - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = document.createElement( "input" ); - input.setAttribute( "type", "hidden" ); - el.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( el.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 ( el.querySelectorAll( ":enabled" ).length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Support: IE9-11+ - // IE's :disabled selector does not pick up the children of disabled fieldsets - docElem.appendChild( el ).disabled = true; - if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Support: Opera 10 - 11 only - // Opera 10-11 does not throw on post-comma invalid pseudos - el.querySelectorAll( "*,:x" ); - rbuggyQSA.push( ",.*:" ); - } ); - } - - if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector ) ) ) ) { - - assert( function( el ) { - - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( el, "*" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( el, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - } ); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully self-exclusive - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - ) ); - } : - function( a, b ) { - if ( b ) { - while ( ( b = b.parentNode ) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } - - // Calculate position if both inputs belong to the same document - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - 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 - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( a == document || a.ownerDocument == preferredDoc && - contains( preferredDoc, a ) ) { - return -1; - } - - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( b == document || b.ownerDocument == preferredDoc && - contains( preferredDoc, b ) ) { - return 1; - } - - // Maintain original order - return sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - /* eslint-disable eqeqeq */ - return a == document ? -1 : - b == document ? 1 : - /* eslint-enable eqeqeq */ - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( ( cur = cur.parentNode ) ) { - ap.unshift( cur ); - } - cur = b; - while ( ( cur = cur.parentNode ) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[ i ] === bp[ i ] ) { - i++; - } - - return i ? - - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[ i ], bp[ i ] ) : - - // Otherwise nodes in our document sort first - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - /* eslint-disable eqeqeq */ - ap[ i ] == preferredDoc ? -1 : - bp[ i ] == preferredDoc ? 1 : - /* eslint-enable eqeqeq */ - 0; - }; - - return document; -}; - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - setDocument( elem ); - - if ( support.matchesSelector && documentIsHTML && - !nonnativeSelectorCache[ expr + " " ] && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch ( e ) { - nonnativeSelectorCache( expr, true ); - } - } - - return Sizzle( expr, document, null, [ elem ] ).length > 0; -}; - -Sizzle.contains = function( context, elem ) { - - // Set document vars if needed - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( ( context.ownerDocument || context ) != document ) { - setDocument( context ); - } - return contains( context, elem ); -}; - -Sizzle.attr = function( elem, name ) { - - // Set document vars if needed - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - 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.escape = function( sel ) { - return ( sel + "" ).replace( rcssescape, fcssescape ); -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); - - if ( hasDuplicate ) { - while ( ( elem = results[ i++ ] ) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; -}; - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - - // If no nodeType, this is expected to be an array - while ( ( node = elem[ i++ ] ) ) { - - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - - // Do not include comment or processing instruction nodes - - return ret; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[ 1 ] = match[ 1 ].replace( runescape, funescape ); - - // Move the given value to match[3] whether quoted or unquoted - match[ 3 ] = ( match[ 3 ] || match[ 4 ] || - match[ 5 ] || "" ).replace( runescape, funescape ); - - if ( match[ 2 ] === "~=" ) { - match[ 3 ] = " " + match[ 3 ] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[ 1 ] = match[ 1 ].toLowerCase(); - - if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { - - // nth-* requires argument - if ( !match[ 3 ] ) { - Sizzle.error( match[ 0 ] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[ 4 ] = +( match[ 4 ] ? - match[ 5 ] + ( match[ 6 ] || 1 ) : - 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); - match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); - - // other types prohibit arguments - } else if ( match[ 3 ] ) { - Sizzle.error( match[ 0 ] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var excess, - unquoted = !match[ 6 ] && match[ 2 ]; - - if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { - return null; - } - - // Accept quoted arguments as-is - if ( match[ 3 ] ) { - match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; - - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - - // Get excess from tokenize (recursively) - ( excess = tokenize( unquoted, true ) ) && - - // advance to the next closing parenthesis - ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { - - // excess is a negative index - match[ 0 ] = match[ 0 ].slice( 0, excess ); - match[ 2 ] = unquoted.slice( 0, excess ); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { - return true; - } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; - - return pattern || - ( pattern = new RegExp( "(^|" + whitespace + - ")" + className + "(" + whitespace + "|$)" ) ) && classCache( - className, function( elem ) { - return pattern.test( - typeof elem.className === "string" && elem.className || - typeof elem.getAttribute !== "undefined" && - elem.getAttribute( "class" ) || - "" - ); - } ); - }, - - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - /* eslint-disable max-len */ - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - /* eslint-enable max-len */ - - }; - }, - - "CHILD": function( type, what, _argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : - - function( elem, _context, xml ) { - var cache, uniqueCache, outerCache, node, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType, - diff = false; - - if ( parent ) { - - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( ( node = node[ dir ] ) ) { - if ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) { - - return false; - } - } - - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [ forward ? parent.firstChild : parent.lastChild ]; - - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - - // Seek `elem` from a previously-cached index - - // ...in a gzip-friendly way - node = parent; - outerCache = node[ expando ] || ( node[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - ( outerCache[ node.uniqueID ] = {} ); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex && cache[ 2 ]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; - - while ( ( node = ++nodeIndex && node && node[ dir ] || - - // Fallback to seeking `elem` from the start - ( diff = nodeIndex = 0 ) || start.pop() ) ) { - - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } - - } else { - - // Use previously-cached element index if available - if ( useCache ) { - - // ...in a gzip-friendly way - node = elem; - outerCache = node[ expando ] || ( node[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - ( outerCache[ node.uniqueID ] = {} ); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex; - } - - // xml :nth-child(...) - // or :nth-last-child(...) or :nth(-last)?-of-type(...) - if ( diff === false ) { - - // Use the same loop as above to seek `elem` from the start - while ( ( node = ++nodeIndex && node && node[ dir ] || - ( diff = nodeIndex = 0 ) || start.pop() ) ) { - - if ( ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) && - ++diff ) { - - // Cache the index of each encountered element - if ( useCache ) { - outerCache = node[ expando ] || - ( node[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - ( outerCache[ node.uniqueID ] = {} ); - - uniqueCache[ type ] = [ dirruns, diff ]; - } - - if ( node === elem ) { - break; - } - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction( function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf( seed, matched[ i ] ); - seed[ idx ] = !( matches[ idx ] = matched[ i ] ); - } - } ) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - - // Potentially complex pseudos - "not": markFunction( function( selector ) { - - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction( function( seed, matches, _context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( ( elem = unmatched[ i ] ) ) { - seed[ i ] = !( matches[ i ] = elem ); - } - } - } ) : - function( elem, _context, xml ) { - input[ 0 ] = elem; - matcher( input, null, xml, results ); - - // Don't keep the element (issue #299) - input[ 0 ] = null; - return !results.pop(); - }; - } ), - - "has": markFunction( function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - } ), - - "contains": markFunction( function( text ) { - text = text.replace( runescape, funescape ); - return function( elem ) { - return ( elem.textContent || 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": createDisabledPseudo( false ), - "disabled": createDisabledPseudo( 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 ) { - // eslint-disable-next-line no-unused-expressions - 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 > length ? - 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, - skip = combinator.next, - key = skip || dir, - checkNonElements = base && key === "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 ); - } - } - return false; - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, uniqueCache, outerCache, - newCache = [ dirruns, doneName ]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching - if ( xml ) { - while ( ( elem = elem[ dir ] ) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( ( elem = elem[ dir ] ) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || ( elem[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ elem.uniqueID ] || - ( outerCache[ elem.uniqueID ] = {} ); - - if ( skip && skip === elem.nodeName.toLowerCase() ) { - elem = elem[ dir ] || elem; - } else if ( ( oldCache = uniqueCache[ key ] ) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { - - // Assign to newCache so results back-propagate to previous elements - return ( newCache[ 2 ] = oldCache[ 2 ] ); - } else { - - // Reuse newcache so results back-propagate to previous elements - uniqueCache[ key ] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { - return true; - } - } - } - } - } - return false; - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[ i ]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[ 0 ]; -} - -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[ i ], results ); - } - return results; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( ( elem = unmatched[ i ] ) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction( function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( - selector || "*", - context.nodeType ? [ context ] : context, - [] - ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( ( elem = temp[ i ] ) ) { - matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( ( elem = matcherOut[ i ] ) ) { - - // Restore matcherIn since elem is not yet a final match - temp.push( ( matcherIn[ i ] = elem ) ); - } - } - postFinder( null, ( matcherOut = [] ), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( ( elem = matcherOut[ i ] ) && - ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { - - seed[ temp ] = !( results[ temp ] = elem ); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - } ); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[ 0 ].type ], - implicitRelative = leadingRelative || Expr.relative[ " " ], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - ( checkContext = context ).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - - // Avoid hanging onto element (issue #299) - checkContext = null; - return ret; - } ]; - - for ( ; i < len; i++ ) { - if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { - matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; - } else { - matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[ j ].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens - .slice( 0, i - 1 ) - .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), - - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), - len = elems.length; - - if ( outermost ) { - - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - outermostContext = context == document || context || outermost; - } - - // Add elements passing elementMatchers directly to results - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( !context && elem.ownerDocument != document ) { - setDocument( elem ); - xml = !documentIsHTML; - } - while ( ( matcher = elementMatchers[ j++ ] ) ) { - if ( matcher( elem, context || document, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - - // They will have gone through all possible matchers - if ( ( elem = !matcher && elem ) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // `i` is now the count of elements visited above, and adding it to `matchedCount` - // makes the latter nonnegative. - matchedCount += i; - - // Apply set filters to unmatched elements - // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` - // equals `i`), unless we didn't visit _any_ elements in the above loop because we have - // no element matchers and no seed. - // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that - // case, which will result in a "00" `matchedCount` that differs from `i` but is also - // numerically zero. - if ( bySet && i !== matchedCount ) { - j = 0; - while ( ( matcher = setMatchers[ j++ ] ) ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !( unmatched[ i ] || setMatched[ i ] ) ) { - setMatched[ i ] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; - - if ( !cached ) { - - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[ i ] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( - selector, - matcherFromGroupMatchers( elementMatchers, setMatchers ) - ); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; -}; - -/** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ -select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( ( selector = compiled.selector || selector ) ); - - results = results || []; - - // Try to minimize operations if there is only one selector in the list and no seed - // (the latter of which guarantees us context) - if ( match.length === 1 ) { - - // Reduce context if the leading compound selector is an ID - tokens = match[ 0 ] = match[ 0 ].slice( 0 ); - if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && - context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { - - context = ( Expr.find[ "ID" ]( token.matches[ 0 ] - .replace( runescape, funescape ), context ) || [] )[ 0 ]; - if ( !context ) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; - } - - selector = selector.slice( tokens.shift().value.length ); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[ i ]; - - // Abort if we hit a combinator - if ( Expr.relative[ ( type = token.type ) ] ) { - break; - } - if ( ( find = Expr.find[ type ] ) ) { - - // Search, expanding context for leading sibling combinators - if ( ( seed = find( - token.matches[ 0 ].replace( runescape, funescape ), - rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || - context - ) ) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - !context || rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; -}; - -// One-time assignments - -// Sort stability -support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; - -// Support: Chrome 14-35+ -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = !!hasDuplicate; - -// Initialize against the default document -setDocument(); - -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) -// Detached nodes confoundingly follow *each other* -support.sortDetached = assert( function( el ) { - - // Should return 1, but returns 4 (following) - return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; -} ); - -// Support: IE<8 -// Prevent attribute/property "interpolation" -// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert( function( el ) { - el.innerHTML = ""; - return el.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( el ) { - el.innerHTML = ""; - el.firstChild.setAttribute( "value", "" ); - return el.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( el ) { - return el.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; - -// Deprecated -jQuery.expr[ ":" ] = jQuery.expr.pseudos; -jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; -jQuery.escapeSelector = Sizzle.escape; - - - - -var dir = function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; - - while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); - } - } - return matched; -}; - - -var siblings = function( n, elem ) { - var matched = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } - } - - return matched; -}; - - -var rneedsContext = jQuery.expr.match.needsContext; - - - -function nodeName( elem, name ) { - - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - -} -var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); - - - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - return !!qualifier.call( elem, i, elem ) !== not; - } ); - } - - // Single element - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - } ); - } - - // Arraylike of elements (jQuery, arguments, Array) - if ( typeof qualifier !== "string" ) { - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) > -1 ) !== not; - } ); - } - - // Filtered directly for both simple and complex selectors - return jQuery.filter( qualifier, elements, not ); -} - -jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; - - if ( not ) { - expr = ":not(" + expr + ")"; - } - - if ( elems.length === 1 && elem.nodeType === 1 ) { - return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; - } - - return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - } ) ); -}; - -jQuery.fn.extend( { - find: function( selector ) { - var i, ret, - len = this.length, - self = this; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter( function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - } ) ); - } - - ret = this.pushStack( [] ); - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - return len > 1 ? jQuery.uniqueSort( ret ) : ret; - }, - filter: function( selector ) { - return this.pushStack( winnow( this, selector || [], false ) ); - }, - not: function( selector ) { - return this.pushStack( winnow( this, selector || [], true ) ); - }, - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } -} ); - - -// Initialize a jQuery object - - -// A central reference to the root jQuery(document) -var rootjQuery, - - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - // Shortcut simple #id case for speed - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, - - init = jQuery.fn.init = function( selector, context, root ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Method init() accepts an alternate rootjQuery - // so migrate can support jQuery.sub (gh-2101) - root = root || rootjQuery; - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector[ 0 ] === "<" && - selector[ selector.length - 1 ] === ">" && - selector.length >= 3 ) { - - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && ( match[ 1 ] || !context ) ) { - - // HANDLE: $(html) -> $(array) - if ( match[ 1 ] ) { - context = context instanceof jQuery ? context[ 0 ] : context; - - // Option to run scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[ 1 ], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - - // Properties of context are called as methods if possible - if ( 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 ] ); - - if ( elem ) { - - // Inject the element directly into the jQuery object - this[ 0 ] = elem; - this.length = 1; - } - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || root ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this[ 0 ] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( isFunction( selector ) ) { - return root.ready !== undefined ? - root.ready( selector ) : - - // Execute immediately if ready is not present - selector( jQuery ); - } - - return jQuery.makeArray( selector, this ); - }; - -// Give the init function the jQuery prototype for later instantiation -init.prototype = jQuery.fn; - -// Initialize central reference -rootjQuery = jQuery( document ); - - -var rparentsprev = /^(?:parents|prev(?:Until|All))/, - - // Methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend( { - has: function( target ) { - var targets = jQuery( target, this ), - l = targets.length; - - return this.filter( function() { - var i = 0; - for ( ; i < l; i++ ) { - if ( jQuery.contains( this, targets[ i ] ) ) { - return true; - } - } - } ); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - targets = typeof selectors !== "string" && jQuery( selectors ); - - // Positional selectors never match, since there's no _selection_ context - if ( !rneedsContext.test( selectors ) ) { - for ( ; i < l; i++ ) { - for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { - - // Always skip document fragments - if ( cur.nodeType < 11 && ( targets ? - targets.index( cur ) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector( cur, selectors ) ) ) { - - matched.push( cur ); - break; - } - } - } - } - - return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); - }, - - // Determine the position of an element within the set - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; - } - - // Index in selector - if ( typeof elem === "string" ) { - return indexOf.call( jQuery( elem ), this[ 0 ] ); - } - - // Locate the position of the desired element - return indexOf.call( this, - - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[ 0 ] : elem - ); - }, - - add: function( selector, context ) { - return this.pushStack( - jQuery.uniqueSort( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - } -} ); - -function sibling( cur, dir ) { - while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} - return cur; -} - -jQuery.each( { - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, _i, until ) { - return dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, _i, until ) { - return dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, _i, until ) { - return dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return siblings( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return siblings( elem.firstChild ); - }, - contents: function( elem ) { - if ( elem.contentDocument != null && - - // Support: IE 11+ - // elements with no `data` attribute has an object - // `contentDocument` with a `null` prototype. - getProto( elem.contentDocument ) ) { - - return elem.contentDocument; - } - - // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only - // Treat the template element as a regular one in browsers that - // don't support it. - if ( nodeName( elem, "template" ) ) { - elem = elem.content || elem; - } - - return jQuery.merge( [], elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var matched = jQuery.map( this, fn, until ); - - if ( name.slice( -5 ) !== "Until" ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - matched = jQuery.filter( selector, matched ); - } - - if ( this.length > 1 ) { - - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - jQuery.uniqueSort( matched ); - } - - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - matched.reverse(); - } - } - - return this.pushStack( matched ); - }; -} ); -var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); - - - -// Convert String-formatted options into Object-formatted ones -function createOptions( options ) { - var object = {}; - jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { - object[ flag ] = true; - } ); - return object; -} - -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - createOptions( options ) : - jQuery.extend( {}, options ); - - var // Flag to know if list is currently firing - firing, - - // Last fire value for non-forgettable lists - memory, - - // Flag to know if list was already fired - fired, - - // Flag to prevent firing - locked, - - // Actual callback list - list = [], - - // Queue of execution data for repeatable lists - queue = [], - - // Index of currently firing callback (modified by add/remove as needed) - firingIndex = -1, - - // Fire callbacks - fire = function() { - - // Enforce single-firing - locked = locked || options.once; - - // Execute callbacks for all pending executions, - // respecting firingIndex overrides and runtime changes - fired = firing = true; - for ( ; queue.length; firingIndex = -1 ) { - memory = queue.shift(); - while ( ++firingIndex < list.length ) { - - // Run callback and check for early termination - if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && - options.stopOnFalse ) { - - // Jump to end and forget the data so .add doesn't re-fire - firingIndex = list.length; - memory = false; - } - } - } - - // Forget the data if we're done with it - if ( !options.memory ) { - memory = false; - } - - firing = false; - - // Clean up if we're done firing for good - if ( locked ) { - - // Keep an empty list if we have data for future add calls - if ( memory ) { - list = []; - - // Otherwise, this object is spent - } else { - list = ""; - } - } - }, - - // Actual Callbacks object - self = { - - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - - // If we have memory from a past run, we should fire after adding - if ( memory && !firing ) { - firingIndex = list.length - 1; - queue.push( memory ); - } - - ( function add( args ) { - jQuery.each( args, function( _, arg ) { - if ( isFunction( arg ) ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && toType( arg ) !== "string" ) { - - // Inspect recursively - add( arg ); - } - } ); - } )( arguments ); - - if ( memory && !firing ) { - fire(); - } - } - return this; - }, - - // Remove a callback from the list - remove: function() { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - - // Handle firing indexes - if ( index <= firingIndex ) { - firingIndex--; - } - } - } ); - return this; - }, - - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? - jQuery.inArray( fn, list ) > -1 : - list.length > 0; - }, - - // Remove all callbacks from the list - empty: function() { - if ( list ) { - list = []; - } - return this; - }, - - // Disable .fire and .add - // Abort any current/pending executions - // Clear all callbacks and values - disable: function() { - locked = queue = []; - list = memory = ""; - return this; - }, - disabled: function() { - return !list; - }, - - // Disable .fire - // Also disable .add unless we have memory (since it would have no effect) - // Abort any pending executions - lock: function() { - locked = queue = []; - if ( !memory && !firing ) { - list = memory = ""; - } - return this; - }, - locked: function() { - return !!locked; - }, - - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( !locked ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - queue.push( args ); - if ( !firing ) { - fire(); - } - } - return this; - }, - - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; - - -function Identity( v ) { - return v; -} -function Thrower( ex ) { - throw ex; -} - -function adoptValue( value, resolve, reject, noValue ) { - var method; - - try { - - // Check for promise aspect first to privilege synchronous behavior - if ( value && isFunction( ( method = value.promise ) ) ) { - method.call( value ).done( resolve ).fail( reject ); - - // Other thenables - } else if ( value && isFunction( ( method = value.then ) ) ) { - method.call( value, resolve, reject ); - - // Other non-thenables - } else { - - // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: - // * false: [ value ].slice( 0 ) => resolve( value ) - // * true: [ value ].slice( 1 ) => resolve() - resolve.apply( undefined, [ value ].slice( noValue ) ); - } - - // For Promises/A+, convert exceptions into rejections - // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in - // Deferred#then to conditionally suppress rejection. - } catch ( value ) { - - // Support: Android 4.0 only - // Strict mode functions invoked without .call/.apply get global-object context - reject.apply( undefined, [ value ] ); - } -} - -jQuery.extend( { - - Deferred: function( func ) { - var tuples = [ - - // action, add listener, callbacks, - // ... .then handlers, argument index, [final state] - [ "notify", "progress", jQuery.Callbacks( "memory" ), - jQuery.Callbacks( "memory" ), 2 ], - [ "resolve", "done", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 0, "resolved" ], - [ "reject", "fail", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 1, "rejected" ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - "catch": function( fn ) { - return promise.then( null, fn ); - }, - - // Keep pipe for back-compat - pipe: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - - return jQuery.Deferred( function( newDefer ) { - jQuery.each( tuples, function( _i, tuple ) { - - // Map tuples (progress, done, fail) to arguments (done, fail, progress) - var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; - - // deferred.progress(function() { bind to newDefer or newDefer.notify }) - // deferred.done(function() { bind to newDefer or newDefer.resolve }) - // deferred.fail(function() { bind to newDefer or newDefer.reject }) - deferred[ tuple[ 1 ] ]( function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && isFunction( returned.promise ) ) { - returned.promise() - .progress( newDefer.notify ) - .done( newDefer.resolve ) - .fail( newDefer.reject ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( - this, - fn ? [ returned ] : arguments - ); - } - } ); - } ); - fns = null; - } ).promise(); - }, - then: function( onFulfilled, onRejected, onProgress ) { - var maxDepth = 0; - function resolve( depth, deferred, handler, special ) { - return function() { - var that = this, - args = arguments, - mightThrow = function() { - var returned, then; - - // Support: Promises/A+ section 2.3.3.3.3 - // https://promisesaplus.com/#point-59 - // Ignore double-resolution attempts - if ( depth < maxDepth ) { - return; - } - - returned = handler.apply( that, args ); - - // Support: Promises/A+ section 2.3.1 - // https://promisesaplus.com/#point-48 - if ( returned === deferred.promise() ) { - throw new TypeError( "Thenable self-resolution" ); - } - - // Support: Promises/A+ sections 2.3.3.1, 3.5 - // https://promisesaplus.com/#point-54 - // https://promisesaplus.com/#point-75 - // Retrieve `then` only once - then = returned && - - // Support: Promises/A+ section 2.3.4 - // https://promisesaplus.com/#point-64 - // Only check objects and functions for thenability - ( typeof returned === "object" || - typeof returned === "function" ) && - returned.then; - - // Handle a returned thenable - if ( isFunction( then ) ) { - - // Special processors (notify) just wait for resolution - if ( special ) { - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ) - ); - - // Normal processors (resolve) also hook into progress - } else { - - // ...and disregard older resolution values - maxDepth++; - - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ), - resolve( maxDepth, deferred, Identity, - deferred.notifyWith ) - ); - } - - // Handle all other returned values - } else { - - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Identity ) { - that = undefined; - args = [ returned ]; - } - - // Process the value(s) - // Default process is resolve - ( special || deferred.resolveWith )( that, args ); - } - }, - - // Only normal processors (resolve) catch and reject exceptions - process = special ? - mightThrow : - function() { - try { - mightThrow(); - } catch ( e ) { - - if ( jQuery.Deferred.exceptionHook ) { - jQuery.Deferred.exceptionHook( e, - process.stackTrace ); - } - - // Support: Promises/A+ section 2.3.3.3.4.1 - // https://promisesaplus.com/#point-61 - // Ignore post-resolution exceptions - if ( depth + 1 >= maxDepth ) { - - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Thrower ) { - that = undefined; - args = [ e ]; - } - - deferred.rejectWith( that, args ); - } - } - }; - - // Support: Promises/A+ section 2.3.3.3.1 - // https://promisesaplus.com/#point-57 - // Re-resolve promises immediately to dodge false rejection from - // subsequent errors - if ( depth ) { - process(); - } else { - - // Call an optional hook to record the stack, in case of exception - // since it's otherwise lost when execution goes async - if ( jQuery.Deferred.getStackHook ) { - process.stackTrace = jQuery.Deferred.getStackHook(); - } - window.setTimeout( process ); - } - }; - } - - return jQuery.Deferred( function( newDefer ) { - - // progress_handlers.add( ... ) - tuples[ 0 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onProgress ) ? - onProgress : - Identity, - newDefer.notifyWith - ) - ); - - // fulfilled_handlers.add( ... ) - tuples[ 1 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onFulfilled ) ? - onFulfilled : - Identity - ) - ); - - // rejected_handlers.add( ... ) - tuples[ 2 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onRejected ) ? - onRejected : - Thrower - ) - ); - } ).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 = {}; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 5 ]; - - // promise.progress = list.add - // promise.done = list.add - // promise.fail = list.add - promise[ tuple[ 1 ] ] = list.add; - - // Handle state - if ( stateString ) { - list.add( - function() { - - // state = "resolved" (i.e., fulfilled) - // state = "rejected" - state = stateString; - }, - - // rejected_callbacks.disable - // fulfilled_callbacks.disable - tuples[ 3 - i ][ 2 ].disable, - - // rejected_handlers.disable - // fulfilled_handlers.disable - tuples[ 3 - i ][ 3 ].disable, - - // progress_callbacks.lock - tuples[ 0 ][ 2 ].lock, - - // progress_handlers.lock - tuples[ 0 ][ 3 ].lock - ); - } - - // progress_handlers.fire - // fulfilled_handlers.fire - // rejected_handlers.fire - list.add( tuple[ 3 ].fire ); - - // deferred.notify = function() { deferred.notifyWith(...) } - // deferred.resolve = function() { deferred.resolveWith(...) } - // deferred.reject = function() { deferred.rejectWith(...) } - deferred[ tuple[ 0 ] ] = function() { - deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); - return this; - }; - - // deferred.notifyWith = list.fireWith - // deferred.resolveWith = list.fireWith - // deferred.rejectWith = list.fireWith - 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( singleValue ) { - var - - // count of uncompleted subordinates - remaining = arguments.length, - - // count of unprocessed arguments - i = remaining, - - // subordinate fulfillment data - resolveContexts = Array( i ), - resolveValues = slice.call( arguments ), - - // the primary Deferred - primary = jQuery.Deferred(), - - // subordinate callback factory - updateFunc = function( i ) { - return function( value ) { - resolveContexts[ i ] = this; - resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( !( --remaining ) ) { - primary.resolveWith( resolveContexts, resolveValues ); - } - }; - }; - - // Single- and empty arguments are adopted like Promise.resolve - if ( remaining <= 1 ) { - adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, - !remaining ); - - // Use .then() to unwrap secondary thenables (cf. gh-3000) - if ( primary.state() === "pending" || - isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { - - return primary.then(); - } - } - - // Multiple arguments are aggregated like Promise.all array elements - while ( i-- ) { - adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); - } - - return primary.promise(); - } -} ); - - -// These usually indicate a programmer mistake during development, -// warn about them ASAP rather than swallowing them by default. -var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; - -jQuery.Deferred.exceptionHook = function( error, stack ) { - - // Support: IE 8 - 9 only - // Console exists when dev tools are open, which can happen at any time - if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { - window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); - } -}; - - - - -jQuery.readyException = function( error ) { - window.setTimeout( function() { - throw error; - } ); -}; - - - - -// The deferred used on DOM ready -var readyList = jQuery.Deferred(); - -jQuery.fn.ready = function( fn ) { - - readyList - .then( fn ) - - // Wrap jQuery.readyException in a function so that the lookup - // happens at the time of error handling instead of callback - // registration. - .catch( function( error ) { - jQuery.readyException( error ); - } ); - - 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, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - } -} ); - -jQuery.ready.then = readyList.then; - -// The ready event handler and self cleanup method -function completed() { - document.removeEventListener( "DOMContentLoaded", completed ); - window.removeEventListener( "load", completed ); - jQuery.ready(); -} - -// Catch cases where $(document).ready() is called -// after the browser event has already occurred. -// Support: IE <=9 - 10 only -// Older IE sometimes signals "interactive" too soon -if ( document.readyState === "complete" || - ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { - - // Handle it asynchronously to allow scripts the opportunity to delay ready - window.setTimeout( jQuery.ready ); - -} else { - - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed ); -} - - - - -// Multifunctional method to get and set values of a collection -// The value/s can optionally be executed if it's a function -var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - len = elems.length, - bulk = key == null; - - // Sets many values - if ( toType( key ) === "object" ) { - chainable = true; - for ( i in key ) { - access( elems, fn, i, key[ i ], true, emptyGet, raw ); - } - - // Sets one value - } else if ( value !== undefined ) { - chainable = true; - - if ( !isFunction( value ) ) { - raw = true; - } - - if ( bulk ) { - - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, _key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } - - if ( fn ) { - for ( ; i < len; i++ ) { - fn( - elems[ i ], key, raw ? - value : - value.call( elems[ i ], i, fn( elems[ i ], key ) ) - ); - } - } - } - - if ( chainable ) { - return elems; - } - - // Gets - if ( bulk ) { - return fn.call( elems ); - } - - return len ? fn( elems[ 0 ], key ) : emptyGet; -}; - - -// Matches dashed string for camelizing -var rmsPrefix = /^-ms-/, - rdashAlpha = /-([a-z])/g; - -// Used by camelCase as callback to replace() -function fcamelCase( _all, letter ) { - return letter.toUpperCase(); -} - -// Convert dashed to camelCase; used by the css and data modules -// Support: IE <=9 - 11, Edge 12 - 15 -// Microsoft forgot to hump their vendor prefix (#9572) -function camelCase( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); -} -var acceptData = function( owner ) { - - // Accepts only: - // - Node - // - Node.ELEMENT_NODE - // - Node.DOCUMENT_NODE - // - Object - // - Any - return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); -}; - - - - -function Data() { - this.expando = jQuery.expando + Data.uid++; -} - -Data.uid = 1; - -Data.prototype = { - - cache: function( owner ) { - - // Check if the owner object already has a cache - var value = owner[ this.expando ]; - - // If not, create one - if ( !value ) { - value = {}; - - // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. - // Always return an empty object. - if ( acceptData( owner ) ) { - - // If it is a node unlikely to be stringify-ed or looped over - // use plain assignment - if ( owner.nodeType ) { - owner[ this.expando ] = value; - - // Otherwise secure it in a non-enumerable property - // configurable must be true to allow the property to be - // deleted when data is removed - } else { - Object.defineProperty( owner, this.expando, { - value: value, - configurable: true - } ); - } - } - } - - return value; - }, - set: function( owner, data, value ) { - var prop, - cache = this.cache( owner ); - - // Handle: [ owner, key, value ] args - // Always use camelCase key (gh-2257) - if ( typeof data === "string" ) { - cache[ camelCase( data ) ] = value; - - // Handle: [ owner, { properties } ] args - } else { - - // Copy the properties one-by-one to the cache object - for ( prop in data ) { - cache[ camelCase( prop ) ] = data[ prop ]; - } - } - return cache; - }, - get: function( owner, key ) { - return key === undefined ? - this.cache( owner ) : - - // Always use camelCase key (gh-2257) - owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; - }, - access: function( owner, key, value ) { - - // In cases where either: - // - // 1. No key was specified - // 2. A string key was specified, but no value provided - // - // Take the "read" path and allow the get method to determine - // which value to return, respectively either: - // - // 1. The entire cache object - // 2. The data stored at the key - // - if ( key === undefined || - ( ( key && typeof key === "string" ) && value === undefined ) ) { - - return this.get( owner, key ); - } - - // When the key is not a string, or both a key and value - // are specified, set or extend (existing objects) with either: - // - // 1. An object of properties - // 2. A key and value - // - this.set( owner, key, value ); - - // Since the "set" path can have two possible entry points - // return the expected data based on which path was taken[*] - return value !== undefined ? value : key; - }, - remove: function( owner, key ) { - var i, - cache = owner[ this.expando ]; - - if ( cache === undefined ) { - return; - } - - if ( key !== undefined ) { - - // Support array or space separated string of keys - if ( Array.isArray( key ) ) { - - // If key is an array of keys... - // We always set camelCase keys, so remove that. - key = key.map( camelCase ); - } else { - key = camelCase( key ); - - // If a key with the spaces exists, use it. - // Otherwise, create an array by matching non-whitespace - key = key in cache ? - [ key ] : - ( key.match( rnothtmlwhite ) || [] ); - } - - i = key.length; - - while ( i-- ) { - delete cache[ key[ i ] ]; - } - } - - // Remove the expando if there's no more data - if ( key === undefined || jQuery.isEmptyObject( cache ) ) { - - // Support: Chrome <=35 - 45 - // Webkit & Blink performance suffers when deleting properties - // from DOM nodes, so set to undefined instead - // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) - if ( owner.nodeType ) { - owner[ this.expando ] = undefined; - } else { - delete owner[ this.expando ]; - } - } - }, - hasData: function( owner ) { - var cache = owner[ this.expando ]; - return cache !== undefined && !jQuery.isEmptyObject( cache ); - } -}; -var dataPriv = new Data(); - -var dataUser = new Data(); - - - -// Implementation Summary -// -// 1. Enforce API surface and semantic compatibility with 1.9.x branch -// 2. Improve the module's maintainability by reducing the storage -// paths to a single mechanism. -// 3. Use the same single mechanism to support "private" and "user" data. -// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) -// 5. Avoid exposing implementation details on user objects (eg. expando properties) -// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 - -var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /[A-Z]/g; - -function getData( data ) { - if ( data === "true" ) { - return true; - } - - if ( data === "false" ) { - return false; - } - - if ( data === "null" ) { - return null; - } - - // Only convert to a number if it doesn't change the string - if ( data === +data + "" ) { - return +data; - } - - if ( rbrace.test( data ) ) { - return JSON.parse( data ); - } - - return data; -} - -function dataAttr( elem, key, data ) { - var name; - - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = getData( data ); - } catch ( e ) {} - - // Make sure we set the data so it isn't changed later - dataUser.set( elem, key, data ); - } else { - data = undefined; - } - } - return data; -} - -jQuery.extend( { - hasData: function( elem ) { - return dataUser.hasData( elem ) || dataPriv.hasData( elem ); - }, - - data: function( elem, name, data ) { - return dataUser.access( elem, name, data ); - }, - - removeData: function( elem, name ) { - dataUser.remove( elem, name ); - }, - - // TODO: Now that all calls to _data and _removeData have been replaced - // with direct calls to dataPriv methods, these can be deprecated. - _data: function( elem, name, data ) { - return dataPriv.access( elem, name, data ); - }, - - _removeData: function( elem, name ) { - dataPriv.remove( elem, name ); - } -} ); - -jQuery.fn.extend( { - data: function( key, value ) { - var i, name, data, - elem = this[ 0 ], - attrs = elem && elem.attributes; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = dataUser.get( elem ); - - if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { - i = attrs.length; - while ( i-- ) { - - // Support: IE 11 only - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = camelCase( name.slice( 5 ) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - dataPriv.set( elem, "hasDataAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each( function() { - dataUser.set( this, key ); - } ); - } - - return access( this, function( value ) { - var data; - - // The calling jQuery object (element matches) is not empty - // (and therefore has an element appears at this[ 0 ]) and the - // `value` parameter was not undefined. An empty jQuery object - // will result in `undefined` for elem = this[ 0 ] which will - // throw an exception if an attempt to read a data cache is made. - if ( elem && value === undefined ) { - - // Attempt to get data from the cache - // The key will always be camelCased in Data - data = dataUser.get( elem, key ); - if ( data !== undefined ) { - return data; - } - - // Attempt to "discover" the data in - // HTML5 custom data-* attrs - data = dataAttr( elem, key ); - if ( data !== undefined ) { - return data; - } - - // We tried really hard, but the data doesn't exist. - return; - } - - // Set the data... - this.each( function() { - - // We always store the camelCased key - dataUser.set( this, key, value ); - } ); - }, null, value, arguments.length > 1, null, true ); - }, - - removeData: function( key ) { - return this.each( function() { - dataUser.remove( this, key ); - } ); - } -} ); - - -jQuery.extend( { - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = dataPriv.get( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || Array.isArray( data ) ) { - queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // Clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // Not public - generate a queueHooks object, or return the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { - empty: jQuery.Callbacks( "once memory" ).add( function() { - dataPriv.remove( elem, [ type + "queue", key ] ); - } ) - } ); - } -} ); - -jQuery.fn.extend( { - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[ 0 ], type ); - } - - return data === undefined ? - this : - this.each( function() { - var queue = jQuery.queue( this, type, data ); - - // Ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - } ); - }, - dequeue: function( type ) { - return this.each( function() { - jQuery.dequeue( this, type ); - } ); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while ( i-- ) { - tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } -} ); -var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; - -var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); - - -var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; - -var documentElement = document.documentElement; - - - - var isAttached = function( elem ) { - return jQuery.contains( elem.ownerDocument, elem ); - }, - composed = { composed: true }; - - // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only - // Check attachment across shadow DOM boundaries when possible (gh-3504) - // Support: iOS 10.0-10.2 only - // Early iOS 10 versions support `attachShadow` but not `getRootNode`, - // leading to errors. We need to check for `getRootNode`. - if ( documentElement.getRootNode ) { - isAttached = function( elem ) { - return jQuery.contains( elem.ownerDocument, elem ) || - elem.getRootNode( composed ) === elem.ownerDocument; - }; - } -var isHiddenWithinTree = function( elem, el ) { - - // isHiddenWithinTree might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - - // Inline style trumps all - return elem.style.display === "none" || - elem.style.display === "" && - - // Otherwise, check computed style - // Support: Firefox <=43 - 45 - // Disconnected elements can have computed display: none, so first confirm that elem is - // in the document. - isAttached( elem ) && - - jQuery.css( elem, "display" ) === "none"; - }; - - - -function adjustCSS( elem, prop, valueParts, tween ) { - var adjusted, scale, - maxIterations = 20, - currentValue = tween ? - function() { - return tween.cur(); - } : - function() { - return jQuery.css( elem, prop, "" ); - }, - initial = currentValue(), - unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), - - // Starting value computation is required for potential unit mismatches - initialInUnit = elem.nodeType && - ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && - rcssNum.exec( jQuery.css( elem, prop ) ); - - if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { - - // Support: Firefox <=54 - // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) - initial = initial / 2; - - // Trust units reported by jQuery.css - unit = unit || initialInUnit[ 3 ]; - - // Iteratively approximate from a nonzero starting point - initialInUnit = +initial || 1; - - while ( maxIterations-- ) { - - // Evaluate and update our best guess (doubling guesses that zero out). - // Finish if the scale equals or crosses 1 (making the old*new product non-positive). - jQuery.style( elem, prop, initialInUnit + unit ); - if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { - maxIterations = 0; - } - initialInUnit = initialInUnit / scale; - - } - - initialInUnit = initialInUnit * 2; - jQuery.style( elem, prop, initialInUnit + unit ); - - // Make sure we update the tween properties later on - valueParts = valueParts || []; - } - - if ( valueParts ) { - initialInUnit = +initialInUnit || +initial || 0; - - // Apply relative offset (+=/-=) if specified - adjusted = valueParts[ 1 ] ? - initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : - +valueParts[ 2 ]; - if ( tween ) { - tween.unit = unit; - tween.start = initialInUnit; - tween.end = adjusted; - } - } - return adjusted; -} - - -var defaultDisplayMap = {}; - -function getDefaultDisplay( elem ) { - var temp, - doc = elem.ownerDocument, - nodeName = elem.nodeName, - display = defaultDisplayMap[ nodeName ]; - - if ( display ) { - return display; - } - - temp = doc.body.appendChild( doc.createElement( nodeName ) ); - display = jQuery.css( temp, "display" ); - - temp.parentNode.removeChild( temp ); - - if ( display === "none" ) { - display = "block"; - } - defaultDisplayMap[ nodeName ] = display; - - return display; -} - -function showHide( elements, show ) { - var display, elem, - values = [], - index = 0, - length = elements.length; - - // Determine new display value for elements that need to change - for ( ; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - - display = elem.style.display; - if ( show ) { - - // Since we force visibility upon cascade-hidden elements, an immediate (and slow) - // check is required in this first loop unless we have a nonempty display value (either - // inline or about-to-be-restored) - if ( display === "none" ) { - values[ index ] = dataPriv.get( elem, "display" ) || null; - if ( !values[ index ] ) { - elem.style.display = ""; - } - } - if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { - values[ index ] = getDefaultDisplay( elem ); - } - } else { - if ( display !== "none" ) { - values[ index ] = "none"; - - // Remember what we're overwriting - dataPriv.set( elem, "display", display ); - } - } - } - - // Set the display of the elements in a second loop to avoid constant reflow - for ( index = 0; index < length; index++ ) { - if ( values[ index ] != null ) { - elements[ index ].style.display = values[ index ]; - } - } - - return elements; -} - -jQuery.fn.extend( { - 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 ( isHiddenWithinTree( this ) ) { - jQuery( this ).show(); - } else { - jQuery( this ).hide(); - } - } ); - } -} ); -var rcheckableType = ( /^(?:checkbox|radio)$/i ); - -var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); - -var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); - - - -( function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); - - // Support: Android 4.0 - 4.3 only - // Check state lost if the name is set (#11217) - // Support: Windows Web Apps (WWA) - // `name` and `type` must use .setAttribute for WWA (#14901) - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Android <=4.1 only - // Older WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE <=11 only - // Make sure textarea (and checkbox) defaultValue is properly cloned - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; - - // Support: IE <=9 only - // IE <=9 replaces "; - support.option = !!div.lastChild; -} )(); - - -// We have to close these tags to support XHTML (#13200) -var wrapMap = { - - // XHTML parsers do not magically insert elements in the - // same way that tag soup parsers do. So we cannot shorten - // this by omitting or other required elements. - thead: [ 1, "", "
" ], - col: [ 2, "", "
" ], - tr: [ 2, "", "
" ], - td: [ 3, "", "
" ], - - _default: [ 0, "", "" ] -}; - -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// Support: IE <=9 only -if ( !support.option ) { - wrapMap.optgroup = wrapMap.option = [ 1, "" ]; -} - - -function getAll( context, tag ) { - - // Support: IE <=9 - 11 only - // Use typeof to avoid zero-argument method invocation on host objects (#15151) - var ret; - - if ( typeof context.getElementsByTagName !== "undefined" ) { - ret = context.getElementsByTagName( tag || "*" ); - - } else if ( typeof context.querySelectorAll !== "undefined" ) { - ret = context.querySelectorAll( tag || "*" ); - - } else { - ret = []; - } - - if ( tag === undefined || tag && nodeName( context, tag ) ) { - return jQuery.merge( [ context ], ret ); - } - - return ret; -} - - -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - dataPriv.set( - elems[ i ], - "globalEval", - !refElements || dataPriv.get( refElements[ i ], "globalEval" ) - ); - } -} - - -var rhtml = /<|&#?\w+;/; - -function buildFragment( elems, context, scripts, selection, ignored ) { - var elem, tmp, tag, wrap, attached, j, - fragment = context.createDocumentFragment(), - nodes = [], - i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - elem = elems[ i ]; - - if ( elem || elem === 0 ) { - - // Add nodes directly - if ( toType( elem ) === "object" ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; - - // Descend through wrappers to the right content - j = wrap[ 0 ]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, tmp.childNodes ); - - // Remember the top-level container - tmp = fragment.firstChild; - - // Ensure the created nodes are orphaned (#12392) - tmp.textContent = ""; - } - } - } - - // Remove wrapper from fragment - fragment.textContent = ""; - - i = 0; - while ( ( elem = nodes[ i++ ] ) ) { - - // Skip elements already in the context collection (trac-4087) - if ( selection && jQuery.inArray( elem, selection ) > -1 ) { - if ( ignored ) { - ignored.push( elem ); - } - continue; - } - - attached = isAttached( elem ); - - // Append to fragment - tmp = getAll( fragment.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( attached ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( ( elem = tmp[ j++ ] ) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - return fragment; -} - - -var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; - -function returnTrue() { - return true; -} - -function returnFalse() { - return false; -} - -// Support: IE <=9 - 11+ -// focus() and blur() are asynchronous, except when they are no-op. -// So expect focus to be synchronous when the element is already active, -// and blur to be synchronous when the element is not already active. -// (focus and blur are always synchronous in other supported browsers, -// this just defines when we can count on it). -function expectSync( elem, type ) { - return ( elem === safeActiveElement() ) === ( type === "focus" ); -} - -// Support: IE <=9 only -// Accessing document.activeElement can throw unexpectedly -// https://bugs.jquery.com/ticket/13393 -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} - -function on( elem, types, selector, data, fn, one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - on( elem, type, selector, data, types[ type ], one ); - } - return elem; - } - - if ( data == null && fn == null ) { - - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return elem; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return elem.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - } ); -} - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - global: {}, - - add: function( elem, types, handler, data, selector ) { - - var handleObjIn, eventHandle, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.get( elem ); - - // Only attach events to objects that accept data - if ( !acceptData( elem ) ) { - 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; - } - - // Ensure that invalid selectors throw exceptions at attach time - // Evaluate against documentElement in case elem is a non-element node (e.g., document) - if ( selector ) { - jQuery.find.matchesSelector( documentElement, 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 = Object.create( null ); - } - if ( !( eventHandle = elemData.handle ) ) { - eventHandle = elemData.handle = function( e ) { - - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? - jQuery.event.dispatch.apply( elem, arguments ) : undefined; - }; - } - - // Handle multiple events separated by a space - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend( { - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join( "." ) - }, handleObjIn ); - - // Init the event handler queue if we're the first - if ( !( handlers = events[ type ] ) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener if the special events handler returns false - if ( !special.setup || - special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - }, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var j, origCount, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); - - if ( !elemData || !( events = elemData.events ) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[ 2 ] && - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); - - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || - selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); - - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || - special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove data and the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - dataPriv.remove( elem, "handle events" ); - } - }, - - dispatch: function( nativeEvent ) { - - var i, j, ret, matched, handleObj, handlerQueue, - args = new Array( arguments.length ), - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( nativeEvent ), - - handlers = ( - dataPriv.get( this, "events" ) || Object.create( null ) - )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[ 0 ] = event; - - for ( i = 1; i < arguments.length; i++ ) { - args[ i ] = arguments[ i ]; - } - - 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() ) { - - // If the event is namespaced, then each handler is only invoked if it is - // specially universal or its namespaces are a superset of the event's. - if ( !event.rnamespace || handleObj.namespace === false || - event.rnamespace.test( handleObj.namespace ) ) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || - handleObj.handler ).apply( matched.elem, args ); - - if ( ret !== undefined ) { - if ( ( event.result = ret ) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - handlers: function( event, handlers ) { - var i, handleObj, sel, matchedHandlers, matchedSelectors, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Find delegate handlers - if ( delegateCount && - - // Support: IE <=9 - // Black-hole SVG instance trees (trac-13180) - cur.nodeType && - - // Support: Firefox <=42 - // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) - // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click - // Support: IE 11 only - // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) - !( event.type === "click" && event.button >= 1 ) ) { - - for ( ; cur !== this; cur = cur.parentNode || this ) { - - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { - matchedHandlers = []; - matchedSelectors = {}; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if ( matchedSelectors[ sel ] === undefined ) { - matchedSelectors[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) > -1 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matchedSelectors[ sel ] ) { - matchedHandlers.push( handleObj ); - } - } - if ( matchedHandlers.length ) { - handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); - } - } - } - } - - // Add the remaining (directly-bound) handlers - cur = this; - if ( delegateCount < handlers.length ) { - handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); - } - - return handlerQueue; - }, - - addProp: function( name, hook ) { - Object.defineProperty( jQuery.Event.prototype, name, { - enumerable: true, - configurable: true, - - get: isFunction( hook ) ? - function() { - if ( this.originalEvent ) { - return hook( this.originalEvent ); - } - } : - function() { - if ( this.originalEvent ) { - return this.originalEvent[ name ]; - } - }, - - set: function( value ) { - Object.defineProperty( this, name, { - enumerable: true, - configurable: true, - writable: true, - value: value - } ); - } - } ); - }, - - fix: function( originalEvent ) { - return originalEvent[ jQuery.expando ] ? - originalEvent : - new jQuery.Event( originalEvent ); - }, - - special: { - load: { - - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - click: { - - // Utilize native event to ensure correct state for checkable inputs - setup: function( data ) { - - // For mutual compressibility with _default, replace `this` access with a local var. - // `|| data` is dead code meant only to preserve the variable through minification. - var el = this || data; - - // Claim the first handler - if ( rcheckableType.test( el.type ) && - el.click && nodeName( el, "input" ) ) { - - // dataPriv.set( el, "click", ... ) - leverageNative( el, "click", returnTrue ); - } - - // Return false to allow normal processing in the caller - return false; - }, - trigger: function( data ) { - - // For mutual compressibility with _default, replace `this` access with a local var. - // `|| data` is dead code meant only to preserve the variable through minification. - var el = this || data; - - // Force setup before triggering a click - if ( rcheckableType.test( el.type ) && - el.click && nodeName( el, "input" ) ) { - - leverageNative( el, "click" ); - } - - // Return non-false to allow normal event-path propagation - return true; - }, - - // For cross-browser consistency, suppress native .click() on links - // Also prevent it if we're currently inside a leveraged native-event stack - _default: function( event ) { - var target = event.target; - return rcheckableType.test( target.type ) && - target.click && nodeName( target, "input" ) && - dataPriv.get( target, "click" ) || - nodeName( 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; - } - } - } - } -}; - -// Ensure the presence of an event listener that handles manually-triggered -// synthetic events by interrupting progress until reinvoked in response to -// *native* events that it fires directly, ensuring that state changes have -// already occurred before other listeners are invoked. -function leverageNative( el, type, expectSync ) { - - // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add - if ( !expectSync ) { - if ( dataPriv.get( el, type ) === undefined ) { - jQuery.event.add( el, type, returnTrue ); - } - return; - } - - // Register the controller as a special universal handler for all event namespaces - dataPriv.set( el, type, false ); - jQuery.event.add( el, type, { - namespace: false, - handler: function( event ) { - var notAsync, result, - saved = dataPriv.get( this, type ); - - if ( ( event.isTrigger & 1 ) && this[ type ] ) { - - // Interrupt processing of the outer synthetic .trigger()ed event - // Saved data should be false in such cases, but might be a leftover capture object - // from an async native handler (gh-4350) - if ( !saved.length ) { - - // Store arguments for use when handling the inner native event - // There will always be at least one argument (an event object), so this array - // will not be confused with a leftover capture object. - saved = slice.call( arguments ); - dataPriv.set( this, type, saved ); - - // Trigger the native event and capture its result - // Support: IE <=9 - 11+ - // focus() and blur() are asynchronous - notAsync = expectSync( this, type ); - this[ type ](); - result = dataPriv.get( this, type ); - if ( saved !== result || notAsync ) { - dataPriv.set( this, type, false ); - } else { - result = {}; - } - if ( saved !== result ) { - - // Cancel the outer synthetic event - event.stopImmediatePropagation(); - event.preventDefault(); - - // Support: Chrome 86+ - // In Chrome, if an element having a focusout handler is blurred by - // clicking outside of it, it invokes the handler synchronously. If - // that handler calls `.remove()` on the element, the data is cleared, - // leaving `result` undefined. We need to guard against this. - return result && result.value; - } - - // If this is an inner synthetic event for an event with a bubbling surrogate - // (focus or blur), assume that the surrogate already propagated from triggering the - // native event and prevent that from happening again here. - // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the - // bubbling surrogate propagates *after* the non-bubbling base), but that seems - // less bad than duplication. - } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { - event.stopPropagation(); - } - - // If this is a native event triggered above, everything is now in order - // Fire an inner synthetic event with the original arguments - } else if ( saved.length ) { - - // ...and capture the result - dataPriv.set( this, type, { - value: jQuery.event.trigger( - - // Support: IE <=9 - 11+ - // Extend with the prototype to reset the above stopImmediatePropagation() - jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), - saved.slice( 1 ), - this - ) - } ); - - // Abort handling of the native event - event.stopImmediatePropagation(); - } - } - } ); -} - -jQuery.removeEvent = function( elem, type, handle ) { - - // This "if" is needed for plain objects - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle ); - } -}; - -jQuery.Event = function( src, props ) { - - // Allow instantiation without the 'new' keyword - if ( !( this instanceof jQuery.Event ) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - - // Support: Android <=2.3 only - src.returnValue === false ? - returnTrue : - returnFalse; - - // Create target properties - // Support: Safari <=6 - 7 only - // Target should not be a text node (#504, #13143) - this.target = ( src.target && src.target.nodeType === 3 ) ? - src.target.parentNode : - src.target; - - this.currentTarget = src.currentTarget; - this.relatedTarget = src.relatedTarget; - - // 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 || Date.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - constructor: jQuery.Event, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - isSimulated: false, - - preventDefault: function() { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - - if ( e && !this.isSimulated ) { - e.preventDefault(); - } - }, - stopPropagation: function() { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopPropagation(); - } - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } -}; - -// Includes all common event props including KeyEvent and MouseEvent specific props -jQuery.each( { - altKey: true, - bubbles: true, - cancelable: true, - changedTouches: true, - ctrlKey: true, - detail: true, - eventPhase: true, - metaKey: true, - pageX: true, - pageY: true, - shiftKey: true, - view: true, - "char": true, - code: true, - charCode: true, - key: true, - keyCode: true, - button: true, - buttons: true, - clientX: true, - clientY: true, - offsetX: true, - offsetY: true, - pointerId: true, - pointerType: true, - screenX: true, - screenY: true, - targetTouches: true, - toElement: true, - touches: true, - which: true -}, jQuery.event.addProp ); - -jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { - jQuery.event.special[ type ] = { - - // Utilize native event if possible so blur/focus sequence is correct - setup: function() { - - // Claim the first handler - // dataPriv.set( this, "focus", ... ) - // dataPriv.set( this, "blur", ... ) - leverageNative( this, type, expectSync ); - - // Return false to allow normal processing in the caller - return false; - }, - trigger: function() { - - // Force setup before trigger - leverageNative( this, type ); - - // Return non-false to allow normal event-path propagation - return true; - }, - - // Suppress native focus or blur as it's already being fired - // in leverageNative. - _default: function() { - return true; - }, - - delegateType: delegateType - }; -} ); - -// Create mouseenter/leave events using mouseover/out and event-time checks -// so that event delegation works in jQuery. -// Do the same for pointerenter/pointerleave and pointerover/pointerout -// -// Support: Safari 7 only -// Safari sends mouseenter too often; see: -// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 -// for the description of the bug (it existed in older Chrome versions as well). -jQuery.each( { - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mouseenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -} ); - -jQuery.fn.extend( { - - on: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn ); - }, - one: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? - handleObj.origType + "." + handleObj.namespace : - handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each( function() { - jQuery.event.remove( this, types, fn, selector ); - } ); - } -} ); - - -var - - // Support: IE <=10 - 11, Edge 12 - 13 only - // In IE/Edge using regex groups here causes severe slowdowns. - // See https://connect.microsoft.com/IE/feedback/details/1736512/ - rnoInnerhtml = /\s*$/g; - -// Prefer a tbody over its parent table for containing new rows -function manipulationTarget( elem, content ) { - if ( nodeName( elem, "table" ) && - nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { - - return jQuery( elem ).children( "tbody" )[ 0 ] || elem; - } - - return elem; -} - -// Replace/restore the type attribute of script elements for safe DOM manipulation -function disableScript( elem ) { - elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; - return elem; -} -function restoreScript( elem ) { - if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { - elem.type = elem.type.slice( 5 ); - } else { - elem.removeAttribute( "type" ); - } - - return elem; -} - -function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, udataOld, udataCur, events; - - if ( dest.nodeType !== 1 ) { - return; - } - - // 1. Copy private data: events, handlers, etc. - if ( dataPriv.hasData( src ) ) { - pdataOld = dataPriv.get( src ); - events = pdataOld.events; - - if ( events ) { - dataPriv.remove( dest, "handle events" ); - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - } - - // 2. Copy user data - if ( dataUser.hasData( src ) ) { - udataOld = dataUser.access( src ); - udataCur = jQuery.extend( {}, udataOld ); - - dataUser.set( dest, udataCur ); - } -} - -// Fix IE bugs, see support tests -function fixInput( src, dest ) { - var nodeName = dest.nodeName.toLowerCase(); - - // Fails to persist the checked state of a cloned checkbox or radio button. - if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - dest.checked = src.checked; - - // Fails to return the selected option to the default selected state when cloning options - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } -} - -function domManip( collection, args, callback, ignored ) { - - // Flatten any nested arrays - args = flat( args ); - - var fragment, first, scripts, hasScripts, node, doc, - i = 0, - l = collection.length, - iNoClone = l - 1, - value = args[ 0 ], - valueIsFunction = isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( valueIsFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return collection.each( function( index ) { - var self = collection.eq( index ); - if ( valueIsFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - domManip( self, args, callback, ignored ); - } ); - } - - if ( l ) { - fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - // Require either new content or an interest in ignored elements to invoke the callback - if ( first || ignored ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item - // instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( collection[ i ], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !dataPriv.access( node, "globalEval" ) && - jQuery.contains( doc, node ) ) { - - if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { - - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl && !node.noModule ) { - jQuery._evalUrl( node.src, { - nonce: node.nonce || node.getAttribute( "nonce" ) - }, doc ); - } - } else { - DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); - } - } - } - } - } - } - - return collection; -} - -function remove( elem, selector, keepData ) { - var node, - nodes = selector ? jQuery.filter( selector, elem ) : elem, - i = 0; - - for ( ; ( node = nodes[ i ] ) != null; i++ ) { - if ( !keepData && node.nodeType === 1 ) { - jQuery.cleanData( getAll( node ) ); - } - - if ( node.parentNode ) { - if ( keepData && isAttached( node ) ) { - setGlobalEval( getAll( node, "script" ) ); - } - node.parentNode.removeChild( node ); - } - } - - return elem; -} - -jQuery.extend( { - htmlPrefilter: function( html ) { - return html; - }, - - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var i, l, srcElements, destElements, - clone = elem.cloneNode( true ), - inPage = isAttached( elem ); - - // Fix IE cloning issues - if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && - !jQuery.isXMLDoc( elem ) ) { - - // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - fixInput( srcElements[ i ], destElements[ i ] ); - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - cloneCopyEvent( srcElements[ i ], destElements[ i ] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - // Return the cloned set - return clone; - }, - - cleanData: function( elems ) { - var data, elem, type, - special = jQuery.event.special, - i = 0; - - for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { - if ( acceptData( elem ) ) { - if ( ( data = elem[ dataPriv.expando ] ) ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataPriv.expando ] = undefined; - } - if ( elem[ dataUser.expando ] ) { - - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataUser.expando ] = undefined; - } - } - } - } -} ); - -jQuery.fn.extend( { - detach: function( selector ) { - return remove( this, selector, true ); - }, - - remove: function( selector ) { - return remove( this, selector ); - }, - - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().each( function() { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - this.textContent = value; - } - } ); - }, null, value, arguments.length ); - }, - - append: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - } ); - }, - - prepend: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - } ); - }, - - before: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - } ); - }, - - after: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - } ); - }, - - empty: function() { - var elem, - i = 0; - - for ( ; ( elem = this[ i ] ) != null; i++ ) { - if ( elem.nodeType === 1 ) { - - // Prevent memory leaks - jQuery.cleanData( getAll( elem, false ) ); - - // Remove any remaining nodes - elem.textContent = ""; - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map( function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - } ); - }, - - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; - - if ( value === undefined && elem.nodeType === 1 ) { - return elem.innerHTML; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { - - value = jQuery.htmlPrefilter( value ); - - try { - for ( ; i < l; i++ ) { - elem = this[ i ] || {}; - - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch ( e ) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function() { - var ignored = []; - - // Make the changes, replacing each non-ignored context element with the new content - return domManip( this, arguments, function( elem ) { - var parent = this.parentNode; - - if ( jQuery.inArray( this, ignored ) < 0 ) { - jQuery.cleanData( getAll( this ) ); - if ( parent ) { - parent.replaceChild( elem, this ); - } - } - - // Force callback invocation - }, ignored ); - } -} ); - -jQuery.each( { - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1, - i = 0; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone( true ); - jQuery( insert[ i ] )[ original ]( elems ); - - // Support: Android <=4.0 only, PhantomJS 1 only - // .get() because push.apply(_, arraylike) throws on ancient WebKit - push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; -} ); -var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); - -var getStyles = function( elem ) { - - // Support: IE <=11 only, Firefox <=30 (#15098, #14150) - // IE throws on elements created in popups - // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" - var view = elem.ownerDocument.defaultView; - - if ( !view || !view.opener ) { - view = window; - } - - return view.getComputedStyle( elem ); - }; - -var swap = function( elem, options, callback ) { - 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.call( elem ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; -}; - - -var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); - - - -( function() { - - // Executing both pixelPosition & boxSizingReliable tests require only one layout - // so they're executed at the same time to save the second computation. - function computeStyleTests() { - - // This is a singleton, we need to execute it only once - if ( !div ) { - return; - } - - container.style.cssText = "position:absolute;left:-11111px;width:60px;" + - "margin-top:1px;padding:0;border:0"; - div.style.cssText = - "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + - "margin:auto;border:1px;padding:1px;" + - "width:60%;top:1%"; - documentElement.appendChild( container ).appendChild( div ); - - var divStyle = window.getComputedStyle( div ); - pixelPositionVal = divStyle.top !== "1%"; - - // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 - reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; - - // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 - // Some styles come back with percentage values, even though they shouldn't - div.style.right = "60%"; - pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; - - // Support: IE 9 - 11 only - // Detect misreporting of content dimensions for box-sizing:border-box elements - boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; - - // Support: IE 9 only - // Detect overflow:scroll screwiness (gh-3699) - // Support: Chrome <=64 - // Don't get tricked when zoom affects offsetWidth (gh-4029) - div.style.position = "absolute"; - scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; - - documentElement.removeChild( container ); - - // Nullify the div so it wouldn't be stored in the memory and - // it will also be a sign that checks already performed - div = null; - } - - function roundPixelMeasures( measure ) { - return Math.round( parseFloat( measure ) ); - } - - var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, - reliableTrDimensionsVal, reliableMarginLeftVal, - container = document.createElement( "div" ), - div = document.createElement( "div" ); - - // Finish early in limited (non-browser) environments - if ( !div.style ) { - return; - } - - // Support: IE <=9 - 11 only - // Style of cloned element affects source element cloned (#8908) - div.style.backgroundClip = "content-box"; - div.cloneNode( true ).style.backgroundClip = ""; - support.clearCloneStyle = div.style.backgroundClip === "content-box"; - - jQuery.extend( support, { - boxSizingReliable: function() { - computeStyleTests(); - return boxSizingReliableVal; - }, - pixelBoxStyles: function() { - computeStyleTests(); - return pixelBoxStylesVal; - }, - pixelPosition: function() { - computeStyleTests(); - return pixelPositionVal; - }, - reliableMarginLeft: function() { - computeStyleTests(); - return reliableMarginLeftVal; - }, - scrollboxSize: function() { - computeStyleTests(); - return scrollboxSizeVal; - }, - - // Support: IE 9 - 11+, Edge 15 - 18+ - // IE/Edge misreport `getComputedStyle` of table rows with width/height - // set in CSS while `offset*` properties report correct values. - // Behavior in IE 9 is more subtle than in newer versions & it passes - // some versions of this test; make sure not to make it pass there! - // - // Support: Firefox 70+ - // Only Firefox includes border widths - // in computed dimensions. (gh-4529) - reliableTrDimensions: function() { - var table, tr, trChild, trStyle; - if ( reliableTrDimensionsVal == null ) { - table = document.createElement( "table" ); - tr = document.createElement( "tr" ); - trChild = document.createElement( "div" ); - - table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; - tr.style.cssText = "border:1px solid"; - - // Support: Chrome 86+ - // Height set through cssText does not get applied. - // Computed height then comes back as 0. - tr.style.height = "1px"; - trChild.style.height = "9px"; - - // Support: Android 8 Chrome 86+ - // In our bodyBackground.html iframe, - // display for all div elements is set to "inline", - // which causes a problem only in Android 8 Chrome 86. - // Ensuring the div is display: block - // gets around this issue. - trChild.style.display = "block"; - - documentElement - .appendChild( table ) - .appendChild( tr ) - .appendChild( trChild ); - - trStyle = window.getComputedStyle( tr ); - reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + - parseInt( trStyle.borderTopWidth, 10 ) + - parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; - - documentElement.removeChild( table ); - } - return reliableTrDimensionsVal; - } - } ); -} )(); - - -function curCSS( elem, name, computed ) { - var width, minWidth, maxWidth, ret, - - // Support: Firefox 51+ - // Retrieving style before computed somehow - // fixes an issue with getting wrong values - // on detached elements - style = elem.style; - - computed = computed || getStyles( elem ); - - // getPropertyValue is needed for: - // .css('filter') (IE 9 only, #12537) - // .css('--customProperty) (#3144) - if ( computed ) { - ret = computed.getPropertyValue( name ) || computed[ name ]; - - if ( ret === "" && !isAttached( elem ) ) { - ret = jQuery.style( elem, name ); - } - - // A tribute to the "awesome hack by Dean Edwards" - // Android Browser returns percentage for some values, - // but width seems to be reliably pixels. - // This is against the CSSOM draft spec: - // https://drafts.csswg.org/cssom/#resolved-values - if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.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; - } - } - - return ret !== undefined ? - - // Support: IE <=9 - 11 only - // IE returns zIndex value as an integer. - ret + "" : - ret; -} - - -function addGetHookIf( conditionFn, hookFn ) { - - // Define the hook, we'll check on the first run if it's really needed. - return { - get: function() { - if ( conditionFn() ) { - - // Hook not needed (or it's not possible to use it due - // to missing dependency), remove it. - delete this.get; - return; - } - - // Hook needed; redefine it so that the support test is not executed again. - return ( this.get = hookFn ).apply( this, arguments ); - } - }; -} - - -var cssPrefixes = [ "Webkit", "Moz", "ms" ], - emptyStyle = document.createElement( "div" ).style, - vendorProps = {}; - -// Return a vendor-prefixed property or undefined -function vendorPropName( name ) { - - // Check for vendor prefixed names - var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), - i = cssPrefixes.length; - - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in emptyStyle ) { - return name; - } - } -} - -// Return a potentially-mapped jQuery.cssProps or vendor prefixed property -function finalPropName( name ) { - var final = jQuery.cssProps[ name ] || vendorProps[ name ]; - - if ( final ) { - return final; - } - if ( name in emptyStyle ) { - return name; - } - return vendorProps[ name ] = vendorPropName( name ) || name; -} - - -var - - // 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]).+)/, - rcustomProp = /^--/, - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: "0", - fontWeight: "400" - }; - -function setPositiveNumber( _elem, value, subtract ) { - - // Any relative (+/-) values have already been - // normalized at this point - var matches = rcssNum.exec( value ); - return matches ? - - // Guard against undefined "subtract", e.g., when used as in cssHooks - Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : - value; -} - -function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { - var i = dimension === "width" ? 1 : 0, - extra = 0, - delta = 0; - - // Adjustment may not be necessary - if ( box === ( isBorderBox ? "border" : "content" ) ) { - return 0; - } - - for ( ; i < 4; i += 2 ) { - - // Both box models exclude margin - if ( box === "margin" ) { - delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); - } - - // If we get here with a content-box, we're seeking "padding" or "border" or "margin" - if ( !isBorderBox ) { - - // Add padding - delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - - // For "border" or "margin", add border - if ( box !== "padding" ) { - delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - - // But still keep track of it otherwise - } else { - extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - - // If we get here with a border-box (content + padding + border), we're seeking "content" or - // "padding" or "margin" - } else { - - // For "content", subtract padding - if ( box === "content" ) { - delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - } - - // For "content" or "padding", subtract border - if ( box !== "margin" ) { - delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } - } - - // Account for positive content-box scroll gutter when requested by providing computedVal - if ( !isBorderBox && computedVal >= 0 ) { - - // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border - // Assuming integer scroll gutter, subtract the rest and round down - delta += Math.max( 0, Math.ceil( - elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - - computedVal - - delta - - extra - - 0.5 - - // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter - // Use an explicit zero to avoid NaN (gh-3964) - ) ) || 0; - } - - return delta; -} - -function getWidthOrHeight( elem, dimension, extra ) { - - // Start with computed style - var styles = getStyles( elem ), - - // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). - // Fake content-box until we know it's needed to know the true value. - boxSizingNeeded = !support.boxSizingReliable() || extra, - isBorderBox = boxSizingNeeded && - jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - valueIsBorderBox = isBorderBox, - - val = curCSS( elem, dimension, styles ), - offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); - - // Support: Firefox <=54 - // Return a confounding non-pixel value or feign ignorance, as appropriate. - if ( rnumnonpx.test( val ) ) { - if ( !extra ) { - return val; - } - val = "auto"; - } - - - // Support: IE 9 - 11 only - // Use offsetWidth/offsetHeight for when box sizing is unreliable. - // In those cases, the computed value can be trusted to be border-box. - if ( ( !support.boxSizingReliable() && isBorderBox || - - // Support: IE 10 - 11+, Edge 15 - 18+ - // IE/Edge misreport `getComputedStyle` of table rows with width/height - // set in CSS while `offset*` properties report correct values. - // Interestingly, in some cases IE 9 doesn't suffer from this issue. - !support.reliableTrDimensions() && nodeName( elem, "tr" ) || - - // Fall back to offsetWidth/offsetHeight when value is "auto" - // This happens for inline elements with no explicit setting (gh-3571) - val === "auto" || - - // Support: Android <=4.1 - 4.3 only - // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) - !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && - - // Make sure the element is visible & connected - elem.getClientRects().length ) { - - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; - - // Where available, offsetWidth/offsetHeight approximate border box dimensions. - // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the - // retrieved value as a content box dimension. - valueIsBorderBox = offsetProp in elem; - if ( valueIsBorderBox ) { - val = elem[ offsetProp ]; - } - } - - // Normalize "" and auto - val = parseFloat( val ) || 0; - - // Adjust for the element's box model - return ( val + - boxModelAdjustment( - elem, - dimension, - extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox, - styles, - - // Provide the current computed size to request scroll gutter calculation (gh-3589) - val - ) - ) + "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: { - "animationIterationCount": true, - "columnCount": true, - "fillOpacity": true, - "flexGrow": true, - "flexShrink": true, - "fontWeight": true, - "gridArea": true, - "gridColumn": true, - "gridColumnEnd": true, - "gridColumnStart": true, - "gridRow": true, - "gridRowEnd": true, - "gridRowStart": 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: {}, - - // 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 = camelCase( name ), - isCustomProp = rcustomProp.test( name ), - style = elem.style; - - // Make sure that we're working with the right name. We don't - // want to query the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } - - // Gets hook for the prefixed version, then unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // Check if we're setting a value - if ( value !== undefined ) { - type = typeof value; - - // Convert "+=" or "-=" to relative numbers (#7345) - if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { - value = adjustCSS( elem, name, ret ); - - // Fixes bug #9237 - type = "number"; - } - - // Make sure that null and NaN values aren't set (#7116) - if ( value == null || value !== value ) { - return; - } - - // If a number was passed in, add the unit (except for certain CSS properties) - // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append - // "px" to a few hardcoded values. - if ( type === "number" && !isCustomProp ) { - value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); - } - - // background-* props affect original clone's values - 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 ) { - - if ( isCustomProp ) { - style.setProperty( name, value ); - } else { - style[ name ] = value; - } - } - - } 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 val, num, hooks, - origName = camelCase( name ), - isCustomProp = rcustomProp.test( name ); - - // Make sure that we're working with the right name. We don't - // want to modify the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } - - // Try prefixed name followed by the unprefixed name - 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 ]; - } - - // Make numeric if forced or a qualifier was provided and val looks numeric - if ( extra === "" || extra ) { - num = parseFloat( val ); - return extra === true || isFinite( num ) ? num || 0 : val; - } - - return val; - } -} ); - -jQuery.each( [ "height", "width" ], function( _i, dimension ) { - jQuery.cssHooks[ dimension ] = { - get: function( elem, computed, extra ) { - if ( computed ) { - - // Certain elements can have dimension info if we invisibly show them - // but it must have a current display style that would benefit - return rdisplayswap.test( jQuery.css( elem, "display" ) ) && - - // Support: Safari 8+ - // Table columns in Safari have non-zero offsetWidth & zero - // getBoundingClientRect().width unless display is changed. - // Support: IE <=11 only - // Running getBoundingClientRect on a disconnected node - // in IE throws an error. - ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? - swap( elem, cssShow, function() { - return getWidthOrHeight( elem, dimension, extra ); - } ) : - getWidthOrHeight( elem, dimension, extra ); - } - }, - - set: function( elem, value, extra ) { - var matches, - styles = getStyles( elem ), - - // Only read styles.position if the test has a chance to fail - // to avoid forcing a reflow. - scrollboxSizeBuggy = !support.scrollboxSize() && - styles.position === "absolute", - - // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) - boxSizingNeeded = scrollboxSizeBuggy || extra, - isBorderBox = boxSizingNeeded && - jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - subtract = extra ? - boxModelAdjustment( - elem, - dimension, - extra, - isBorderBox, - styles - ) : - 0; - - // Account for unreliable border-box dimensions by comparing offset* to computed and - // faking a content-box to get border and padding (gh-3699) - if ( isBorderBox && scrollboxSizeBuggy ) { - subtract -= Math.ceil( - elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - - parseFloat( styles[ dimension ] ) - - boxModelAdjustment( elem, dimension, "border", false, styles ) - - 0.5 - ); - } - - // Convert to pixels if value adjustment is needed - if ( subtract && ( matches = rcssNum.exec( value ) ) && - ( matches[ 3 ] || "px" ) !== "px" ) { - - elem.style[ dimension ] = value; - value = jQuery.css( elem, dimension ); - } - - return setPositiveNumber( elem, value, subtract ); - } - }; -} ); - -jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, - function( elem, computed ) { - if ( computed ) { - return ( parseFloat( curCSS( elem, "marginLeft" ) ) || - elem.getBoundingClientRect().left - - swap( elem, { marginLeft: 0 }, function() { - return elem.getBoundingClientRect().left; - } ) - ) + "px"; - } - } -); - -// 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 ( prefix !== "margin" ) { - 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 ( Array.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 ); - } -} ); - - -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 || jQuery.easing._default; - 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; - - // Use a property on the element directly when it is not a DOM element, - // or when there is no matching style property that exists. - if ( tween.elem.nodeType !== 1 || - tween.elem[ tween.prop ] != null && 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. - // 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 available and use plain properties where available. - if ( jQuery.fx.step[ tween.prop ] ) { - jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.nodeType === 1 && ( - jQuery.cssHooks[ tween.prop ] || - tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { - jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); - } else { - tween.elem[ tween.prop ] = tween.now; - } - } - } -}; - -// Support: IE <=9 only -// 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; - }, - _default: "swing" -}; - -jQuery.fx = Tween.prototype.init; - -// Back compat <1.8 extension point -jQuery.fx.step = {}; - - - - -var - fxNow, inProgress, - rfxtypes = /^(?:toggle|show|hide)$/, - rrun = /queueHooks$/; - -function schedule() { - if ( inProgress ) { - if ( document.hidden === false && window.requestAnimationFrame ) { - window.requestAnimationFrame( schedule ); - } else { - window.setTimeout( schedule, jQuery.fx.interval ); - } - - jQuery.fx.tick(); - } -} - -// Animations created synchronously will run synchronously -function createFxNow() { - window.setTimeout( function() { - fxNow = undefined; - } ); - return ( fxNow = Date.now() ); -} - -// Generate parameters to create a standard animation -function genFx( type, includeWidth ) { - var which, - i = 0, - attrs = { height: type }; - - // If we include width, step value is 1 to do all cssExpand values, - // otherwise 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 = ( Animation.tweeners[ prop ] || [] ).concat( Animation.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 ) { - var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, - isBox = "width" in props || "height" in props, - anim = this, - orig = {}, - style = elem.style, - hidden = elem.nodeType && isHiddenWithinTree( elem ), - dataShow = dataPriv.get( elem, "fxshow" ); - - // Queue-skipping animations hijack the fx hooks - 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() { - - // Ensure the complete handler is called before this completes - anim.always( function() { - hooks.unqueued--; - if ( !jQuery.queue( elem, "fx" ).length ) { - hooks.empty.fire(); - } - } ); - } ); - } - - // Detect show/hide animations - for ( prop in props ) { - value = props[ prop ]; - if ( rfxtypes.test( value ) ) { - delete props[ prop ]; - toggle = toggle || value === "toggle"; - if ( value === ( hidden ? "hide" : "show" ) ) { - - // Pretend to be hidden if this is a "show" and - // there is still data from a stopped show/hide - if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { - hidden = true; - - // Ignore all other no-op show/hide data - } else { - continue; - } - } - orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); - } - } - - // Bail out if this is a no-op like .hide().hide() - propTween = !jQuery.isEmptyObject( props ); - if ( !propTween && jQuery.isEmptyObject( orig ) ) { - return; - } - - // Restrict "overflow" and "display" styles during box animations - if ( isBox && elem.nodeType === 1 ) { - - // Support: IE <=9 - 11, Edge 12 - 15 - // Record all 3 overflow attributes because IE does not infer the shorthand - // from identically-valued overflowX and overflowY and Edge just mirrors - // the overflowX value there. - opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; - - // Identify a display type, preferring old show/hide data over the CSS cascade - restoreDisplay = dataShow && dataShow.display; - if ( restoreDisplay == null ) { - restoreDisplay = dataPriv.get( elem, "display" ); - } - display = jQuery.css( elem, "display" ); - if ( display === "none" ) { - if ( restoreDisplay ) { - display = restoreDisplay; - } else { - - // Get nonempty value(s) by temporarily forcing visibility - showHide( [ elem ], true ); - restoreDisplay = elem.style.display || restoreDisplay; - display = jQuery.css( elem, "display" ); - showHide( [ elem ] ); - } - } - - // Animate inline elements as inline-block - if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { - if ( jQuery.css( elem, "float" ) === "none" ) { - - // Restore the original display value at the end of pure show/hide animations - if ( !propTween ) { - anim.done( function() { - style.display = restoreDisplay; - } ); - if ( restoreDisplay == null ) { - display = style.display; - restoreDisplay = display === "none" ? "" : display; - } - } - style.display = "inline-block"; - } - } - } - - if ( opts.overflow ) { - style.overflow = "hidden"; - anim.always( function() { - style.overflow = opts.overflow[ 0 ]; - style.overflowX = opts.overflow[ 1 ]; - style.overflowY = opts.overflow[ 2 ]; - } ); - } - - // Implement show/hide animations - propTween = false; - for ( prop in orig ) { - - // General show/hide setup for this element animation - if ( !propTween ) { - if ( dataShow ) { - if ( "hidden" in dataShow ) { - hidden = dataShow.hidden; - } - } else { - dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); - } - - // Store hidden/visible for toggle so `.stop().toggle()` "reverses" - if ( toggle ) { - dataShow.hidden = !hidden; - } - - // Show elements before animating them - if ( hidden ) { - showHide( [ elem ], true ); - } - - /* eslint-disable no-loop-func */ - - anim.done( function() { - - /* eslint-enable no-loop-func */ - - // The final step of a "hide" animation is actually hiding the element - if ( !hidden ) { - showHide( [ elem ] ); - } - dataPriv.remove( elem, "fxshow" ); - for ( prop in orig ) { - jQuery.style( elem, prop, orig[ prop ] ); - } - } ); - } - - // Per-property setup - propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); - if ( !( prop in dataShow ) ) { - dataShow[ prop ] = propTween.start; - if ( hidden ) { - propTween.end = propTween.start; - propTween.start = 0; - } - } - } -} - -function propFilter( props, specialEasing ) { - var index, name, easing, value, hooks; - - // camelCase, specialEasing and expand cssHook pass - for ( index in props ) { - name = camelCase( index ); - easing = specialEasing[ name ]; - value = props[ index ]; - if ( Array.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 won't overwrite existing keys. - // Reusing 'index' 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 = Animation.prefilters.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 ), - - // Support: Android 2.3 only - // 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 there's more to do, yield - if ( percent < 1 && length ) { - return remaining; - } - - // If this was an empty animation, synthesize a final progress notification - if ( !length ) { - deferred.notifyWith( elem, [ animation, 1, 0 ] ); - } - - // Resolve the animation and report its conclusion - deferred.resolveWith( elem, [ animation ] ); - return false; - }, - animation = deferred.promise( { - elem: elem, - props: jQuery.extend( {}, properties ), - opts: jQuery.extend( true, { - specialEasing: {}, - easing: jQuery.easing._default - }, 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.notifyWith( elem, [ animation, 1, 0 ] ); - 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 = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); - if ( result ) { - if ( isFunction( result.stop ) ) { - jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = - result.stop.bind( result ); - } - return result; - } - } - - jQuery.map( props, createTween, animation ); - - if ( isFunction( animation.opts.start ) ) { - animation.opts.start.call( elem, animation ); - } - - // Attach callbacks from options - animation - .progress( animation.opts.progress ) - .done( animation.opts.done, animation.opts.complete ) - .fail( animation.opts.fail ) - .always( animation.opts.always ); - - jQuery.fx.timer( - jQuery.extend( tick, { - elem: elem, - anim: animation, - queue: animation.opts.queue - } ) - ); - - return animation; -} - -jQuery.Animation = jQuery.extend( Animation, { - - tweeners: { - "*": [ function( prop, value ) { - var tween = this.createTween( prop, value ); - adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); - return tween; - } ] - }, - - tweener: function( props, callback ) { - if ( isFunction( props ) ) { - callback = props; - props = [ "*" ]; - } else { - props = props.match( rnothtmlwhite ); - } - - var prop, - index = 0, - length = props.length; - - for ( ; index < length; index++ ) { - prop = props[ index ]; - Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; - Animation.tweeners[ prop ].unshift( callback ); - } - }, - - prefilters: [ defaultPrefilter ], - - prefilter: function( callback, prepend ) { - if ( prepend ) { - Animation.prefilters.unshift( callback ); - } else { - Animation.prefilters.push( callback ); - } - } -} ); - -jQuery.speed = function( speed, easing, fn ) { - var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { - complete: fn || !fn && easing || - isFunction( speed ) && speed, - duration: speed, - easing: fn && easing || easing && !isFunction( easing ) && easing - }; - - // Go to the end state if fx are off - if ( jQuery.fx.off ) { - opt.duration = 0; - - } else { - if ( typeof opt.duration !== "number" ) { - if ( opt.duration in jQuery.fx.speeds ) { - opt.duration = jQuery.fx.speeds[ opt.duration ]; - - } else { - 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 ( 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( isHiddenWithinTree ).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 || dataPriv.get( 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 ) { - this.queue( type || "fx", [] ); - } - - return this.each( function() { - var dequeue = true, - index = type != null && type + "queueHooks", - timers = jQuery.timers, - data = dataPriv.get( 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 = dataPriv.get( 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, - i = 0, - timers = jQuery.timers; - - fxNow = Date.now(); - - for ( ; i < timers.length; i++ ) { - timer = timers[ i ]; - - // Run the timer and safely remove it when done (allowing for external removal) - 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 ); - jQuery.fx.start(); -}; - -jQuery.fx.interval = 13; -jQuery.fx.start = function() { - if ( inProgress ) { - return; - } - - inProgress = true; - schedule(); -}; - -jQuery.fx.stop = function() { - inProgress = null; -}; - -jQuery.fx.speeds = { - slow: 600, - fast: 200, - - // Default speed - _default: 400 -}; - - -// Based off of the plugin by Clint Helfers, with permission. -// https://web.archive.org/web/20100324014747/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 = window.setTimeout( next, time ); - hooks.stop = function() { - window.clearTimeout( timeout ); - }; - } ); -}; - - -( function() { - var input = document.createElement( "input" ), - select = document.createElement( "select" ), - opt = select.appendChild( document.createElement( "option" ) ); - - input.type = "checkbox"; - - // Support: Android <=4.3 only - // Default value for a checkbox should be "on" - support.checkOn = input.value !== ""; - - // Support: IE <=11 only - // Must access selectedIndex to make default options select - support.optSelected = opt.selected; - - // Support: IE <=11 only - // An input loses its value after becoming a radio - input = document.createElement( "input" ); - input.value = "t"; - input.type = "radio"; - support.radioValue = input.value === "t"; -} )(); - - -var boolHook, - attrHandle = jQuery.expr.attrHandle; - -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 ret, hooks, - nType = elem.nodeType; - - // Don't get/set attributes on text, comment and attribute nodes - if ( nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === "undefined" ) { - return jQuery.prop( elem, name, value ); - } - - // Attribute hooks are determined by the lowercase version - // Grab necessary hook if one is defined - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - hooks = jQuery.attrHooks[ name.toLowerCase() ] || - ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); - } - - if ( value !== undefined ) { - if ( value === null ) { - jQuery.removeAttr( elem, name ); - return; - } - - if ( hooks && "set" in hooks && - ( ret = hooks.set( elem, value, name ) ) !== undefined ) { - return ret; - } - - elem.setAttribute( name, value + "" ); - return value; - } - - if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { - return ret; - } - - ret = jQuery.find.attr( elem, name ); - - // Non-existent attributes return null, we normalize to undefined - return ret == null ? undefined : ret; - }, - - attrHooks: { - type: { - set: function( elem, value ) { - if ( !support.radioValue && value === "radio" && - nodeName( elem, "input" ) ) { - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - } - }, - - removeAttr: function( elem, value ) { - var name, - i = 0, - - // Attribute names can contain non-HTML whitespace characters - // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 - attrNames = value && value.match( rnothtmlwhite ); - - if ( attrNames && elem.nodeType === 1 ) { - while ( ( name = attrNames[ i++ ] ) ) { - elem.removeAttribute( name ); - } - } - } -} ); - -// Hooks for boolean attributes -boolHook = { - set: function( elem, value, name ) { - if ( value === false ) { - - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - elem.setAttribute( name, name ); - } - return name; - } -}; - -jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { - var getter = attrHandle[ name ] || jQuery.find.attr; - - attrHandle[ name ] = function( elem, name, isXML ) { - var ret, handle, - lowercaseName = name.toLowerCase(); - - if ( !isXML ) { - - // Avoid an infinite loop by temporarily removing this function from the getter - handle = attrHandle[ lowercaseName ]; - attrHandle[ lowercaseName ] = ret; - ret = getter( elem, name, isXML ) != null ? - lowercaseName : - null; - attrHandle[ lowercaseName ] = handle; - } - return ret; - }; -} ); - - - - -var rfocusable = /^(?:input|select|textarea|button)$/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 ) { - return this.each( function() { - delete this[ jQuery.propFix[ name ] || name ]; - } ); - } -} ); - -jQuery.extend( { - prop: function( elem, name, value ) { - var ret, hooks, - nType = elem.nodeType; - - // Don't get/set properties on text, comment and attribute nodes - if ( nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - if ( hooks && "set" in hooks && - ( ret = hooks.set( elem, value, name ) ) !== undefined ) { - return ret; - } - - return ( elem[ name ] = value ); - } - - if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { - return ret; - } - - return elem[ name ]; - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - - // Support: IE <=9 - 11 only - // elem.tabIndex doesn't always return the - // correct value when it hasn't been explicitly set - // https://web.archive.org/web/20141116233347/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" ); - - if ( tabindex ) { - return parseInt( tabindex, 10 ); - } - - if ( - rfocusable.test( elem.nodeName ) || - rclickable.test( elem.nodeName ) && - elem.href - ) { - return 0; - } - - return -1; - } - } - }, - - propFix: { - "for": "htmlFor", - "class": "className" - } -} ); - -// Support: IE <=11 only -// Accessing the selectedIndex property -// forces the browser to respect setting selected -// on the option -// The getter ensures a default option is selected -// when in an optgroup -// eslint rule "no-unused-expressions" is disabled for this code -// since it considers such accessions noop -if ( !support.optSelected ) { - jQuery.propHooks.selected = { - get: function( elem ) { - - /* eslint no-unused-expressions: "off" */ - - var parent = elem.parentNode; - if ( parent && parent.parentNode ) { - parent.parentNode.selectedIndex; - } - return null; - }, - set: function( elem ) { - - /* eslint no-unused-expressions: "off" */ - - var parent = elem.parentNode; - if ( parent ) { - parent.selectedIndex; - - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - } - }; -} - -jQuery.each( [ - "tabIndex", - "readOnly", - "maxLength", - "cellSpacing", - "cellPadding", - "rowSpan", - "colSpan", - "useMap", - "frameBorder", - "contentEditable" -], function() { - jQuery.propFix[ this.toLowerCase() ] = this; -} ); - - - - - // Strip and collapse whitespace according to HTML spec - // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace - function stripAndCollapse( value ) { - var tokens = value.match( rnothtmlwhite ) || []; - return tokens.join( " " ); - } - - -function getClass( elem ) { - return elem.getAttribute && elem.getAttribute( "class" ) || ""; -} - -function classesToArray( value ) { - if ( Array.isArray( value ) ) { - return value; - } - if ( typeof value === "string" ) { - return value.match( rnothtmlwhite ) || []; - } - return []; -} - -jQuery.fn.extend( { - addClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; - - if ( isFunction( value ) ) { - return this.each( function( j ) { - jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); - } ); - } - - classes = classesToArray( value ); - - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); - - if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { - if ( cur.indexOf( " " + clazz + " " ) < 0 ) { - cur += clazz + " "; - } - } - - // Only assign if different to avoid unneeded rendering. - finalValue = stripAndCollapse( cur ); - if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; - - if ( isFunction( value ) ) { - return this.each( function( j ) { - jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); - } ); - } - - if ( !arguments.length ) { - return this.attr( "class", "" ); - } - - classes = classesToArray( value ); - - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); - - // This expression is here for better compressibility (see addClass) - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); - - if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { - - // Remove *all* instances - while ( cur.indexOf( " " + clazz + " " ) > -1 ) { - cur = cur.replace( " " + clazz + " ", " " ); - } - } - - // Only assign if different to avoid unneeded rendering. - finalValue = stripAndCollapse( cur ); - if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isValidValue = type === "string" || Array.isArray( value ); - - if ( typeof stateVal === "boolean" && isValidValue ) { - return stateVal ? this.addClass( value ) : this.removeClass( value ); - } - - if ( isFunction( value ) ) { - return this.each( function( i ) { - jQuery( this ).toggleClass( - value.call( this, i, getClass( this ), stateVal ), - stateVal - ); - } ); - } - - return this.each( function() { - var className, i, self, classNames; - - if ( isValidValue ) { - - // Toggle individual class names - i = 0; - self = jQuery( this ); - classNames = classesToArray( value ); - - 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 ( value === undefined || type === "boolean" ) { - className = getClass( this ); - if ( className ) { - - // Store className if set - dataPriv.set( this, "__className__", 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. - if ( this.setAttribute ) { - this.setAttribute( "class", - className || value === false ? - "" : - dataPriv.get( this, "__className__" ) || "" - ); - } - } - } ); - }, - - hasClass: function( selector ) { - var className, elem, - i = 0; - - className = " " + selector + " "; - while ( ( elem = this[ i++ ] ) ) { - if ( elem.nodeType === 1 && - ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { - return true; - } - } - - return false; - } -} ); - - - - -var rreturn = /\r/g; - -jQuery.fn.extend( { - val: function( value ) { - var hooks, ret, valueIsFunction, - 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; - - // Handle most common string cases - if ( typeof ret === "string" ) { - return ret.replace( rreturn, "" ); - } - - // Handle cases where value is null/undef or number - return ret == null ? "" : ret; - } - - return; - } - - valueIsFunction = isFunction( value ); - - return this.each( function( i ) { - var val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( valueIsFunction ) { - 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 ( Array.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: IE <=10 - 11 only - // option.text throws exceptions (#14686, #14858) - // Strip and collapse whitespace - // https://html.spec.whatwg.org/#strip-and-collapse-whitespace - stripAndCollapse( jQuery.text( elem ) ); - } - }, - select: { - get: function( elem ) { - var value, option, i, - options = elem.options, - index = elem.selectedIndex, - one = elem.type === "select-one", - values = one ? null : [], - max = one ? index + 1 : options.length; - - if ( index < 0 ) { - i = max; - - } else { - i = one ? index : 0; - } - - // Loop through all the selected options - for ( ; i < max; i++ ) { - option = options[ i ]; - - // Support: IE <=9 only - // IE8-9 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 - !option.disabled && - ( !option.parentNode.disabled || - !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 ]; - - /* eslint-disable no-cond-assign */ - - if ( option.selected = - jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 - ) { - optionSet = true; - } - - /* eslint-enable no-cond-assign */ - } - - // Force browsers to behave consistently when non-matching value is set - if ( !optionSet ) { - elem.selectedIndex = -1; - } - return values; - } - } - } -} ); - -// Radios and checkboxes getter/setter -jQuery.each( [ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - set: function( elem, value ) { - if ( Array.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); - } - } - }; - if ( !support.checkOn ) { - jQuery.valHooks[ this ].get = function( elem ) { - return elem.getAttribute( "value" ) === null ? "on" : elem.value; - }; - } -} ); - - - - -// Return jQuery for attributes-only inclusion - - -support.focusin = "onfocusin" in window; - - -var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - stopPropagationCallback = function( e ) { - e.stopPropagation(); - }; - -jQuery.extend( jQuery.event, { - - trigger: function( event, data, elem, onlyHandlers ) { - - var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, - eventPath = [ elem || document ], - type = hasOwn.call( event, "type" ) ? event.type : event, - namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; - - cur = lastElement = 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( "." ) > -1 ) { - - // 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.rnamespace = 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 && !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() ) { - lastElement = cur; - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && - dataPriv.get( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && handle.apply && 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 ) && - acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name as the event. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && isFunction( elem[ type ] ) && !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; - - if ( event.isPropagationStopped() ) { - lastElement.addEventListener( type, stopPropagationCallback ); - } - - elem[ type ](); - - if ( event.isPropagationStopped() ) { - lastElement.removeEventListener( type, stopPropagationCallback ); - } - - jQuery.event.triggered = undefined; - - if ( tmp ) { - elem[ ontype ] = tmp; - } - } - } - } - - return event.result; - }, - - // Piggyback on a donor event to simulate a different one - // Used only for `focus(in | out)` events - simulate: function( type, elem, event ) { - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true - } - ); - - jQuery.event.trigger( e, null, elem ); - } - -} ); - -jQuery.fn.extend( { - - 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 ); - } - } -} ); - - -// Support: Firefox <=44 -// Firefox doesn't have focus(in | out) events -// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 -// -// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 -// focus(in | out) events fire after focus & blur events, -// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order -// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 -if ( !support.focusin ) { - 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 ) ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - - // Handle: regular nodes (via `this.ownerDocument`), window - // (via `this.document`) & document (via `this`). - var doc = this.ownerDocument || this.document || this, - attaches = dataPriv.access( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this.document || this, - attaches = dataPriv.access( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - dataPriv.remove( doc, fix ); - - } else { - dataPriv.access( doc, fix, attaches ); - } - } - }; - } ); -} -var location = window.location; - -var nonce = { guid: Date.now() }; - -var rquery = ( /\?/ ); - - - -// Cross-browser xml parsing -jQuery.parseXML = function( data ) { - var xml, parserErrorElem; - if ( !data || typeof data !== "string" ) { - return null; - } - - // Support: IE 9 - 11 only - // IE throws on parseFromString with invalid input. - try { - xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); - } catch ( e ) {} - - parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; - if ( !xml || parserErrorElem ) { - jQuery.error( "Invalid XML: " + ( - parserErrorElem ? - jQuery.map( parserErrorElem.childNodes, function( el ) { - return el.textContent; - } ).join( "\n" ) : - data - ) ); - } - return xml; -}; - - -var - 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 ( Array.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" && v != null ? i : "" ) + "]", - v, - traditional, - add - ); - } - } ); - - } else if ( !traditional && toType( 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, valueOrFunction ) { - - // If value is a function, invoke it and use its return value - var value = isFunction( valueOrFunction ) ? - valueOrFunction() : - valueOrFunction; - - s[ s.length ] = encodeURIComponent( key ) + "=" + - encodeURIComponent( value == null ? "" : value ); - }; - - if ( a == null ) { - return ""; - } - - // If an array was passed in, assume that it is an array of form elements. - if ( Array.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( "&" ); -}; - -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(); - - if ( val == null ) { - return null; - } - - if ( Array.isArray( val ) ) { - return jQuery.map( val, function( val ) { - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - } ); - } - - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - } ).get(); - } -} ); - - -var - r20 = /%20/g, - rhash = /#.*$/, - rantiCache = /([?&])_=[^&]*/, - rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, - - // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, - rnoContent = /^(?:GET|HEAD)$/, - rprotocol = /^\/\//, - - /* 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( "*" ), - - // Anchor tag for parsing the document origin - originAnchor = document.createElement( "a" ); - -originAnchor.href = location.href; - -// 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( rnothtmlwhite ) || []; - - if ( isFunction( func ) ) { - - // For each dataType in the dataTypeExpression - while ( ( dataType = dataTypes[ i++ ] ) ) { - - // Prepend if requested - if ( dataType[ 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 key, deep, - 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 ct, type, finalDataType, firstDataType, - 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: location.href, - type: "GET", - isLocal: rlocalProtocol.test( location.protocol ), - 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: /\bxml\b/, - html: /\bhtml/, - json: /\bjson\b/ - }, - - 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": JSON.parse, - - // 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 transport, - - // URL without anti-cache param - cacheURL, - - // Response headers - responseHeadersString, - responseHeaders, - - // timeout handle - timeoutTimer, - - // Url cleanup var - urlAnchor, - - // Request state (becomes false upon send and true upon completion) - completed, - - // To know if global events are to be dispatched - fireGlobals, - - // Loop variable - i, - - // uncached part of the url - uncached, - - // 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 = {}, - - // Default abort message - strAbort = "canceled", - - // Fake xhr - jqXHR = { - readyState: 0, - - // Builds headers hashtable if needed - getResponseHeader: function( key ) { - var match; - if ( completed ) { - if ( !responseHeaders ) { - responseHeaders = {}; - while ( ( match = rheaders.exec( responseHeadersString ) ) ) { - responseHeaders[ match[ 1 ].toLowerCase() + " " ] = - ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) - .concat( match[ 2 ] ); - } - } - match = responseHeaders[ key.toLowerCase() + " " ]; - } - return match == null ? null : match.join( ", " ); - }, - - // Raw string - getAllResponseHeaders: function() { - return completed ? responseHeadersString : null; - }, - - // Caches the header - setRequestHeader: function( name, value ) { - if ( completed == null ) { - name = requestHeadersNames[ name.toLowerCase() ] = - requestHeadersNames[ name.toLowerCase() ] || name; - requestHeaders[ name ] = value; - } - return this; - }, - - // Overrides response content-type header - overrideMimeType: function( type ) { - if ( completed == null ) { - s.mimeType = type; - } - return this; - }, - - // Status-dependent callbacks - statusCode: function( map ) { - var code; - if ( map ) { - if ( completed ) { - - // Execute the appropriate callbacks - jqXHR.always( map[ jqXHR.status ] ); - } else { - - // Lazy-add the new callbacks in a way that preserves old ones - for ( code in map ) { - statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; - } - } - } - 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 ); - - // Add protocol if not provided (prefilters might expect it) - // 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 || location.href ) + "" ) - .replace( rprotocol, location.protocol + "//" ); - - // Alias method option to type as per ticket #12004 - s.type = options.method || options.type || s.method || s.type; - - // Extract dataTypes list - s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; - - // A cross-domain request is in order when the origin doesn't match the current origin. - if ( s.crossDomain == null ) { - urlAnchor = document.createElement( "a" ); - - // Support: IE <=8 - 11, Edge 12 - 15 - // IE throws exception on accessing the href property if url is malformed, - // e.g. http://example.com:80x/ - try { - urlAnchor.href = s.url; - - // Support: IE <=8 - 11 only - // Anchor's host property isn't correctly set when s.url is relative - urlAnchor.href = urlAnchor.href; - s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== - urlAnchor.protocol + "//" + urlAnchor.host; - } catch ( e ) { - - // If there is an error parsing the URL, assume it is crossDomain, - // it can be rejected by the transport if it is invalid - s.crossDomain = true; - } - } - - // 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 ( completed ) { - return jqXHR; - } - - // We can fire global events as of now if asked to - // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) - fireGlobals = jQuery.event && 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 - // Remove hash to simplify url manipulation - cacheURL = s.url.replace( rhash, "" ); - - // More options handling for requests with no content - if ( !s.hasContent ) { - - // Remember the hash so we can put it back - uncached = s.url.slice( cacheURL.length ); - - // If data is available and should be processed, append data to url - if ( s.data && ( s.processData || typeof s.data === "string" ) ) { - cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; - - // #9682: remove data so that it's not used in an eventual retry - delete s.data; - } - - // Add or update anti-cache param if needed - if ( s.cache === false ) { - cacheURL = cacheURL.replace( rantiCache, "$1" ); - uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + - uncached; - } - - // Put hash and anti-cache on the URL that will be requested (gh-1732) - s.url = cacheURL + uncached; - - // Change '%20' to '+' if this is encoded form body content (gh-2658) - } else if ( s.data && s.processData && - ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { - s.data = s.data.replace( r20, "+" ); - } - - // 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 || completed ) ) { - - // Abort if not done already and return - return jqXHR.abort(); - } - - // Aborting is no longer a cancellation - strAbort = "abort"; - - // Install callbacks on deferreds - completeDeferred.add( s.complete ); - jqXHR.done( s.success ); - jqXHR.fail( s.error ); - - // 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 ] ); - } - - // If request was aborted inside ajaxSend, stop there - if ( completed ) { - return jqXHR; - } - - // Timeout - if ( s.async && s.timeout > 0 ) { - timeoutTimer = window.setTimeout( function() { - jqXHR.abort( "timeout" ); - }, s.timeout ); - } - - try { - completed = false; - transport.send( requestHeaders, done ); - } catch ( e ) { - - // Rethrow post-completion exceptions - if ( completed ) { - throw e; - } - - // Propagate others as results - done( -1, e ); - } - } - - // Callback for when everything is done - function done( status, nativeStatusText, responses, headers ) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Ignore repeat invocations - if ( completed ) { - return; - } - - completed = true; - - // Clear timeout if it exists - if ( timeoutTimer ) { - window.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 ); - } - - // Use a noop converter for missing script but not if jsonp - if ( !isSuccess && - jQuery.inArray( "script", s.dataTypes ) > -1 && - jQuery.inArray( "json", s.dataTypes ) < 0 ) { - s.converters[ "text script" ] = function() {}; - } - - // 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 { - - // Extract error from statusText and normalize 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 ( isFunction( data ) ) { - type = type || callback; - callback = data; - data = undefined; - } - - // The url can be an options object (which then must have .url) - return jQuery.ajax( jQuery.extend( { - url: url, - type: method, - dataType: type, - data: data, - success: callback - }, jQuery.isPlainObject( url ) && url ) ); - }; -} ); - -jQuery.ajaxPrefilter( function( s ) { - var i; - for ( i in s.headers ) { - if ( i.toLowerCase() === "content-type" ) { - s.contentType = s.headers[ i ] || ""; - } - } -} ); - - -jQuery._evalUrl = function( url, options, doc ) { - return jQuery.ajax( { - url: url, - - // Make this explicit, since user can override this through ajaxSetup (#11264) - type: "GET", - dataType: "script", - cache: true, - async: false, - global: false, - - // Only evaluate the response if it is successful (gh-4126) - // dataFilter is not invoked for failure responses, so using it instead - // of the default converter is kludgy but it works. - converters: { - "text script": function() {} - }, - dataFilter: function( response ) { - jQuery.globalEval( response, options, doc ); - } - } ); -}; - - -jQuery.fn.extend( { - wrapAll: function( html ) { - var wrap; - - if ( this[ 0 ] ) { - if ( isFunction( html ) ) { - html = html.call( this[ 0 ] ); - } - - // The elements to wrap the target around - 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.firstElementChild ) { - elem = elem.firstElementChild; - } - - return elem; - } ).append( this ); - } - - return this; - }, - - wrapInner: function( html ) { - if ( 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 htmlIsFunction = isFunction( html ); - - return this.each( function( i ) { - jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); - } ); - }, - - unwrap: function( selector ) { - this.parent( selector ).not( "body" ).each( function() { - jQuery( this ).replaceWith( this.childNodes ); - } ); - return this; - } -} ); - - -jQuery.expr.pseudos.hidden = function( elem ) { - return !jQuery.expr.pseudos.visible( elem ); -}; -jQuery.expr.pseudos.visible = function( elem ) { - return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); -}; - - - - -jQuery.ajaxSettings.xhr = function() { - try { - return new window.XMLHttpRequest(); - } catch ( e ) {} -}; - -var xhrSuccessStatus = { - - // File protocol always yields status code 0, assume 200 - 0: 200, - - // Support: IE <=9 only - // #1450: sometimes IE returns 1223 when it should be 204 - 1223: 204 - }, - xhrSupported = jQuery.ajaxSettings.xhr(); - -support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); -support.ajax = xhrSupported = !!xhrSupported; - -jQuery.ajaxTransport( function( options ) { - var callback, errorCallback; - - // Cross domain only allowed if supported through XMLHttpRequest - if ( support.cors || xhrSupported && !options.crossDomain ) { - return { - send: function( headers, complete ) { - var i, - xhr = options.xhr(); - - 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 ) { - xhr.setRequestHeader( i, headers[ i ] ); - } - - // Callback - callback = function( type ) { - return function() { - if ( callback ) { - callback = errorCallback = xhr.onload = - xhr.onerror = xhr.onabort = xhr.ontimeout = - xhr.onreadystatechange = null; - - if ( type === "abort" ) { - xhr.abort(); - } else if ( type === "error" ) { - - // Support: IE <=9 only - // On a manual native abort, IE9 throws - // errors on any property access that is not readyState - if ( typeof xhr.status !== "number" ) { - complete( 0, "error" ); - } else { - complete( - - // File: protocol always yields status 0; see #8605, #14207 - xhr.status, - xhr.statusText - ); - } - } else { - complete( - xhrSuccessStatus[ xhr.status ] || xhr.status, - xhr.statusText, - - // Support: IE <=9 only - // IE9 has no XHR2 but throws on binary (trac-11426) - // For XHR2 non-text, let the caller handle it (gh-2498) - ( xhr.responseType || "text" ) !== "text" || - typeof xhr.responseText !== "string" ? - { binary: xhr.response } : - { text: xhr.responseText }, - xhr.getAllResponseHeaders() - ); - } - } - }; - }; - - // Listen to events - xhr.onload = callback(); - errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); - - // Support: IE 9 only - // Use onreadystatechange to replace onabort - // to handle uncaught aborts - if ( xhr.onabort !== undefined ) { - xhr.onabort = errorCallback; - } else { - xhr.onreadystatechange = function() { - - // Check readyState before timeout as it changes - if ( xhr.readyState === 4 ) { - - // Allow onerror to be called first, - // but that will not handle a native abort - // Also, save errorCallback to a variable - // as xhr.onerror cannot be accessed - window.setTimeout( function() { - if ( callback ) { - errorCallback(); - } - } ); - } - }; - } - - // Create the abort callback - callback = callback( "abort" ); - - try { - - // Do send the request (this may raise an exception) - xhr.send( options.hasContent && options.data || null ); - } catch ( e ) { - - // #14683: Only rethrow if this hasn't been notified as an error yet - if ( callback ) { - throw e; - } - } - }, - - abort: function() { - if ( callback ) { - callback(); - } - } - }; - } -} ); - - - - -// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) -jQuery.ajaxPrefilter( function( s ) { - if ( s.crossDomain ) { - s.contents.script = false; - } -} ); - -// Install script dataType -jQuery.ajaxSetup( { - accepts: { - script: "text/javascript, application/javascript, " + - "application/ecmascript, application/x-ecmascript" - }, - contents: { - script: /\b(?:java|ecma)script\b/ - }, - converters: { - "text script": function( text ) { - jQuery.globalEval( text ); - return text; - } - } -} ); - -// Handle cache's special case and crossDomain -jQuery.ajaxPrefilter( "script", function( s ) { - if ( s.cache === undefined ) { - s.cache = false; - } - if ( s.crossDomain ) { - s.type = "GET"; - } -} ); - -// Bind script tag hack transport -jQuery.ajaxTransport( "script", function( s ) { - - // This transport only deals with cross domain or forced-by-attrs requests - if ( s.crossDomain || s.scriptAttrs ) { - var script, callback; - return { - send: function( _, complete ) { - script = jQuery( " - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

app module

-
-
-parse_contents(contents, filename, date)
-
- -
-
-update_output(list_of_contents, list_of_names, list_of_dates)
-
- -
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/docs/_build/html/autotranscript.app.html b/docs/_build/html/autotranscript.app.html deleted file mode 100644 index 5beafa2..0000000 --- a/docs/_build/html/autotranscript.app.html +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - autotranscript.app package — AutoTranscript documentation - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

autotranscript.app package

-
-

Submodules

-
-
-

autotranscript.app.qtfaststart module

-

This file contains a modified version of qtfaststart by qtfaststart -https://github.com/danielgtaylor/qtfaststart/tree/master

-

All credit goes to the original author. -Copyright (C) 2008 - 2013 Daniel G. Taylor <dan@programmer-art.org> -Permission is hereby granted, free of charge, to any person obtaining a copy of this -software and associated documentation files (the “Software”), -to deal in the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the -Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions:

-

The above copyright notice and this permission notice shall be included in all copies -or substantial portions of the Software.

-

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE.

-
-
-class Atom(name, position, size)
-

Bases: tuple

-
-
-__repr__()
-

Return a nicely formatted representation string

-
- -
-
-name
-

Alias for field number 0

-
- -
-
-position
-

Alias for field number 1

-
- -
-
-size
-

Alias for field number 2

-
- -
- -
-
-exception FastStartException
-

Bases: Exception

-

Raised when something bad happens during processing.

-
- -
-
-exception FastStartSetupError
-

Bases: FastStartException

-

Rasised when asked to process a file that does not need processing

-
- -
-
-exception MalformedFileError
-

Bases: FastStartException

-

Raised when the input file is setup in an unexpected way

-
- -
-
-exception UnsupportedFormatError
-

Bases: FastStartException

-

Raised when a movie file is recognized as a format not supported.

-
- -
-
-find_atoms(size, datastream)
-

Compatibilty interface for _find_atoms_ex

-
- -
-
-get_chunks(stream, chunk_size, limit)
-
- -
-
-get_index(datastream)
-

Return an index of top level atoms, their absolute byte-position in the -file and their size in a list:

-
-
index = [

(“ftyp”, 0, 24), -(“moov”, 25, 2658), -(“free”, 2683, 8), -…

-
-
-

]

-

The tuple elements will be in the order that they appear in the file.

-
- -
-
-process(infilename, limit=inf)
-

Convert a Quicktime/MP4 file for streaming by moving the metadata to -the front of the file. This method writes a new file.

-

If limit is set to something other than zero it will be used as the -number of bytes to write of the atoms following the moov atom. This -is very useful to create a small sample of a file with full headers, -which can then be used in bug reports and such.

-
- -
-
-read_atom(datastream)
-

Read an atom and return a tuple of (size, type) where size is the size -in bytes (including the 8 bytes already read) and type is a “fourcc” -like “ftyp” or “moov”.

-
- -
-
-

Module contents

-
-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/docs/_build/html/autotranscript.html b/docs/_build/html/autotranscript.html deleted file mode 100644 index 302040a..0000000 --- a/docs/_build/html/autotranscript.html +++ /dev/null @@ -1,833 +0,0 @@ - - - - - - - - - autotranscript package — AutoTranscript documentation - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

autotranscript package

-
-

Subpackages

- -
-
-

Submodules

-
-
-

autotranscript.audio module

-
-

Audio Processor Module

-

This module provides the AudioProcessor class, utilizing PyTorchaudio for handling audio files. -It includes functionalities to load, cut, and manage audio waveforms, offering efficient and -flexible audio processing.

-

Available Classes: -- AudioProcessor: Processes audio waveforms and provides methods for loading,

-
-

cutting, and handling audio.

-
-
-
Usage:

from .audio_import AudioProcessor

-

processor = AudioProcessor.from_file(“path/to/audiofile.wav”) -cut_waveform = processor.cut(start=1.0, end=5.0)

-
-
-

Constants: -- SAMPLE_RATE (int): Default sample rate for processing. -- NORMALIZATION_FACTOR (float): Normalization factor for audio waveform.

-
-
-class AudioProcessor(waveform: torch.Tensor, sr: int = 16000, *args, **kwargs)
-

Bases: object

-

Audio Processor class that leverages PyTorchaudio to provide functionalities -for loading, cutting, and handling audio waveforms.

-
-
Attributes:
-
waveform: torch.Tensor

The audio waveform tensor.

-
-
sr: int

The sample rate of the audio.

-
-
-
-
-
-
-__init__(waveform: torch.Tensor, sr: int = 16000, *args, **kwargs) None
-

Initialize the AudioProcessor object.

-
-
Args:

waveform (torch.Tensor): The audio waveform tensor. -sr (int, optional): The sample rate of the audio. Defaults to SAMPLE_RATE. -args: Additional arguments. -kwargs: Additional keyword arguments, e.g., device to use for processing. -If CUDA is available, it defaults to CUDA.

-
-
Raises:

ValueError: If the provided sample rate is not of type int.

-
-
-
- -
-
-__repr__() str
-

Return repr(self).

-
- -
-
-cut(start: float, end: float) torch.Tensor
-

Cut a segment from the audio waveform between the specified start and end times.

-
-
Args:

start (float): Start time in seconds. -end (float): End time in seconds.

-
-
Returns:

torch.Tensor: The cut waveform segment.

-
-
-
- -
-
-classmethod from_file(file: str, *args, **kwargs) AudioProcessor
-

Create an AudioProcessor instance from an audio file.

-
-
Args:

file (str): The audio file path.

-
-
Returns:

AudioProcessor: An instance of the AudioProcessor class containing the loaded audio.

-
-
-
- -
-
-static load_audio(file: str, sr: int = 16000)
-

Open an audio file and read it as a mono waveform, resampling if necessary. -This method ensures compatibility with pyannote.audio -and requires the ffmpeg CLI in PATH.

-
-
Args:

file (str): The audio file to open. -sr (int, optional): The desired sample rate. Defaults to SAMPLE_RATE.

-
-
Returns:
-
tuple: A NumPy array containing the audio waveform in float32 dtype

and the sample rate.

-
-
-
-
Raises:

RuntimeError: If failed to load audio.

-
-
-
- -
- -
-
-
-

autotranscript.autotranscript module

-
-

AutoTranscribe Class

-

This class serves as the core of the transcription system, responsible for handling -transcription and diarization of audio files. It leverages pretrained models for -speech-to-text (such as Whisper) and speaker diarization (such as pyannote.audio), -providing an accessible interface for audio processing tasks such as transcription, -speaker separation, and timestamping.

-

By encapsulating the complexities of underlying models, it allows for straightforward -integration into various applications, ranging from transcription services to voice assistants.

-

Available Classes: -- AutoTranscribe: Main class for performing transcription and diarization.

-
-

Includes methods for loading models, processing audio files, -and formatting the transcription output.

-
-
-
Usage:

from .autotranscribe import AutoTranscribe

-

model = AutoTranscribe(whisper_model=”path/to/whisper/model”, dia_model=”path/to/diarisation/model”) -transcript = model.transcribe(“path/to/audiofile.wav”)

-
-
-
-
-class AutoTranscribe(whisper_model: Union[bool, str, whisper] = None, dia_model: Union[bool, str, DiarisationType] = None, **kwargs)
-

Bases: object

-

AutoTranscribe is a class responsible for managing the transcription and diarization of audio files. -It serves as the core of the transcription system, incorporating pretrained models -for speech-to-text (such as Whisper) and speaker diarization (such as pyannote.audio), -allowing for comprehensive audio processing.

-
-
Attributes:

transcriber (Transcriber): The transcriber object to handle transcription. -diariser (Diariser): The diariser object to handle diarization.

-
-
Methods:

__init__: Initializes the AutoTranscribe class with appropriate models. -transcribe: Transcribes an audio file using the whisper model and pyannote diarization model. -remove_audio_file: Removes the original audio file to avoid disk space issues or ensure data privacy. -get_audio_file: Gets an audio file as an AudioProcessor object.

-
-
-
-
-__init__(whisper_model: Union[bool, str, whisper] = None, dia_model: Union[bool, str, DiarisationType] = None, **kwargs) None
-

Initializes the AutoTranscribe class.

-
-
Args:
-
whisper_model (Union[bool, str, whisper], optional):

Path to whisper model or whisper model itself.

-
-
diarisation_model (Union[bool, str, DiarisationType], optional):

Path to pyannote diarization model or model itself.

-
-
**kwargs: Additional keyword arguments for whisper

and pyannote diarization models.

-
-
-
-
-
- -
-
-static get_audio_file(audio_file: Union[str, torch.Tensor, numpy.ndarray], *args, **kwargs) AudioProcessor
-

Gets an audio file as TorchAudioProcessor.

-
-
Args:
-
audio_file (Union[str, torch.Tensor, ndarray]): Path to the audio file or

a tensor representing the audio.

-
-
-

*args: Additional positional arguments. -**kwargs: Additional keyword arguments.

-
-
Returns:
-
AudioProcessor: An object containing the waveform and sample rate in

torch.Tensor format.

-
-
-
-
-
- -
-
-static remove_audio_file(audio_file: str, shred: bool = False) None
-

Removes the original audio file to avoid disk space issues or ensure data privacy.

-
-
Args:

audio_file_path (str): Path to the audio file. -shred (bool, optional): If True, the audio file will be shredded,

-
-

not just removed.

-
-
-
-
- -
-
-transcribe(audio_file: Union[str, torch.Tensor, numpy.ndarray], remove_original: bool = False, **kwargs) Transcript
-

Transcribes an audio file using the whisper model and pyannote diarization model.

-
-
Args:
-
audio_file (Union[str, torch.Tensor, ndarray]):

Path to audio file or a tensor representing the audio.

-
-
remove_original (bool, optional): If True, the original audio file will

be removed after transcription.

-
-
-

*args: Additional positional arguments for diarization and transcription. -**kwargs: Additional keyword arguments for diarization and transcription.

-
-
Returns:
-
Transcript: A Transcript object containing the transcription,

which can be exported to different formats.

-
-
-
-
-
- -
- -
-
-cli()
-

Command-Line Interface (CLI) for the AutoTranscribe class, allowing for user interaction to transcribe -and diarize audio files. The function includes arguments for specifying the audio files, model paths, -output formats, and other options necessary for transcription.

-

This function can be executed from the command line to perform transcription tasks, providing a -user-friendly way to access the AutoTranscribe class functionalities.

-
- -
-
-
-

autotranscript.diarisation module

-
-

Diarisation Class

-

This class serves as the heart of the speaker diarization system, responsible for identifying -and segmenting individual speakers from a given audio file. It leverages a pretrained model -from pyannote.audio, providing an accessible interface for audio processing tasks such as -speaker separation, and timestamping.

-

By encapsulating the complexities of the underlying model, it allows for straightforward -integration into various applications, ranging from transcription services to voice assistants.

-

Available Classes: -- Diariser: Main class for performing speaker diarization.

-
-

Includes methods for loading models, processing audio files, -and formatting the diarization output.

-
-

Constants: -- TOKEN_PATH (str): Path to the Pyannote token. -- PYANNOTE_DEFAULT_PATH (str): Default path to Pyannote models. -- PYANNOTE_DEFAULT_CONFIG (str): Default configuration for Pyannote models.

-
-
Usage:

from .diarisation import Diariser

-

model = Diariser.load_model(model=”path/to/model/config.yaml”) -diarisation_output = model.diarization(“path/to/audiofile.wav”)

-
-
-
-
-class Diariser(model)
-

Bases: object

-

Handles the diarization process of an audio file using a pretrained model -from pyannote.audio. Diarization is the task of determining “who spoke when.”

-
-
Args:

model: The pretrained model to use for diarization.

-
-
-
-
-__init__(model) None
-
- -
-
-__repr__()
-

Return repr(self).

-
- -
-
-diarization(audiofile: Union[str, torch.Tensor, dict], *args, **kwargs) Annotation
-

Perform speaker diarization on the provided audio file, -effectively separating different speakers -and providing a timestamp for each segment.

-
-
Args:
-
audiofile: The path to the audio file or a torch.Tensor

containing the audio data.

-
-
-

args: Additional arguments for the diarization model. -kwargs: Additional keyword arguments for the diarization model.

-
-
Returns:
-
dict: A dictionary containing speaker names,

segments, and other information related -to the diarization process.

-
-
-
-
-
- -
-
-static format_diarization_output(dia: Annotation) dict
-

Formats the raw diarization output into a more usable structure for this project.

-
-
Args:

dia: Raw diarization output.

-
-
Returns:
-
dict: A structured representation of the diarization, with speaker names

as keys and a list of tuples representing segments as values.

-
-
-
-
-
- -
-
-classmethod load_model(model: str = '/home/ortizcruzc/.cache/torch/models/pyannote/config.yaml', token: str = None, cache_token: bool = False, cache_dir: Union[Path, str] = '/home/ortizcruzc/.cache/torch/models/pyannote', hparams_file: Union[str, Path] = None) pyannote.audio.Pipeline
-

Loads a pretrained model from pyannote.audio, -either from a local cache or online repository.

-
-
Args:
-
model: Path or identifier for the pyannote model.

default: /models/pyannote/speaker_diarization/config.yaml

-
-
-

token: Optional HUGGINGFACE_TOKEN for authenticated access. -cache_token: Whether to cache the token locally for future use. -cache_dir: Directory for caching models. -hparams_file: Path to a YAML file containing hyperparameters.

-
-
Returns:

Pipeline: A pyannote.audio Pipeline object, encapsulating the loaded model.

-
-
-
- -
- -
-
-
-

autotranscript.misc module

-
-
-config_diarization_yaml(file_path: str, path_to_segmentation: str = None) None
-

Configure diarization pipeline from a YAML file.

-

This function updates the YAML file to use the given segmentation model -offline, and avoids manual file manipulation.

-
-
Args:

file_path (str): Path to the YAML file. -path_to_segmentation (str, optional): Optional path to the segmentation model.

-
-
Raises:

FileNotFoundError: If the segmentation model file is not found.

-
-
-
- -
-
-

autotranscript.transcriber module

-
-

Transcriber Module

-

This module provides the Transcriber class, a comprehensive tool for working with Whisper models. -The Transcriber class offers functionalities such as loading different Whisper models, transcribing audio files, -and saving transcriptions to text files. It acts as an interface between various Whisper models and the user, -simplifying the process of audio transcription.

-
-
Main Features:
    -
  • Loading different sizes and versions of Whisper models.

  • -
  • Transcribing audio in various formats including str, Tensor, and nparray.

  • -
  • Saving the transcriptions to the specified paths.

  • -
  • Adaptable to various language specifications.

  • -
  • Options to control the verbosity of the transcription process.

  • -
-
-
Constants:

WHISPER_DEFAULT_PATH: Default path for downloading and loading Whisper models.

-
-
Usage:
>>> from your_package import Transcriber
->>> transcriber = Transcriber.load_model(model="medium")
->>> transcript = transcriber.transcribe(audio="path/to/audio.wav")
->>> transcriber.save_transcript(transcript, "path/to/save.txt")
-
-
-
-
-
-
-class Transcriber(model: whisper)
-

Bases: object

-

The Transcriber class serves as a wrapper around Whisper models for efficient audio -transcription. By encapsulating the intricacies of loading models, processing audio, -and saving transcripts, it offers an easy-to-use interface -for users to transcribe audio files.

-
-
Attributes:

model (whisper): The Whisper model used for transcription.

-
-
Methods:

transcribe: Transcribes the given audio file. -save_transcript: Saves the transcript to a file. -load_model: Loads a specific Whisper model. -_get_whisper_kwargs: Private method to get valid keyword arguments for the whisper model.

-
-
Examples:
>>> transcriber = Transcriber.load_model(model="medium")
->>> transcript = transcriber.transcribe(audio="path/to/audio.wav")
->>> transcriber.save_transcript(transcript, "path/to/save.txt")
-
-
-
-
Note:

The class supports various sizes and versions of Whisper models. Please refer to -the load_model method for available options.

-
-
-
-
-__init__(model: whisper) None
-

Initialize the Transcriber class with a Whisper model.

-
-
Args:

model (whisper): The Whisper model to use for transcription.

-
-
-
- -
-
-__repr__() str
-

Return repr(self).

-
- -
-
-classmethod load_model(model: str = 'medium', download_root: str = '/home/ortizcruzc/.cache/torch/models/whisper', device: Optional[Union[str, torch.device]] = None, in_memory: bool = False) Transcriber
-

Load whisper model.

-
-
Args:
-
model (str): Whisper model. Available models include:
    -
  • ‘tiny.en’

  • -
  • ‘tiny’

  • -
  • ‘base.en’

  • -
  • ‘base’

  • -
  • ‘small.en’

  • -
  • ‘small’

  • -
  • ‘medium.en’

  • -
  • ‘medium’

  • -
  • ‘large-v1’

  • -
  • ‘large-v2’

  • -
  • ‘large’

  • -
-
-
download_root (str, optional): Path to download the model.

Defaults to WHISPER_DEFAULT_PATH.

-
-
device (Optional[Union[str, torch.device]], optional):

Device to load model on. Defaults to None.

-
-
in_memory (bool, optional): Whether to load model in memory.

Defaults to False.

-
-
-
-
Returns:

Transcriber: A Transcriber object initialized with the specified model.

-
-
-
- -
-
-static save_transcript(transcript: str, save_path: str) None
-

Save a transcript to a file.

-
-
Args:

transcript (str): The transcript as a string. -save_path (str): The path to save the transcript.

-
-
Returns:

None

-
-
-
- -
-
-transcribe(audio: Union[str, torch.Tensor, numpy.ndarray], *args, **kwargs) str
-

Transcribe an audio file.

-
-
Args:

audio (Union[str, Tensor, nparray]): The audio file to transcribe. -*args: Additional arguments. -**kwargs: Additional keyword arguments,

-
-

such as the language of the audio file.

-
-
-
Returns:

str: The transcript as a string.

-
-
-
- -
- -
-
-
-

autotranscript.transcript_exporter module

-
-
-class Transcript(transcript: dict)
-

Bases: object

-

Class for storing transcript data, including speaker information and text segments, -and exporting it to various file formats such as JSON, HTML, and LaTeX.

-
-
-__init__(transcript: dict) None
-

Initializes the Transcript object with the given transcript data.

-
-
Args:
-
transcript (dict): A dictionary containing the formatted transcript string.

Keys should correspond to segment IDs, and values should -contain speaker and segment information.

-
-
-
-
-
- -
-
-__repr__() str
-

Return a string representation of the Transcript object.

-
-
Returns:

str: A string that provides an informative description of the object.

-
-
-
- -
-
-__str__() str
-

Converts the transcript to a string representation.

-
-
Returns:
-
str: String representation of the transcript, including speaker names and

time stamps for each segment.

-
-
-
-
-
- -
-
-annotate(*args, **kwargs) dict
-

Annotates the transcript to associate specific names with speakers.

-
-
Args:

args (list): List of speaker names. These will be mapped sequentially to the speakers. -kwargs (dict): Dictionary with speaker names as keys and list of segments as values.

-
-
Returns:

dict: Dictionary with speaker names as keys and the corresponding annotation as values.

-
-
Raises:
-
ValueError: If the number of speaker names does not match the number

of speakers, or if an unknown speaker is found.

-
-
-
-
-
- -
-
-get_dict() dict
-

Get transcript as dict

-
-
Returns:
-

transcript as dict

-
-
Return type:
-

dict

-
-
-
- -
-
-get_html() str
-

Get transcript as html string

-
-
Returns:
-

transcript as html string

-
-
Return type:
-

str

-
-
-
- -
-
-get_json(*args, **kwargs) str
-

Get transcript as json string -:return: transcript as json string -:rtype: str

-
- -
-
-get_md() str
-

Get transcript as Markdown string, using HTML formatting.

-
-
Returns:

str: Transcript as a Markdown string.

-
-
-
- -
-
-get_tex() str
-

Get transcript as LaTeX string. If no annotations are present, the speakers will -be annotated with the first letters of the alphabet.

-
-
Returns:

str: Transcript as LaTeX string.

-
-
-
- -
-
-save(path: str, *args, **kwargs) None
-

Save transcript to file with the given path and file format.

-

This method can save the transcript in various formats including JSON, TXT, -MD, HTML, TEX, and PDF. The file format is determined by the extension of -the path.

-
-
Args:

path (str): Path to save the file, including the desired file extension. -*args: Additional positional arguments to be passed to the specific save methods. -**kwargs: Additional keyword arguments to be passed to the specific save methods.

-
-
Raises:

ValueError: If the file format specified in the path is unknown.

-
-
-
- -
-
-to_html(path: str) None
-

Save transcript as html file

-
-
Parameters:
-

path (str) – path to save file

-
-
-
- -
-
-to_json(path, *args, **kwargs) None
-

Save transcript as json file

-
-
Args:

path (str): path to save file

-
-
-
- -
-
-to_md(path: str) None
-

Get transcript as Markdown string, using HTML formatting.

-
-
Returns:

str: Transcript as a Markdown string.

-
-
-
- -
-
-to_pdf(path: str) None
-

Save transcript as a PDF file (placeholder function, implementation needed).

-
-
Args:

path (str): Path to save the PDF file.

-
-
-
- -
-
-to_tex(path: str) None
-

Save transcript as a LaTeX file (placeholder function, implementation needed).

-
-
Args:

path (str): Path to save the LaTeX file.

-
-
-
- -
-
-to_txt(path: str) None
-

Save transcript as a LaTeX file (placeholder function, implementation needed).

-
-
Args:

path (str): Path to save the LaTeX file.

-
-
-
- -
- -
-
-

autotranscript.version module

-
-
-get_version(build_version=False)
-
- -
-
-git_version()
-
- -
-
-

Module contents

-
-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/docs/_build/html/genindex.html b/docs/_build/html/genindex.html deleted file mode 100644 index 2afa676..0000000 --- a/docs/_build/html/genindex.html +++ /dev/null @@ -1,459 +0,0 @@ - - - - - - - - Index — AutoTranscript documentation - - - - - - - - - - - - - - - - - - -
-
-
- - -
- - -

Index

- -
- _ - | A - | C - | D - | F - | G - | L - | M - | N - | P - | R - | S - | T - | U - -
-

_

- - - -
- -

A

- - - -
    -
  • - autotranscript.autotranscript - -
  • -
  • - autotranscript.diarisation - -
  • -
  • - autotranscript.misc - -
  • -
  • - autotranscript.transcriber - -
  • -
  • - autotranscript.transcript_exporter - -
  • -
  • - autotranscript.version - -
  • -
- -

C

- - - -
- -

D

- - - -
- -

F

- - - -
- -

G

- - - -
- -

L

- - - -
- -

M

- - -
- -

N

- - -
- -

P

- - - -
- -

R

- - - -
- -

S

- - - -
- -

T

- - - -
- -

U

- - - -
- - - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/docs/_build/html/gradio_app.html b/docs/_build/html/gradio_app.html deleted file mode 100644 index 139df0d..0000000 --- a/docs/_build/html/gradio_app.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - gradio_app module — AutoTranscript documentation - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

gradio_app module

-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/docs/_build/html/index.html b/docs/_build/html/index.html deleted file mode 100644 index d5670e7..0000000 --- a/docs/_build/html/index.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - Welcome to AutoTranscript’s documentation! — AutoTranscript documentation - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

Welcome to AutoTranscript’s documentation!

-

AutoTranscript: Fully Automated Transcription using AI

-

AutoTranscript is a PyTorch based interface speech-to-text tool to generate fully automated transcriptions. AutoTranscript uses AI models containing speaker diarization models:

- -
-
-

Indices and tables

- -
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/docs/_build/html/modules.html b/docs/_build/html/modules.html deleted file mode 100644 index aea5c52..0000000 --- a/docs/_build/html/modules.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - - - autotranscript — AutoTranscript documentation - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/_build/html/objects.inv b/docs/_build/html/objects.inv deleted file mode 100644 index 8076eb1007c3a3d87b4e2dd74b5f1d9cb8c175c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 940 zcmV;d15^AXAX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkGb#!l3 za$#V>iAPOTORA^-&a%F8{X>Md?av*PJAarPHb0B7EY-J#6 zb0A}HZE$jBb8}^6Aa!$TZf78RY-wUH3V7PJn9Xk7AP~pz`xLI)>sswKw@6K-9wJ3b zsva$Z$GappP#8zMIrTOAdVP|D@viZ%?PLwUSbWWo0sbC7h?I%kUsWQnOGv&ZM9OrF zRr%SKtiL4dl`WG*X~?MH2pqLFDQZrU37&lGj1H}9nG=Le)F^A5Y+R#2MYyJlN$h*l zt2%e8UrkQOaaR2SLi!sEqERDJ7?+k_qo^#BmPBhi3nRo2qS7o=AXSz%ZUSya9s$Zp z1r|sU6?>`?A~2=UtXcWUT+QBM`g&_p4>onPqaY6s!!Z*F{s36Z8>NJbNWUXxAyftV zEh`~5{3qA7ltQ7wn@$ME?x0{i&xl#kv!F7cxdF`Rw&pL9nZ{Mv#Y0LZDCmejDj;qy z1CVvjL`WRA_UX0#-n-#BwT#5QNjFX~Cgw5Da60B)2z)JD4Hphtsmggm?tUi~;Fm{9AN#}$wLC%!lJhuozM{vNVe%NG zYGR`5$xapt9Trc!WCpwD%pF5U9_{F>8}&>z4FjWyY7`x=tx>ebWypkcfdpXzv^{y` zjN(FQYq}8nS~tyZjV%1hI=jQYISnt6b1z-MtjsMB*GjeK7W0pF@+=J1e0tWCKHQ z$K#;Ri-8yC7PtZK-i9ouBv0nRVnBydXa2(`R~tp_b?&6guGF>lTD9Zu@U4kQ{sko! z6(lGU|9&U&-=DuaG41OLI5vmdPbTthYH8Mb0Tt1J0G;)eOoj%Gb<1FPA~U+ zqjKKwOaoDL+c$J&&gQ|@-`jcD_C3{it0{2pTwObT2-;rO$Fwt0?I1&T2V{5F^GV(1 O+5x&&t=)fOt(N>GOSZBA diff --git a/docs/_build/html/py-modindex.html b/docs/_build/html/py-modindex.html deleted file mode 100644 index e5840ab..0000000 --- a/docs/_build/html/py-modindex.html +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - Python Module Index — AutoTranscript documentation - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- - -

Python Module Index

- -
- a -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
- a
- app -
- autotranscript -
    - autotranscript.app -
    - autotranscript.app.qtfaststart -
    - autotranscript.audio -
    - autotranscript.autotranscript -
    - autotranscript.diarisation -
    - autotranscript.misc -
    - autotranscript.transcriber -
    - autotranscript.transcript_exporter -
    - autotranscript.version -
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/docs/_build/html/search.html b/docs/_build/html/search.html deleted file mode 100644 index 50a7dc9..0000000 --- a/docs/_build/html/search.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - Search — AutoTranscript documentation - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -

Search

- - - - -

- Searching for multiple words only shows matches that contain - all words. -

- - -
- - - -
- - - -
- -
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/docs/_build/html/searchindex.js b/docs/_build/html/searchindex.js deleted file mode 100644 index 9b1692d..0000000 --- a/docs/_build/html/searchindex.js +++ /dev/null @@ -1 +0,0 @@ -Search.setIndex({"docnames": ["app", "autotranscript", "autotranscript.app", "gradio_app", "index", "modules", "setup", "test_autotranscript", "transcribe"], "filenames": ["app.rst", "autotranscript.rst", "autotranscript.app.rst", "gradio_app.rst", "index.rst", "modules.rst", "setup.rst", "test_autotranscript.rst", "transcribe.rst"], "titles": ["app module", "autotranscript package", "autotranscript.app package", "gradio_app module", "Welcome to AutoTranscript\u2019s documentation!", "autotranscript", "setup module", "test_autotranscript module", "transcribe module"], "terms": {"parse_cont": 0, "content": [0, 5], "filenam": 0, "date": 0, "update_output": 0, "list_of_cont": 0, "list_of_nam": 0, "list_of_d": 0, "app": [1, 4, 5], "qtfaststart": [1, 5], "thi": [1, 2], "provid": [1, 2], "audioprocessor": 1, "util": 1, "pytorchaudio": 1, "handl": 1, "file": [1, 2], "It": 1, "includ": [1, 2], "function": 1, "load": 1, "cut": 1, "manag": 1, "waveform": 1, "offer": 1, "effici": 1, "flexibl": 1, "process": [1, 2], "avail": 1, "method": [1, 2], "usag": 1, "from": [1, 2], "audio_import": 1, "from_fil": 1, "path": 1, "audiofil": 1, "wav": 1, "cut_waveform": 1, "start": 1, "1": [1, 2], "0": [1, 2], "end": 1, "5": 1, "constant": 1, "sample_r": 1, "int": 1, "default": 1, "sampl": [1, 2], "rate": 1, "normalization_factor": 1, "float": 1, "normal": 1, "factor": 1, "torch": 1, "tensor": 1, "sr": 1, "16000": 1, "arg": 1, "kwarg": 1, "base": [1, 2, 4], "object": 1, "leverag": 1, "attribut": 1, "The": [1, 2], "__init__": 1, "none": 1, "initi": 1, "option": 1, "addit": 1, "argument": 1, "keyword": 1, "e": 1, "g": [1, 2], "devic": 1, "us": [1, 2, 4], "If": [1, 2], "cuda": 1, "rais": [1, 2], "valueerror": 1, "type": [1, 2], "__repr__": [1, 2], "str": 1, "return": [1, 2], "repr": 1, "self": 1, "segment": 1, "between": 1, "specifi": 1, "time": 1, "second": 1, "classmethod": 1, "creat": [1, 2], "an": [1, 2], "instanc": 1, "contain": [1, 2, 4], "static": 1, "load_audio": 1, "open": 1, "read": [1, 2], "mono": 1, "resampl": 1, "necessari": 1, "ensur": 1, "compat": 1, "pyannot": 1, "requir": 1, "ffmpeg": 1, "cli": 1, "desir": 1, "tupl": [1, 2], "A": [1, 2], "numpi": 1, "arrai": 1, "float32": 1, "dtype": 1, "runtimeerror": 1, "fail": 1, "serv": 1, "core": 1, "transcript": [1, 4], "system": 1, "respons": 1, "diariz": [1, 4], "pretrain": 1, "model": [1, 4], "speech": [1, 4], "text": [1, 4], "whisper": 1, "speaker": [1, 4], "access": 1, "interfac": [1, 2, 4], "task": 1, "separ": 1, "timestamp": 1, "By": 1, "encapsul": 1, "complex": 1, "underli": 1, "allow": 1, "straightforward": 1, "integr": 1, "variou": 1, "applic": 1, "rang": 1, "servic": 1, "voic": 1, "assist": 1, "main": 1, "perform": 1, "format": [1, 2], "output": 1, "import": 1, "whisper_model": 1, "dia_model": 1, "union": 1, "bool": 1, "diarisationtyp": 1, "incorpor": 1, "comprehens": 1, "appropri": 1, "remove_audio_fil": 1, "remov": 1, "origin": [1, 2], "avoid": 1, "disk": 1, "space": 1, "issu": 1, "data": 1, "privaci": 1, "get_audio_fil": 1, "get": 1, "itself": 1, "diarisation_model": 1, "audio_fil": 1, "ndarrai": 1, "torchaudioprocessor": 1, "repres": 1, "posit": [1, 2], "shred": 1, "fals": 1, "audio_file_path": 1, "true": 1, "just": 1, "remove_origin": 1, "after": 1, "which": [1, 2], "can": [1, 2], "export": 1, "differ": 1, "command": 1, "line": 1, "user": 1, "interact": 1, "other": [1, 2], "execut": 1, "friendli": 1, "wai": [1, 2], "heart": 1, "identifi": 1, "individu": 1, "given": 1, "token_path": 1, "token": 1, "pyannote_default_path": 1, "pyannote_default_config": 1, "configur": 1, "load_model": 1, "config": 1, "yaml": 1, "diarisation_output": 1, "determin": 1, "who": 1, "spoke": 1, "when": [1, 2], "dict": 1, "annot": 1, "effect": 1, "each": 1, "dictionari": 1, "name": [1, 2], "inform": 1, "relat": 1, "format_diarization_output": 1, "dia": 1, "raw": 1, "more": 1, "usabl": 1, "structur": 1, "project": 1, "represent": [1, 2], "kei": 1, "list": [1, 2], "valu": 1, "home": 1, "ortizcruzc": 1, "cach": 1, "cache_token": 1, "cache_dir": 1, "hparams_fil": 1, "pipelin": 1, "either": 1, "local": 1, "onlin": 1, "repositori": 1, "speaker_diar": 1, "huggingface_token": 1, "authent": 1, "whether": [1, 2], "futur": 1, "directori": 1, "hyperparamet": 1, "config_diarization_yaml": 1, "file_path": 1, "path_to_segment": 1, "updat": 1, "offlin": 1, "manual": 1, "manipul": 1, "filenotfounderror": 1, "found": 1, "tool": [1, 4], "work": 1, "save": 1, "act": 1, "simplifi": 1, "featur": 1, "size": [1, 2], "nparrai": 1, "adapt": 1, "languag": 1, "specif": 1, "control": 1, "verbos": 1, "whisper_default_path": 1, "download": 1, "your_packag": 1, "medium": 1, "save_transcript": 1, "txt": 1, "wrapper": 1, "around": 1, "intricaci": 1, "easi": 1, "_get_whisper_kwarg": 1, "privat": 1, "valid": 1, "exampl": 1, "note": 1, "support": [1, 2], "pleas": 1, "refer": 1, "download_root": 1, "in_memori": 1, "tini": 1, "en": 1, "small": [1, 2], "larg": 1, "v1": 1, "v2": 1, "memori": 1, "save_path": 1, "string": [1, 2], "store": 1, "json": 1, "html": 1, "latex": 1, "should": 1, "correspond": 1, "id": 1, "descript": 1, "__str__": 1, "convert": [1, 2], "stamp": 1, "associ": [1, 2], "These": 1, "map": 1, "sequenti": 1, "number": [1, 2], "doe": [1, 2], "match": 1, "unknown": 1, "get_dict": 1, "get_html": 1, "get_json": 1, "rtype": 1, "get_md": 1, "markdown": 1, "get_tex": 1, "ar": 1, "present": 1, "first": 1, "letter": 1, "alphabet": 1, "md": 1, "tex": 1, "pdf": 1, "extens": 1, "pass": 1, "to_html": 1, "paramet": 1, "to_json": 1, "to_md": 1, "to_pdf": 1, "placehold": 1, "implement": 1, "need": [1, 2], "to_tex": 1, "to_txt": 1, "get_vers": 1, "build_vers": 1, "git_vers": 1, "modifi": 2, "version": [2, 5], "http": 2, "github": 2, "com": 2, "danielgtaylor": 2, "tree": 2, "master": 2, "all": 2, "credit": 2, "goe": 2, "author": 2, "copyright": 2, "c": 2, "2008": 2, "2013": 2, "daniel": 2, "taylor": 2, "dan": 2, "programm": 2, "art": 2, "org": 2, "permiss": 2, "herebi": 2, "grant": 2, "free": 2, "charg": 2, "ani": 2, "person": 2, "obtain": 2, "copi": 2, "softwar": 2, "document": 2, "deal": 2, "without": 2, "restrict": 2, "limit": 2, "right": 2, "merg": 2, "publish": 2, "distribut": 2, "sublicens": 2, "sell": 2, "permit": 2, "whom": 2, "furnish": 2, "do": 2, "so": 2, "subject": 2, "follow": 2, "condit": 2, "abov": 2, "notic": 2, "shall": 2, "substanti": 2, "portion": 2, "THE": 2, "IS": 2, "AS": 2, "warranti": 2, "OF": 2, "kind": 2, "express": 2, "OR": 2, "impli": 2, "BUT": 2, "NOT": 2, "TO": 2, "merchant": 2, "fit": 2, "FOR": 2, "particular": 2, "purpos": 2, "AND": 2, "noninfring": 2, "IN": 2, "NO": 2, "event": 2, "holder": 2, "BE": 2, "liabl": 2, "claim": 2, "damag": 2, "liabil": 2, "action": 2, "contract": 2, "tort": 2, "otherwis": 2, "aris": 2, "out": 2, "connect": 2, "WITH": 2, "class": [2, 5], "atom": 2, "nice": 2, "alia": 2, "field": 2, "2": 2, "except": 2, "faststartexcept": 2, "someth": 2, "bad": 2, "happen": 2, "dure": 2, "faststartsetuperror": 2, "rasis": 2, "ask": 2, "malformedfileerror": 2, "input": 2, "setup": [2, 4, 5], "unexpect": 2, "unsupportedformaterror": 2, "movi": 2, "recogn": 2, "find_atom": 2, "datastream": 2, "compatibilti": 2, "_find_atoms_ex": 2, "get_chunk": 2, "stream": 2, "chunk_siz": 2, "get_index": 2, "index": [2, 4], "top": 2, "level": 2, "absolut": 2, "byte": 2, "ftyp": 2, "24": 2, "moov": 2, "25": 2, "2658": 2, "2683": 2, "8": 2, "element": 2, "order": 2, "thei": 2, "appear": 2, "infilenam": 2, "inf": 2, "quicktim": 2, "mp4": 2, "move": 2, "metadata": 2, "front": 2, "write": 2, "new": 2, "set": 2, "than": 2, "zero": 2, "veri": 2, "full": 2, "header": 2, "bug": 2, "report": 2, "read_atom": 2, "where": 2, "alreadi": 2, "fourcc": 2, "like": 2, "modul": [4, 5], "search": 4, "page": 4, "packag": [4, 5], "subpackag": 5, "submodul": 5, "audio": 5, "processor": 5, "autotranscrib": 5, "diaris": 5, "misc": 5, "transcrib": [4, 5], "transcript_export": 5, "gradio_app": [4, 5], "test_autotranscript": [4, 5], "fulli": 4, "autom": 4, "ai": 4, "pytorch": 4, "gener": 4}, "objects": {"": [[0, 0, 0, "-", "app"], [1, 0, 0, "-", "autotranscript"]], "app": [[0, 1, 1, "", "parse_contents"], [0, 1, 1, "", "update_output"]], "autotranscript": [[2, 0, 0, "-", "app"], [1, 0, 0, "-", "audio"], [1, 0, 0, "-", "autotranscript"], [1, 0, 0, "-", "diarisation"], [1, 0, 0, "-", "misc"], [1, 0, 0, "-", "transcriber"], [1, 0, 0, "-", "transcript_exporter"], [1, 0, 0, "-", "version"]], "autotranscript.app": [[2, 0, 0, "-", "qtfaststart"]], "autotranscript.app.qtfaststart": [[2, 2, 1, "", "Atom"], [2, 5, 1, "", "FastStartException"], [2, 5, 1, "", "FastStartSetupError"], [2, 5, 1, "", "MalformedFileError"], [2, 5, 1, "", "UnsupportedFormatError"], [2, 1, 1, "", "find_atoms"], [2, 1, 1, "", "get_chunks"], [2, 1, 1, "", "get_index"], [2, 1, 1, "", "process"], [2, 1, 1, "", "read_atom"]], "autotranscript.app.qtfaststart.Atom": [[2, 3, 1, "", "__repr__"], [2, 4, 1, "", "name"], [2, 4, 1, "", "position"], [2, 4, 1, "", "size"]], "autotranscript.audio": [[1, 2, 1, "", "AudioProcessor"]], "autotranscript.audio.AudioProcessor": [[1, 3, 1, "", "__init__"], [1, 3, 1, "", "__repr__"], [1, 3, 1, "", "cut"], [1, 3, 1, "", "from_file"], [1, 3, 1, "", "load_audio"]], "autotranscript.autotranscript": [[1, 2, 1, "", "AutoTranscribe"], [1, 1, 1, "", "cli"]], "autotranscript.autotranscript.AutoTranscribe": [[1, 3, 1, "", "__init__"], [1, 3, 1, "", "get_audio_file"], [1, 3, 1, "", "remove_audio_file"], [1, 3, 1, "", "transcribe"]], "autotranscript.diarisation": [[1, 2, 1, "", "Diariser"]], "autotranscript.diarisation.Diariser": [[1, 3, 1, "", "__init__"], [1, 3, 1, "", "__repr__"], [1, 3, 1, "", "diarization"], [1, 3, 1, "", "format_diarization_output"], [1, 3, 1, "", "load_model"]], "autotranscript.misc": [[1, 1, 1, "", "config_diarization_yaml"]], "autotranscript.transcriber": [[1, 2, 1, "", "Transcriber"]], "autotranscript.transcriber.Transcriber": [[1, 3, 1, "", "__init__"], [1, 3, 1, "", "__repr__"], [1, 3, 1, "", "load_model"], [1, 3, 1, "", "save_transcript"], [1, 3, 1, "", "transcribe"]], "autotranscript.transcript_exporter": [[1, 2, 1, "", "Transcript"]], "autotranscript.transcript_exporter.Transcript": [[1, 3, 1, "", "__init__"], [1, 3, 1, "", "__repr__"], [1, 3, 1, "", "__str__"], [1, 3, 1, "", "annotate"], [1, 3, 1, "", "get_dict"], [1, 3, 1, "", "get_html"], [1, 3, 1, "", "get_json"], [1, 3, 1, "", "get_md"], [1, 3, 1, "", "get_tex"], [1, 3, 1, "", "save"], [1, 3, 1, "", "to_html"], [1, 3, 1, "", "to_json"], [1, 3, 1, "", "to_md"], [1, 3, 1, "", "to_pdf"], [1, 3, 1, "", "to_tex"], [1, 3, 1, "", "to_txt"]], "autotranscript.version": [[1, 1, 1, "", "get_version"], [1, 1, 1, "", "git_version"]]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:class", "3": "py:method", "4": "py:attribute", "5": "py:exception"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "class", "Python class"], "3": ["py", "method", "Python method"], "4": ["py", "attribute", "Python attribute"], "5": ["py", "exception", "Python exception"]}, "titleterms": {"app": [0, 2], "modul": [0, 1, 2, 3, 6, 7, 8], "autotranscript": [1, 2, 4, 5], "packag": [1, 2], "subpackag": 1, "submodul": [1, 2], "audio": 1, "processor": 1, "autotranscrib": 1, "class": 1, "diaris": 1, "misc": 1, "transcrib": [1, 8], "transcript_export": 1, "version": 1, "content": [1, 2, 4], "qtfaststart": 2, "gradio_app": 3, "welcom": 4, "s": 4, "document": 4, "indic": 4, "tabl": 4, "setup": 6, "test_autotranscript": 7}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 6, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 56}}) \ No newline at end of file diff --git a/docs/_build/html/setup.html b/docs/_build/html/setup.html deleted file mode 100644 index 0761842..0000000 --- a/docs/_build/html/setup.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - setup module — AutoTranscript documentation - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

setup module

-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/docs/_build/html/test_autotranscript.html b/docs/_build/html/test_autotranscript.html deleted file mode 100644 index 1aedcf1..0000000 --- a/docs/_build/html/test_autotranscript.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - test_autotranscript module — AutoTranscript documentation - - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

test_autotranscript module

-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/docs/_build/html/transcribe.html b/docs/_build/html/transcribe.html deleted file mode 100644 index 2d979f2..0000000 --- a/docs/_build/html/transcribe.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - transcribe module — AutoTranscript documentation - - - - - - - - - - - - - - - - - - - -
-
-
- - -
- -
-

transcribe module

-
- - -
- -
-
- -
-
- - - - - - - \ No newline at end of file diff --git a/docs/app.rst b/docs/app.rst deleted file mode 100644 index ceb7f40..0000000 --- a/docs/app.rst +++ /dev/null @@ -1,7 +0,0 @@ -app module -========== - -.. automodule:: app - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/autotranscript.app.rst b/docs/autotranscript.app.rst deleted file mode 100644 index ee68a6f..0000000 --- a/docs/autotranscript.app.rst +++ /dev/null @@ -1,21 +0,0 @@ -autotranscript.app package -========================== - -Submodules ----------- - -autotranscript.app.qtfaststart module -------------------------------------- - -.. automodule:: autotranscript.app.qtfaststart - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: autotranscript.app - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/autotranscript.rst b/docs/autotranscript.rst deleted file mode 100644 index 5ba3195..0000000 --- a/docs/autotranscript.rst +++ /dev/null @@ -1,77 +0,0 @@ -autotranscript package -====================== - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - autotranscript.app - -Submodules ----------- - -autotranscript.audio module ---------------------------- - -.. automodule:: autotranscript.audio - :members: - :undoc-members: - :show-inheritance: - -autotranscript.autotranscript module ------------------------------------- - -.. automodule:: autotranscript.autotranscript - :members: - :undoc-members: - :show-inheritance: - -autotranscript.diarisation module ---------------------------------- - -.. automodule:: autotranscript.diarisation - :members: - :undoc-members: - :show-inheritance: - -autotranscript.misc module --------------------------- - -.. automodule:: autotranscript.misc - :members: - :undoc-members: - :show-inheritance: - -autotranscript.transcriber module ---------------------------------- - -.. automodule:: autotranscript.transcriber - :members: - :undoc-members: - :show-inheritance: - -autotranscript.transcript\_exporter module ------------------------------------------- - -.. automodule:: autotranscript.transcript_exporter - :members: - :undoc-members: - :show-inheritance: - -autotranscript.version module ------------------------------ - -.. automodule:: autotranscript.version - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: autotranscript - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index 61d9ec0..0000000 --- a/docs/conf.py +++ /dev/null @@ -1,69 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -import os -import sys -sys.path.insert(0, os.path.abspath('../autotranscript')) - - -# -- Project information ----------------------------------------------------- - -project = 'AutoTranscript' -copyright = '2023, Jacob Schmieder' -author = 'Jacob Schmieder' - - -# -- General configuration --------------------------------------------------- - -# Mock unavailable library modules -autodoc_mock_imports = ["dash", "torch", "pytest", "numpy", "tqdm", "pyannote", "yaml", "whisper"] - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.autodoc', -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - -# Disable prepending module names -add_module_names = False - -# Document __init__, __repr__, and __str__ methods -def skip(app, what, name, obj, would_skip, options): - if name in ("__init__", "__repr__", "__str__"): - return False - return would_skip -def setup(app): - app.connect("autodoc-skip-member", skip) - - - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'alabaster' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] diff --git a/docs/gradio_app.rst b/docs/gradio_app.rst deleted file mode 100644 index bafaed0..0000000 --- a/docs/gradio_app.rst +++ /dev/null @@ -1,7 +0,0 @@ -gradio\_app module -================== - -.. automodule:: gradio_app - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index 0033a97..0000000 --- a/docs/index.rst +++ /dev/null @@ -1,27 +0,0 @@ -.. AutoTranscript documentation master file, created by - sphinx-quickstart on Thu Aug 31 08:17:31 2023. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to AutoTranscript's documentation! -========================================== - -`AutoTranscript`: Fully Automated Transcription using AI - -`AutoTranscript` is a PyTorch based interface speech-to-text tool to generate fully automated transcriptions. AutoTranscript uses AI models containing speaker diarization models: - - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - modules - - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index 32bb245..0000000 --- a/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=. -set BUILDDIR=_build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/docs/modules.rst b/docs/modules.rst deleted file mode 100644 index b1fd70c..0000000 --- a/docs/modules.rst +++ /dev/null @@ -1,12 +0,0 @@ -autotranscript -============== - -.. toctree:: - :maxdepth: 4 - - app - autotranscript - gradio_app - setup - test_autotranscript - transcribe diff --git a/docs/setup.rst b/docs/setup.rst deleted file mode 100644 index 552eb49..0000000 --- a/docs/setup.rst +++ /dev/null @@ -1,7 +0,0 @@ -setup module -============ - -.. automodule:: setup - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/test_autotranscript.rst b/docs/test_autotranscript.rst deleted file mode 100644 index 6bf3220..0000000 --- a/docs/test_autotranscript.rst +++ /dev/null @@ -1,7 +0,0 @@ -test\_autotranscript module -=========================== - -.. automodule:: test_autotranscript - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/transcribe.rst b/docs/transcribe.rst deleted file mode 100644 index d03031f..0000000 --- a/docs/transcribe.rst +++ /dev/null @@ -1,7 +0,0 @@ -transcribe module -================= - -.. automodule:: transcribe - :members: - :undoc-members: - :show-inheritance: From 6b315917c308bf1c62a5ed18521e74d073dae3aa Mon Sep 17 00:00:00 2001 From: ortizcruz Date: Fri, 22 Sep 2023 15:42:59 +0200 Subject: [PATCH 11/18] readme update --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5c86a1b..34862b1 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,19 @@ model = AutoTranscribe() text = model.transcribe("audio.wav") print(f"Transcription: \n{text}") +``` +To have advanced control of the usage you can use the following options: + +- Number of speakers in the file: `num_speakers` +- Specify the language: `language`, +- Task to process :`task` + +For example ``` +text = model.transcribe("audio.wav", language="german", task="transcribe") +``` + Refer to [whisper](https://github.com/openai/whisper) and [payannote-audio](https://github.com/pyannote/pyannote-audio) for further options. @@ -64,7 +75,7 @@ Refer to [whisper](https://github.com/openai/whisper) and [payannote-audio](http You can also run ScrAIbe in a [Gradio App](https://github.com/gradio-app/gradio) interface using the following command-line: - scraibe audio.wav + scraibe --audio-files "audio.wav" --port 7860 --hf-token "your personal Hugging Face token" --server-name "name of the server" --task "translate" Some example of important functionalities are: @@ -72,10 +83,8 @@ Some example of important functionalities are: - `--hf-token`: Personal `Hugging Face` token. - `--server-name`: Name of the Web Server. If empty 127.0.0.1 or 0.0.0.0 will be used. - `--port`: To run the Gradio app. The default is 7860. - - `--whisper-model-name`: Name of the [whisper](https://github.com/openai/whisper) model to be used. Default is `medium`. - Run the following to view all available options: scraibe -h From 882287996a24ca98bc740cfe600834516131c783 Mon Sep 17 00:00:00 2001 From: Jaikinator Date: Fri, 22 Sep 2023 16:17:32 +0200 Subject: [PATCH 12/18] make project relaease ready --- setup.cfg | 31 +++++++++++ setup.py | 16 +++++- test_autotranscript.py | 120 ----------------------------------------- 3 files changed, 46 insertions(+), 121 deletions(-) create mode 100644 setup.cfg delete mode 100644 test_autotranscript.py diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..0b40e31 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,31 @@ +[metadata] +name = scraibe +version = attr: scraibe.__version__ +author = Jacob Schmieder +author_email = Jacob.Schmieder@dbfz.de +description = My package description +long_description = file: README.md, LICENSE +platforms = Linux +keywords = transcription speech recognition whisper pyannote audio speech-to-text speech-to-text transcription speech-to-text recognition voice-to-speech +license = GPL-3.0 +classifiers = + Development Status :: 3 - Alpha + Environment :: GPU :: NVIDIA CUDA :: 11.2 + License :: OSI Approved :: Open Software License 3.0 (OSL-3.0) + Topic :: Scientific/Engineering :: Artificial Intelligence + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + +[options] +zip_safe = False +include_package_data = True +packages = find: +python_requires = >=3.7 +install_requires = + requests + importlib-metadata; python_version<"3.8" + +[options.entry_points] +console_scripts = + executable-name = scraibe.cli:cli diff --git a/setup.py b/setup.py index 6efaf3b..1b9570d 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,4 @@ +from calendar import c import pkg_resources import os from setuptools import setup, find_packages @@ -36,11 +37,24 @@ if __name__ == "__main__": 'https://download.pytorch.org/whl/cu113', ], url= github_url, - license='', + + license='GPL-3', author='Jacob Schmieder', author_email='Jacob.Schmieder@dbfz.de', description='Transcription tool for audio files based on Whisper and Pyannote', + classifiers=[ + 'Development Status :: 3 - Alpha', + 'Environment :: GPU :: NVIDIA CUDA :: 11.2', + 'License :: OSI Approved :: Open Software License 3.0 (OSL-3.0)', + 'Topic :: Scientific/Engineering :: Artificial Intelligence', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10'], + keywords = ['transcription', 'speech recognition', 'whisper', 'pyannote', 'audio', + 'speech-to-text', 'speech-to-text transcription', 'speech-to-text recognition', + 'voice-to-speech'], package_data={ "header" : ["app/header.html"], "logo" : ["app/Logo_KIDA_bmel_green.svg"]}, entry_points={'console_scripts': ['scraibe = scraibe.cli:cli']} + ) diff --git a/test_autotranscript.py b/test_autotranscript.py deleted file mode 100644 index 475f4de..0000000 --- a/test_autotranscript.py +++ /dev/null @@ -1,120 +0,0 @@ -import pytest -from scraibe import Transcriber -from unittest.mock import patch, mock_open -import os - -def test_load_pyannote_model(): - """ - Test load_pyannote_test - """ - from pyannote.audio.pipelines.speaker_diarization import SpeakerDiarization - from pyannote.audio import Pipeline - - pipeline = Pipeline.from_pretrained("models/pyannote/speaker_diarization/config.yaml") - assert isinstance(pipeline, SpeakerDiarization) - -# Test Transcribtion class - - -@pytest.fixture -def transcriber(): - """ - Prepare Transcriber for testing - Returns: Transcriber Object - """ - - return Transcriber.load_model("medium", local=True) - - -def test_Transcriber_init(transcriber): - """ - Test Transcriber initialization with a whisper model - """ - - assert isinstance(transcriber, Transcriber) - -def test_transcription(transcriber): - """ - Test transcription - """ - - transcript = transcriber.transcribe("tests/test.wav") - assert isinstance(transcript, str) - -def test_save_transcript_to_file(transcriber): - """ - Test save_transcript_to_file - """ - transcript = transcriber.transcribe("tests/test.wav") - - Transcriber.save_transcript(transcript, "tests/output.txt") - - assert os.path.exists("tests/output.txt") - - os.remove("tests/output.txt") - -# Test Diaraization class - -from scraibe import Diariser - -@pytest.fixture -def diarisation(): - """ - Prepare Diarisation for testing - Returns: Diarisation Object - """ - - return Diariser.load_model("models/pyannote/speaker_diarization/config.yaml", local=True) - -def test_Diarisation_init(diarisation): - """ - Test Diarisation initialization with a pyannote model - """ - - assert isinstance(diarisation, Diariser) - -def test_diarisation(diarisation): - """ - Test diarisation - """ - - diarisation = diarisation.diarization("tests/test.wav") - assert isinstance(diarisation, dict) - -# Test AudioProcessor - -from scraibe import AudioProcessor , TorchAudioProcessor - - -def test_AudioProcessor_init(): - """ - Test AudioProcessor initialization - """ - audio = AudioProcessor("tests/test.wav") - assert isinstance(audio, AudioProcessor) - -def test_AudioProcessor_convert(): - """ - Test AudioProcessor convert - """ - audio = AudioProcessor("tests/test.wav") - audio.convert_audio("tests/test.mp3", format="mp3") - assert os.path.exists("tests/test.mp3") - -def test_TorchAudioProcessor_from_file(): - """ - Test TorchAudioProcessor initialization - """ - audio = TorchAudioProcessor.from_file("tests/test.wav") - - assert isinstance(audio, TorchAudioProcessor) - - os.remove("tests/test.mp3") - - -def test_TorchAudioProcessor_from_ffmpeg(): - """ - Test TorchAudioProcessor initialization - """ - audio = TorchAudioProcessor.from_ffmpeg("tests/test.wav") - assert isinstance(audio, TorchAudioProcessor) From 9c6d183c890c9462e273a328206c7e3d31075b3e Mon Sep 17 00:00:00 2001 From: Jaikinator Date: Fri, 22 Sep 2023 18:07:21 +0200 Subject: [PATCH 13/18] updated readme --- Pictures/gradio_app.png | Bin 0 -> 134500 bytes README.md | 126 ++++++++++++++++++++++++++-------------- 2 files changed, 84 insertions(+), 42 deletions(-) create mode 100644 Pictures/gradio_app.png diff --git a/Pictures/gradio_app.png b/Pictures/gradio_app.png new file mode 100644 index 0000000000000000000000000000000000000000..7060598d5991c80a3aee48150d05674ac5763268 GIT binary patch literal 134500 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

mvmKe1lgJQz1- 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 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 34862b1..3876588 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ Designed as a comprehensive AI toolkit, it uses multiple AI models: - [whisper](https://github.com/openai/whisper): A general-purpose speech recognition model. - [payannote-audio](https://github.com/pyannote/pyannote-audio): An open-source toolkit for speaker diarization. -The framework utilizes a PyanNet-inspired pipeline with the `Pyannote` library for speaker diarization and `VoxCeleb` for speaker embedding. +The framework utilizes a PyanNet-inspired pipeline, with the `Pyannote` library for speaker diarization and `VoxCeleb` for speaker embedding. -During post-diarization, each audio segment is processed by the OpenAI `Whisper` model, in a transformer encoder-decoder structure. Initially, a CNN mitigates noise and enhances speech. Before transcription, `VoxLingua` dentifies the language segment, facilitating Whisper's role in both transcription and text translation. +During post-diarization, each audio segment is processed by the OpenAI `Whisper` model, in a transformer encoder-decoder structure. Initially, a CNN mitigates noise and enhances speech. Before transcription, `VoxLingua` identifies the language segment, facilitating Whisper's role in both transcription and text translation. -The following graphic illustates the whole pipeline: +The following graphic illustrates the whole pipeline: ![Pipeline](Pictures/pipeline.png#gh-dark-mode-only) ![Pipeline](Pictures/pipeline_light.png#gh-light-mode-only) @@ -23,14 +23,14 @@ The following graphic illustates the whole pipeline: The following command will pull and install the latest commit from this repository, along with its Python dependencies. - pip install git+https://github.com/JSchmie/autotranscript.git + pip install scraibe - **Python version**: Python 3.8 - **PyTorch version**: Python 1.11.0 - **CUDA version**: Cuda-toolkit 11.3.1 -Important: For the `Pyannote` model you need to be granted access in Hugging Face. +Important: For the `Pyannote` model, you need to be granted access to Hugging Face. Check the [Pyannote model page](https://huggingface.co/pyannote/speaker-diarization) to get access to the model. Additionally, you need to generate a [Hugging Face token](https://huggingface.co/docs/hub/security-tokens). @@ -41,87 +41,128 @@ We've developed ScrAIbe with several access points to cater to diverse user need ### Python usage -It enables full control over the functionalities as well as process customization. - -Some usage examples: - -- Usage of `AutoTranscribe`, core of the transcription system, for performing trancription and diarization of audio files. +It enables full control over the functionalities as well as process customization. ```python -from scraibe import AutoTranscribe +from scraibe import Scraibe -model = AutoTranscribe() +model = Scraibe(use_auth_token = "hf_yourhftoken") -text = model.transcribe("audio.wav") +text = model.autotranscribe("audio.wav") print(f"Transcription: \n{text}") ``` -To have advanced control of the usage you can use the following options: +The `Scraibe` Class is taking care of the models being properly loaded. Therefore, you can choose the other [whisper](https://github.com/openai/whisper/blob/main/model-card.md) models using the `whisper_model` keyword. +You can also change the `pyannote` diarization model using the `dia_model` keyword. -- Number of speakers in the file: `num_speakers` -- Specify the language: `language`, -- Task to process :`task` -For example +As input, `autoranscribe` accepts every format which is compatible with [ffmgeg](https://ffmpeg.org/ffmpeg-formats.html). Examples therefore are `.mp4 .mp3 .wav .ogg .flac` and many more. + +To further control the pipeline of `ScrAIbe` you can parse almost any keyword you also cloud parsed towards `whisper` or `pyannote` if you need more option, try to check out the documentations tows two Frameworks, you might have a good chance that these keywords will work here as well. +Here's are some examples regarding the `diarization` (which relies on the `pyannote` pipeline): + +- `num_speakers` Number of speakers in the audio file +- `min_speakers` Minimal Number of speakers in the audio file +- `max_speakers` maximal Number of speakers in the audio file + +Then there are arguments about the transcription process, which uses the "whisper" model. + +- `language` Specify the language ([list to supported languages](https://github.com/openai/whisper/blob/main/language-breakdown.svg)) +- `task` can be just `transcribe` or `translate`. If `translate` is selected, the transcribed audio will be translated to English. + +For example: ``` -text = model.transcribe("audio.wav", language="german", task="transcribe") +text = model.autotranscribe("audio.wav", language="german", num_speakers = 2) ``` +`Scraibe` also contains the option to just do a transcription +```python +transcription = model.transcribe("audio.wav") +``` +or just do a diarization: -Refer to [whisper](https://github.com/openai/whisper) and [payannote-audio](https://github.com/pyannote/pyannote-audio) for further options. +```python +diarization = model.diarize("audio.wav") +``` ### Command-line usage -You can also run ScrAIbe in a [Gradio App](https://github.com/gradio-app/gradio) interface using the following command-line: +Next to the Pyhton interface, you can also run ScrAIbe using the command-line interface: - scraibe --audio-files "audio.wav" --port 7860 --hf-token "your personal Hugging Face token" --server-name "name of the server" --task "translate" + scraibe -f "audio.wav" --hf-token "hf_yourhftoken" --language "german" --num_speakers 2 -Some example of important functionalities are: +For the full list of options, run: -- `--task`: Task to be performed, either transcription, diarization or translation into English. Default is transcription. -- `--hf-token`: Personal `Hugging Face` token. -- `--server-name`: Name of the Web Server. If empty 127.0.0.1 or 0.0.0.0 will be used. -- `--port`: To run the Gradio app. The default is 7860. -- `--whisper-model-name`: Name of the [whisper](https://github.com/openai/whisper) model to be used. Default is `medium`. + scraibe -h + +### Gradio App + +The Gradio App is a user-friendly interface for ScrAIbe. It enables you to run the model without any coding knowledge. Therefore, you can run the app in your browser and upload your audio file, or you can make the Framework avail on your network and run it on your local machine. + +#### Running the Gradio App on your local machine + +To run the Gradio App on your local machine, just use the following command: + +``` +scraibe --start_server --port 7860 --hf_token hf_yourhftoken +``` + +- `--start_server`: Command to start the Gradio App. +- `--port`: Flag for connecting the container internal port to the port on your local machine. +- `--hf_token`: Flag for entering your personal HuggingFace token in the container. + +When the app is running, it will show you at which address you can access it. +The default address is: http://127.0.0.1:7860 or http://0.0.0.0:7860 + +After the app is running, you can upload your audio file and select the desired options. +An example is shown below: + +![Gradio App](Pictures/gradio_app.png) -Run the following to view all available options: - - scraibe -h ### Running a Docker container +Another option to run ScrAIbe is to use a Docker container. This option is especially useful if you want to run the model on a server or if you would like to use the GPU without dealing with CUDA. After you have installed Docker, you can execute the following commands in the terminal. -``` -sudo docker build . --build-arg="hf_token=[enter your HuggingFace token] " -t [image name] +First, you need to build the Docker image. Therefore, you need to enter your HuggingFace token and the image name. +``` +docker build . --build-arg="hf_token=[enter your HuggingFace token] " -t scraibe +``` + +After the image is built, you can run the container with the following command: + +``` sudo docker run -it -p 7860:7860 --name [container name][image name] --hf_token [enter your HuggingFace token] --start_server ``` -- `-p`: Flag for connecting the container interal port to the port on your local machine. +- `-p`: Flag for connecting the container internal port to the port on your local machine. - `--hf_token`: Flag for entering your personal HuggingFace token in the container. - `--start_server`: Command to start the Gradio App. -Then click the following link to run the app: +Inside the container, the `cli` is used. Therefore, you can use the same commands as in the command-line interface. -http://0.0.0.0:7860 +#### Enabling GPU usage -- Enabling GPU usage +To use the GPU, ensure your Docker installation supports GPU usage. +For further information, check: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker +To enable GPU usage, you need to add the following flag to the `docker run` command: ``` -sudo docker run -it -p 7860:7860 --gpus 'all,capabilities=utility' --name [container name][image name] --hf_token [enter your HuggingFace token] --start_server +docker run -it -p 7860:7860 --gpus 'all,capabilities=utility' --name [container name][image name] --hf_token [enter your HuggingFace token] --start_server ``` -For further guidance check: https://blog.roboflow.com/use-the-gpu-in-docker/ +For further guidance, check: https://blog.roboflow.com/use-the-gpu-in-docker/ ## Documentation -For further insights check the [documentation page](https://cristinaortizcruz.github.io/Test/). +For further insights, check the [documentation page](). ## Contributions -We are happy for any interest in contributing and about feedback: In order to do that, create an issue with your feedback or feel free to contact us. +We are happy to have any interest in contributing and about feedback: In order to do that, create an issue with your feedback or feel free to contact us. ## Roadmap @@ -151,8 +192,9 @@ ScrAIbe is licensed under GNU General Public License. ## Acknowledgments -Special thanks go to the KIDA project and the BMEL (Bundesministerium für Ernährung und Landwirtschaft), especially to the AI Consultancy Team and the Infrastructure Team. +Special thanks go to the KIDA project and the BMEL (Bundesministerium für Ernährung und Landwirtschaft), especially to the AI Consultancy Team. ![KIDA](Pictures/kida_dark.png#gh-dark-mode-only)   ![BMEL](Pictures/BMEL_dark.png#gh-dark-mode-only)      ![DBFZ](Pictures/DBFZ_dark.png#gh-dark-mode-only)       ![MRI](Pictures/MRI.png#gh-dark-mode-only) ![KIDA](Pictures/kida.png#gh-light-mode-only)   ![BMEL](Pictures/BMEL.jpg#gh-light-mode-only)      ![DBFZ](Pictures/DBFZ.png#gh-light-mode-only)       ![MRI](Pictures/MRI.png#gh-light-mode-only) + From 30141b96164b0508129392d41f460148498d0eef Mon Sep 17 00:00:00 2001 From: Jaikinator Date: Fri, 22 Sep 2023 18:12:08 +0200 Subject: [PATCH 14/18] fixed bug where header.html was not found --- scraibe/app/gradio_app.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scraibe/app/gradio_app.py b/scraibe/app/gradio_app.py index f5126c7..fa3e8fb 100644 --- a/scraibe/app/gradio_app.py +++ b/scraibe/app/gradio_app.py @@ -33,6 +33,8 @@ Usage: """ import json +import os +from tkinter import CURRENT import gradio as gr from tqdm import tqdm @@ -60,6 +62,8 @@ LANGUAGES = [ "Vietnamese", "Welsh" ] +CURRENT_PATH = os.path.dirname(os.path.realpath(__file__)) + class GradioTranscriptionInterface: """ Interface handling the interaction between Gradio UI and the Audio Transcription system. @@ -348,7 +352,8 @@ def gradio_Interface(model : Scraibe = None): with gr.Blocks(theme=theme,title='ScrAIbe: Automatic Audio Transcription') as demo: # Define components - header = open("header.html", "r").read() + hname = os.path.join(CURRENT_PATH, "header.html") + header = open(hname, "r").read() gr.HTML(header, visible= True, show_label=False) with gr.Row(): From f267fc1041984ff295953e98dc57e3b26221f778 Mon Sep 17 00:00:00 2001 From: Jaikinator Date: Fri, 22 Sep 2023 18:14:48 +0200 Subject: [PATCH 15/18] install works --- setup.cfg | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 0b40e31..3e2cac7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,4 +28,4 @@ install_requires = [options.entry_points] console_scripts = - executable-name = scraibe.cli:cli + executable-name = scraibe.cli:cli \ No newline at end of file diff --git a/setup.py b/setup.py index 1b9570d..98d178e 100644 --- a/setup.py +++ b/setup.py @@ -53,7 +53,7 @@ if __name__ == "__main__": keywords = ['transcription', 'speech recognition', 'whisper', 'pyannote', 'audio', 'speech-to-text', 'speech-to-text transcription', 'speech-to-text recognition', 'voice-to-speech'], - package_data={ "header" : ["app/header.html"], "logo" : ["app/Logo_KIDA_bmel_green.svg"]}, + package_data={'scraibe.app' : ["*.html", "*.svg"]}, entry_points={'console_scripts': ['scraibe = scraibe.cli:cli']} From 00fba653f2a70d461c87b01cb4fa953042138aae Mon Sep 17 00:00:00 2001 From: Jacob Schmieder Date: Fri, 22 Sep 2023 18:16:04 +0200 Subject: [PATCH 16/18] Delete app.py old dash version removed --- app.py | 101 --------------------------------------------------------- 1 file changed, 101 deletions(-) delete mode 100644 app.py diff --git a/app.py b/app.py deleted file mode 100644 index c9beffe..0000000 --- a/app.py +++ /dev/null @@ -1,101 +0,0 @@ -from dash import Dash, dcc, html, dash_table, Input, Output, State, callback - -import base64 -from scraibe.app.qtfaststart import process -from scraibe import AutoTranscribe -import io -import subprocess as sp -import numpy as np -from scraibe.audio import SAMPLE_RATE - -# Setup auto-transcript -autot = AutoTranscribe() # whisper_model="tiny", whisper_kwargs={"local" : False} - -# Setup FFmpeg -PROBLEMATIC_FILE_TYPES : tuple = "mov","mp4","m4a","3gp","3g2","mj2" - - -# Setup Dash -external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] - -app = Dash(__name__, external_stylesheets=external_stylesheets) - -app.layout = html.Div([ - dcc.Upload( - id='upload-data', - children=html.Div([ - 'Drag and Drop or ', - html.A('Select Files') - ]), - style={ - 'width': '100%', - 'height': '60px', - 'lineHeight': '60px', - 'borderWidth': '1px', - 'borderStyle': 'dashed', - 'borderRadius': '5px', - 'textAlign': 'center', - 'margin': '10px' - }, - # Allow multiple files to be uploaded - multiple=True - ), - html.Div(id='output-data-upload'), -]) - -def parse_contents(contents, filename, date): - content_type, content_string = contents.split(',') - - decoded = base64.b64decode(content_string) - file = io.BytesIO(decoded).read() - - if filename.endswith(PROBLEMATIC_FILE_TYPES): - # mp4 and other files need to be processed with qtfaststart - # since theire metadata is at the end of the file - # and we need it at the beginning - file = process(file) - - cmd = [ - "ffmpeg", - "-nostdin", - "-threads", "0", - "-i",'pipe:', - "-f", "s16le", - '-hide_banner', - '-loglevel', 'error', - "-c", "copy", - "-vn", - "-ac", "1", - "-acodec", "pcm_s16le", - "-ar", str(SAMPLE_RATE), - "-" - ] - - proc = sp.Popen(cmd, stdout=sp.PIPE, stdin=sp.PIPE) - - out = proc.communicate(input=file)[0] - out = np.frombuffer(out, np.int16).flatten().astype(np.float32) / 32768.0 - out = np.array([out, SAMPLE_RATE]) - - transcript = str(autot.transcribe(out)) - - return html.Div([ - html.H5(f"File Name: {filename} \n" \ - "Transcript: \n" - ), - html.P(transcript) - ]) - -@callback(Output('output-data-upload', 'children'), - Input('upload-data', 'contents'), - State('upload-data', 'filename'), - State('upload-data', 'last_modified')) -def update_output(list_of_contents, list_of_names, list_of_dates): - if list_of_contents is not None: - children = [ - parse_contents(c, n, d) for c, n, d in - zip(list_of_contents, list_of_names, list_of_dates)] - return children - -if __name__ == '__main__': - app.run_server() From 485a32cd514bdd998732fe5fc29b3ed0d9e81c94 Mon Sep 17 00:00:00 2001 From: Jacob Schmieder Date: Fri, 22 Sep 2023 18:16:46 +0200 Subject: [PATCH 17/18] Delete app2.py Identical copy of scraibe/app/gradio_app.py --- app2.py | 317 -------------------------------------------------------- 1 file changed, 317 deletions(-) delete mode 100644 app2.py diff --git a/app2.py b/app2.py deleted file mode 100644 index 55cb11b..0000000 --- a/app2.py +++ /dev/null @@ -1,317 +0,0 @@ -""" -Gradio Audio Transcription App. --------------------------------- - -This module provides an interface to transcribe audio files using the -AutoTranscribe model. Users can either upload an audio file or record their speech -live for transcription. The application supports multiple languages and provides -options to specify the number of speakers and the language of the audio. - -Attributes: - LANGUAGES (list): A list of supported languages for transcription. - -Usage: - Run this script to start the Gradio web interface for audio transcription. - -""" - - -import json - -import gradio as gr -from scraibe import AutoTranscribe, Transcript - - - -theme = gr.themes.Soft( - primary_hue="green", - secondary_hue='orange', - neutral_hue="gray", - -) -LANGUAGES = [ - "Afrikaans", "Arabic", "Armenian", "Azerbaijani", "Belarusian", - "Bosnian", "Bulgarian", "Catalan", "Chinese", "Croatian", - "Czech", "Danish", "Dutch", "English", "Estonian", - "Finnish", "French", "Galician", "German", "Greek", - "Hebrew", "Hindi", "Hungarian", "Icelandic", "Indonesian", - "Italian", "Japanese", "Kannada", "Kazakh", "Korean", - "Latvian", "Lithuanian", "Macedonian", "Malay", "Marathi", - "Maori", "Nepali", "Norwegian", "Persian", "Polish", - "Portuguese", "Romanian", "Russian", "Serbian", "Slovak", - "Slovenian", "Spanish", "Swahili", "Swedish", "Tagalog", - "Tamil", "Thai", "Turkish", "Ukrainian", "Urdu", - "Vietnamese", "Welsh" -] - -class GradioTranscriptionInterface: - """ - Interface handling the interaction between Gradio UI and the Audio Transcription system. - """ - - def __init__(self, model: AutoTranscribe = AutoTranscribe()): - """ - Initializes the GradioTranscriptionInterface with a transcription model. - - Args: - model (AutoTranscribe): Model responsible for audio transcription tasks. - """ - self.model = model - - def auto_transcribe(self, source, - num_speakers : int, - translation : bool, - language : str): - """ - Shortcut method for the AutoTranscribe task. - - Returns: - tuple: Transcribed text (str), JSON output (dict) - """ - - kwargs = { - "num_speakers": num_speakers if num_speakers != 0 else None, - "language": language if language != "None" else None, - "task": 'translate' if translation else None - } - - try: - result = self.model.autotranscribe(source, **kwargs) - except ValueError: - raise gr.Error("Couldn't detect any speech in the provided audio. \ - Please try again!") - return str(result), result.get_json() - - - def transcribe(self, source, translation, language): - """ - Shortcut method for the Transcribe task. - - Returns: - str: Transcribed text. - """ - kwargs = { - "language": language if language != "None" else None, - "task": 'translate' if translation == "Yes" else None - } - - result = self.model.transcribe(source, **kwargs) - return str(result) - - def perform_diarisation(self, source, num_speakers): - """ - Shortcut method for the Diarisation task. - - Returns: - str: JSON output of diarisation result. - """ - kwargs = { - "num_speakers": num_speakers if num_speakers != 0 else None, - } - - - try: - result = self.model.diarization(source, **kwargs) - except ValueError: - raise gr.Error("Couldn't detect any speech in the provided audio. \ - Please try again!") - return json.dumps(result, indent=2) - -#### -# Gradio Interface -#### - -pipe = GradioTranscriptionInterface() - - -def select_task(choice): - if choice == 'Auto Transcribe': - - return (gr.update(visible = True), - gr.update(visible = True), - gr.update(visible = True)) - - - elif choice == 'Transcribe': - - return (gr.update(visible = False), - gr.update(visible = True), - gr.update(visible = True)) - - - elif choice == 'Diarisation': - - return (gr.update(visible = True), - gr.update(visible = False), - gr.update(visible = False)) - -def select_origin(choice): - if choice == "Upload Audio": - - return (gr.update(visible = True), - gr.update(visible = False, value = None), - gr.update(visible = False, value = None), - gr.update(visible = False, value = None), - gr.update(visible = False, value = None)) - - elif choice == "Record Audio": - - return (gr.update(visible = False, value = None), - gr.update(visible = True), - gr.update(visible = False, value = None), - gr.update(visible = False, value = None), - gr.update(visible = False, value = None)) - - elif choice == "Upload Video": - - return (gr.update(visible = False, value = None), - gr.update(visible = False, value = None), - gr.update(visible = True), - gr.update(visible = False, value = None), - gr.update(visible = False, value = None)) - - elif choice == "Record Video": - - return (gr.update(visible = False, value = None), - gr.update(visible = False, value = None), - gr.update(visible = False, value = None), - gr.update(visible = True), - gr.update(visible = False, value = None)) - - elif choice == "File": - - return (gr.update(visible = False, value = None), - gr.update(visible = False, value = None), - gr.update(visible = False, value = None), - gr.update(visible = False, value = None), - gr.update(visible = True)) - -def run_scribe(task, num_speakers, translate, language, audio1, audio2, video1, video2, file_in, progress = gr.Progress(track_tqdm= True)): - # get *args which are not None - progress(0, desc='Starting task...') - source = audio1 or audio2 or video1 or video2 or file_in - - if task == 'Auto Transcribe': - - out_str , out_json = pipe.auto_transcribe(source = source, - num_speakers = num_speakers, - translation = translate, - language = language) - - return (gr.update(value = out_str, visible = True), - gr.update(value = out_json, visible = True), - gr.update(visible = True), - gr.update(visible = True)) - - elif task == 'Transcribe': - - out = pipe.transcribe(source = source, - translation = translate, - language = language) - - return (gr.update(value = out, visible = True), - gr.update(value = None, visible = False), - gr.update(visible = False), - gr.update(visible = False)) - - elif task == 'Diarisation': - - out = pipe.perform_diarisation(source = source, - num_speakers = num_speakers) - - return (gr.update(value = None, visible = False), - gr.update(value = out, visible = True), - gr.update(visible = False), - gr.update(visible = False)) - -def annotate_output(annoation : str, out_json : dict): - # get *args which are not None - - trans = Transcript.from_json(out_json) - trans = trans.annotate(*annoation.split(",")) - - return gr.update(value = str(trans)),gr.update(value = trans.get_json()) - - -with gr.Blocks(theme=theme,title='ScrAIbe: Automatic Audio Transcription') as demo: - - # Define components - header = open("header.html", "r").read() - gr.HTML(header, visible= True, show_label=False) - - with gr.Row(): - - with gr.Column(): - - task = gr.Radio(["Auto Transcribe", "Transcribe", "Diarisation"], label="Task", - value= 'Auto Transcribe') - - num_speakers = gr.Number(value=0, label= "Number of speakers (optional)", - info = "Number of speakers in the audio file. If you don't know,\ - leave it at 0.", visible= True) - - translate = gr.Checkbox(label="Translation", choices=[True, False], value = False, - info="Select 'Yes' to have the output translated into English.", - visible= True) - - language = gr.Dropdown(LANGUAGES, - label="Language (optional)", value = "None", - info="Language of the audio file. If you don't know,\ - leave it at None.", visible= True) - - input = gr.Radio(["Upload Audio", "Record Audio", "Upload Video","Record Video" - ,"File"], label="Input Type", value="Upload Audio") - - audio1 = gr.Audio(source="upload", type="filepath", label="Upload Audio", - interactive= True, visible= True) - audio2 = gr.Audio(source="microphone", label="Record Audio", type="filepath", - interactive= True, visible= False) - video1 = gr.Video(source="upload", type="filepath", label="Upload Video", - interactive= True, visible= False) - video2 = gr.Video(source="webcam", label="Record Video", type="filepath", - interactive= True, visible= False) - file_in = gr.File(label="Upload File", interactive= True, visible= False) - - submit = gr.Button() - - with gr.Column(): - - out_txt = gr.Textbox(label="Output", - visible= True, show_copy_button=True) - - out_json = gr.JSON(label="JSON Output", - visible= False, show_copy_button=True) - - annoation = gr.Textbox(label="Name your speaker's", - info= "Please provide a list of the speakers arranged \ - in the order in which they appear in the input. Use comma ',' \ - as a seperator. Be aware that the first name is given \ - to SPEAKER_00 the second to SPEAKER_01 and so on.", - visible= False, interactive= True) - - annotate = gr.Button(value="Annotate", visible= False, interactive= True) - - # Define usage of components - input.change(fn=select_origin, inputs=[input], - outputs=[audio1, audio2, video1, video2, file_in]) - - task.change(fn=select_task, inputs=[task], - outputs=[num_speakers, translate, language]) - - translate.change(fn= lambda x : gr.update(value = x), - inputs=[translate], outputs=[translate]) - num_speakers.change(fn= lambda x : gr.update(value = x), - inputs=[num_speakers], outputs=[num_speakers]) - language.change(fn= lambda x : gr.update(value = x), - inputs=[language], outputs=[language]) - - submit.click(fn = run_scribe, - inputs=[task, num_speakers, translate, language, audio1, - audio2, video1, video2, file_in], - outputs=[out_txt, out_json, annoation, annotate]) - - annotate.click(fn = annotate_output, inputs=[annoation, out_json], - outputs=[out_txt, out_json]) - - -demo.queue().launch() \ No newline at end of file From 064aac9c5b8dd514dacda4b22c01c63e159553ca Mon Sep 17 00:00:00 2001 From: Jacob Schmieder Date: Fri, 22 Sep 2023 18:17:20 +0200 Subject: [PATCH 18/18] Delete transcribe.py Delete due to the improved README --- transcribe.py | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 transcribe.py diff --git a/transcribe.py b/transcribe.py deleted file mode 100644 index 5a22ff3..0000000 --- a/transcribe.py +++ /dev/null @@ -1,8 +0,0 @@ - -from scraibe import Scraibe -model = Scraibe() - -text = model.autotranscocribe('kida.mp4', num_speakers=2) - -print("Transcription:\n") -print(text)