Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement single-line text input #3585

Merged
merged 10 commits into from Nov 13, 2014

Implement document focus context and hook it up to click events.

  • Loading branch information
jdm committed Nov 13, 2014
commit 84bc17e7ad99d11ff416f2126acb2031b680dc19
@@ -96,6 +96,10 @@ pub struct Document {
anchors: MutNullableJS<HTMLCollection>,
applets: MutNullableJS<HTMLCollection>,
ready_state: Cell<DocumentReadyState>,
/// The element that has most recently requested focus for itself.
possibly_focused: MutNullableJS<Element>,
/// The element that currently has the document focus context.
focused: MutNullableJS<Element>,
}

impl DocumentDerived for EventTarget {
@@ -178,6 +182,10 @@ pub trait DocumentHelpers<'a> {
fn load_anchor_href(self, href: DOMString);
fn find_fragment_node(self, fragid: DOMString) -> Option<Temporary<Element>>;
fn set_ready_state(self, state: DocumentReadyState);
fn get_focused_element(self) -> Option<Temporary<Element>>;
fn begin_focus_transaction(self);
fn request_focus(self, elem: JSRef<Element>);
fn commit_focus_transaction(self);
}

impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
@@ -327,6 +335,30 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self);
let _ = target.DispatchEvent(*event);
}

/// Return the element that currently has focus.
// https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#events-focusevent-doc-focus
fn get_focused_element(self) -> Option<Temporary<Element>> {
self.focused.get()
}

/// Initiate a new round of checking for elements requesting focus. The last element to call
/// `request_focus` before `commit_focus_transaction` is called will receive focus.
fn begin_focus_transaction(self) {
self.possibly_focused.clear();
}

/// Request that the given element receive focus once the current transaction is complete.
fn request_focus(self, elem: JSRef<Element>) {
self.possibly_focused.assign(Some(elem))
}

/// Reassign the focus context to the element that last requested focus during this
/// transaction, or none if no elements requested it.
fn commit_focus_transaction(self) {
//TODO: dispatch blur, focus, focusout, and focusin events
self.focused.assign(self.possibly_focused.get());
}
}

#[deriving(PartialEq)]
@@ -390,6 +422,8 @@ impl Document {
anchors: Default::default(),
applets: Default::default(),
ready_state: Cell::new(ready_state),
possibly_focused: Default::default(),
focused: Default::default(),
}
}

@@ -415,6 +415,9 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLInputElement> {
}
_ => {}
}

let doc = document_from_node(*self).root();
doc.request_focus(ElementCast::from_ref(*self));
}
}
}
@@ -928,11 +928,13 @@ impl ScriptTask {
let frame = page.frame();
let window = frame.as_ref().unwrap().window.root();
let doc = window.Document().root();
let focused = doc.get_focused_element().root();
let body = doc.GetBody().root();

let target: JSRef<EventTarget> = match body {
Some(body) => EventTargetCast::from_ref(*body),
None => EventTargetCast::from_ref(*window),
let target: JSRef<EventTarget> = match (&focused, &body) {
(&Some(ref focused), _) => EventTargetCast::from_ref(**focused),
(&None, &Some(ref body)) => EventTargetCast::from_ref(**body),
(&None, &None) => EventTargetCast::from_ref(*window),
};

let ctrl = modifiers.contains(Control);
@@ -956,10 +958,10 @@ impl ScriptTask {
let _ = target.DispatchEvent(EventCast::from_ref(*event));

if state != Released && props.is_printable() {
let event = KeyboardEvent::new(*window, "keypress".to_string(), true, true, Some(*window),
0, props.key.clone(), props.code.clone(), props.location,
is_repeating, is_composing, ctrl, alt, shift, meta,
props.char_code, props.key_code).root();
let event = KeyboardEvent::new(*window, "keypress".to_string(), true, true, Some(*window),
0, props.key.clone(), props.code.clone(), props.location,
is_repeating, is_composing, ctrl, alt, shift, meta,
props.char_code, props.key_code).root();
let _ = target.DispatchEvent(EventCast::from_ref(*event));
}
}
@@ -1065,13 +1067,17 @@ impl ScriptTask {
match *page.frame() {
Some(ref frame) => {
let window = frame.window.root();
let doc = window.Document().root();
doc.begin_focus_transaction();

let event =
Event::new(&global::Window(*window),
"click".to_string(),
Bubbles, Cancelable).root();
let eventtarget: JSRef<EventTarget> = EventTargetCast::from_ref(node);
let _ = eventtarget.dispatch_event_with_target(None, *event);

doc.commit_focus_transaction();
window.flush_layout();
}
None => {}
@@ -0,0 +1,7 @@
<body>
<input id="focused">
<script>
document.body.addEventListener('keydown', function() { alert("body"); }, false);
document.getElementById('focused').addEventListener('keydown', function() { alert("input"); }, false);
</script>
</body>
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.