@@ -73,204 +73,188 @@ equivalent values: `["hello", 1, 2, 3]`.
73
73
74
74
Should you require lower level API access to FFI features, you can find such
75
75
builtin functions under the ` pyscript.ffi ` namespace in both Pyodide and
76
- MicroPython. The available functions are described in our section on
77
- [ builtin helpers ] ( ../builtins ) .
76
+ MicroPython. The available functions are described in our section on the
77
+ [ builtin API ] ( ../../api ) .
78
78
79
79
Advanced users may wish to explore the
80
80
[ technical details of the FFI] ( ../ffi ) .
81
81
82
- ## PyDom
83
-
84
- The Standard Web APIs are massive and not always very user-friendly. ` PyDom ` is
85
- a Python module that exposes the power of the web with an easy and idiomatic
86
- Pythonic interface on top.
87
-
88
- While the [ FFI] ( #ffi ) interface described above focuses on giving full access
89
- to the entire Standard Web APIs, ` pydom ` focuses on providing a small,
90
- intuitive and yet powerful API that prioritises common use cases fist. For this
91
- reason, its first layer is simple (but limited to the most common use cases),
92
- but ` pydom ` also provides a secondary layer to directly use full FFI interface
93
- of a specific element.
94
-
95
- PyDom does not aim to replace the regular web (Javascript) API nor to be as
96
- wide and offer feature parity. On the contrary, it is intentionally small and
97
- focused on the most popular use cases while still providing (backdoor) access
98
- to the full JavaScript API.
99
-
100
- ` Pydom ` draws inspiration from popular Python APIs/Libraries known to be
101
- friendly and easy to learn, and other successful projects related the web as
102
- well (for instance, ` JQuery ` was a source of inspiration).
82
+ ## ` pyscript.web `
103
83
104
84
!!! warning
105
85
106
- PyDom is currently a work in progress.
86
+ The `pyscript.web` module is currently a work in progress.
107
87
108
88
We welcome feedback and suggestions.
109
89
90
+ The ` pyscript.web ` module is an idiomatically Pythonic API for interacting with
91
+ the DOM. It wraps the FFI in a way that is more familiar to Python developers
92
+ and works natively with the Python language. Technical documentation for this
93
+ module can be found in [ the API] ( ../../api/#pyscriptweb ) section.
110
94
111
- ### Core Concepts
95
+ There are three core concepts to remember:
112
96
113
- ` Pydom ` builds on topic of very few and simple core concepts:
114
-
115
- * __ ` Element ` :__ any component that is part of a web page. This is a rough
116
- abstraction of an
117
- [ HTMLElement] ( https://developer.mozilla.org/en-US/docs/Glossary/Element ) .
118
- In general, ` pydom ` elements always map to an underlying ` HTML ` ` Element ` in
119
- a web page
120
- * __ ` ElementCollection ` :__ a collection of one or more ` Elements ` . It is a
121
- rough abstraction of an
122
- [ HTMLCollection] ( https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection ) .
123
- * __ Querying:__ a method to query elements on a page based on a
124
- [ selector] ( https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors ) .
125
- Pydom supports standard HTML DOM query selectors to
126
- [ locate DOM elements] ( https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model/Locating_DOM_elements_using_selectors )
127
- as other native ` JavaScript ` methods like ` querySelector ` or
97
+ * Find elements on the page via
98
+ [ CSS selectors] ( https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors ) .
99
+ The ` find ` API uses exactly the [ same queries] ( https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Locating_DOM_elements_using_selectors )
100
+ as those used by native browser methods like ` qurerySelector ` or
128
101
` querySelectorAll ` .
102
+ * Use classes in the ` pyscript.web.elements ` namespace to create and organise
103
+ new elements on the web page.
104
+ * Collections of elements allow you to access and change attributes en-mass.
105
+ Such collections are returned from ` find ` queries and are also used for the
106
+ [ children] ( https://developer.mozilla.org/en-US/docs/Web/API/Element/children )
107
+ of an element.
108
+
109
+ You have several options for accessing the content of the page (i.e. the DOM),
110
+ and these can be found in the ` pyscript.web.dom ` object. The ` head ` and ` body `
111
+ attributes reference the page's head and body. Furthermore, the ` find ` method
112
+ can be used to return collections of elements matching your CSS query. Finally,
113
+ all elements have a ` find ` method that searches within their children for
114
+ elements matching your CSS query.
129
115
130
- Let's look into each of these aspects in more in detail.
131
-
132
- ### Element
116
+ ``` python
117
+ from pyscript.web import dom
133
118
134
- A PyDom ` Element ` is simply an abstraction of a tranditional ` Element ` in a web
135
- page. Every PyDom ` Element ` maps to an underlying JavaScript ` Element ` in a
136
- web page. These two elements are always in sync and any change of state in one
137
- is reflected in the other.
138
119
139
- #### Creating a new element
120
+ # Print all the child elements of the document's head.
121
+ print (dom.head.children)
122
+ # Find all the paragraphs in the DOM.
123
+ paragraphs = dom.find(" p" )
124
+ ```
140
125
141
- New elements are created using the ` pydom.create ` method and passing the type
142
- of element being created. Here's an example of what it looks like :
126
+ The object returned from a query, or used as a reference to an element's
127
+ children is iterable :
143
128
144
129
``` python
145
- from pyweb import pydom
130
+ from pyscript.web import dom
146
131
147
- # Creating an element directly from pydom creates an unbounded element.
148
- new_div = pydom.create(" div" )
149
132
150
- # Creating an element from another element automatically creates that element
151
- # as a child of the original element
152
- new_p = new_div.create(
153
- " p" ,
154
- classes = [" code-description" ],
155
- html = " Ciao PyScripters!"
156
- )
133
+ # Get all the paragraphs in the DOM.
134
+ paragraphs = dom.find(" p" )
157
135
158
- # elements can be appended to any other element on the page
159
- pydom[' #element-creation-example' ][0 ].append(new_div)
136
+ # Print the inner html of each paragraph.
137
+ for p in paragraphs:
138
+ print (p.html)
160
139
```
161
140
162
- #### Setting an element's content
163
-
164
- The ` Element ` interface offers two ways to set an element's content: the ` html `
165
- and the ` content ` attributes:
166
-
167
- * ` html ` : directly sets the ` innerHTML ` field of the underlying element without
168
- attemnpting any conversion.
169
- * ` content ` : sets the ` innerHTML ` field via the PyScript ` display ` function.
170
- This takes care of properly rendering the object being passed based on the
171
- object mimetype. So, for instance, if the objects is an image, it'll be
172
- properly rendered within the element
141
+ Alternatively, it is also indexable / sliceable:
173
142
174
- In general, we suggest using ` content ` directly as it'll take care of most use
175
- cases without requiring any extra work from the user.
143
+ ``` python
144
+ from pyscript.web import dom
176
145
177
- #### Changing an element's style
178
146
179
- Elements have a ` style ` attribute to change the element style rules. The
180
- ` style ` attribute is a dictionary and, to set a style rule for the element,
181
- simply set the correct key on the ` .style ` attribute. For instance, the
182
- following code changes the background color (of the element created in the
183
- example above):
147
+ # Get an ElementCollection of all the paragraphs in the DOM
148
+ paragraphs = dom.find(" p" )
184
149
185
- ``` python
186
- new_p.style[" background-color" ] = " yellow"
150
+ # Only the final two paragraphs.
151
+ for p in paragraphs[- 2 :]:
152
+ print (p.html)
187
153
```
188
154
189
- To remove a style key, simply use the ` pop ` method as you'd to to remove
190
- a key from a dictionary :
155
+ It also makes available the following read and writable attributes related to
156
+ all contained elements :
191
157
192
- ``` python
193
- new_p.style.pop(" background-color" )
194
- ```
158
+ * ` classes ` - the list of classes associated with the elements.
159
+ * ` innerHTML ` - the innerHTML of each element.
160
+ * ` style ` - a dictionary like object for interacting with CSS style rules.
161
+ * ` value ` - the ` value ` attribute associated with each element.
162
+
163
+ For example, to continue the example above, ` paragraphs.innerHTML ` will return
164
+ a list of all the values of the ` innerHTML ` attribute on each contained
165
+ element. Alternatively, set an attribute for all elements contained in the
166
+ collection like this: ` paragraphs.style["background-color"] = "blue" ` .
195
167
196
- In addition to the dictionary interface to explicitly set CSS rules, the
197
- ` style ` attribute also offers a convenient ` visible ` property that can be use
198
- show/hide an element.
168
+ It's possible to create new elements to add to the DOM:
199
169
200
170
``` python
201
- new_p.style.visible = False
171
+ from pyscript.web import dom
172
+ from pyscript.web.elements import *
173
+
174
+
175
+ dom.body.append(
176
+ div(
177
+ div(" Hello!" , classes = " a-css-class" , id = " hello" ),
178
+ select(
179
+ option(" apple" , value = 1 ),
180
+ option(" pear" , value = 2 ),
181
+ option(" orange" , value = 3 ),
182
+ ),
183
+ div(
184
+ button(span(" Hello! " ), span(" World!" ), id = " my-button" ),
185
+ br(),
186
+ button(" Click me!" ),
187
+ classes = [" css-class1" , " css-class2" ],
188
+ style = {" background-color" : " red" }
189
+ ),
190
+ div(
191
+ children = [
192
+ button(
193
+ children = [
194
+ span(" Hello! " ),
195
+ span(" Again!" )
196
+ ],
197
+ id = " another-button"
198
+ ),
199
+ br(),
200
+ button(" b" ),
201
+ ],
202
+ classes = [" css-class1" , " css-class2" ]
203
+ )
204
+ )
205
+ )
202
206
```
203
207
204
- #### Other useful aspects of the Element API
208
+ This example demonstrates a declaritive way to add elements to the body of the
209
+ DOM. Notice how the first (unnamed) arguments to an element are its children.
210
+ The named arguments (such as ` id ` , ` classes ` and ` style ` ) refer to attributes
211
+ of the underlying HTML element. If you'd rather be explicit about the children
212
+ of an element, you can always pass in a list of such elements as the named
213
+ ` children ` argument (you see this in the final ` div ` in the example above).
205
214
206
- * ` append ` : a method to append a new child to the element.
207
- * ` children ` : list of the children of the element.
208
- * ` value ` : allows to set the ` value ` attribute of an element.
209
- * ` clone ` : a method that creates a clone of the element. NOTE: The cloned
210
- elements will not be attached to any other element.
211
- * ` show_me ` : a method to scroll the page to where the element is placed.
215
+ Of course, you can achieve similar results in an imperative style of
216
+ programming:
212
217
213
- ### Element collections
218
+ ``` python
219
+ from pyscript.web import dom
220
+ from pyscript.web.elements import *
214
221
215
- Element collections represent a collection of elements typically returned from
216
- a query. For instance:
217
222
218
- ``` python
219
- paragraphs = pydom[' p' ]
220
- ```
221
223
222
- In the example above, ` paragraphs ` is an ` ElementCollection ` that maps to all
223
- ` p ` elements in the page.
224
+ my_div = div()
225
+ my_div.style[" background-color" ] = " red"
226
+ my_div.classes.append(" a-css-class" )
224
227
225
- An ` ElementCollection ` can be used to iterate over a collection of elements or
226
- to pick specific elements or slices of elements in the collection. For
227
- instance:
228
+ my_p = p()
229
+ my_p.content = " This is a paragraph."
228
230
229
- ``` python
230
- for element in paragraphs:
231
- display(element.html)
231
+ my_div.append(my_p)
232
232
233
- # let's now display only the last 2 elements
234
- for element in paragraphs[- 2 :]:
235
- display(element.html)
233
+ # etc...
236
234
```
237
235
238
- #### Interacting with an ElementCollection
239
-
240
- Besides allowing operations as an iterable object, ` ElementCollection ` objects
241
- also offer a few convenience methods to directly interact with the elements
242
- within the collection. For instance, it's possible to ask for specific
243
- attributes of the elements in the collection directly:
236
+ It's also important to note that the ` pyscript.when ` decorator understands
237
+ element references from ` pyscript.web ` :
244
238
245
239
``` python
246
- display(paragraphs.html)
247
- ```
248
-
249
- This displays a list with the values of the ` html ` attribute for all the
250
- elements in the ` paragraphs ` collection.
240
+ from pyscript import when
241
+ from pyscript.web import dom
251
242
252
- In the same way we can read attributes, we can also set an attribute directly
253
- in the collection. For instance, you can directly set the html content of all
254
- the elements in the collection:
255
243
256
- ``` python
257
- # This will change the text of all H1 elements in the page
258
- pydom[' h1' ].html = " That's cool :)"
259
- ```
244
+ btn = dom.find(" #my-button" )
260
245
261
- Or perhaps change their style:
262
246
263
- ```
264
- paragraphs.style['background-color'] = 'lightyellow'
247
+ @when (" click" , btn)
248
+ def my_button_click_handler (event ):
249
+ print (" The button has been clicked!" )
265
250
```
266
251
267
- The ` ElementCollection ` class currently supports the following attributes:
252
+ Should you wish direct access to the proxy object representing the underlying
253
+ HTML element, each Python element has a ` _dom_element ` property for this
254
+ purpose.
268
255
269
- * ` style ` : just like in ` Element ` , this proxy attribute can be used to change
270
- the style of the elements in a collection by setting the proper CSS rules,
271
- using ` style ` with the same API as a dictionary.
272
- * ` html ` : changes the ` html ` attribute on all the elements of a collection.
273
- * ` value ` : changes the ` value ` attribute on all the elements of a collection.
256
+ Once again, the technical details of these classes are described in the
257
+ [ built-in API documentation] ( ../../api/#pyscriptweb ) .
274
258
275
259
## Working with JavaScript
276
260
0 commit comments