From aadc6fbc73f1ca0b93f8c406c46cdb2600bce890 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Fri, 31 Jul 2020 03:03:02 +0000 Subject: CTAN sync 202007310303 --- macros/latex/contrib/ltx4yt/ltx4yt.dtx | 651 +++++++++++++++++++++++++++++++++ 1 file changed, 651 insertions(+) create mode 100644 macros/latex/contrib/ltx4yt/ltx4yt.dtx (limited to 'macros/latex/contrib/ltx4yt/ltx4yt.dtx') diff --git a/macros/latex/contrib/ltx4yt/ltx4yt.dtx b/macros/latex/contrib/ltx4yt/ltx4yt.dtx new file mode 100644 index 0000000000..ef6356d9ff --- /dev/null +++ b/macros/latex/contrib/ltx4yt/ltx4yt.dtx @@ -0,0 +1,651 @@ +%\iffalse +%<*copyright> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% ltx4yt.sty package, %% +%% Copyright (C) 2020 %% +%% dpstory@uakron.edu %% +%% %% +%% This program can redistributed and/or modified under %% +%% the terms of the LaTeX Project Public License %% +%% Distributed from CTAN archives in directory %% +%% macros/latex/base/lppl.txt; either version 1 of the %% +%% License, or (at your option) any later version. %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%\NeedsTeXFormat{LaTeX2e}[1997/12/01] +%\ProvidesPackage{ltx4yt} +% [2020/07/30 v0.7 ltx4yt: Play YouTube videos in the default browser (dps)] +%<*driver> +\documentclass{ltxdoc} +\usepackage[colorlinks,hyperindex=false]{hyperref} +\hypersetup{pdfpagemode=useNone} +\usepackage{fancyvrb} +%\def\texorpdfstring#1#2{#1} +%\pdfstringdefDisableCommands{\let\\\textbackslash} +\OnlyDescription % comment out for implementation details +\EnableCrossrefs +\CodelineIndex +\RecordChanges +\InputIfFileExists{aebdocfmt.def}{\PackageInfo{ltx4yt}{Inputting aebdocfmt.def}} + {\def\IndexOpt{\DescribeMacro}\def\IndexKey{\DescribeMacro}\let\setupFullwidth\relax + \PackageInfo{ltx4yt}{aebdocfmt.def cannot be found}} +\EnableCrossrefs \CodelineIndex \RecordChanges +\makeatletter +\renewcommand{\paragraph} + {\@startsection{paragraph}{4}{0pt}{6pt}{-3pt} + {\normalfont\normalsize\bfseries}} +\renewenvironment{quote}[1][] + {\def\@rgi{#1}\ifx\@rgi\@empty + \let\rghtm\@empty\else\def\rghtm{\rightmargin\leftmargin}\fi + \list{}{\rghtm} %{\rightmargin\leftmargin}% + \item\relax} + {\endlist} +\makeatother +\bgroup\ttfamily +\gdef\brpr#1{\char123\relax#1\char125\relax}\egroup +\let\darg\brpr +\let\env\texttt +\let\opt\texttt +\let\app\textsf +\let\tops\texorpdfstring +\def\nmpsep#1{\hskip-\marginparsep\texttt{#1}} +\def\visispace{\symbol{32}} +\def\ameta#1{\ensuremath{\langle\textit{\texttt{#1}}\rangle}} +\def\meta#1{\textsl{\texttt{#1}}} +\def\SUB#1{\ensuremath{{}_{\mbox{\scriptsize\ttfamily#1}}}} +\def\ltag{<}\def\rtag{>} +\def\EXCL{!} +\let\app\textsf\let\pkg\textsf +\begin{document} + \GetFileInfo{ltx4yt.sty} + \title{The \textsf{ltx4yt} Package} + \author{D. P. Story\\ + Email: \texttt{dpstory@acrotex.net}} + \date{processed \today} + \maketitle + \tableofcontents + \let\Email\texttt + \DocInput{ltx4yt.dtx} +\IfFileExists{\jobname.ind}{\newpage\setupFullwidth\par\PrintIndex}{\paragraph*{Index} The index goes here.\\Execute + \texttt{makeindex -s gind.ist -o ltx4yt.ind ltx4yt.idx} on the command line and recompile + \texttt{ltx4yt.dtx}.} +\IfFileExists{\jobname.gls}{\PrintChanges}{\paragraph*{Change History} The list of changes goes here.\\Execute + \texttt{makeindex -s gglo.ist -o ltx4yt.gls ltx4yt.glo} on the command line and recompile + \texttt{ltx4yt.dtx}.} +\end{document} +% +% \fi +% \MakeShortVerb{|} +% \InputIfFileExists{aebdonotindex.def}{\PackageInfo{ltx4yt}{Inputting aebdonotindex.def}} +% {\PackageInfo{ltx4yt}{cannot find aebdonotindex.def}} +% \DoNotIndex{\g@addto@macro,\divide,\box,\setbox,\x,\y,\z} +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \section{Introduction} +% +% It is July 2020 and Adobe's support for Flash will vanish in December. Google stopped +% supporting Flash several years ago, so the package \pkg{yt4pdf} is no longer functional +% and will be withdrawn from CTAN. If we cannot play videos within PDF anymore, the next best +% course is to develop some basic commands for playing YouTube videos in the default browser, preferably +% without any annoying advertisements. This can be done for some videos, but for others it cannot be done. +% +%\changes{v0.1}{2020/07/17}{Begin new package \string\pkg{ltx4yt}} +%\changes{v0.2}{2020/07/17}{Commands to pass arguments to urls} +%\changes{v0.6}{2020/07/25}{Final version before first publication} +%\changes{v0.7}{2020/07/30}{Corrected upload} +% \begin{macrocode} +\RequirePackage{xkeyval} +% \end{macrocode} +% \leavevmode\IndexOpt{usepopup} When this option is taken, additional code to support +% the use of popup menus is input. We also support \IndexOpt[\protect\EXCL]{!usepopup}\opt{!popup}, +% which is a convenience option for not using \opt{usepopup}. +% \begin{macrocode} +\DeclareOption{usepopup}{\def\lo@dpu{\InputIfFileExists{ytpu.def} + {\PackageInfo{ltx4yt}{Loading ytpu.def}} + {\PackageInfo{ltx4yt}{Can't find ytpu.def}}}} +\DeclareOption{!usepopup}{} +\let\lo@dpu\relax +\AtEndOfPackage{\lo@dpu} +\ProcessOptions +\RequirePackage{xcolor} +\RequirePackage{eforms} +% \end{macrocode} +% If the \opt{usepopup} option is taken, we load the \pkg{popupmenu} package. +% \begin{macrocode} +\ifx\lo@dpu\relax\else +\def\YT@rpPU{\RequirePackage{popupmenu}[2020/07/26]}\expandafter +\YT@rpPU\fi +% \end{macrocode} +% +% \section{Implementation} +% +% The JavaScript method \texttt{app.launchURL\darg{\ameta{URL}}} is used to open the default browser +% on the page determined by \ameta{URL}. The links created use \cs{URI} (\texttt{/S/URI/URI}), this action type +% allows links to be functional in all PDF viewers, even on hand held devices. +% +% We have three implementations of this plan: (1)~links (\cs{ytvId} and \cs{ytLink}) for all devices; +% (2)~dropdown menus (combo boxes) (\cs{ytComboList} (uses JavaScript); +% and (3)~pop-up menus using the \env{popupmenu} environment of the \pkg{popupmenu} package (uses JavaScript). +% The methods that use JavaScript will not function in the near future on hand held devices. +% +% \subsection{Playing a YouTube video from its Video ID} +% +% In this section, we create several ways of calling for a YouTube video to play +% in the default browser. +% +% \subsubsection{Using a Link} +% \begin{macro}{\ytvIdPresets}\nmpsep{\darg{\ameta{KV-pairs}}} +% The options for the \cs{ytvId} link. The default is given below in the definition. +% Initially, the preset is to produce \texttt{webbrown} colored links. +% \begin{macrocode} +\newcommand{\ytvIdPresets}[1]{\def\yt@vIdPresets{#1}} +\definecolor{webbrown}{rgb}{.6,0,0} % from the web package +\ytvIdPresets{\linktxtcolor{webbrown}} +% \end{macrocode} +% \end{macro} +% Here is a convenience command. This definition has since been made +% in \pkg{insdljs}. +% \begin{macrocode} +\providecommand{\URI}[1]{/S/URI/URI(#1)} +% \end{macrocode} +% Define \DescribeMacro\ytURL\cs{ytURL} to expand to the YouTube web site. +% \begin{macrocode} +\def\ytNF{false} +\def\ytURL{https://www.youtube.com} +% \end{macrocode} +% \begin{macro}{\ytvId}\nmpsep{*[\ameta{opts}]\darg{\ameta{ytvID}}\darg{\ameta{text}}} +% The \cs{ytvId} is link which when pressed plays the video whose Video Id is \ameta{ytvID}) +% in the default browser. +% \begin{quote} +% \begin{itemize} +% \item[\texttt*] If the \texttt*-option is taken, you have determined that this +% video cannot be embedded (which is the ideal) and must be played normally on YouTube +% with all advertisements and other extraneous information. +% \item[{\ameta{opts}}:] link optional KV-pairs to modify the appearance of the link. +% \item[{\ameta{ytvID}}:] The video Id for the YouTube video to play +% \item[{\ameta{text}}:] The text that displays the link. +%\end{itemize} +%\end{quote} +% \begin{macrocode} +\newcommand{\ytvId}{\@ifstar{\def\yt@ask{*}\yt@@vId} + {\let\yt@ask\@empty\yt@@vId}} +\newcommand{\yt@@vId}[3][]{% + \ifx\yt@ask\@empty + \def\yt@lnk@hash{embed/#2}\else + \def\yt@lnk@hash{watch?v=#2}\fi + \setLink[\presets{\yt@vIdPresets}#1 + \A{\URI{\ytURL/\yt@lnk@hash}}]{#3}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\ytvIdML}\nmpsep{*[\ameta{opts}]\darg{\ameta{ytvID}}\darg{\ameta{text}}} +% The \cs{ytvId} is link which when pressed plays the video whose Video Id is \ameta{ytvID}) +% in the default browser. This is a multi-line link, it requires the \pkg{aeb\_mlink} package +% and the \app{dvips\,\texttt{->}\,distiller} workflow. +% \begin{macrocode} +\newcommand{\ytvIdML}{\@ifstar{\def\yt@ask{*}\yt@@vIdML} + {\let\yt@ask\@empty\yt@@vIdML}} +\newcommand{\yt@@vIdML}[3][]{% + \ifx\yt@ask\@empty + \def\yt@lnk@hash{embed/#2}\else + \def\yt@lnk@hash{watch?v=#2}\fi + \mlsetLink[\presets{\yt@vIdPresets}#1 + \A{\URI{\ytURL/\yt@lnk@hash}}]{#3}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\ytLink}\nmpsep{[\ameta{opts}]\darg{\ameta{spec}}\darg{\ameta{text}}} +% We create a custom link for youtube videos. The \ameta{spec} (specification) argument has several +% forms for maximum convenience and flexibility. +% \begin{itemize} +% \item |\ytLink{\embedId{|\ameta{ytvID}|}\params{|\ameta{parameters}|}}{|\ameta{text}|}|\\[3pt] This is the form +% for playing a video with \ameta{ytvID} that \emph{can be embedded} (this best type of video). The \cs{params} +% argument must follow the \cs{embedId}, its argument are any parameters you want to append to the URL. +% The use of \cs{params} is optional; however, without the \cs{params} you may as well use +% |\ytvId{|\ameta{ytvID}|}{|\ameta{text}|}|. +% +% \item |\ytLink{\watchId{|\ameta{ytvID}|}\params{|\ameta{parameters}|}}{|\ameta{text}|}|\\[3pt] This is the form +% for playing a video with \ameta{ytvID} that \emph{cannot be embedded} (advertisements and other information +% appears). The \cs{params} argument must follow the \cs{watchId}, its argument are any parameters you want to append to the URL. +% The use of \cs{params} is optional; however, without the \cs{params} you may as well use +% |\ytvId*{|\ameta{ytvID}|}{|\ameta{text}|}|. +% +% \item |\ytLink{\embed{|\ameta{spec}|}}{|\ameta{text}|}|\\[3pt] +% A form that does not specify a video ID. It is useful for more general actions, such as +% searches, for example, +% \begin{flushleft} +% |\ytLink{\embed{listType=search&list=Adobe Acrobat DC}}|\\ +% \qquad|{Search for Adobe Acrobat DC}| +% \end{flushleft} +% This form does not have a \cs{params} optional argument as all the parameters are built into the +% argument of \cs{embed}. +% +% \item |\ytLink{|\ameta{spec}|}{|\ameta{text}|}|\\[3pt] The most general form. The action of this +% link is |\URI{\ytURL/|\ameta{spec}|}|; for example, +% \begin{flushleft} +% |\ytLink{embed?listType=search&list=Adobe Acrobat DC}|\\ +% \qquad|{Search for Adobe Acrobat DC}| +% \end{flushleft} +% Here you are free to build whatever URL you can imagine. +% +% \item |\ytLink{\channel{|\ameta{name}|}}{|\ameta{text}|}|\\[3pt] +% Such a link displays the channel \ameta{name}. For example, +% \begin{flushleft} +% |\ytLink{\channel{rocketjump}}{The RocketJump Channel}| +% \end{flushleft} +% This link opens the YouTube channel named \texttt{rocketjump}. +% \end{itemize} +% \paragraph*{Passing Player Parameters.} +% As was illustrated above, the custom link \cs{ytLink} can pass various recognizable +% parameters to YouTube. After reviewing, +% \begin{flushleft} +% \url{https://developers.google.com/youtube/player_parameters#Parameters} +% \end{flushleft} +% the following parameters are recommended, some of them are illustrated in the +% sample document \texttt{ltx4yt-1.tex}: +% \begin{itemize} +% \item \texttt{autoplay=\ameta{\upshape{0\string|1}}} (default \texttt{0}) +% \item \texttt{controls=\ameta{\upshape{0\string|1}}} (default \texttt{1}) +% \item \texttt{fs=\ameta{\upshape{0\string|1}}} (default \texttt{1}) +% \item \texttt{modestbranding=\ameta{\upshape{0\string|0}}} +% \item \texttt{playlist=\ameta{list}} +% \item \texttt{listType=search\&list=\ameta{query}} +% \end{itemize} +% The specialized needs of the document author is most easily accommodated through the use +% of the \cs{ytLink} command, for example, +% \begin{flushleft}\obeylines +% |\ytLink{\embedId{5y9-EVmreU4}\params{autoplay=1&modestbranding=1}}| +% \qquad|{Lori's Corner: Episode \#1}| +% \end{flushleft} +% \begin{macrocode} +\newif\ifytwatch \ytwatchfalse +% \end{macrocode} +% \paragraph*{The \cs{ytLink} command.} Before getting to \cs{ytLink} an d\cs{ytLinkML}, +% there is a long stream of commands to parse the \ameta{spec} argument of \cs{ytLink}. +% It goes through looking for \cs{watchId}, \cs{embedId}, \cs{embed}, and \cs{params}. +% As it progresses, it adds code to the macro \cs{ytspec}, which at the end of things +% will hold the fully formed \ameta{spec} for insertion into the URL. +% \begin{macrocode} +\def\yt@@parse{\let\ytspec\@empty\yt@parse} +\def\yt@parse{\@ifnextchar\@nil{\@gobble}{\yt@parsei}} +\def\yt@parsei{\@ifnextchar\watchId{% check for \watchId + \ytwatchtrue\yt@parse@watch}{\yt@parseii}} +\def\yt@parse@watch\watchId#1{\g@addto@macro + \ytspec{\watchId{#1}}\yt@parse} +\def\yt@parseii{\@ifnextchar\embedId{% check for \embedId + \yt@parse@embedId}{\yt@parseiii}} +\def\yt@parse@embedId\embedId#1{\g@addto@macro + \ytspec{\embedId{#1}}\yt@parse} +\def\yt@parseiii{\@ifnextchar\embed{% check for \embed + \yt@parse@embed}{\yt@parseiv}} +\def\yt@parse@embed\embed#1{\g@addto@macro + \ytspec{\embed{#1}}\yt@parse} +\def\yt@parseiv{\@ifnextchar\params{% check for \params + \yt@parse@params}{\yt@parsev}} +\def\yt@parse@params\params#1{\ifytwatch + \g@addto@macro\ytspec{}\else + \g@addto@macro\ytspec{?#1}\fi + \yt@parse} +% \end{macrocode} +% If we get this far, \ameta{spec} is raw, has none +% of the helper commands. So we just insert the +% entire argument into \cs{ytspec}. +% \begin{macrocode} +\def\yt@parsev#1\@nil{\g@addto@macro\ytspec{#1}} +% \end{macrocode} +% All preliminaries done, we define \cs{ytLink} +% \begin{macrocode} +\newcommand{\ytLink}[3][]{\begingroup + \def\embedId##1{embed/##1}% + \def\params##1{##1}\def\embed##1{embed?##1}% + \def\watchId##1{watch?v=##1}\def\channel##1{c/##1}% + \def\user##1{user/##1}% + \yt@@parse#2\@nil % returns arg in \ytspec + \def\URLArg{\ytURL/\ytspec}% + \setLink[\presets{\yt@vIdPresets}#1\A{\URI{\URLArg}} + ]{#3}\endgroup +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\ytLinkML}\nmpsep{[\ameta{opts}]\darg{\ameta{spec}}\darg{\ameta{text}}} +% is the multi-line version of \cs{ytLink}. It requires a \app{dvips\,\texttt{->}\,distiller} workflow +% as well as the \pkg{aeb\_mlink} package. +% \begin{macrocode} +\newcommand{\ytLinkML}[3][]{\begingroup + \def\embedId##1{embed/##1}% + \def\params##1{##1}\def\embed##1{embed?##1}% + \def\watchId##1{watch?v=##1}\def\channel##1{c/##1}% + \def\user##1{user/##1}% + \yt@@parse#2\@nil % returns arg in \ytspec + \def\URLArg{\ytURL/\ytspec}% + \mlsetLink[\presets{\yt@vIdPresets}#1 + \A{\URI{\URLArg}} + ]{#3}\endgroup +} +% \end{macrocode} +% \end{macro} +% \subsubsection{Using a Combobox} +% All commands associate with a combo box play list. +% \begin{macro}{\ytComboList}\nmpsep{[\ameta{opts}]\darg{\ameta{name}}\darg{\ameta{wd}}\darg{\ameta{ht}}} +% The \cs{ytComboList} command produces a combo box (dropdown menu) of video Ids and titles. The user selects a +% video based on its title, then presses the PLAY button. The two commands +% \cs{ytComboListPresets} and \cs{ytComboBtnPresets} are used to set the appearances +% of the combo box and the PLAY button. +%\begin{quote} +%\begin{itemize} +% \item[\ameta{opts}:] eforms key-value pairs +% \item[\ameta{name}:] A unique name (ASCII letters and numbers) +% \item[\ameta{wd}:] The width of the combo box +% \item[\ameta{ht}:] The height of the combo box +%\end{itemize} +%\end{quote} +% Now we have the code for \cs{ytComboList} +% \begin{macrocode} +\newcommand{\ytComboList}[4][]{% + \comboBox[\Ff{\FfCommitOnSelChange}\DV{\yt@pl@def}\V{\yt@pl@def} + \presets{\yt@ComboListPresets}#1]{ytSelect#2} + {#3}{#4}{*\yt@pl@pl}% 2020/07/22 v0.4 +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\ytComboBtn}\nmpsep{[\ameta{opts}]\darg{\ameta{name}}\darg{\ameta{wd}}\darg{\ameta{ht}}} +% A button to play the selection made in the combo box. The caption of the push button +% is determined by the command \DescribeMacro\ytStrPLAY\cs{ytStrPlay}. +% The parameters for \cs{ytComboBtn} are, +% \begin{quote} +%\begin{itemize} +% \item[\ameta{opts}:] The KV-pairs to pass to the underlying push button. +% \item[\ameta{name}:] A unique name (ASCII letters and numbers) +% \item[\ameta{wd}:] The width of the combo box +% \item[\ameta{ht}:] The height of the combo box +%\end{itemize} +%\end{quote} +% \begin{macrocode} +\newcommand{\ytStrPLAY}{PLAY} +\newcommand{\ytComboBtn}[4][]{% + \pushButton[\TU{Click to play}\CA{\ytStrPLAY} + \presets{\yt@ComboBtnPresets}#1 + \A{\JS{var f=this.getField("ytSelect#2");\r + var ytID=f.value;\r + var i=f.currentValueIndices;\r + var ytFV=f.getItemAt(i,false);\r + var i=ytFV.indexOf("*");\r + if ( i == -1 )\r\t + app.launchURL("\ytURL/embed/"+ytID,\ytNF);\r + else\r\t + app.launchURL("\ytURL/watch?v="+ytID,\ytNF); + }}]{ytSelectBtn#2}{#3}{#4}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\ytPlayList}\nmpsep{\darg{\ameta{ytvID}}\darg{\ameta{\cs{cmd}}}} +% This command is executed before \cs{ytComboList} to set the initial/default value (\ameta{ytvID}) of the +% combo box and the play list (\ameta{\cs{cmd}}). Here \ameta{\cs{cmd}} is a command defined by the +% \cs{declarePlayList} command. Use the \cs{ytPlayList} to pass the play list to the next combo box. +% \begin{macrocode} +\newcommand{\ytPlayList}{\begingroup\@makeother\_\@makeother\' + \ytPlayList@i} +\def\ytPlayList@i#1#2{\gdef\yt@pl@def{#1}\xdef\yt@pl@pl{#2}\endgroup} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\ytComboListPresets}\nmpsep{\darg{\ameta{opts}}} The KV-pairs +% for \cs{ytComboList}. +% \begin{macrocode} +\newcommand{\ytComboListPresets}[1]{\def\yt@ComboListPresets{#1}} +\let\yt@ComboListPresets\@empty +% \end{macrocode} +% \end{macro} +% \begin{macro}{\ytComboBtnPresets}\nmpsep{\darg{\ameta{opts}}} The KV-pairs +% for \cs{ytComboBtn}. +% \begin{macrocode} +\newcommand{\ytComboBtnPresets}[1]{\def\yt@ComboBtnPresets{#1}} +\let\yt@ComboBtnPresets\@empty +% \end{macrocode} +% \end{macro} +% \leavevmode\DescribeMacro{\ytIdTitle}\nmpsep{\darg{\ameta{text}}\darg{\ameta{VidID}}} +% A convenience command to lay out the playlist. +% \begin{macrocode} +\newcommand{\ytIdTitle}[2]{[(#2)(#1)]} +% \end{macrocode} +% \begin{macro}{\declarePlayList} +% A video ID may contain characters {\LaTeX} considers special, so we sanitize these +% special characters before reading in the video ID. Near as I can determine, a video +% id consists of 11 characters comprising combinations of letters (A-Z,a-z) numbers +% (0-9) and special characters underscore and hyphen (\_ and -). We sanitize the last two. +%\begin{Verbatim}[xleftmargin=\parindent,codes={\catcode`\%=9},commandchars={!()}] +%\declarePlayList{!ameta(\cmd)}{ +% \ytIdTitle{!ameta(text)}{!ameta(VidID)} +% ... +% \ytIdTitle{!ameta(text)}{!ameta(VidID)} +% } +%\end{Verbatim} +%The entries may also be in raw form `|[(\ameta{VidID})(\ameta{text})]|'. Note that the two arguments are +%enclosed in parentheses, there is a problem with parsing if \ameta{text} itself contains +%parentheses. Within \ameta{text} enclose matching parentheses in braces, for example, +%\begin{flushleft}|\ytIdTitle{Kung-Fu Fighting {(Bruce Lee version)}}{GZ9e3Dy7obA}|\end{flushleft} +%\paragraph*{The role of \texttt* in the title.} If an \texttt{*} appears in the title, this means +%that the video cannot be embedded. Viewing the video will come with advertisements and other information +%that YouTube generates. +%\begin{flushleft}|\ytIdTitle{Kung-Fu Fighting* {(Original version)}}{jhUkGIsKvn0}|\end{flushleft} +%\changes{v0.4}{2020/07/22}{Changed parsing of \string\cs{declarePlayList} to accomodate +%\string\cs{pdfstringdef}} +% \begin{macrocode} +\newcommand{\declarePlayList}[1]{\bgroup + \Hy@unicodefalse + \let\pl@yList\@empty + \ifpdfmarkup + \def\Esc{\eqbs}\else\def\Esc{}\fi + \def\cs##1{\eqbs\eqbs##1}\relax + \@makeother\_\@makeother\- + \yt@declarePlayList{#1}% +} +\def\yt@declarePlayList#1#2{% + \yt@declarePlayList@i#2\@nil\relax\relax + \toks@=\expandafter{\pl@yList}\relax + \xdef#1{\pl@yList}\egroup +} +\def\yt@declarePlayList@i{\@ifnextchar\@nil + {\expandafter\@gobbletwo\@gobble} + {\yt@declarePlayList@ii}% +} +\def\yt@declarePlayList@ii\ytIdTitle#1#2{% + \pdfstringdef\yt@PLTitle{#1}% + \edef\y{[(#2)(\yt@PLTitle)]}% + \expandafter\g@addto@macro\expandafter + \pl@yList\expandafter{\y}% + \yt@declarePlayList@i +} +% \end{macrocode} +% \end{macro} +%An example of use of \cs{declarePlayList}: +%\begin{Verbatim}[xleftmargin=\parindent,codes={\catcode`\%=9},commandchars={!()}] +%\declarePlayList{\playListii}{% +% \ytIdTitle{Elfego Baca}{gRwa0MdeqVs} +% \ytIdTitle{Texas John Slaughter}{7yrk1BvtLE8} +% \ytIdTitle{Swamp Fox}{-SBPnw5riLM&NR} +% \ytIdTitle{Zorro Promo}{cKludhxEoJ0} +%} +%\end{Verbatim} +% \begin{macrocode} +% +%<*pujs> +% \end{macrocode} +% \subsubsection{Using a popup menu} +% These code lines (including the document JavaScript) are only included +% when the \opt{usepopup} option is taken. +% \begin{macro}{\ytUseMenus}\nmpsep{\darg{\ameta{menu-names}}} +% A command used to list popupmenu data. It defines a command +% \cs{ytPopupData} that is used in the JS support for popup menus. The argument +% \ameta{menu-names} is a comma-delimited list of menu names defined by a \env{popupmenu} environment. The command +% needs to be in the preamble. +% \begin{macrocode} +\def\ytPopupAllMenuData{// ltx4yt: Begin popup menu data^^J}% +\let\ytMenuNames\@gobble +\newcommand{\ytUseMenus}[1]{\bgroup + \@for\yt@menu:=#1\do{% + \edef\x{\noexpand\g@addto@macro\noexpand + \ytMenuNames{,"\yt@menu"}}\x + \edef\x{\expandafter\noexpand\@nameuse{\yt@menu}}% + \toks@=\expandafter{\x^^J}% + \expandafter\g@addto@macro\expandafter + \ytPopupAllMenuData\expandafter{\the\toks@}% + }\g@addto@macro\ytPopupAllMenuData + {// ltx4yt: End of popup menu data}% + \egroup +} +\@onlypreamble\ytUseMenus +% \end{macrocode} +% \end{macro} +% \begin{macro}{\puIdTitle} +% A convenience macro for entering popupmenu data for youtube videos. +%\begin{Verbatim}[xleftmargin=\parindent,fontsize=\small,codes={\catcode`\%=9},commandchars={!()}] +%\begin{popupmenu}{YTMenu} +% \puIdTitle{Select a YouTube Video}{} % A title has no yt Id +% \begin{submenu}{title=Music Videos} +% \puIdTitle{Kung-Fu Fighting (Bruce Lee version)}{GZ9e3Dy7obA} +% \puIdTitle{\string\"Sea Hunt\string\" TV serie}{MW-IZ67iADU} +% ... +% \end{submenu} +%\end{popupmenu} +%\end{Verbatim} +% Note that we must protect the double quote. +% \begin{macrocode} +%\newcommand{\puIdTitle}[2]{\item{title={#1},% +% return={[\itemindex,'#2']}}} +\newcommand{\puIdTitle}[2]{\Hy@unicodefalse\pdfstringdef\x@YT{#1}% + \edef\y@YT{\noexpand\item{title={\x@YT},% + return={[\noexpand\itemindex,'#2']}}}\y@YT} +% \end{macrocode} +% \end{macro} +% Some convenience commands for setting up a push button to display the popupmenu +% on rollover. +% \begin{macrocode} +\def\ytpubtnCnt{0} +\newcommand{\ytPopupBtn}[4][]{\bgroup + \@tempcnta\ytpubtnCnt\relax + \advance\@tempcnta\@ne + \xdef\ytpubtnCnt{\the\@tempcnta}% + \pushButton[\cmd{\pmpvCAOff}\CA{YT Menu} + \textColor{0 0 1}\W1\BC{}\textSize{0} + \H{N}\S{S}\presets{\yt@PopupPresets}#1 + \AAmouseenter{ytPopupMenu("#2");} % dps + ]{ytPopup\ytpubtnCnt}{#3}{#4}\egroup +} +\newcommand{\ytPopupPresets}[1]{\def\yt@PopupPresets{#1}} +\let\yt@PopupPresets\@empty +% \end{macrocode} +% \begin{macrocode} +% +%<*package> +% \end{macrocode} +% \subsection{Search YouTube interactively} +% \begin{macro}{\ytInputQuery}\nmpsep{[\ameta{opts}]\darg{\ameta{wd}}\darg{\ameta{ht}}} +% Provides a text field to enter a query string. +% \begin{macrocode} +\newcommand{\ytInputQuery}[3][]{% + \textField[\TU{Enter a query text string}#1]{ytSearchTxt}{#2}{#3}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\ytSearch}\nmpsep{[\ameta{opts}]\darg{\ameta{wd}}\darg{\ameta{ht}}} +% A push button what will search YouTube based on the query string. +% \begin{macrocode} +\newcommand{\ytSearch}[3][]{% + \pushButton[\CA{Search}#1\AAmouseup{% + var f=this.getField("ytSearchTxt");\r + var v=f.value;\r + if ( v.replace(/\string\s/g,"") != "" )\r\t + app.launchURL("\ytURL/embed?listType=search&list="+v);} + ]{ytSearchBtn}{#2}{#3}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\ytClearQuery}\nmpsep{[\ameta{opts}]\darg{\ameta{wd}}\darg{\ameta{ht}}} +% A button to clear the query string. +% \begin{macrocode} +\newcommand{\ytClearQuery}[3][]{% + \pushButton[\CA{Clear}#1 + \AAmouseup{this.resetForm("ytSearchTxt");} + ]{ytSearchClr}{#2}{#3}% +} +% \end{macrocode} +% \end{macro} +% \begin{macrocode} +% +%<*pujs> +% \end{macrocode} +%\subsection{Document JavaScript} +% Some JavaScript to process the user's choice and to launch the browser +% to view the selected video. +% \changes{v0.5}{2020/07/24}{Manage multiple menus} +% \begin{macrocode} +\begin{insDLJS*}{yt} +\begin{newsegment}{ltx4yt: % +Popup Menu Data and JavaScript support functions} +var YTdebug=false; +var aYTLastChoice=new Array; +var bYTLastChoice=false; +\ytPopupAllMenuData +var aChoice; // make local +function ytProcessMenu(cMenu) { // aMenu->cMenu now a string + var aMenu=eval(cMenu); + var cChoice = app.popUpMenuEx.apply( app, aMenu ); + ytProcessMenu.cChoice=cChoice; + if ( cChoice != null ) { + aChoice=eval(cChoice); + if (aChoice[1]=="") return null; + var thisChoice=aChoice[0]; + eval(cMenu+thisChoice).bMarked=true; + if (!bYTLastChoice) { + eval(cMenu+aChoice[0]).bMarked=true; + } else { + var structLoc=eval(aYTLastChoice[1])[0] + eval(aYTLastChoice[0]+structLoc).bMarked=false; + eval(cMenu+aChoice[0]).bMarked=true; + } + return aChoice; + } else return null; +} +function ytPopupMenu(cMenu) { // cMenu now a string + var aChoice=ytProcessMenu(cMenu); + var cChoice=ytProcessMenu.cChoice; + var aMenu=eval(cMenu); + if (aChoice!=null) { + var title=eval(cMenu+aChoice[0]).cName; + var i=title.indexOf("*"); + var _hash=(i == -1)?"embed/"+aChoice[1]:"watch?v="+aChoice[1]; + if (!bYTLastChoice) { + if(YTdebug) % +console.println("launching url https://www.youtube.com/"+_hash); + else app.launchURL("https://www.youtube.com/"+_hash,false); + aYTLastChoice=[cMenu,cChoice]; + bYTLastChoice=true; + } else { + var cLastMenu=eval(aYTLastChoice[1])[0] + aYTLastChoice=[cMenu,cChoice]; + if (cLastMenu!=aChoice[0]) { + if (YTdebug) % +console.println("will launch url: https://www.youtube.com/"+_hash); + else app.launchURL("https://www.youtube.com/"+_hash,false); + } else { + if (YTdebug) console.println("will NOT launch url"); + // choice is the same, uncheck this item + eval(cMenu+aChoice[0]).bMarked=false; + bYTLastChoice=false; + } + } + } +} +\end{newsegment} +\end{insDLJS*} +% \end{macrocode} +% \begin{macrocode} +%<*pujs> +%<*package> +% +% \end{macrocode} +% \Finale +\endinput + +https://developers.google.com/youtube/iframe_api_reference?csw=1 -- cgit v1.2.3