"""
domonic.dQuery
===================================
alt + 0
"""
import json
from domonic.dom import *
from domonic.html import *
from domonic.javascript import *
class EventHandler:
def __init__(self):
self.events = []
def bindEvent(self, event: str, callback, targetElement):
"""[binds an event to a callback]
Args:
event ([str]): [type of event]
callback (function): [callback function]
targetElement ([type]): [target element]
"""
self.unbindEvent(event, targetElement)
targetElement.addEventListener(event, callback, False)
self.events.append({"_type": event, "event": callback, "target": targetElement})
def findEvent(self, event):
"""[finds an event]
Args:
event ([str]): [event]
Returns:
[type]: [event]
"""
return [e for e in self.events[0] if e == event["_type"]]
def unbindEvent(self, event, targetElement):
"""[unbinds an event]
Args:
event ([str]): [event]
targetElement ([type]): [description]
"""
foundEvent = self.findEvent(event)
if foundEvent is not None:
targetElement.removeEventListener(event, foundEvent["event"], False)
self.events = [e for e in self.events if e != event["_type"]]
[docs]class dQuery_el:
"""
alt + 0
dQuery - methods for querying domonic
"""
DOM = None
def __init__(self, dom, *args, **kwargs):
"""Return a collection of matched elements found in the DOM based on passed arguments,
or created by passing an HTML string."""
# if first char is < . returs a new html dom node < init() does this
# if its a selector. execs on the current dom < init() does this
# if its a dom . set that as default target
self.q = None
self.elements = None
if type(dom) == str:
# print("DO NOT CALL THIS METHOD DIRECTLY! use dQuery or º ")
return
else:
dQuery_el.DOM = dom
self.dom = dom
def __str__(self):
# print(type(self.elements))
if type(self.elements) is tuple:
# if isinstance(self.elements, (list, tuple)):
# print([str(el) for el in self.elements])
return "".join([str(el) for el in self.elements])
else:
# print('asd')
return str(self.elements)
def __getitem__(self, index):
return self.elements[index]
@property
def dom(self):
# print('getting')
if dQuery_el.DOM is None:
from domonic.dom import document
return document
# else:
# print('GOT ONE')
return dQuery_el.DOM
@dom.setter
def dom(self, dom):
if isinstance(dom, (html, Document)):
dQuery_el.DOM = dom
def init(self, q=""):
self.q = q
if type(q) is not str:
return
# if q == "":
# return
if self.q[0] == "<":
from domonic import domonic
self.elements = domonic.load(self.q)
# print(self.elements)
# print(type(self.elements))
if isinstance(self.elements, (html, Document)):
self.dom = self.elements
else:
try:
# element by selector not working on just classes as always needs a tag
if self.q[0] == ".":
# NOTE - if jquery is not present chrome assigns $ to querySelector NOT querySelectorAll
# so differing behaviours may be expected.
# detect if there's a list in each method if not do it to first item?
# so it does bit of both? aka .append
self.elements = self.dom.querySelectorAll(self.q)
return
self.elements = self.dom.getElementsBySelector(self.q, self.dom)
except Exception as e:
print("Error. No DOM has been set!!", e)
raise e
# def _listify(func):
# from functools import wraps
# @wraps(func)
# def as_list_wrapper(self, value=None, *args, **kwargs):
# if not isinstance(self.elements, (list, tuple)):
# self.elements = (self.elements,)
# value = func(value, *args, **kwargs)
# return value
# return as_list_wrapper
[docs] def add(self, elements):
"""Create a new dQuery object with elements added to the set of matched elements."""
"""
dq = None
if type(elements) == str:
dq = º(elements).elements
if type(dq) not in [list, tuple]:
dq = [dq]
if type(self.elements) not in [list, tuple]:
self.elements = [self.elements]
# if type(dq) not in [list, tuple]:
# self.elements = [self.elements]
self.elements = list(self.elements) + list(dq)
return self
"""
# return self
raise NotImplementedError
[docs] def addBack(self, selector):
"""Add the previous set of elements on the stack to the current set, optionally filtered by a selector."""
raise NotImplementedError
[docs] def addClass(self, name: str):
"""Adds the specified class to each element in the set of matched elements."""
# print(self.elements, name)
# print(type(self.elements))
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
# print(type(self.elements))
for el in self.elements:
if el.getAttribute("class") is not None:
el.setAttribute("class", el.getAttribute("class") + " " + name)
else:
el.setAttribute("class", name)
return self
[docs] def after(self, newnode):
"""Insert content, specified by the parameter, after each element in the set of matched elements."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
p = el.parentNode
for i, n in enumerate(p.children):
if n == el:
l = list(p.args)
l.insert(i + 1, newnode)
p.args = tuple(l)
return self
[docs] def ajaxComplete(self, handler):
"""Register a handler to be called when Ajax requests complete. This is an Ajax Event"""
raise NotImplementedError
[docs] def ajaxError(self, handler):
"""Register a handler to be called when Ajax requests complete with an error. This is an Ajax Event"""
raise NotImplementedError
[docs] def ajaxSend(self, handler):
"""Register a handler to be called when Ajax requests complete successfully. This is an Ajax Event"""
raise NotImplementedError
[docs] def ajaxStart(self, handler):
"""Register a handler to be called when the first Ajax request begins. This is an Ajax Event"""
raise NotImplementedError
[docs] def ajaxStop(self, handler):
"""Register a handler to be called when all Ajax requests have completed. This is an Ajax Event"""
raise NotImplementedError
[docs] def ajaxSuccess(self, handler):
"""Attach a function to be executed whenever an Ajax request completes successfully. This is an Ajax Event."""
raise NotImplementedError
[docs] def andSelf(self):
"""Add the previous set of elements on the stack to the current set."""
raise NotImplementedError
[docs] def animate(self):
"""Perform a custom animation of a set of CSS properties."""
raise NotImplementedError
[docs] def append(self, html):
"""Insert content, specified by the parameter, to the end of each element in the set of matched elements."""
# print('running append', self.elements, html)
# print(len(self.elements))
# print(":::::::::::", type(self.elements))
if type(self.elements) is not tuple and type(self.elements) is not list:
self.elements.innerHTML = self.elements.innerHTML + str(html)
return self
for el in self.elements:
# print('EL!!')
el.innerHTML = el.innerHTML + str(html)
# print('APPEND SAYS:', self.elements)
# return self
[docs] def appendTo(self, target):
"""Insert every element in the set of matched elements to the end of the target."""
target += self.elements
return target
[docs] def attr(self, property, value=None):
"""Get the value of an attribute for the first element in the set of matched elements
or set one or more attributes for every matched element."""
# if not isinstance(self.elements, (list, tuple)):
# self.elements = (self.elements,)
if value is not None:
if self.elements[0].getAttribute(property) is not None:
self.elements[0].setAttribute(property, value)
return self
if type(self.elements) is not tuple and type(self.elements) is not list:
return self.elements.getAttribute(property)
else:
return self.elements[0].getAttribute(property)
[docs] def before(self, content): # TODO - test
"""Insert content, specified by the parameter, before each element in the set of matched elements."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
p = el.parentNode
for i, n in enumerate(p.children):
if n == el:
l = list(p.args)
l.insert(i, content)
p.args = tuple(l)
return self
[docs] def bind(self, event, handler): # TODO - untested
"""Attach a function to be executed when an event occurs on a set of matched elements."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
el.addEventListener(event, handler)
return self
[docs] def blur(self, handler): # TODO - untested
"""Bind an event handler to the “blur” JavaScript event, or trigger that event on an element."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
el.triggerEvent("blur")
return self
[docs] def change(self, handler): # TODO - untested... from description sound like would be something like this?
"""Bind an event handler to the “change” JavaScript event, or trigger that event on an element."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
if el.hasEvent("change"):
el.triggerEvent("change")
else:
el.addEventListener("change", handler)
# el.triggerEvent('change')
return self
[docs] def children(self, selector=None): # TODO - test
"""Get the children of each element in the set of matched elements, optionally filtered by a selector."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
if selector is None:
return self.elements
else:
return [el for el in self.elements if selector(el)]
[docs] def clearQueue(self):
"""Remove from the queue all items that have not yet been run."""
# if not isinstance(self.elements, (list, tuple)):
# self.elements = (self.elements,)
# for el in self.elements:
# el.clearQueue()
# return self
raise NotImplementedError
[docs] def click(self, handler):
"""Bind an event handler to the “click” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
# Create a deep copy of the set of matched elements.
[docs] def clone(self):
"""Create a deep copy of the set of matched elements."""
# if not isinstance(self.elements, (list, tuple)):
# self.elements = (self.elements,)
# new_elements = self.elements.clone()
raise NotImplementedError
[docs] def closest(self, selector=None):
"""For each element in the set, get the first element that matches the selector by testing the element itself
and traversing up through its ancestors in the DOM tree."""
raise NotImplementedError
[docs] def contents(self, selector=None):
"""Get the children of each element in the set of matched elements, including text and comment nodes."""
raise NotImplementedError
@property
def context(self):
"""The DOM node context originally passed to dQuery if none was passed
then context will likely be the document."""
from domonic.dom import document
return document
[docs] def css(self, property, value=None): # TODO - untested
"""Get the value of a computed style property for the first element in the set of matched elements
or set one or more CSS properties for every matched element."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
if value is not None:
if self.elements[0].style.getProperty(property) is not None:
self.elements[0].style.setProperty(property, value)
return self
if type(self.elements) is not tuple and type(self.elements) is not list:
return self.elements.style.getProperty(property)
else:
return self.elements[0].style.getProperty(property)
[docs] def data(self, key, value=None):
"""Store arbitrary data associated with the matched elements or return the value at the named data store
for the first element in the set of matched elements."""
raise NotImplementedError
[docs] def dblclick(self, handler):
"""Bind an event handler to the “dblclick” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
[docs] def delay(self, time):
"""Set a timer to delay execution of subsequent items in the queue."""
raise NotImplementedError
[docs] def delegate(self, selector, event, handler):
"""Attach a handler to one or more events for all elements that match the selector, now or in the future,
based on a specific set of root elements."""
raise NotImplementedError
[docs] def dequeue(self):
"""Execute the next function on the queue for the matched elements."""
raise NotImplementedError
[docs] def detach(self): # TODO - test
"""Remove the set of matched elements from the DOM."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
p = el.parentNode
for i, n in enumerate(p.children):
if n == el:
l = list(p.args)
l.pop(i)
p.args = tuple(l)
return self
[docs] def die(self):
"""Remove event handlers previously attached using .live from the elements."""
raise NotImplementedError
[docs] def each(self, func):
"""Iterate over a dQuery object, executing a function for each matched element."""
# TODO - untested
for index, value in enumerate(self.elements):
try:
func(index, value)
except Exception as e:
func(index)
return self
# @_listify
[docs] def empty(self):
"""Remove all child nodes of the set of matched elements from the DOM."""
# TODO - test
for el in self.elements:
el.args = []
return self
[docs] def end(self):
"""End the most recent filtering operation in the current chain and return the
set of matched elements to its previous state."""
raise NotImplementedError
[docs] def eq(self, index):
"""Reduce the set of matched elements to the one at the specified index."""
return self.elements[index]
[docs] def error(self, handler):
"""Bind an event handler to the “error” JavaScript event."""
raise NotImplementedError
[docs] def even(self): # TODO - untested
"""Reduce the set of matched elements to the even ones in the set, numbered from zero."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
return [el for el in self.elements if el.index % 2 == 0]
[docs] def fadeIn(self):
"""Display the matched elements by fading them to opaque."""
raise NotImplementedError
[docs] def fadeOut(self):
"""Hide the matched elements by fading them to transparent."""
raise NotImplementedError
[docs] def fadeTo(self):
"""Adjust the opacity of the matched elements."""
raise NotImplementedError
[docs] def fadeToggle(self):
"""Display or hide the matched elements by animating their opacity."""
raise NotImplementedError
[docs] def filter(self, selector): # TODO - untested
"""Reduce the set of matched elements to those that match the selector or pass the function’s test."""
if isinstance(selector, str):
return self.elements.filter(selector)
elif callable(selector):
return [el for el in self.elements if selector(el)]
else:
raise TypeError("selector must be a string or a callable")
[docs] def find(self, selector):
"""Get the descendants of each element in the current set of matched elements, filtered by a selector,
dQuery object, or element."""
# if isinstance(selector, str):
# return self.elements.find(selector)
raise NotImplementedError
[docs] def finish(self):
"""Stop the currently-running animation, remove all queued animations, and complete all animations
for the matched elements."""
raise NotImplementedError
[docs] def first(self):
"""Reduce the set of matched elements to the first in the set."""
if isinstance(self.elements, (list, tuple)):
self.elements = self.elements[0]
return self
[docs] def focus(self):
"""Bind an event handler to the “focus” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
[docs] def focusin(self):
"""Bind an event handler to the “focusin” event."""
raise NotImplementedError
[docs] def focusout(self):
"""Bind an event handler to the “focusout” JavaScript event."""
raise NotImplementedError
# def get(self):
# """ Retrieve the DOM elements matched by the dQuery object."""
# raise NotImplementedError
[docs] def has(self, selector): # TODO - test
"""Reduce the set of matched elements to those that have a descendant
that matches the selector or DOM element."""
if isinstance(selector, str):
return self.elements.has(selector)
elif callable(selector):
return [el for el in self.elements if selector(el)]
else:
raise TypeError("selector must be a string or a callable")
[docs] def hasClass(self, classname):
"""Determine whether any of the matched elements are assigned the given class."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
if el.getAttribute("class") is not None:
if classname in el.getAttribute("class"):
return True
return False
[docs] def height(self):
"""Get the current computed height for the first element in the set of matched elements or set the height
of every matched element."""
raise NotImplementedError
[docs] def hide(self):
"""Hide the matched elements."""
for el in self.elements:
el.style.display = "none"
return self
[docs] def hover(self):
"""Bind one or two handlers to the matched elements, to be executed when the mouse pointer enters and
leaves the elements."""
raise NotImplementedError
[docs] def html(self, html=None):
"""Get the HTML contents of the first element in the set of matched elements or set the HTML contents
of every matched element."""
if html == None:
return self.elements[0].innerHTML
for el in self.elements:
el.innerHTML = html
return self
[docs] def index(self): # TODO - test
"""Search for a given element from among the matched elements."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for index, value in enumerate(self.elements):
if value == self.elements:
return index
return -1
[docs] def innerHeight(self):
"""Get the current computed inner height (including padding but not border) for the first element in the set
of matched elements or set the inner height of every matched element."""
raise NotImplementedError
[docs] def innerWidth(self):
"""Get the current computed inner width (including padding but not border) for the first element in the set
of matched elements or set the inner width of every matched element."""
raise NotImplementedError
[docs] def insertAfter(self, target): # TODO - test
"""Insert the matched elements after the specified target element."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
if isinstance(target, (list, tuple)):
for index, value in enumerate(target):
for el in self.elements:
el.insertAfter(value)
elif isinstance(target, str):
for el in self.elements:
el.insertAfter(target)
elif isinstance(target, Element):
for el in self.elements:
el.insertAfter(target)
return self
[docs] def insertBefore(self, target): # TODO - test
"""Insert every element in the set of matched elements before the target."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
if isinstance(target, (list, tuple)):
for index, value in enumerate(target):
for el in self.elements:
el.insertBefore(value)
elif isinstance(target, str):
for el in self.elements:
el.insertBefore(target)
elif isinstance(target, Element):
for el in self.elements:
el.insertBefore(target)
return self
# def is(self):
""" Check the current matched set of elements against a selector, element,
or dQuery object and return true if at least one of these elements matches the given arguments."""
# raise NotImplementedError
[docs] def keydown(self):
"""Bind an event handler to the “keydown” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
[docs] def keypress(self):
"""Bind an event handler to the “keypress” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
[docs] def keyup(self):
"""Bind an event handler to the “keyup” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
[docs] def last(self):
"""Reduce the set of matched elements to the final one in the set."""
if isinstance(self.elements, (list, tuple)):
self.elements = self.elements[len(self.elements) - 1]
return self
@property
def length(self):
"""The number of elements in the dQuery object."""
return len(self.elements)
[docs] def live(self):
"""Attach an event handler for all elements which match the current selector, now and in the future."""
raise NotImplementedError
[docs] def load(self, url, data=None, complete=None): # TODO - test
"""Load data from the server and place the returned HTML into the matched elements."""
if data is None:
data = {}
if complete is None:
complete = lambda x: x
for el in self.elements:
el.innerHTML = ""
el.innerHTML = "<div class='loading'></div>"
def load(el, url, data, complete):
def onload(response):
el.innerHTML = ""
el.innerHTML = response
complete(response)
dQuery.ajax(url, data, onload)
load(el, url, data, complete)
return self
[docs] def map(self, func): # TODO - test
"""Pass each element in the current matched set through a function,
producing a new dQuery object containing the return values."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
return dQuery(map(func, self.elements))
[docs] def mousedown(self):
"""Bind an event handler to the “mousedown” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
[docs] def mouseenter(self):
"""Bind an event handler to be fired when the mouse enters an element,
or trigger that handler on an element."""
raise NotImplementedError
[docs] def mouseleave(self):
"""Bind an event handler to be fired when the mouse leaves an element,
or trigger that handler on an element."""
raise NotImplementedError
[docs] def mousemove(self):
"""Bind an event handler to the “mousemove” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
[docs] def mouseout(self):
"""Bind an event handler to the “mouseout” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
[docs] def mouseover(self):
"""Bind an event handler to the “mouseover” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
[docs] def mouseup(self):
"""Bind an event handler to the “mouseup” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
[docs] def next(self, selector): # TODO - test
"""Get the immediately following sibling of each element in the set of matched elements.
If a selector is provided, it retrieves the next sibling only if it matches that selector."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
if isinstance(selector, str):
for el in self.elements:
el.next(selector)
elif isinstance(selector, Element):
for el in self.elements:
el.next(selector)
return self
[docs] def nextAll(self, selector):
"""Get all following siblings of each element in the set of matched elements,
optionally filtered by a selector."""
# if not isinstance(self.elements, (list, tuple)):
# self.elements = (self.elements,)
# for el in self.elements:
# el.nextAll(selector)
# return self
raise NotImplementedError
[docs] def nextUntil(self, selector):
"""Get all following siblings of each element up to but not including the element matched by the selector,
DOM node, or dQuery object passed."""
raise NotImplementedError
# def not(self):
""" Remove elements from the set of matched elements."""
# raise NotImplementedError
[docs] def odd(self): # TODO - untested
"""Reduce the set of matched elements to the odd ones in the set, numbered from zero."""
return self.filter(lambda x: x % 2 == 1)
[docs] def off(self, event):
"""Remove an event handler."""
for el in self.elements:
self.eventHandler.unbindEvent(event, el)
[docs] def offset(self, coordinates):
"""Get the current coordinates of the first element, or set the coordinates of every element,
in the set of matched elements, relative to the document."""
raise NotImplementedError
[docs] def offsetParent(self):
"""Get the closest ancestor element that is positioned."""
raise NotImplementedError
[docs] def on(self, event, callback):
"""Attach an event handler function for one or more events to the selected elements."""
for el in self.elements:
self.eventHandler.bindEvent(event, callback, el)
return self
[docs] def one(self):
"""Attach a handler to an event for the elements.
The handler is executed at most once per element per event type."""
raise NotImplementedError
[docs] def outerHeight(self):
"""Get the current computed outer height (including padding, border,
and optionally margin) for the first element in the set of matched elements or set the outer height
of every matched element."""
raise NotImplementedError
[docs] def outerWidth(self):
"""Get the current computed outer width (including padding, border, and optionally margin) for the
first element in the set of matched elements or set the outer width of every matched element."""
raise NotImplementedError
[docs] def parent(self, selector): # TODO - test
"""Get the parent of each element in the current set of matched elements,
optionally filtered by a selector."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
parents = []
if isinstance(selector, str):
for el in self.elements:
p = el.parent
parents.append(p)
return parents
[docs] def parents(self, selector): # TODO - untested
"""Get the ancestors of each element in the current set of matched elements,
optionally filtered by a selector."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
parents = []
if isinstance(selector, str):
for el in self.elements:
p = el.parents
parents.append(p)
return parents
[docs] def parentsUntil(self, selector):
"""Get the ancestors of each element in the current set of matched elements,
up to but not including the element matched by the selector, DOM node, or dQuery object."""
# if not isinstance(self.elements, (list, tuple)):
# self.elements = (self.elements,)
# parents = []
raise NotImplementedError
[docs] def position(self):
"""Get the current coordinates of the first element in the set of matched elements,
relative to the offset parent."""
raise NotImplementedError
[docs] def prepend(self, html):
"""Insert content, specified by the parameter, to the beginning of each element
in the set of matched elements."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
el.innerHTML = html + el.innerHTML
return self
[docs] def prependTo(self, target): # TODO - test
"""Insert every element in the set of matched elements to the beginning of the target."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
target.append(el)
return self
[docs] def prev(self, selector): # TODO - untested
"""Get the immediately preceding sibling of each element in the set of matched elements.
If a selector is provided, it retrieves the previous sibling only if it matches that selector."""
# if not isinstance(self.elements, (list, tuple)):
# self.elements = (self.elements,)
# prevs = []
# for el in self.elements:
# prev = el.prev
# # prevs.append(prev)
# if selector:
# if prev.matches(selector):
# prevs.append(prev)
# return prevs
raise NotImplementedError
[docs] def prevAll(self, selector): # TODO - untested
"""Get all preceding siblings of each element in the set of matched elements,
optionally filtered by a selector."""
# if not isinstance(self.elements, (list, tuple)):
# self.elements = (self.elements,)
# prevs = []
# for el in self.elements:
# prev = el.prevAll(selector)
# prevs.append(prev)
# return prevs
raise NotImplementedError
[docs] def prevUntil(self, selector): # TODO - untested
"""Get all preceding siblings of each element up to but not including the element matched by the selector,
DOM node, or dQuery object."""
# if not isinstance(self.elements, (list, tuple)):
# self.elements = (self.elements,)
# prevs = []
# for el in self.elements:
# prev = el.prevUntil(selector)
# prevs.append(prev)
# return prevs
raise NotImplementedError
[docs] def promise(self):
"""Return a Promise object to observe when all actions of a certain type bound to the collection,
queued or not, have finished."""
raise NotImplementedError
[docs] def prop(self, property, value):
"""Get the value of a property for the first element in the set of matched elements or set one or more properties
for every matched element."""
if value is not None:
if self.elements[0].getAttribute(property) is not None:
self.elements[0].setAttribute(property, value)
return self
if type(self.elements) is not tuple and type(self.elements) is not list:
return self.elements.getAttribute(property)
else:
return self.elements[0].getAttribute(property)
[docs] def pushStack(self, stack): # TODO - test
"""Add a collection of DOM elements onto the dQuery."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
el.append(stack)
return self
[docs] def queue(self):
"""Show or manipulate the queue of functions to be executed on the matched elements."""
raise NotImplementedError
[docs] def ready(self, callback):
"""Specify a function to execute when the DOM is fully loaded."""
raise NotImplementedError
[docs] def remove(self, items): # TODO - test
"""Remove the set of matched elements from the DOM."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
el.remove() # wont work . does this method even exist?
return self
[docs] def removeAttr(self, attr: str): # TODO - test
"""Remove an attribute from each element in the set of matched elements."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
el.removeAttribute(attr)
return self
[docs] def removeClass(self, classname: str):
"""Remove a single class, multiple classes, or all classes from each element in the set of matched elements."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
if el.getAttribute("class") is not None:
if classname in el.getAttribute("class"):
removed = "".join(el.getAttribute("class").split(classname)).strip()
removed = removed.replace(" ", " ")
el.setAttribute("class", removed)
return self
[docs] def removeData(self, name: str):
"""Remove a previously-stored piece of data."""
raise NotImplementedError
[docs] def removeProp(self, prop: str): # TODO -
"""Remove a property for the set of matched elements."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
el.removeAttribute(prop)
return self
[docs] def replaceAll(self, elements): # TODO - untested
"""Replace each target element with the set of matched elements."""
raise NotImplementedError
[docs] def replaceWith(self, replacement): # TODO - test
"""Replace each element in the set of matched elements with the provided new content and return the set
of elements that was removed."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
old_elements = []
for el in self.elements:
old_elements.append(el)
el.parentNode.replaceChild(replacement, el)
return self
[docs] def resize(self, callback):
"""Bind an event handler to the “resize” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
[docs] def select(self, selector):
"""Bind an event handler to the “select” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
[docs] def serialize(self):
"""Encode a set of form elements as a string for submission."""
# raise NotImplementedError
# from domonic.javascript import Global
if isinstance(self.elements, (tuple, list)):
form = self.elements[0]
else:
form = self.elements
if form.nodeName != "FORM":
return
q = []
for el in form.elements:
if el.getAttribute("name") == "":
continue
if el.nodeName == "INPUT":
if el.type in ["email", "text", "hidden", "password", "button", "reset", "submit", "email"]:
q.append(el.getAttribute("name") + "=" + Global.encodeURIComponent(el.nodeValue))
elif el.type in ["checkbox", "radio"]:
if el.checked:
q.append(el.getAttribute("name") + "=" + Global.encodeURIComponent(el.nodeValue))
elif el.nodeName == "TEXTAREA":
q.append(el.getAttribute("name") + "=" + Global.encodeURIComponent(el.nodeValue))
elif el.nodeName == "SELECT":
if el.getAttribute("multiple") != None:
for option in el.getElementsByTagName("option"):
if option.getAttribute("selected") != None:
q.append(el.getAttribute("name") + "=" + Global.encodeURIComponent(option.nodeValue))
else:
q.append(el.getAttribute("name") + "=" + Global.encodeURIComponent(el.nodeValue))
elif el.nodeName == "BUTTON":
if el.type in ["reset", "submit", "button"]:
q.append(el.getAttribute("name") + "=" + Global.encodeURIComponent(el.nodeValue))
return "&".join(q)
[docs] def serializeArray(self, array):
"""Encode an array of form elements as a string for submission."""
raise NotImplementedError
[docs] def show(self):
"""Display the matched elements."""
for el in self.elements:
el.style.display = ""
return self
[docs] def siblings(self, selector): # TODO - untested
"""Return the siblings of the matched elements. filter by selector."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
siblings = []
for el in self.elements:
siblings.append(el.parentNode.getElementsByTagName(selector))
return siblings
[docs] def size(self):
"""Return the number of elements in the dQuery object."""
return len(self.elements)
[docs] def slice(self, start, end): # TODO - test
"""Return a new dQuery object containing the set of matched elements starting at the specified index
and ending at the specified index."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
return dQuery(self.elements[start:end])
[docs] def slideDown(self):
"""Display the matched elements with a sliding motion."""
raise NotImplementedError
[docs] def slideToggle(self):
"""Display or hide the matched elements with a sliding motion."""
raise NotImplementedError
[docs] def slideUp(self):
"""Hide the matched elements with a sliding motion."""
raise NotImplementedError
[docs] def stop(self):
"""Stop the currently-running animation on the matched elements."""
raise NotImplementedError
[docs] def submit(self):
"""Bind an event handler to the “submit” JavaScript event, or trigger that event on an element."""
raise NotImplementedError
[docs] def text(self, newVal: str = None):
"""Get the combined text contents of each element in the set of matched elements, including their descendants,
or set the text contents of the matched elements."""
if newVal is not None:
for el in self.elements:
el.textContent = newVal
else:
return [el.textContent for el in self.elements]
[docs] def toArray(self):
"""Retrieve all the elements contained in the dQuery set, as an array."""
# raise NotImplementedError
if isinstance(self.elements, (list, tuple)):
return self.elements
else:
return [self.elements]
[docs] def toggle(self): # TODO - test
"""Display or hide the matched elements."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
el.style.display = "" if el.style.display == "none" else "none"
return self
# @_listify
[docs] def toggleClass(self, className):
"""
Add or remove one or more classes from each element in the set of matched elements
"""
# TODO - untested / not working
# if not isinstance(self.elements, (list, tuple)):
# self.elements = (self.elements,)
# for el in self.elements:
# if º(el).hasClass(className):
# º(el).addClass(className)
# else:
# º(el).removeClass(className)
raise NotImplementedError
[docs] def trigger(self, eventName, eventArg=None): # TODO - test
"""Execute all handlers and behaviors attached to the matched elements for the given event type."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
if el.nodeName == "A":
# el.triggerEvent(eventName, eventArg)
el.dispatchEvent(eventName, eventArg)
else:
# el.trigger(eventName, eventArg)
el.dispatchEvent(eventName, eventArg)
return self
[docs] def triggerHandler(self):
"""Execute all handlers attached to an element for an event."""
raise NotImplementedError
[docs] def unbind(self):
"""Remove a previously-attached event handler from the elements."""
raise NotImplementedError
[docs] def undelegate(self):
"""Remove a handler from the event for all elements which match the current selector,
based upon a specific set of root elements."""
raise NotImplementedError
[docs] def unload(self):
"""Bind an event handler to the “unload” JavaScript event."""
raise NotImplementedError
[docs] def unwrap(self): # TODO - untested
"""Remove the parents of the set of matched elements from the DOM,
leaving the matched elements in their place."""
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
if el.parentNode.parentNode:
el.parentNode.parentNode.replaceChild(el, el.parentNode)
return self
[docs] def val(self, newVal=None):
"""Get the current value of the first element in the set of matched elements
or set the value of every matched element."""
if newVal is not None:
for el in self.elements:
el.value = newVal
else:
return self.elements.value
# return self
[docs] def width(self):
"""Get the current computed width for the first element in the set of matched elements
or set the width of every matched element."""
raise NotImplementedError
[docs] def wrap(self, wrappingElement): # TODO - untested
"""Wrap an HTML structure around each element in the set of matched elements."""
if isinstance(wrappingElement, str):
from domonic.html import create_element
wrappingElement = create_element(wrappingElement)
if not isinstance(self.elements, (list, tuple)):
self.elements = (self.elements,)
for el in self.elements:
wrappingElement.appendChild(el)
el.parentNode.replaceChild(wrappingElement, el)
return self
[docs] def wrapAll(self, wrappingElement):
"""Wrap an HTML structure around all elements in the set of matched elements."""
raise NotImplementedError
[docs] def wrapInner(self):
"""Wrap an HTML struct"""
raise NotImplementedError
# class Callbacks(): # TODO - untested. copilot wrote it
# def __init__(self):
# self.callbacks = {}
# def add(self, callback, *args):
# """[Add a callback or a collection of callbacks to a callback list.]
# Args:
# callback (function): [a callback]
# """
# if callback in self.callbacks:
# self.callbacks[callback].append(args)
# else:
# self.callbacks[callback] = [args]
# def disable(self, callback):
# """[Disable a callback or a collection of callbacks from doing anything.]
# Args:
# callback (function): [a callback]
# """
# self.callbacks[callback] = []
# def disabled(self, callback):
# """ Determine if the callbacks list has been disabled."""
# return callback not in self.callbacks
# def empty(self, callback):
# """ Remove all of the callbacks from a list."""
# if callback in self.callbacks:
# del self.callbacks[callback]
# def fire(self, *args):
# """ Call all of the callbacks with the given arguments. """
# for callback in self.callbacks:
# callback(*args)
# def fired(self, *args):
# """ Determine if the callbacks have already been called at least once."""
# return self.callbacks.fired
# def fireWith(self, *args):
# """[Fire the callback(s) with the given arguments.]
# Args:
# callback (function): [a callback]
# """
# self.fire(*args)
# def has(self, callback=None):
# """ Determine whether or not the list has any callbacks attached.
# If a callback is provided as an argument, determine whether it is in a list. """
# if callback is None:
# return bool(self.callbacks)
# return callback in self.callbacks
# def lock(self):
# """ Lock a callback list in its current state. """
# # TODO - test
# raise NotImplementedError
# def locked(self):
# """ Determine whether or not the callback list is locked."""
# return self.lock
# def remove(self, callback):
# """[Remove a callback or a collection of callbacks from a callback list.]
# Args:
# callback (function): [a callback]
# """
# if callback in self.callbacks:
# del self.callbacks[callback]
# else:
# raise ValueError
# class Deferred():
# def __init__(self):
# pass
# def always(self, *args):
# """ Add handlers to be called when the Deferred object is either resolved or rejected."""
# raise NotImplementedError
# def catch(self, *args):
# """ Add handlers to be called when the Deferred object is rejected. """
# raise NotImplementedError
# def done(self, *args):
# """ Add handlers to be called when the Deferred object is resolved. """
# def fail(self):
# """ Add handlers to be called when the Deferred object is rejected."""
# raise NotImplementedError
# def isRejected(self):
# """ Determine whether a Deferred object has been rejected."""
# raise NotImplementedError
# def isResolved(self):
# """ Determine whether a Deferred object has been resolved."""
# raise NotImplementedError
# def notify(self):
# """ Call the progressCallbacks on a Deferred object with the given args."""
# raise NotImplementedError
# def notifyWith(self):
# """ Call the progressCallbacks on a Deferred object with the given context and args."""
# raise NotImplementedError
# def pipe(self):
# """ Utility method to filter and/or chain Deferreds."""
# raise NotImplementedError
# def progress(self):
# """ Add handlers to be called when the Deferred object generates progress notifications."""
# raise NotImplementedError
# def promise(self):
# """ Return a Deferred’s Promise object."""
# raise NotImplementedError
# def reject(self):
# """ Reject a Deferred object and call any failCallbacks with the given args."""
# raise NotImplementedError
# def rejectWith(self):
# """ Reject a Deferred object and call any failCallbacks with the given context and args."""
# raise NotImplementedError
# def resolve(self):
# """ Resolve a Deferred object and call any doneCallbacks with the given args."""
# raise NotImplementedError
# def resolveWith(self):
# """ Resolve a Deferred object and call any doneCallbacks with the given context and args."""
# raise NotImplementedError
# def state(self):
# """ Determine the current state of a Deferred object."""
# raise NotImplementedError
# def then(self):
# """ Add handlers to be called when the Deferred object is resolved, rejected, or still in progress."""
# raise NotImplementedError
# class Event():
# def __init__(self):
# self.currentTarget = None
# self.data = None
# self.delegateTarget = None
# self.metaKey = None
# self.namespace = None
# self.pageX = None
# self.pageY = None
# self.relatedTarget = None
# self.result = None
# self.target = None
# self.timeStamp = None
# self.type = None
# self.which = None
# def isDefaultPrevented(self):
# """ Returns whether event.preventDefault() was ever called on this event object."""
# pass
# def isImmediatePropagationStopped(self):
# """ Returns whether event.stopImmediatePropagation() was ever called on this event object."""
# pass
# def isPropagationStopped(self):
# """ Returns whether event.stopPropagation() was ever called on this event object."""
# pass
# def preventDefault(self):
# """ If this method is called,
# the default action of the event will not be triggered."""
# pass
# def stopImmediatePropagation(self):
# """ Keeps the rest of the handlers from being executed and
# prevents the event from bubbling up the DOM tree."""
# pass
# def stopPropagation(self):
# """ Prevents the event from bubbling up the DOM tree, preventing any parent handlers
# from being notified of the event."""
# pass
def dproxy(q):
el = dQuery_el(q)
el.init(q)
# if type(q) is not str:
return el
# else:
# return el.elements
# def __str__(self):
# return self.elements
class º(dQuery_el):
def __init__(self, selector=None, *args, **kwargs):
super().__init__(selector, *args, **kwargs)
self.init(selector)
def __call__(self, *args, **kwargs):
return dproxy(args[0])
@staticmethod
def ajax(
url="/", type="GET", data=None, contentType=False, processData=False, cache=False, success=None, error=None
):
"""make an ajax request"""
try:
# r = requests.get(url, timeout=3)
from requests import Request, Session
method = type
# if "callback_function" in kwargs:
# del kwargs["callback_function"]
# if "error_handler" in kwargs:
# del kwargs["error_handler"]
# headers = {'Content-type': contentType}
s = Session()
req = Request(method, url, data=data) # , headers=headers)
prepped = s.prepare_request(req)
# prepped.body = 'hello'
# prepped.headers['Keep-Dead'] = 'parrot'
r = s.send(prepped) # , **kwargs)
# resp = s.send(prepped,
# stream=stream,
# verify=verify,
# proxies=proxies,
# cert=cert,
# timeout=timeout
# )
# print(r.status_code)
if r.status_code == 200:
# print('sup')
if success is not None:
success(r.text)
else:
# print('sup2')
if error is not None:
error(r.text)
s.close()
return r
except Exception as e:
print(f"Request Failed for URL: {url}", e)
return None
@staticmethod
def ajaxPrefilter():
"""Handle custom Ajax options or modify existing options before each request is sent
and before they are processed by .ajax"""
raise NotImplementedError
@staticmethod
def ajaxSetup():
"""Set default values for future Ajax requests. Its use is not recommended."""
raise NotImplementedError
@staticmethod
def ajaxTransport():
"""Creates an object that handles the actual transmission of Ajax data."""
raise NotImplementedError
# @staticmethod
# @ty
# def boxModel:
# """ States if the current page, in the user’s browser, is being rendered using the W3C CSS Box Model. """
# raise NotImplementedError
# @staticmethod
# @ty
# def browser:
""" Contains flags for the useragent, read from navigator.userAgent. """
# raise NotImplementedError
@staticmethod
def Callbacks():
"""A multi-purpose callbacks list object that provides a powerful way to manage callback lists."""
raise NotImplementedError
@staticmethod
def contains(parent, child):
"""Check to see if a DOM element is a descendant of another DOM element."""
return parent.contains(child)
# @staticmethod
# @ty
# def cssHooks:
""" Hook directly into dQuery to override how particular CSS properties are retrieved or set,
normalize CSS property naming, or create custom properties. """
# raise NotImplementedError
# @staticmethod
# @ty
# def cssNumber:
""" An object containing all CSS properties that may be used without a unit.
The .css method uses this object to see if it may append px to unitless values. """
# raise NotImplementedError
@staticmethod
def data():
"""Store arbitrary data associated with the specified element and/or return the value that was set."""
raise NotImplementedError
@staticmethod
def Deferred():
"""A factory function that returns a chainable utility object with methods to register multiple callbacks
into callback queues, invoke callback queues, and relay the success or failure state of
any synchronous or asynchronous function."""
raise NotImplementedError
@staticmethod
def dequeue():
"""Execute the next function on the queue for the matched element."""
raise NotImplementedError
@staticmethod
def each(arr, func): # TODO - untested
"""A generic iterator function, which can be used to seamlessly iterate over both objects and arrays."""
for i in arr:
func(i)
@staticmethod
def error(msg):
"""Takes a string and throws an exception containing it."""
raise Exception(msg)
@staticmethod
def escapeSelector(selector): # TODO - untested
"""Returns a string with all special characters replaced with their respective character codes."""
if type(selector) is str:
selector = (
selector.replace(" ", "\\s")
.replace(".", "\\.")
.replace("#", "\\#")
.replace("[", "\\[")
.replace("]", "\\]")
)
# selector = re.sub(r'([^\w\.-])', '\\\1', selector)
return selector.replace(" ", "%20")
else:
return selector
@staticmethod
def extend(*args):
"""Merge the contents of two or more objects together into the first object."""
result = {}
for each in args:
result.update(each)
return result
@staticmethod
def get(url: str, data=None, dataType=False, success=None, error=None):
"""[simplified ajax request]
Args:
url (str): [the url to request]
data ([type]): [the data to send]
dataType (bool, optional): [the dataType]. Defaults to False.
success ([type], optional): [a success function]. Defaults to None.
error ([type], optional): [an error method]. Defaults to None.
Returns:
[type]: [the response]
"""
# print("GO!")
# r = requests.get(url)
# return r.content.decode("utf-8")
r = º.ajax(
{
"url": url,
# 'data': data,
# 'success': success,
# 'dataType': dataType
}
)
return r.content.decode("utf-8")
@staticmethod
def getJSON():
"""Load JSON-encoded data from the server using a GET HTTP request."""
raise NotImplementedError
@staticmethod
def getScript(filename, *args):
"""execute another python file."""
from subprocess import Popen
Popen("python " + filename + ".py")
@staticmethod # TODO - test
def globalEval(code):
"""Execute some python code globally."""
return eval(code, globals(), locals())
@staticmethod # TODO - test
def grep(arr, func):
"""Returns an array of elements from the original array which satisfy a filter function."""
return list(filter(func, arr))
@staticmethod
def hasData(element):
"""Determine whether an element has any dQuery data associated with it."""
raise NotImplementedError
@staticmethod
def holdReady():
"""Holds or releases the execution of dQuery’s ready event."""
raise NotImplementedError
@staticmethod
def htmlPrefilter():
"""Modify and filter HTML strings passed through dQuery manipulation methods."""
raise NotImplementedError
@staticmethod
def inArray(thing, arr):
"""Search for a specified value within an array and return its index or -1 if not found."""
for count, each in enumerate(arr):
if thing == each:
return count
return -1
@staticmethod
def isArray(item):
"""Determine whether the argument is an array."""
return type(item) == Array
@staticmethod
def isEmptyObject(dct):
"""Check to see if an object is empty (contains no enumerable properties)."""
return not bool(dct)
@staticmethod
def isFunction(obj):
"""Determines if its argument is callable as a function."""
return callable(obj)
@staticmethod
def isNumeric(thing):
"""Determine whether the argument is numeric."""
return type(thing) in (int, float, Number)
@staticmethod
def isPlainObject(obj):
"""Check to see if an object is a plain object created using '{}'"""
return type(obj) is dict
@staticmethod
def isWindow(obj):
"""Determine whether the argument is a window object."""
return type(obj) is Window
@staticmethod
def isXMLDoc(obj):
"""Check to see if a DOM node is within an XML document (or is an XML document)."""
obj = str(obj)
return obj.startswith("<") and obj.endswith(">")
@staticmethod
def makeArray(somelist):
"""Convert an array-like object into a true JavaScript array."""
return Array(somelist)
@staticmethod
def map(arr, func):
"""Translate all items in an array or object to new array of items."""
return [func(value) for value in arr]
@staticmethod
def merge(one, *args):
"""Merge the contents of arrays into the first array."""
import itertools
one.append(list(itertools.chain(*args)))
return one
@staticmethod
def noConflict():
"""Relinquish dQuery’s control of the º variable."""
raise NotImplementedError
@staticmethod
def noop():
"""An empty function."""
pass
@staticmethod
def now():
"""Return a number representing the current time."""
return Date.now()
@staticmethod
def param(obj):
"""Create a serialized representation of an array, a plain object,
or a dQuery object suitable for use in a URL query string or Ajax request.
In case a dQuery object is passed, it should contain input elements with name/value properties."""
if isinstance(obj, list):
return json.dumps(obj)
elif isinstance(obj, dict):
return json.dumps(obj)
elif isinstance(obj, dQuery):
return json.dumps(obj.inputs)
else:
raise TypeError(obj)
@staticmethod
def parseHTML(string):
"""Parses a string into an array of DOM nodes."""
# from bs4 import BeautifulSoup
# return BeautifulSoup(string, 'html.parser')
# return BeautifulSoup(string, 'html5lib')
# return BeautifulSoup(string, 'lxml')
# return domonic.domonic.parseString(string, 'domonic')
# return domonic.domonic.parseString(string, 'expat')
return domonic.domonic.parseString(string)
@staticmethod
def parseJSON(string: str):
"""Takes a well-formed JSON string and returns the resulting JavaScript value."""
raise NotImplementedError
@staticmethod
def parseXML(string: str):
"""Parses an XMLstring into a pyml"""
from domonic.domonic import parseString
return parseString(string)
@staticmethod
def post(url, data, success):
"""Send data to the server using a HTTP POST request."""
r = requests.post(url, data)
# if r.ok:
# succss()
return r.content.decode("utf-8")
@staticmethod
def proxy(func):
"""Takes a function and returns a new one that will always have a particular context."""
raise NotImplementedError
@staticmethod
def queue(func):
"""Show or manipulate the queue of functions to be executed on the matched element."""
raise NotImplementedError
# @staticmethod
# @ty
# def ready:
# """ A Promise-like object or “thenable” that resolves when the document is ready. """
# raise NotImplementedError
@staticmethod
def readyException():
"""Handles errors thrown synchronously in functions wrapped in dQuery"""
raise NotImplementedError
@staticmethod
def removeData():
"""Remove a previously-stored piece of data."""
raise NotImplementedError
# @staticmethod
# @ty
# def speed:
# """ Creates an object containing a set of properties ready to be used in the definition
# of custom animations. """
# raise NotImplementedError
@staticmethod
def sub():
"""Creates a new copy of dQuery whose properties and methods can be modified without affecting
the original dQuery object."""
raise NotImplementedError
# @staticmethod
# def t:
# """ A collection of properties that represent the presence of different browser features or bugs. """
# raise NotImplementedError
@staticmethod
def trim(content: str) -> str:
"""Remove the whitespace from the beginning and end of a string."""
content = content.replace("\n", "").replace("\t", "").replace("\r", "").strip()
return content
# @staticmethod
# def type():
# """ Determine the internal JavaScript [[Class]] of an object. """
# raise NotImplementedError
@staticmethod
def unique(arr): # TODO - test
"""[removes duplicate elements.]
Args:
arr ([type]): [list of elements]
Returns:
[type]: [a sorted array without duplicates]
"""
return list(set(arr))
@staticmethod
def uniqueSort(arr): # TODO - test
"""Sorts an array of DOM elements, in place, with the duplicates removed.
Note that this only works on arrays of DOM elements, not strings or numbers."""
arr.sort()
arr = list(set(arr))
arr.sort()
return arr
@staticmethod
def when():
"""Provides a way to execute callback functions based on zero or more Thenable objects,
usually Deferred objects that represent asynchronous events."""
raise NotImplementedError
dQuery = º