Mutation Observers---subtree - webkit

I am reading this http://lists.w3.org/Archives/Public/public-webapps/2011JulSep/1622.html and it seems that Chrome's behavior contrasts to specification. If I understood the specs correctly, defining "subtree" for an element means that changes to the subtree of that element (including the element itself) should be reported. However, when executing this piece of code, I get nothing.
var observer = new WebKitMutationObserver(function(e){console.log(e);})
observer.observe(document.body, {subtree:true, attributes:true});
document.body.appendChild(document.createElement('div'));
What am I missing? Can somebody elaborate on this?
Thanks!

The documentation is unclear, but subtree is ignored unless you also specify childList:true.
The case for attributes and attributeFilter is the same.
Hope it still helps.

According to this article:
childList: Set to true if additions and removals of the target node's child elements (including text nodes) are to be observed.
subtree: Set to true if mutations to not just target, but also target's descendants are to be observed.
This also explains subtree depending on childList.

In mutationObserver config, at least one of attributes, characterData, or childList needs to be set true.
Now, If you just set childList: true, then it will observe only the direct children (depth 1) of the target element and not the complete subtree.
To observe the complete subtree both childList and subtree needs to be set true.
e.g.
{
childList: true,
subtree: true
}
I hope, it's helpful.

Related

How can I detect mouse input on an Area2D node in Godot (viewport and shape_idx error)?

After testing out a few other engines I've settled into Godot for my game development learning process and have really appreciated the conciseness of GDScript, the node/inheritance structure, and the way observer events are covered by signals. I've been building knowledge through various tutorials and by reading through the documentation.
Somehow I'm struggling to solve the very fundamental task of detecting a mouseclick on a sprite. (Well, on a sprite's parent node, either a Node2D or an Area2D.)
My process has been this:
Create an Area2D node (called logo) with a Sprite child and a CollisionShape2D child
Assign a texture to the Sprite node, and change the x and y extent values of the CollisionShape2D node to match the size of the Sprite's texture
Connect the _on_logo_input_event(viewport, event, shape_idx) signal to the Area2D node's script (called logo.gd)
Use the following code:
func _on_logo_input_event(viewport, event, shape_idx):
if (event is InputEventMouseButton && event.pressed):
print("Logo clicked")
When I run the game I get nothing in the output after clicking, and see these errors:
The argument 'viewport' is never used in the function '_on_logo_input_event'. If this is intended, prefix it with an underscore: '_viewport'
The argument 'shape_idx' is never used in the function '_on_logo_input_event'. If this is intended, prefix it with an underscore: '_shape_idx'
I don't know how to address the parameters in this signal's function - My Area2D node is set to Pickable, and the logo Area2D node is a direct child to the game_window Node2D in the main scene. I can't figure out what is going wrong here, whether it's some project setting I need to change or an inspector attribute I need to set. Is there a better way to feed an input signal for a mouse click into a script?
I don't want to clutter stackoverflow with such a simple question but I've tried to do my due diligence and haven't been able to find this error message on any forums. I'd appreciate any help, thanks.
If the CollisionLayer of your Area2D is not empty, and input_pickable is on, then it is capable to get input. Either by connecting the input_event signal or by overriding _input_event.
If that is not working, the likely cause is that there is some Control/UI element that is stopping mouse events. They have a property called mouse_filter, which is set to Stop by default. You will need to find which Control is intercepting the input, and set its mouse_filter to Ignore.
By the way, these:
The argument 'viewport' is never used in the function '_on_logo_input_event'. If this is intended, prefix it with an underscore: '_viewport'
The argument 'shape_idx' is never used in the function '_on_logo_input_event'. If this is intended, prefix it with an underscore: '_shape_idx'
These are warnings. They are not the source of the problem. They tell what they say on the tin: you have some parameter that you are not using, and you can prefix its name with an underscore as a way to suppress the warning.
I would also recommend checking out this video:
https://www.youtube.com/watch?v=iSpWZzL2i1o
The main modification that he makes from what you have done is make a separate click event in Project > Project Settings > Input Map that maps to a left click. He can then reference that in the _on_Area2D_input_event.
extends Node2D
var selected = false
func _ready():
pass
func _on_Area2D_input_event(viewport, event, shape_idx):
if Input.is_action_just_pressed("click"):
selected = true
func _physics_process(delta):
if selected:
global_position = lerp(global_position, get_global_mouse_position(), 25 * delta)
func _input(event):
if event is InputEventMouseButton:
if event.button_index == BUTTON_LEFT and not event.pressed:
selected = false

Why this error message appear?: invalid get index 'game_started' (on base: 'Node')

can you please help me, I have this script:
extends KinematicBody2D
var motion = Vector2(0, 300)
var sensitivity = 13
onready var player = get_node("../Player")
onready var enemy = get_node("../Enemy")
func _ready():
randomize()
reset_ball()
func _physics_process(delta):
if not get_parent().game_started:
return
if is_on_wall():
motion.x *= -1
if is_on_floor():
touch_someone(player)
if is_on_ceiling():
touch_someone(enemy)
move_and_slide(motion, Vector2(0, -1))
func touch_someone(node):
motion.y *= -1
motion.x = (position.x - node.position.x) * sensitivity
func reset_ball():
motion.x = rand_range(-300, 300)
nd when I run the game this error message appears
invalid get index 'game_started' (on base: 'Node').
This is the error
The error is telling you that there isn't a game_started defined in the parent node. There is a parent node, but it does not have a property game_started defined.
You probably intended it to be a property, but you forgot to define it, defined it somewhere else, or you did define it in the correct place, but instanced the node under the wrong parent. However, it is also possible you made it a method and simply forgot (). I don't know which is the case.
Regardless, in Godot, a common design pattern is to access down and signal up the scene tree. In this case, you are trying to access up the scene tree. This is problematic because the scene can't ensure where it will be instanced.
I'll give you a few approaches to solve this problem:
Check if game_started exists.
The change that will have a smaller impact on your architecture is to check if the parent node has game_started before trying to read it. Which looks something like this:
var parent = get_parent
if !"game_started" in parent or !parent.game_started:
return
However please notice that even if this gets rid of the error, it is not fixing the source of the problem. Since game_started is not defined in the parent anyway.
Furthermore, _physics_process is still getting called. There are ways to don't even have the call, which is better for performance. Will come back to that.
Let the parent access the child.
What you want to accomplish is to enable and disable _physics_process based on the value of game_started. There is a way to enable and disable _physics_process in the engine: set_physics_process.
Presumably there is some other code somewhere that sets game_started on the parent, in that moment it could call set_physics_process on the child to disable or enable _physics_process accordingly.
You may even use a property (with setget) to this effect.
For example:
var game_started:bool setget set_game_started
func set_game_started(new_value:bool) -> void:
if game_started == new_value:
return
for child in get_children():
child.set_physics_process(new_value)
game_started = new_value
With this, your script does not have to check game_started. One drawback is that the code only uses set_physics_process on the direct children. We could write a recursive version, however, we can do better!
Use pause.
As you can see in pausing games, you can use get_tree().paused to get or set if the game is paused. Which will stop _physics_process (among other methods) depending on the pause_mode.
Thus, you can have the parent update get_tree().paused...
Assuming, you also want a pause, you may follow this pattern:
var game_started:bool setget set_game_started
var game_paused:bool setget set_game_paused
func set_game_started(new_value:bool) -> void:
game_started = new_value
update_pause()
func set_game_paused(new_value:bool) -> void:
game_paused = new_value
update_pause()
func update_pause() -> void:
get_tree().paused = !game_started or game_paused
Then, for the nodes that should still work when the game is paused or not started, you can se pause_mode = PAUSE_MODE_PROCESS so they don't get _physics_process et.al. disabled. Then they can check game_started and game_paused to distinguish if the game is paused or not started.
A drawback is that this will affect nodes everywhere… If only game_started and game_paused could be available everywhere… Well, we can do that too!
Use an autoload.
Make an autoload (via project settings) of a scene with a node that has game_started et.al. So that it is available from everywhere. Then you can access it from everywhere.
You can do this combined with the paused as explained above. Which is what I would recommend.
Alternatively. Since you can access it from everywhere, you you could simply access it instead of the parent:
if !autoload_name.game_started:
return
This is the exception to the access down and signal up rule. Since the autoload is available everywhere and it does not depend on where or how the scene was instanced.
I remind you, is that paused and set_physics_process will avoid the call to _physics_process, and thus are more performant than checking this way.

Why does Iterator::next return an Option instead of just an item?

It seems to me that whether an option is the right type to return should be up to the implementor.
I notice that it goes away when I try to filter or using other collection methods on the items. Is this simply a replacement for has_next? Won't it have potential performance/memory implications?
Because it needs some way to communicate to the caller that there's nothing left to output.
fn main() {
let mut it = vec![1, 2, 3].into_iter();
assert_eq!(it.next(), Some(1));
assert_eq!(it.next(), Some(2));
assert_eq!(it.next(), Some(3));
assert_eq!(it.next(), None); // End of iterator.
}
As for a hypothetical has_next, that can complicate some iterator designs because it requires the iterator to know whether there is another element. This might require the iterator to compute the next element, then store it somewhere. It's also possible to forget to call has_next, or call it but ignore the result.
With next returning an Option, none of this is an issue; an iterator can compute the next item and return it whilst making it impossible for a caller to forget to ensure the returned value actually has something in it.
One thing this does not let you do is "peek" at the iterator to see if there's something more and then change logic based on that answer, without actually consuming the next item. However, that's what the peekable combinator is for, which gives you what amounts to a traditional has_next: peek().is_some().
On your concerns about performance: I've never seen anything to suggest there is any penalty. Anything using an iterator correctly has to check to see if it's reached the end. As for space, a Rust iterator doesn't need to cache the next item, so they're likely to be the same size or smaller than an iterator for a language that uses has_next.
Finally, as noted in comments, Option is not heap allocated. A None is equivalent to a false followed by some uninitialised space (since there's nothing in it), and a Some(v) is equivalent to a true followed by v.

FreeMarker ?has_content on Iterator

How does FreeMarker implement .iterator()?has_content for Iterator ?
Does it attempt to get the first item to decide whether to render,
and does it keep it for the iteration? Or does it start another iteration?
I have found this
static boolean isEmpty(TemplateModel model) throws TemplateModelException
{
if (model instanceof BeanModel) {
...
} else if (model instanceof TemplateCollectionModel) {
return !((TemplateCollectionModel) model).iterator().hasNext();
...
}
}
But I am not sure what Freemarker wraps the Iterator type to.
Is it TemplateCollectionModel?
It doesn't get the first item, it just calls hasNext(), and yes, with the default ObjectWrapper (see the object_wrapper configuration setting) it will be treated as a TemplateCollectionModel, which can be listed only once though. But prior to 2.3.24 (it's unreleased when I write this), there are some glitches to look out for (see below). Also if you are using pure BeansWrapper instead of the default ObjectWrapper, there's a glitch (see below too).
Glitch (2.3.23 and earlier): If you are using the default ObjectWrapper (you should), and the Iterator is not re-get for the subsequent listing, that is, the same already wrapped value is reused, then it will freak out telling that an Iterator can be listed only once.
Glitch 2, with pure BeansWrapper: It will just always say that it has content, even if the Iterator is empty. That's also fixed in 2.3.24, however, you need to create the BeansWrapper itself (i.e., not (just) the Configuration) with 2.3.24 incompatibleImprovements for the fix to be active.
Note that <#list ...>...<#else>...</#list> has been and is working in all cases (even before 2.3.24).
Last not least, thanks for bringing this topic to my attention. I have fixed these in 2.3.24 because of that. (Nightly can be built from here: https://github.com/apache/incubator-freemarker/tree/2.3-gae)

Check if field is modified in mongoose's post hook for function findOneAndUpdate

In the controller I'm incrementing a field with findOneAndUpdate. The increment is not necessarily always executed, which depends on whether the condition for a update query has been met.
If the field has been incremented tho, an another model should updated as well. So, I was thinking to use:
schema.post('findOneAndUpdate', function(err) {
pseudo-code:
if (field is incremented)
anotherModel.update()
});
The problem is that I don't seem to be able to determine if the field has been modified.
Self reference (this) points to a funny object of considerable size, (unlike in e.g. middleware functions for 'save'), so I don't see much other options to determine if field is modified.
Any ideas?
The argument passed to the callback for findOneAndUpdate's post middleware is the matched document to be updated and not an error as common in the node callback pattern. Within the callback, this is the query object returned from the findOneAndUpdate.
schema.post('findOneAndUpdate', function(doc) {...});
Also note that if you want the updated document rather than original document that matches the query you must specify the new option in the query:
findOneAndUpdate(QUERY, UPDATE, {new: true});