Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
D
dsiUnits
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
DigitalDynamicMeasurement
dsiUnits
Commits
a97d0cfe
Project 'Seeger/dccviewer-js' was moved to 'digitaldynamicmeasurement/dccviewer-js'. Please update any links and bookmarks that may still have the old path.
Commit
a97d0cfe
authored
3 months ago
by
Benedikt
Browse files
Options
Downloads
Patches
Plain Diff
improved sugestions
parent
089c3dba
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
dsiUnits-js/src/dsiUnitInput.js
+29
-19
29 additions, 19 deletions
dsiUnits-js/src/dsiUnitInput.js
with
29 additions
and
19 deletions
dsiUnits-js/src/dsiUnitInput.js
+
29
−
19
View file @
a97d0cfe
...
@@ -14,11 +14,12 @@ export class DSIUnitInput extends HTMLElement {
...
@@ -14,11 +14,12 @@ export class DSIUnitInput extends HTMLElement {
constructor
()
{
constructor
()
{
super
();
super
();
this
.
attachShadow
({
mode
:
"
open
"
});
this
.
attachShadow
({
mode
:
"
open
"
});
// Internal state
: store raw value
.
// Internal state.
this
.
_rawValue
=
""
;
this
.
_rawValue
=
""
;
this
.
liveUpdate
=
true
;
this
.
liveUpdate
=
true
;
this
.
allowedTokens
=
defaultAllowedTokens
;
this
.
allowedTokens
=
defaultAllowedTokens
;
this
.
selectedSuggestionIndex
=
-
1
;
this
.
selectedSuggestionIndex
=
-
1
;
this
.
lastAcceptedToken
=
""
;
// NEW: track last accepted token
// Create elements.
// Create elements.
this
.
input
=
document
.
createElement
(
"
input
"
);
this
.
input
=
document
.
createElement
(
"
input
"
);
...
@@ -29,18 +30,18 @@ export class DSIUnitInput extends HTMLElement {
...
@@ -29,18 +30,18 @@ export class DSIUnitInput extends HTMLElement {
this
.
suggestions
.
className
=
"
autocomplete-list
"
;
this
.
suggestions
.
className
=
"
autocomplete-list
"
;
this
.
suggestions
.
style
.
display
=
"
none
"
;
this
.
suggestions
.
style
.
display
=
"
none
"
;
this
.
display
=
document
.
createElement
(
"
div
"
);
//
For r
endered output on blur.
this
.
display
=
document
.
createElement
(
"
div
"
);
//
R
endered output on blur.
this
.
display
.
id
=
"
dsiDisplay
"
;
this
.
display
.
id
=
"
dsiDisplay
"
;
this
.
display
.
style
.
cursor
=
"
text
"
;
// Make it clickable for editing.
this
.
display
.
style
.
cursor
=
"
text
"
;
// Container
for input and suggestions
.
// Container.
const
container
=
document
.
createElement
(
"
div
"
);
const
container
=
document
.
createElement
(
"
div
"
);
container
.
style
.
position
=
"
relative
"
;
container
.
style
.
position
=
"
relative
"
;
container
.
appendChild
(
this
.
input
);
container
.
appendChild
(
this
.
input
);
container
.
appendChild
(
this
.
suggestions
);
container
.
appendChild
(
this
.
suggestions
);
container
.
appendChild
(
this
.
display
);
container
.
appendChild
(
this
.
display
);
//
Append s
tyles.
//
S
tyles.
const
style
=
document
.
createElement
(
"
style
"
);
const
style
=
document
.
createElement
(
"
style
"
);
style
.
textContent
=
`
style
.
textContent
=
`
#dsiInput {
#dsiInput {
...
@@ -76,7 +77,7 @@ export class DSIUnitInput extends HTMLElement {
...
@@ -76,7 +77,7 @@ export class DSIUnitInput extends HTMLElement {
`
;
`
;
this
.
shadowRoot
.
append
(
style
,
container
);
this
.
shadowRoot
.
append
(
style
,
container
);
// Bind
event
handlers.
// Bind handlers.
this
.
onInput
=
this
.
onInput
.
bind
(
this
);
this
.
onInput
=
this
.
onInput
.
bind
(
this
);
this
.
onKeyDown
=
this
.
onKeyDown
.
bind
(
this
);
this
.
onKeyDown
=
this
.
onKeyDown
.
bind
(
this
);
this
.
onBlur
=
this
.
onBlur
.
bind
(
this
);
this
.
onBlur
=
this
.
onBlur
.
bind
(
this
);
...
@@ -117,19 +118,22 @@ export class DSIUnitInput extends HTMLElement {
...
@@ -117,19 +118,22 @@ export class DSIUnitInput extends HTMLElement {
this
.
display
.
removeEventListener
(
"
click
"
,
this
.
onFocus
);
this
.
display
.
removeEventListener
(
"
click
"
,
this
.
onFocus
);
}
}
// Determine contextual suggestions
based on previous complete token
.
// Determine
s
contextual suggestions.
getContextualSuggestions
()
{
getContextualSuggestions
()
{
const
value
=
this
.
input
.
value
;
const
value
=
this
.
input
.
value
;
const
tokens
=
value
.
split
(
"
\\
"
).
filter
(
Boolean
);
const
tokens
=
value
.
split
(
"
\\
"
).
filter
(
Boolean
);
// If there are no complete tokens, allow all suggestions.
if
(
tokens
.
length
<=
1
)
{
if
(
tokens
.
length
<=
1
)
{
return
this
.
allowedTokens
;
return
this
.
allowedTokens
;
}
}
// Use last accepted token if available.
if
(
this
.
lastAcceptedToken
&&
(
this
.
lastAcceptedToken
in
dsiPrefixesHTML
))
{
return
Object
.
keys
(
dsiUnitsHTML
);
}
const
prevToken
=
tokens
[
tokens
.
length
-
2
];
const
prevToken
=
tokens
[
tokens
.
length
-
2
];
if
(
prevToken
in
dsiPrefixesHTML
)
{
if
(
prevToken
in
dsiPrefixesHTML
)
{
// After a prefix, suggest only allowed units.
return
Object
.
keys
(
dsiUnitsHTML
);
return
Object
.
keys
(
dsiUnitsHTML
);
}
else
if
(
prevToken
in
dsiUnitsHTML
)
{
}
else
if
(
prevToken
in
dsiUnitsHTML
)
{
// After a unit, suggest all allowed tokens.
if
(
value
.
includes
(
"
\\
per
"
))
{
if
(
value
.
includes
(
"
\\
per
"
))
{
return
this
.
allowedTokens
.
filter
(
token
=>
token
!==
"
per
"
);
return
this
.
allowedTokens
.
filter
(
token
=>
token
!==
"
per
"
);
}
}
...
@@ -143,7 +147,7 @@ export class DSIUnitInput extends HTMLElement {
...
@@ -143,7 +147,7 @@ export class DSIUnitInput extends HTMLElement {
onInput
(
e
)
{
onInput
(
e
)
{
this
.
_rawValue
=
this
.
input
.
value
;
this
.
_rawValue
=
this
.
input
.
value
;
// Auto-insert a backslash
if the user types a space after a complete token
.
// Auto-insert a backslash
after a token if a space is typed
.
if
(
this
.
input
.
value
.
endsWith
(
"
"
))
{
if
(
this
.
input
.
value
.
endsWith
(
"
"
))
{
const
trimmed
=
this
.
input
.
value
.
trimEnd
();
const
trimmed
=
this
.
input
.
value
.
trimEnd
();
if
(
!
trimmed
.
endsWith
(
"
\\
"
))
{
if
(
!
trimmed
.
endsWith
(
"
\\
"
))
{
...
@@ -161,7 +165,7 @@ export class DSIUnitInput extends HTMLElement {
...
@@ -161,7 +165,7 @@ export class DSIUnitInput extends HTMLElement {
updateSuggestions
()
{
updateSuggestions
()
{
const
cursorPos
=
this
.
input
.
selectionStart
;
const
cursorPos
=
this
.
input
.
selectionStart
;
const
value
=
this
.
input
.
value
;
const
value
=
this
.
input
.
value
;
//
Do not show
suggestions if caret is inside the braces
of a tothe token
.
//
Suppress
suggestions if caret is inside
to
the braces.
const
regexTothe
=
/
\\
tothe
\{([^
}
]
*
)
$/
;
const
regexTothe
=
/
\\
tothe
\{([^
}
]
*
)
$/
;
const
substring
=
value
.
substring
(
0
,
cursorPos
);
const
substring
=
value
.
substring
(
0
,
cursorPos
);
const
matchTothe
=
substring
.
match
(
regexTothe
);
const
matchTothe
=
substring
.
match
(
regexTothe
);
...
@@ -170,16 +174,23 @@ export class DSIUnitInput extends HTMLElement {
...
@@ -170,16 +174,23 @@ export class DSIUnitInput extends HTMLElement {
this
.
suggestions
.
style
.
display
=
"
none
"
;
this
.
suggestions
.
style
.
display
=
"
none
"
;
return
;
return
;
}
}
// Capture
the
current token (which may be empty).
// Capture current token (which may be empty).
const
regex
=
/
\\([
a-zA-Z
]
*
)
$/
;
const
regex
=
/
\\([
a-zA-Z
]
*
)
$/
;
const
match
=
substring
.
match
(
regex
);
const
match
=
substring
.
match
(
regex
);
let
currentToken
=
""
;
let
currentToken
=
""
;
if
(
match
)
{
if
(
match
)
{
currentToken
=
match
[
1
];
currentToken
=
match
[
1
];
}
}
// If current
T
oken exactly matches a known prefix, treat it as complete.
// If current
t
oken exactly matches a known prefix, treat it as complete.
if
(
currentToken
&&
(
currentToken
in
dsiPrefixesHTML
))
{
if
(
currentToken
&&
(
currentToken
in
dsiPrefixesHTML
))
{
console
.
log
(
"
Token complete: currentToken matches known prefix:
"
,
currentToken
);
console
.
log
(
"
Token complete: using accepted prefix
"
,
currentToken
);
// Update lastAcceptedToken.
this
.
lastAcceptedToken
=
currentToken
;
// Auto-complete by appending a trailing backslash if not already present.
if
(
!
value
.
endsWith
(
"
\\
"
))
{
this
.
input
.
value
=
value
+
"
\\
"
;
this
.
_rawValue
=
this
.
input
.
value
;
}
currentToken
=
""
;
currentToken
=
""
;
}
}
const
tokens
=
value
.
split
(
"
\\
"
).
filter
(
Boolean
);
const
tokens
=
value
.
split
(
"
\\
"
).
filter
(
Boolean
);
...
@@ -206,7 +217,6 @@ export class DSIUnitInput extends HTMLElement {
...
@@ -206,7 +217,6 @@ export class DSIUnitInput extends HTMLElement {
}
}
list
.
forEach
((
token
,
index
)
=>
{
list
.
forEach
((
token
,
index
)
=>
{
const
item
=
document
.
createElement
(
"
div
"
);
const
item
=
document
.
createElement
(
"
div
"
);
// Always render suggestions with a backslash.
item
.
textContent
=
"
\\
"
+
token
;
item
.
textContent
=
"
\\
"
+
token
;
item
.
className
=
"
autocomplete-item
"
;
item
.
className
=
"
autocomplete-item
"
;
if
(
index
===
this
.
selectedSuggestionIndex
)
{
if
(
index
===
this
.
selectedSuggestionIndex
)
{
...
@@ -240,7 +250,7 @@ export class DSIUnitInput extends HTMLElement {
...
@@ -240,7 +250,7 @@ export class DSIUnitInput extends HTMLElement {
if
(
this
.
selectedSuggestionIndex
!==
-
1
)
{
if
(
this
.
selectedSuggestionIndex
!==
-
1
)
{
e
.
preventDefault
();
e
.
preventDefault
();
const
selectedItem
=
items
[
this
.
selectedSuggestionIndex
];
const
selectedItem
=
items
[
this
.
selectedSuggestionIndex
];
const
token
=
selectedItem
.
textContent
.
slice
(
1
);
// remove backslash
const
token
=
selectedItem
.
textContent
.
slice
(
1
);
// remove
leading
backslash
const
tokenStartIndex
=
this
.
input
.
value
.
lastIndexOf
(
"
\\
"
);
const
tokenStartIndex
=
this
.
input
.
value
.
lastIndexOf
(
"
\\
"
);
this
.
acceptSuggestion
(
token
,
tokenStartIndex
);
this
.
acceptSuggestion
(
token
,
tokenStartIndex
);
}
}
...
@@ -264,14 +274,15 @@ export class DSIUnitInput extends HTMLElement {
...
@@ -264,14 +274,15 @@ export class DSIUnitInput extends HTMLElement {
const
before
=
value
.
substring
(
0
,
tokenStartIndex
);
const
before
=
value
.
substring
(
0
,
tokenStartIndex
);
const
after
=
value
.
substring
(
this
.
input
.
selectionStart
);
const
after
=
value
.
substring
(
this
.
input
.
selectionStart
);
if
(
token
===
"
tothe
"
)
{
if
(
token
===
"
tothe
"
)
{
// Append {} and place caret inside.
this
.
input
.
value
=
before
+
"
\\
"
+
token
+
"
{}
"
+
after
;
this
.
input
.
value
=
before
+
"
\\
"
+
token
+
"
{}
"
+
after
;
this
.
_rawValue
=
this
.
input
.
value
;
this
.
_rawValue
=
this
.
input
.
value
;
this
.
lastAcceptedToken
=
token
;
const
newPos
=
before
.
length
+
token
.
length
+
2
;
const
newPos
=
before
.
length
+
token
.
length
+
2
;
this
.
input
.
setSelectionRange
(
newPos
,
newPos
);
this
.
input
.
setSelectionRange
(
newPos
,
newPos
);
}
else
{
}
else
{
this
.
input
.
value
=
before
+
"
\\
"
+
token
+
after
;
this
.
input
.
value
=
before
+
"
\\
"
+
token
+
after
;
this
.
_rawValue
=
this
.
input
.
value
;
this
.
_rawValue
=
this
.
input
.
value
;
this
.
lastAcceptedToken
=
token
;
}
}
this
.
suggestions
.
style
.
display
=
"
none
"
;
this
.
suggestions
.
style
.
display
=
"
none
"
;
this
.
renderOutput
();
this
.
renderOutput
();
...
@@ -279,9 +290,8 @@ export class DSIUnitInput extends HTMLElement {
...
@@ -279,9 +290,8 @@ export class DSIUnitInput extends HTMLElement {
renderOutput
()
{
renderOutput
()
{
try
{
try
{
// No special conversion for "per" is needed now.
const
unit
=
new
DSIUnit
(
this
.
input
.
value
);
const
unit
=
new
DSIUnit
(
this
.
input
.
value
);
//
Pass
oneLine option
if desired
.
//
Call DSIUnit.toHTML with
oneLine option.
this
.
display
.
innerHTML
=
unit
.
toHTML
({
oneLine
:
true
});
this
.
display
.
innerHTML
=
unit
.
toHTML
({
oneLine
:
true
});
if
(
unit
.
warnings
&&
unit
.
warnings
.
length
>
0
)
{
if
(
unit
.
warnings
&&
unit
.
warnings
.
length
>
0
)
{
this
.
display
.
title
=
unit
.
warnings
.
join
(
"
;
"
);
this
.
display
.
title
=
unit
.
warnings
.
join
(
"
;
"
);
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment