# -*- coding:utf-8 -*- """ @Author : g1879 @Contact : g1879@qq.com """ from .._functions.web import location_in_viewport from ..errors import CDPError, NoRectError, PageClosedError, ElementLostError class ElementStates(object): def __init__(self, ele): """ :param ele: ChromiumElement """ self._ele = ele @property def is_selected(self): """返回元素是否被选择""" return self._ele.run_js('return this.selected;') @property def is_checked(self): """返回元素是否被选择""" return self._ele.run_js('return this.checked;') @property def is_displayed(self): """返回元素是否显示""" return not (self._ele.style('visibility') == 'hidden' or self._ele.run_js('return this.offsetParent === null;') or self._ele.style('display') == 'none') @property def is_enabled(self): """返回元素是否可用""" return not self._ele.run_js('return this.disabled;') @property def is_alive(self): """返回元素是否仍在DOM中""" try: self._ele.attrs return True except Exception: return False @property def is_in_viewport(self): """返回元素是否出现在视口中,以元素click_point为判断""" x, y = self._ele.rect.click_point return location_in_viewport(self._ele.page, x, y) if x else False @property def is_whole_in_viewport(self): """返回元素是否整个都在视口内""" x1, y1 = self._ele.rect.location w, h = self._ele.rect.size x2, y2 = x1 + w, y1 + h return location_in_viewport(self._ele.page, x1, y1) and location_in_viewport(self._ele.page, x2, y2) @property def is_covered(self): """返回元素是否被覆盖,与是否在视口中无关,如被覆盖返回覆盖元素的backend id,否则返回False""" lx, ly = self._ele.rect.click_point try: bid = self._ele.page.run_cdp('DOM.getNodeForLocation', x=lx, y=ly).get('backendNodeId') return bid if bid != self._ele._backend_id else False except CDPError: return False @property def has_rect(self): """返回元素是否拥有位置和大小,没有返回False,有返回四个角在页面中坐标组成的列表""" try: return self._ele.rect.corners except NoRectError: return False class ShadowRootStates(object): def __init__(self, ele): """ :param ele: ChromiumElement """ self._ele = ele @property def is_enabled(self): """返回元素是否可用""" return not self._ele.run_js('return this.disabled;') @property def is_alive(self): """返回元素是否仍在DOM中""" try: self._ele.page.run_cdp('DOM.describeNode', backendNodeId=self._ele._backend_id) return True except Exception: return False class PageStates(object): """Page对象、Tab对象使用""" def __init__(self, page): """ :param page: ChromiumBase对象 """ self._page = page @property def is_loading(self): """返回页面是否在加载状态""" return self._page._is_loading @property def is_alive(self): """返回页面对象是否仍然可用""" try: self._page.run_cdp('Page.getLayoutMetrics') return True except PageClosedError: return False @property def ready_state(self): """返回当前页面加载状态,'connecting' 'loading' 'interactive' 'complete'""" return self._page._ready_state @property def has_alert(self): """返回当前页面是否存在弹窗""" return self._page._has_alert class FrameStates(object): def __init__(self, frame): """ :param frame: ChromiumFrame对象 """ self._frame = frame @property def is_loading(self): """返回页面是否在加载状态""" return self._frame._is_loading @property def is_alive(self): """返回frame元素是否可用,且里面仍挂载有frame""" try: node = self._frame._target_page.run_cdp('DOM.describeNode', backendNodeId=self._frame._frame_ele._backend_id)['node'] except (ElementLostError, PageClosedError): return False return 'frameId' in node @property def ready_state(self): """返回加载状态""" return self._frame._ready_state @property def is_displayed(self): """返回iframe是否显示""" return not (self._frame.frame_ele.style('visibility') == 'hidden' or self._frame.frame_ele.run_js('return this.offsetParent === null;') or self._frame.frame_ele.style('display') == 'none') @property def has_alert(self): """返回当前页面是否存在弹窗""" return self._frame._has_alert