o
    _cK                     @   s   d Z ddlZddlZddlZddlZddlmZmZm	Z	m
Z
mZ ddlmZ ddlmZmZ ddlmZmZ ddlmZ ddlmZ erLdd	lmZmZ eeZG d
d deZde	e defddZ dS )zElement handle module.    N)AnyDictListOptionalTYPE_CHECKING)
CDPSession)ExecutionContextJSHandle)ElementHandleErrorNetworkError)
debugError)
merge_dict)FrameFrameManagerc                       s  e Zd ZdZdededededddd	f fd
dZdCddZ	de
d fddZdDddZdeeef fddZde
e fddZdee deeeef  fddZdDddZdEdededd	fddZd edefd!d"ZdDd#d$ZdDd%d&ZdEd'edededd	fd(d)ZdEd*edededd	fd+d,Zde
eeef  fd-d.Zde
e fd/d0ZdEdededefd1d2Zd3ede
d  fd4d5Z d3eded  fd6d7Z!d3ed8ed9edefd:d;Z"d3ed8ed9edefd<d=Z#e Z$e!Z%e"Z&e#Z'd>eded  fd?d@Z(e(Z)de*fdAdBZ+  Z,S )FElementHandlea  ElementHandle class.

    This class represents an in-page DOM element. ElementHandle can be created
    by the :meth:`pyppeteer.page.Page.querySelector` method.

    ElementHandle prevents DOM element from garbage collection unless the
    handle is disposed. ElementHandles are automatically disposed when their
    origin frame gets navigated.

    ElementHandle isinstance can be used as arguments in
    :meth:`pyppeteer.page.Page.querySelectorEval` and
    :meth:`pyppeteer.page.Page.evaluate` methods.
    contextclientremoteObjectpageframeManagerr   returnNc                    s2   t  ||| || _|| _|| _|| _d| _d S )NF)super__init___client_remoteObject_page_frameManagerZ	_disposed)selfr   r   r   r   r   	__class__ C/usr/local/lib/python3.10/dist-packages/pyppeteer/element_handle.pyr   (   s   
zElementHandle.__init__c                 C   s   | S )zReturn this ElementHandle.r    r   r    r    r!   	asElement2   s   zElementHandle.asElementr   c                    sR   | j dd| jdiI dH }|di }t|dts!dS | j|d S )z|Return the content frame for the element handle.

        Return ``None`` if this handle is not referencing iframe.
        zDOM.describeNodeobjectIdNnodeZframeId)r   sendr   get
isinstancestrr   frame)r   ZnodeInfoZnode_objr    r    r!   contentFrame6   s   zElementHandle.contentFramec                    s,   | j d| | jjI d H }|rt|d S )Na  
            async (element, pageJavascriptEnabled) => {
                if (!element.isConnected)
                    return 'Node is detached from document';
                if (element.nodeType !== Node.ELEMENT_NODE)
                    return 'Node is not of type HTMLElement';
                // force-scroll if page's javascript is disabled.
                if (!pageJavascriptEnabled) {
                    element.scrollIntoView({
                        block: 'center',
                        inline: 'center',
                        behavior: 'instant',
                    });
                    return false;
                }
                const visibleRatio = await new Promise(resolve => {
                    const observer = new IntersectionObserver(entries => {
                        resolve(entries[0].intersectionRatio);
                        observer.disconnect();
                    });
                    observer.observe(element);
                });
                if (visibleRatio !== 1.0)
                    element.scrollIntoView({
                        block: 'center',
                        inline: 'center',
                        behavior: 'instant',
                    });
                return false;
            })executionContextevaluater   Z_javascriptEnabledr
   )r   errorr    r    r!   _scrollIntoViewIfNeededC   s   
z%ElementHandle._scrollIntoViewIfNeededc           
   
      s   d }z| j dd| jdiI d H }W n ty, } ztt| W Y d }~nd }~ww |r4|ds8tdg }|dD ]}| |}t	|dkrQ|
| q?|sXtd|d }d}d}|D ]}	||	d 7 }||	d 7 }qb|d	 |d	 d
S )NzDOM.getContentQuadsr$   quads0Node is either not visible or not an HTMLElement   r   xy   r3   r4   )r   r&   r   r'   	Exceptionr   loggerr
   _fromProtocolQuad_computeQuadAreaappend)
r   resulter0   Z_quadZ_qquadr3   r4   pointr    r    r!   _clickablePointe   s>   

zElementHandle._clickablePointc              
      s^   z| j dd| jdiI d H }W |S  ty. } ztt| d }W Y d }~|S d }~ww )NzDOM.getBoxModelr$   )r   r&   r   r'   r   r   r8   )r   r<   r=   r    r    r!   _getBoxModel   s   
zElementHandle._getBoxModelr>   c                 C   sD   |d |d d|d |d d|d |d d|d |d	 dgS )
Nr   r2   r6         r5            r    )r   r>   r    r    r!   r9      s
   zElementHandle._fromProtocolQuadc                    P   |   I dH  |  I dH }|dd}|dd}| jj||I dH  dS )zMove mouse over to center of this element.

        If needed, this method scrolls element into view. If this element is
        detached from DOM tree, the method raises an ``ElementHandleError``.
        Nr3   r   r4   )r/   r@   r'   r   mousemove)r   objr3   r4   r    r    r!   hover      zElementHandle.hoveroptionskwargsc                    s\   t ||}|  I dH  |  I dH }|dd}|dd}| jj|||I dH  dS )a  Click the center of this element.

        If needed, this method scrolls element into view. If the element is
        detached from DOM, the method raises ``ElementHandleError``.

        ``options`` can contain the following fields:

        * ``button`` (str): ``left``, ``right``, of ``middle``, defaults to
          ``left``.
        * ``clickCount`` (int): Defaults to 1.
        * ``delay`` (int|float): Time to wait between ``mousedown`` and
          ``mouseup`` in milliseconds. Defaults to 0.
        Nr3   r   r4   )r   r/   r@   r'   r   rH   click)r   rM   rN   rJ   r3   r4   r    r    r!   rO      s   
zElementHandle.click	filePathsc                    s6   dd |D }| j d}| jd||dI dH S )zUpload files.c                 S   s   g | ]}t j|qS r    )ospathabspath).0pr    r    r!   
<listcomp>   s    z,ElementHandle.uploadFile.<locals>.<listcomp>r$   zDOM.setFileInputFiles)r$   filesN)r   r'   r   r&   )r   rP   rW   r$   r    r    r!   
uploadFile   s   
zElementHandle.uploadFilec                    rG   )zTap the center of this element.

        If needed, this method scrolls element into view. If the element is
        detached from DOM, the method raises ``ElementHandleError``.
        Nr3   r   r4   )r/   r@   r'   r   Ztouchscreentap)r   centerr3   r4   r    r    r!   rY      rL   zElementHandle.tapc                    s   | j d| I dH  dS )zFocus on this element.zelement => element.focus()Nr,   r-   r"   r    r    r!   focus   s   zElementHandle.focustextc                    4   t ||}|  I dH  | jj||I dH  dS )zqFocus the element and then type text.

        Details see :meth:`pyppeteer.input.Keyboard.type` method.
        N)r   r\   r   keyboardtype)r   r]   rM   rN   r    r    r!   r`      s   
zElementHandle.typekeyc                    r^   )a  Press ``key`` onto the element.

        This method focuses the element, and then uses
        :meth:`pyppeteer.input.keyboard.down` and
        :meth:`pyppeteer.input.keyboard.up`.

        :arg str key: Name of key to press, such as ``ArrowLeft``.

        This method accepts the following options:

        * ``text`` (str): If specified, generates an input event with this
          text.
        * ``delay`` (int|float): Time to wait between ``keydown`` and
          ``keyup``. Defaults to 0.
        N)r   r\   r   r_   press)r   ra   rM   rN   r    r    r!   rb      s   
zElementHandle.pressc                    s   |   I dH }|sdS |d d }t|d |d |d |d }t|d |d	 |d
 |d }t|d |d |d |d | }t|d |d	 |d
 |d | }||||dS )a  Return bounding box of this element.

        If the element is not visible, return ``None``.

        This method returns dictionary of bounding box, which contains:

        * ``x`` (int): The X coordinate of the element in pixels.
        * ``y`` (int): The Y coordinate of the element in pixels.
        * ``width`` (int): The width of the element in pixels.
        * ``height`` (int): The height of the element in pixels.
        Nmodelborderr   rB   r5   rE   r2   rC   rD   rF   )r3   r4   widthheight)rA   minmax)r   r<   r>   r3   r4   re   rf   r    r    r!   boundingBox   s   ""zElementHandle.boundingBoxc                    sr   |   I dH }|sdS |di }| |d| |d| |d| |d|d|dd	S )
a8  Return boxes of element.

        Return ``None`` if element is not visible. Boxes are represented as an
        list of points; each Point is a dictionary ``{x, y}``. Box points are
        sorted clock-wise.

        Returned value is a dictionary with the following fields:

        * ``content`` (List[Dict]): Content box.
        * ``padding`` (List[Dict]): Padding box.
        * ``border`` (List[Dict]): Border box.
        * ``margin`` (List[Dict]): Margin box.
        * ``width`` (int): Element's width.
        * ``height`` (int): Element's height.
        Nrc   contentpaddingrd   marginre   rf   )rj   rk   rd   rl   re   rf   )rA   r'   r9   )r   r<   rc   r    r    r!   boxModel  s   zElementHandle.boxModelc                    sr  t ||}d}|  I dH }|stdt| jj}|d |d ks,|d |d krZt|d t	|d t|d t	|d d}t|}|
| | j|I dH  d}|  I dH  |  I dH }|sntd| jdI dH }|d	 d
 }	|d	 d }
i }|
| |d |	 |d< |d |
 |d< d|i}|
| | j|I dH }|r| j|I dH  |S )zTake a screenshot of this element.

        If the element is detached from DOM, this method raises an
        ``ElementHandleError``.

        Available options are same as :meth:`pyppeteer.page.Page.screenshot`.
        FNr1   re   rf   )re   rf   TzPage.getLayoutMetricsZlayoutViewportpageXpageYr3   r4   clip)r   ri   r
   copydeepcopyr   Zviewportrh   mathceilupdateZsetViewportr/   r   r&   
screenshot)r   rM   rN   ZneedsViewportResetri   Zoriginal_viewportZnewViewportZnew_viewport_objrn   ro   rp   optZ	imageDatar    r    r!   rv   '  sX   





zElementHandle.screenshotselectorc                    s:   | j d| |I dH }| }|r|S | I dH  dS )zReturn first element which matches ``selector`` under this element.

        If no element matches the ``selector``, returns ``None``.
        z6(element, selector) => element.querySelector(selector)N)r,   evaluateHandler#   dispose)r   ry   handleelementr    r    r!   querySelectora  s   
zElementHandle.querySelectorc                    `   | j d| |I dH }| I dH }| I dH  g }| D ]}| }|r-|| q |S )zReturn all elements which match ``selector`` under this element.

        If no element matches the ``selector``, returns empty list (``[]``).
        z9(element, selector) => element.querySelectorAll(selector)Nr,   rz   ZgetPropertiesr{   valuesr#   r;   )r   ry   arrayHandle
propertiesr<   propelementHandler    r    r!   querySelectorAllp  s   

zElementHandle.querySelectorAllpageFunctionargsc                    sT   |  |I dH }|std| d| jj||g|R  I dH }| I dH  |S )a  Run ``Page.querySelectorEval`` within the element.

        This method runs ``document.querySelector`` within the element and
        passes it as the first argument to ``pageFunction``. If there is no
        element matching ``selector``, the method raises
        ``ElementHandleError``.

        If ``pageFunction`` returns a promise, then wait for the promise to
        resolve and return its value.

        ``ElementHandle.Jeval`` is a shortcut of this method.

        Example:

        .. code:: python

            tweetHandle = await page.querySelector('.tweet')
            assert (await tweetHandle.querySelectorEval('.like', 'node => node.innerText')) == 100
            assert (await tweetHandle.Jeval('.retweets', 'node => node.innerText')) == 10
        Nz1Error: failed to find element matching selector "")r~   r
   r,   r-   r{   )r   ry   r   r   r   r<   r    r    r!   querySelectorEval  s   
zElementHandle.querySelectorEvalc                    sF   | j d| |I dH }| j j||g|R  I dH }| I dH  |S )a+  Run ``Page.querySelectorAllEval`` within the element.

        This method runs ``Array.from(document.querySelectorAll)`` within the
        element and passes it as the first argument to ``pageFunction``. If
        there is no element matching ``selector``, the method raises
        ``ElementHandleError``.

        If ``pageFunction`` returns a promise, then wait for the promise to
        resolve and return its value.

        Example:

        .. code:: html

            <div class="feed">
                <div class="tweet">Hello!</div>
                <div class="tweet">Hi!</div>
            </div>

        .. code:: python

            feedHandle = await page.J('.feed')
            assert (await feedHandle.JJeval('.tweet', '(nodes => nodes.map(n => n.innerText))')) == ['Hello!', 'Hi!']
        zE(element, selector) => Array.from(element.querySelectorAll(selector))N)r,   rz   r-   r{   )r   ry   r   r   r   r<   r    r    r!   querySelectorAllEval  s   
z"ElementHandle.querySelectorAllEval
expressionc                    r   )zEvaluate the XPath expression relative to this elementHandle.

        If there are no such elements, return an empty list.

        :arg str expression: XPath string to be evaluated.
        a  (element, expression) => {
                const document = element.ownerDocument || element;
                const iterator = document.evaluate(expression, element, null,
                    XPathResult.ORDERED_NODE_ITERATOR_TYPE);
                const array = [];
                let item;
                while ((item = iterator.iterateNext()))
                    array.push(item);
                return array;

            }Nr   )r   r   r   r   r<   propertyr   r    r    r!   xpath  s   


zElementHandle.xpathc                    s   | j d| I dH S )z:Return ``True`` if the element is visible in the viewport.a}  async element => {
            const visibleRatio = await new Promise(resolve => {
                const observer = new IntersectionObserver(entries => {
                    resolve(entries[0].intersectionRatio);
                    observer.disconnect();
                });
                observer.observe(element);
            });
            return visibleRatio > 0;
        }Nr[   r"   r    r    r!   isIntersectingViewport  s   	
z$ElementHandle.isIntersectingViewport)r   r   )r   N)N)-__name__
__module____qualname____doc__r   r   dictr   r   r#   r   r+   r/   r   r)   floatr@   rA   r   intr9   rK   rO   rX   rY   r\   r`   rb   ri   rm   bytesrv   r~   r   r   r   JZJJZJevalZJJevalr   ZJxboolr   __classcell__r    r    r   r!   r      sd    



""

	



:


 
$r   r>   r   c                 C   s^   d}t | D ]&\}}| | }| |d t|   }||d |d  |d |d   d 7 }q|S )Nr   r2   r3   r4   rB   )	enumeratelen)r>   areai_p1p2r    r    r!   r:     s   *r:   )!r   rq   loggingrs   os.pathrQ   typingr   r   r   r   r   Zpyppeteer.connectionr   Zpyppeteer.execution_contextr   r	   Zpyppeteer.errorsr
   r   Zpyppeteer.helperr   Zpyppeteer.utilr   Zpyppeteer.frame_managerr   r   	getLoggerr   r8   r   r   r:   r    r    r    r!   <module>   s&   
   e