void HTMLElementImp::setOnclick(html::Function onclick) { DocumentImp* document = getOwnerDocumentImp(); DocumentWindowPtr window = document->activate(); addEventListener(u"click", new(std::nothrow) EventListenerImp(boost::bind(&ECMAScriptContext::dispatchEvent, window->getContext(), onclick, _1))); }
void HTMLObjectElementImp::eval() { HTMLElementImp::eval(); HTMLElementImp::evalBorder(this); HTMLElementImp::evalHeight(this); HTMLElementImp::evalWidth(this); HTMLElementImp::evalHspace(this); HTMLElementImp::evalVspace(this); if (!active) return; std::u16string classid = getAttribute(u"classid"); if (!classid.empty()) { active = false; return; } std::u16string data = getAttribute(u"data"); if (data.empty()) { active = false; return; } std::u16string type = getAttribute(u"type"); // TODO: Check type is a supported one. DocumentImp* document = getOwnerDocumentImp(); request = new(std::nothrow) HttpRequest(document->getDocumentURI()); if (request) { request->open(u"GET", data); request->setHandler(boost::bind(&HTMLObjectElementImp::notify, this)); document->incrementLoadEventDelayCount(); request->send(); } else active = false; }
void HTMLStyleElementImp::handleMutation(EventListenerImp* listener, events::Event event) { // TODO: update type, media, and scoped. Then check type. events::MutationEvent mutation(interface_cast<events::MutationEvent>(event)); DocumentImp* document = getOwnerDocumentImp(); if (!document) return; if (mutation.getType() == u"DOMNodeRemoved" && event.getTarget().self() == this) styleSheet = 0; else { std::u16string content; for (Node node = getFirstChild(); node; node = node.getNextSibling()) { if (TextImp* text = dynamic_cast<TextImp*>(node.self())) // TODO better to avoid imp call? content += text->getData(); } CSSParser parser; styleSheet = parser.parse(document, content); if (auto imp = dynamic_cast<CSSStyleSheetImp*>(styleSheet.self())) { imp->setOwnerNode(this); if (4 <= getLogLevel()) dumpStyleSheet(std::cerr, imp); } } if (WindowImp* view = document->getDefaultWindow()) view->setFlags(Box::NEED_SELECTOR_REMATCHING); document->resetStyleSheets(); }
void HTMLElementImp::xblEnteredDocument(Node node) { while (node) { if (auto element = dynamic_cast<HTMLElementImp*>(node.self())) { if (element->shadowTarget && !element->shadowImplementation) { DocumentImp* document = element->getOwnerDocumentImp(); DocumentWindowPtr window = document->activate(); ECMAScriptContext* context = window->getContext(); element->shadowImplementation = context->xblCreateImplementation(element->shadowTarget, element->bindingImplementation, element, element->shadowTree); element->shadowImplementation.xblEnteredDocument(); } } if (node.hasChildNodes()) xblEnteredDocument(node.getFirstChild()); node = node.getNextSibling(); } }
void HTMLImageElementImp::notify() { if (request->getStatus() != 200) active = false; else { // TODO: Check type delete image; image = new(std::nothrow) BoxImage; if (!image) active = false; else { if (FILE* file = request->openFile()) { image->open(file); fclose(file); } if (image->getState() != BoxImage::CompletelyAvailable) { active = false; delete image; image = 0; } } } if (Box* box = getBox()) { box->setFlags(Box::NEED_REFLOW); Box* ancestor = box->getParentBox(); if (ancestor && !dynamic_cast<Block*>(ancestor)) { // Update inline image ancestor = ancestor->getParentBox(); while (ancestor && !dynamic_cast<Block*>(ancestor)) ancestor = ancestor->getParentBox(); if (ancestor) ancestor->setFlags(Box::NEED_REFLOW); } } DocumentImp* document = getOwnerDocumentImp(); document->decrementLoadEventDelayCount(); }
void HTMLElementImp::generateShadowContent(CSSStyleDeclarationImp* style) { if (style->binding.getValue() != CSSBindingValueImp::Uri || style->display.getValue() == CSSDisplayValueImp::None) return; if (getShadowTree()) // already attached? return; DocumentImp* document = getOwnerDocumentImp(); assert(document); URL base(document->getDocumentURI()); URL url(base, style->binding.getURL()); if (!base.isSameExceptFragments(url)) { document = dynamic_cast<DocumentImp*>(document->loadBindingDocument(url).self()); if (!document || document->getReadyState() != u"complete") return; } std::u16string hash = url.getHash(); if (hash[0] == '#') hash.erase(0, 1); Element element = document->getElementById(hash); if (!element) return; auto binding = dynamic_cast<HTMLBindingElementImp*>(element.self()); if (!binding) return; bindingImplementation = binding->getImplementation(); if (!bindingImplementation) return; if (html::HTMLTemplateElement shadowTree = binding->cloneTemplate()) { setShadowTree(shadowTree); shadowTarget = new(std::nothrow) EventTargetImp; // TODO: if (not called from the background thread) { #if 0 DocumentWindowPtr window = document->activate(); ECMAScriptContext* context = window->getContext(); shadowImplementation = context->xblCreateImplementation(shadowTarget, bindingImplementation, this, shadowTree); shadowImplementation .xblEnteredDocument(); } #endif }
bool EventTargetImp::dispatchEvent(events::Event evt) { EventImp* event = dynamic_cast<EventImp*>(evt.self()); if (!event) return false; event->setDispatchFlag(true); if (auto documentWindow = dynamic_cast<DocumentWindow*>(this)) event->setTarget(documentWindow->getWindowImp()); else event->setTarget(this); if (NodeImp* node = dynamic_cast<NodeImp*>(this)) { DocumentImp* document = dynamic_cast<DocumentImp*>(node); if (!document) document = node->getOwnerDocumentImp(); assert(document); document->enter(); std::list<EventTargetImp*> eventPath; for (NodeImp* ancestor = node->parentNode; ancestor; ancestor = ancestor->parentNode) { if (auto shadowTree = dynamic_cast<HTMLTemplateElementImp*>(ancestor)) { if (NodeImp* host = dynamic_cast<NodeImp*>(shadowTree->getHost().self())) { // TODO: Fix 'target' of the event as well. // TODO: Check the mouseover and mouseout events. ancestor = host; if (!dynamic_cast<UIEventImp*>(event)) { // To repaint the window, we still need to notify the bound document // of the event. // TODO: Support nesting of bound elements. eventPath.push_front(ancestor->getOwnerDocumentImp()); break; } } } eventPath.push_front(ancestor); } // cf. http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#events-and-the-window-object if (document && event->getType() != u"load") { if (WindowImp* view = document->getDefaultWindow()) eventPath.push_front(view->getDocumentWindow().get()); } event->setEventPhase(events::Event::CAPTURING_PHASE); for (auto i = eventPath.begin(); i != eventPath.end(); ++i) { if (event->getStopPropagationFlag()) break; event->setCurrentTarget(*i); (*i)->invoke(event); } event->setEventPhase(events::Event::AT_TARGET); if (!event->getStopPropagationFlag()) { event->setCurrentTarget(node); node->invoke(event); } if (event->getBubbles()) { event->setEventPhase(events::Event::BUBBLING_PHASE); for (auto i = eventPath.rbegin(); i != eventPath.rend(); ++i) { if (event->getStopPropagationFlag()) break; event->setCurrentTarget(*i); (*i)->invoke(event); } } if (!event->getDefaultPrevented()) { // TODO: Call default actions; // cf. http://www.w3.org/TR/DOM-Level-3-Events/#event-flow-default-cancel // cf. http://www.w3.org/TR/xbl/#the-default-phase0 event->setEventPhase(EventImp::DEFAULT_PHASE); event->setCurrentTarget(node); node->invoke(event); if (event->getBubbles()) { for (auto i = eventPath.rbegin(); i != eventPath.rend(); ++i) { if (event->getDefaultPrevented()) break; event->setCurrentTarget(*i); (*i)->invoke(event); } } } document->exit(); } else if (DocumentWindow* window = dynamic_cast<DocumentWindow*>(this)) { auto proxy = dynamic_cast<WindowImp*>(window->getDocument().getDefaultView().self()); window->enter(proxy); event->setEventPhase(events::Event::AT_TARGET); event->setCurrentTarget(this); invoke(event); window->exit(proxy); } event->setDispatchFlag(false); event->setEventPhase(events::Event::AT_TARGET); event->setCurrentTarget(0); return !event->getDefaultPrevented(); }