phpgt / dom Goto Github PK
View Code? Open in Web Editor NEWModern DOM API.
Home Page: https://www.php.gt/dom
License: MIT License
Modern DOM API.
Home Page: https://www.php.gt/dom
License: MIT License
https://developer.mozilla.org/en-US/docs/Web/API/XMLDocument
It inherits from the generic Document and do not add any specific methods or properties to it: nevertheless, several algorithms behave differently with the two types of documents.
Shall we implement this for the sake of completeness?
https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker
Description of how this functionality can be achieved is found within the notes on DOMNodeList
docs page: http://php.net/manual/en/class.domnodelist.php
The different core traversals are listed here: https://www.w3.org/TR/ElementTraversal/#rel-dom1core
4.1. DOM Level 1 Core
This specification provides an interface that has functional similarity to the DOM navigation attributes of DOM 1 Core, but operates only on element nodes, not other node types. The most comparable DOM 1 Core attributes are firstChild, lastChild, previousSibling, nextSibling, and nodeList.length.
4.2. DOM Level 2 Traversal & Range
Document Object Model Level 2 Traversal & Range is a comprehensive document navigation specification, but may require more device and implementor resources than Element Traversal. As Element Traversal consists of an optimized subset of the functionality of DOM 2 Traversal, a user agent that implements both may do so in a way that leverages the functionality of Traversal.
4.3. DOM Level 3 Core
This is a supplementary specification to DOM 3 Core.
The latest commits have seriously lowered the test coverage... Need to be pretty close to 100% before v1.0.0 release.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement
I noticed there was no support for this type of element when I tried to get the label
property of an input. If an input element has an associated label, in JavaScript, it can be accessed via the label
property.
Curiously, label
isn't documented on MDN, but does in fact work... needs investigating.
If the build process involves code coverage (which it does according to the php unit config), xdebug is required for development.
Using shields.io, add a badge that matches the others to show the current version release in Packagist.
Symfony's looks like this:
https://www.w3.org/TR/DOM-Level-2-HTML/changes.html
A.1.1: Changes to DOM Level 1 interfaces and exceptions
Interface HTMLDocument
the method getElementById is now inherited from the Document interface [DOM Level 2 Core] where it was moved.
Interface HTMLSelectElement
The type of the attribute options was changed from HTMLCollection to HTMLOptionsCollection.
The attribute length is no longer readonly and is now unsigned.
Interface HTMLOptionElement
Changing the defaultSelected attribute does not reset the state of the form control.
index is readonly.
Interface HTMLInputElement
the attribute type is no longer read only.
The type of the attribute size was changed from DOMString to unsigned long.
Interface HTMLTextAreaElement
Changing the defaultValue attribute does not reset the contents of the form control.
Interface HTMLBlockquoteElement
this interface has been removed. BLOCKQUOTE elements are now supported by the HTMLQuoteElement interface.
Interface HTMLBaseFontElement
The attribute size is of type long.
Interface HTMLImageElement
The lowSrc attribute was removed.
The types of the attributes height, hspace, width and vspace were changed from DOMString to long.
Interface HTMLObjectElement
The attribute contentDocument was added.
Interface HTMLAppletElement
The types of the attributes hspace and vspace were changed from DOMString to long.
The attribute object returns the value of the HTML object attribute.
Interface HTMLTableElement
caption, tHead, tFoot, insertRow, and deleteRow may raise exceptions.
index uses a logical order, and not a document order.
Interface HTMLTableSectionElement
The methods insertRow and deleteRow may raise exceptions.
Interface HTMLTableRowElement
The attributes rowIndex, sectionRowIndex, and cells are readonly.
The methods insertCell and deleteCell may raise exceptions.
rowIndex uses a logical order, and not a document order.
Interface HTMLFrameElement
the attribute contentDocument was added.
Interface HTMLIFrameElement
the attribute contentDocument was added.
Module and package name
The module name used in the OMG IDL is now html2.
The package name used in the Java bindings is now org.w3c.dom.html2.
A.1.2: New InterfacesInterface HTMLOptionsCollection
The HTMLOptionsCollection interface was added to the HTML module.
This is an issue with the underlying libxml implementation, but it should be this repo's responsibility to fix.
<?php
$html = <<<HTML
<!doctype html>
<h1>Hello!</h1>
<script>
// here is some HTML enclosed in strings within the script tag.
// but when the DOMDocument is output, the div tags are stripped/manipulated... why?
var startingTag = '<div>';
var endingTag = '</div>';
</script>
<h2>Goodbye!</h2>
HTML;
$document = new DOMDocument("1.0", "utf-8");
libxml_use_internal_errors(true);
$document->loadHTML($html);
echo $document->saveHTML();
Outputs:
<!DOCTYPE html>
<html><body><h1>Hello!</h1>
<script>
// here is some HTML enclosed in strings within the script tag.
// but when the DOMDocument is output, the div tags are stripped/manipulated... why?
var startingTag = '<div>';
var endingTag = '';
</script><h2>Goodbye!</h2></body></html>
Notice that the ending tag within the string is removed by libxml. It's going to be a hack to fix this without replacing libxml, but a useful hack nonetheless.
Passing in a DOMDocument rather than a string of HTML would be beneficial to a project I was working on earlier this week.
Good documentation:
In certain browsers Custom Elements can be used to define markup, style and behaviour of reusable components of a website. Providing custom elements support on the server is a really clean way of getting the benefits of custom elements, with the added benefit of pre-rendering everything on the server (for caching purposes).
The browser version of this feature works like this:
<app-calendar date="2012-06-14"></app-calendar>
The PHP version should work like this:
<app-calendar date="2012-06-14"></app-calendar>
src/component/app-calendar.scss
src/component/app-calendar.js
, src/component/app-calendar.html
, src/component/app-calendar.php
Everything will automatically register and get linked for you. If there is no matching files within the component directory, it is left for client-side web component support to pick up.
When using the DOM instead of a template engine, manipulating the page via CSS selectors unnecessarily couples the data to the markup.
An inject data method will take an associative array and apply it to the document (or a node), outputting the contents of the data to the page where a matching attribute is found.
The key of the associative array will be used to match against a DOM attribute, e.g. the name attribute of elements on the page.
To help protect the design of the underlying data structure, a specified attribute can be used, which is removed from the page at render.
Should we be using extends
rather than use
ing the traits?
HTMLCollections already have the $length
property, but they should respond to count()
with the same value.
Simply running phpunit
in the directory doesn't execute any tests because it can't find the correct classes through composer.
Originaled reported in #13:
alvaro@alvaro-pc:~/Documents/dom$ phpunit PHP Fatal error: Trait 'phpgt\dom\LiveProperty' not found in /home/alvaro/Documents/dom/test/ExampleLiveProperty.php on line 5
https://www.w3.org/TR/DOM-Level-2-Traversal-Range/traversal.html
This needs to be addressed within the DOM, to allow serverside usage of templates, but the template factory-style interfaces should be contained within their own repository.
https://www.w3.org/TR/selectors-api/
Basically, querySelector
and querySelectorAll
capability.
The HTMLElement
interface has some server-side capabilities that a normal Element
doesn't, but the main point in introducing this class is to allow other classes to extend the functionality of a normal Element.
For example, input
elements and select
elements have certain capabilities according to their state. Rather than adding conditional logic into the main Element
class for each type of sub-element, the logic should exist in its own Element-derived class.
The select
element behaves differently to input
, as they don't have their own value
attribute - instead, the selected option
element's value should be returned.
Setting the value of a select element should set the selected attribute to the matching option, if one matches.
Potential pitfall: when a select element has no "selected" option, the value should default to the first option.
Would be very useful to either implement StreamInterface or provide a method that gets one, to allow HTMLDocument
s to be used easily with PSR7 ResponseInterface
s.
When developing the implementation in phpgt v2, this Stack Overflow answer helped tremendously: http://stackoverflow.com/questions/11309194/php-domdocument-failing-to-handle-utf-8-characters
Ensure there are tests for these special characters!
Missing DOM Level 2 attributes:
https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-1689064
$element->textContent = "<p>Test</p>";
The above example should not create a paragraph element as a child of the element. It should escape the content correctly, displaying the chevrons to the browser.
This is due to the difference between textContent and innerHTML. The latter sets literal html within the element whereas textContent should escape any HTML strings. Hopefully this is handled by the native DOMDocument but tests are needed to make sure.
https://www.w3.org/TR/DOM-Level-2-Core/changes.html
Changes to DOM Level 1 Core interfaces and exceptions
Interface Attr
The Attr interface has one new attribute: ownerElement.
Interface Document
The Document interface has five new methods: importNode, createElementNS, createAttributeNS, getElementsByTagNameNS and getElementById.
Interface NamedNodeMap
The NamedNodeMap interface has three new methods: getNamedItemNS, setNamedItemNS, removeNamedItemNS.
Interface Node
The Node interface has two new methods: isSupported and hasAttributes.
normalize, previously in the Element interface, has been moved in the Node interface.
The Node interface has three new attributes: namespaceURI, prefix and localName.
The ownerDocument attribute was specified to be null when the node is a Document. It now is also null when the node is a DocumentType which is not used with any Document yet.
Interface DocumentType
The DocumentType interface has three attributes: publicId, systemId and internalSubset.
Interface DOMImplementation
The DOMImplementation interface has two new methods: createDocumentType and createDocument.
Interface Element
The Element interface has eight new methods: getAttributeNS, setAttributeNS, removeAttributeNS, getAttributeNodeNS, setAttributeNodeNS, getElementsByTagNameNS, hasAttribute and hasAttributeNS.
The method normalize is now inherited from the Node interface where it was moved.
Exception DOMException
The DOMException has five new exception codes: INVALID_STATE_ERR, SYNTAX_ERR, INVALID_MODIFICATION_ERR, NAMESPACE_ERR and INVALID_ACCESS_ERR.
A.1.2: New featuresA.1.2.1: New types
DOMTimeStamp
The DOMTimeStamp type was added to the Core module.
innerHTML, innerText, etc. Where are these documented?
Remember to test case sensitivity!
This means that PHPStorm (and presumably other IDEs) are unable to syntax-check common patterns like:
$domDoc->getElementById("your-name")->setValue("monkey");
Instead, they fire a warning that the referenced method is not found.
Suspect the fix is to add the return types to the PhpGt/Dom versions of the methods?
https://google.github.io/styleguide/htmlcssguide.xml?showone=Optional_Tags#Optional_Tags
When using this approach, putting link
and script
elements (along with meta
, title
, etc.) before any content will cause the browser to create a head
and put the elements in there.
We need some tests to ensure that this behaviour works serverside too.
For clarification:
<!doctype html>
<meta charset="utf-8" />
<title>Hello, World!</title>
<link rel="stylesheet" href="/style/main.css" />
<p>This is a test.
assertEquals(3, count($document->head->children));
https://yourfirstpr.github.io/
Your First PR shares starter issues on Twitter, at @yourfirstpr. If you know of any projects posting issues ideal for someones first contribution to a project, send us a tweet or create an issue on our GitHub Page.
https://developer.mozilla.org/en/docs/Web/API/Element/matches
The Element.matches() method returns true if the element would be selected by the specified selector string; otherwise, returns false.
https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
The Element.closest() method returns the closest ancestor of the current element (or the current element itself) which matches the selectors given in parameter. If there isn't such an ancestor, it returns null.
Provide array access using square brackets to the HTMLCollection class.
Other repos are in the Gt* namespace. Correct this.
Have a look into whether this actually speeds anything up: http://php.net/manual/en/libxml.constants.php
LIBXML_COMPACT (integer)
Activate small nodes allocation optimization. This may speed up your application without needing to change the code
It's clearly my fault for creating the HTMLDocument with an empty string, but it might be defensive to do an is_null check on the documentElement before attempting to access it. Given an empty HTMLDocument you might expect a querySelector call for anything to successfully return nothing rather than cause a fatal error.
$domDoc = new \phpgt\dom\HTMLDocument("");
$domDoc->querySelector("div");
PHP Fatal error: Uncaught Error: Call to a member function querySelector() on null in phpgt/dom/src/HTMLDocument.php:35
In PHP 7.1 we can finally get nullable type hints, which is extremely useful when working with the DOM APIs, as a lot of DOM methods return Element OR null, which isn't possible to hint in PHP 7.
Certain live properties are not documented; don't show up in IDEs.
According to MDN, a DocumentFragment has the querySelector*() and getElementByID() methods.
Without these methods there is no way to manipulate a fragment without adding it into the dom and then running a query to get it back out.
$element->classList->toggle, etc.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.