mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-04 06:23:45 +00:00
add selection api to HTMLTextAreaElement
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
const js = @import("../../../js/js.zig");
|
const js = @import("../../../js/js.zig");
|
||||||
const Page = @import("../../../Page.zig");
|
const Page = @import("../../../Page.zig");
|
||||||
|
|
||||||
@@ -23,12 +24,17 @@ const Node = @import("../../Node.zig");
|
|||||||
const Element = @import("../../Element.zig");
|
const Element = @import("../../Element.zig");
|
||||||
const HtmlElement = @import("../Html.zig");
|
const HtmlElement = @import("../Html.zig");
|
||||||
const Form = @import("Form.zig");
|
const Form = @import("Form.zig");
|
||||||
|
const Selection = @import("../../Selection.zig");
|
||||||
|
|
||||||
const TextArea = @This();
|
const TextArea = @This();
|
||||||
|
|
||||||
_proto: *HtmlElement,
|
_proto: *HtmlElement,
|
||||||
_value: ?[]const u8 = null,
|
_value: ?[]const u8 = null,
|
||||||
|
|
||||||
|
_selection_start: u32 = 0,
|
||||||
|
_selection_end: u32 = 0,
|
||||||
|
_selection_direction: Selection.SelectionDirection = .none,
|
||||||
|
|
||||||
pub fn asElement(self: *TextArea) *Element {
|
pub fn asElement(self: *TextArea) *Element {
|
||||||
return self._proto._proto;
|
return self._proto._proto;
|
||||||
}
|
}
|
||||||
@@ -109,6 +115,108 @@ pub fn setRequired(self: *TextArea, required: bool, page: *Page) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn select(self: *TextArea) !void {
|
||||||
|
const len = if (self._value) |v| @as(u32, @intCast(v.len)) else 0;
|
||||||
|
try self.setSelectionRange(0, len, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const HowSelected = union(enum) { partial: struct { u32, u32 }, full, none };
|
||||||
|
|
||||||
|
fn howSelected(self: *const TextArea) HowSelected {
|
||||||
|
const value = self._value orelse return .none;
|
||||||
|
|
||||||
|
if (self._selection_start == self._selection_end) return .none;
|
||||||
|
if (self._selection_start == 0 and self._selection_end == value.len) return .full;
|
||||||
|
return .{ .partial = .{ self._selection_start, self._selection_end } };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn innerInsert(self: *TextArea, str: []const u8, page: *Page) !void {
|
||||||
|
const arena = page.arena;
|
||||||
|
|
||||||
|
switch (self.howSelected()) {
|
||||||
|
.full => {
|
||||||
|
// if the text area is fully selected, replace the content.
|
||||||
|
const new_value = try arena.dupe(u8, str);
|
||||||
|
try self.setValue(new_value, page);
|
||||||
|
self._selection_start = 1;
|
||||||
|
self._selection_end = 1;
|
||||||
|
self._selection_direction = .none;
|
||||||
|
},
|
||||||
|
.partial => |range| {
|
||||||
|
// if the text area is partially selected, replace the selected content.
|
||||||
|
const current_value = self.getValue();
|
||||||
|
const before = current_value[0..range[0]];
|
||||||
|
const remaining = current_value[range[1]..];
|
||||||
|
|
||||||
|
const new_value = try std.mem.concat(
|
||||||
|
arena,
|
||||||
|
u8,
|
||||||
|
&.{ before, str, remaining },
|
||||||
|
);
|
||||||
|
try self.setValue(new_value, page);
|
||||||
|
|
||||||
|
const new_pos = range[0] + str.len;
|
||||||
|
self._selection_start = @intCast(new_pos);
|
||||||
|
self._selection_end = @intCast(new_pos);
|
||||||
|
self._selection_direction = .none;
|
||||||
|
},
|
||||||
|
.none => {
|
||||||
|
// if the text area is not selected, just insert at cursor.
|
||||||
|
const current_value = self.getValue();
|
||||||
|
const new_value = try std.mem.concat(arena, u8, &.{ current_value, str });
|
||||||
|
try self.setValue(new_value, page);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getSelectionDirection(self: *const TextArea) []const u8 {
|
||||||
|
return @tagName(self._selection_direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getSelectionStart(self: *const TextArea) u32 {
|
||||||
|
return self._selection_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setSelectionStart(self: *TextArea, value: u32) void {
|
||||||
|
self._selection_start = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getSelectionEnd(self: *const TextArea) u32 {
|
||||||
|
return self._selection_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setSelectionEnd(self: *TextArea, value: u32) void {
|
||||||
|
self._selection_end = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setSelectionRange(self: *TextArea, selection_start: u32, selection_end: u32, selection_dir: ?[]const u8) !void {
|
||||||
|
const direction = blk: {
|
||||||
|
if (selection_dir) |sd| {
|
||||||
|
break :blk std.meta.stringToEnum(Selection.SelectionDirection, sd) orelse .none;
|
||||||
|
} else break :blk .none;
|
||||||
|
};
|
||||||
|
|
||||||
|
const value = self._value orelse {
|
||||||
|
self._selection_start = 0;
|
||||||
|
self._selection_end = 0;
|
||||||
|
self._selection_direction = .none;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
const len_u32: u32 = @intCast(value.len);
|
||||||
|
var start: u32 = if (selection_start > len_u32) len_u32 else selection_start;
|
||||||
|
const end: u32 = if (selection_end > len_u32) len_u32 else selection_end;
|
||||||
|
|
||||||
|
// If end is less than start, both are equal to end.
|
||||||
|
if (end < start) {
|
||||||
|
start = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
self._selection_direction = direction;
|
||||||
|
self._selection_start = start;
|
||||||
|
self._selection_end = end;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn getForm(self: *TextArea, page: *Page) ?*Form {
|
pub fn getForm(self: *TextArea, page: *Page) ?*Form {
|
||||||
const element = self.asElement();
|
const element = self.asElement();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user