Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F88816490
scale.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, Oct 20, 20:10
Size
6 KB
Mime Type
text/x-c++
Expires
Tue, Oct 22, 20:10 (2 d)
Engine
blob
Format
Raw Data
Handle
21819372
Attached To
rOACCT Open Access Compliance Check Tool (OACCT)
scale.js
View Options
'use strict'
;
const
colors
=
require
(
'ansi-colors'
);
const
ArrayPrompt
=
require
(
'../types/array'
);
const
utils
=
require
(
'../utils'
);
class
LikertScale
extends
ArrayPrompt
{
constructor
(
options
=
{})
{
super
(
options
);
this
.
widths
=
[].
concat
(
options
.
messageWidth
||
50
);
this
.
align
=
[].
concat
(
options
.
align
||
'left'
);
this
.
linebreak
=
options
.
linebreak
||
false
;
this
.
edgeLength
=
options
.
edgeLength
||
3
;
this
.
newline
=
options
.
newline
||
'\n '
;
let
start
=
options
.
startNumber
||
1
;
if
(
typeof
this
.
scale
===
'number'
)
{
this
.
scaleKey
=
false
;
this
.
scale
=
Array
(
this
.
scale
).
fill
(
0
).
map
((
v
,
i
)
=>
({
name
:
i
+
start
}));
}
}
async
reset
()
{
this
.
tableized
=
false
;
await
super
.
reset
();
return
this
.
render
();
}
tableize
()
{
if
(
this
.
tableized
===
true
)
return
;
this
.
tableized
=
true
;
let
longest
=
0
;
for
(
let
ch
of
this
.
choices
)
{
longest
=
Math
.
max
(
longest
,
ch
.
message
.
length
);
ch
.
scaleIndex
=
ch
.
initial
||
2
;
ch
.
scale
=
[];
for
(
let
i
=
0
;
i
<
this
.
scale
.
length
;
i
++
)
{
ch
.
scale
.
push
({
index
:
i
});
}
}
this
.
widths
[
0
]
=
Math
.
min
(
this
.
widths
[
0
],
longest
+
3
);
}
async
dispatch
(
s
,
key
)
{
if
(
this
.
multiple
)
{
return
this
[
key
.
name
]
?
await
this
[
key
.
name
](
s
,
key
)
:
await
super
.
dispatch
(
s
,
key
);
}
this
.
alert
();
}
heading
(
msg
,
item
,
i
)
{
return
this
.
styles
.
strong
(
msg
);
}
separator
()
{
return
this
.
styles
.
muted
(
this
.
symbols
.
ellipsis
);
}
right
()
{
let
choice
=
this
.
focused
;
if
(
choice
.
scaleIndex
>=
this
.
scale
.
length
-
1
)
return
this
.
alert
();
choice
.
scaleIndex
++
;
return
this
.
render
();
}
left
()
{
let
choice
=
this
.
focused
;
if
(
choice
.
scaleIndex
<=
0
)
return
this
.
alert
();
choice
.
scaleIndex
--
;
return
this
.
render
();
}
indent
()
{
return
''
;
}
format
()
{
if
(
this
.
state
.
submitted
)
{
let
values
=
this
.
choices
.
map
(
ch
=>
this
.
styles
.
info
(
ch
.
index
));
return
values
.
join
(
', '
);
}
return
''
;
}
pointer
()
{
return
''
;
}
/**
* Render the scale "Key". Something like:
* @return {String}
*/
renderScaleKey
()
{
if
(
this
.
scaleKey
===
false
)
return
''
;
if
(
this
.
state
.
submitted
)
return
''
;
let
scale
=
this
.
scale
.
map
(
item
=>
`
$
{
item
.
name
}
-
$
{
item
.
message
}
`
);
let
key
=
[
''
,
...
scale
].
map
(
item
=>
this
.
styles
.
muted
(
item
));
return
key
.
join
(
'\n'
);
}
/**
* Render the heading row for the scale.
* @return {String}
*/
renderScaleHeading
(
max
)
{
let
keys
=
this
.
scale
.
map
(
ele
=>
ele
.
name
);
if
(
typeof
this
.
options
.
renderScaleHeading
===
'function'
)
{
keys
=
this
.
options
.
renderScaleHeading
.
call
(
this
,
max
);
}
let
diff
=
this
.
scaleLength
-
keys
.
join
(
''
).
length
;
let
spacing
=
Math
.
round
(
diff
/
(
keys
.
length
-
1
));
let
names
=
keys
.
map
(
key
=>
this
.
styles
.
strong
(
key
));
let
headings
=
names
.
join
(
' '
.
repeat
(
spacing
));
let
padding
=
' '
.
repeat
(
this
.
widths
[
0
]);
return
this
.
margin
[
3
]
+
padding
+
this
.
margin
[
1
]
+
headings
;
}
/**
* Render a scale indicator => ◯ or ◉ by default
*/
scaleIndicator
(
choice
,
item
,
i
)
{
if
(
typeof
this
.
options
.
scaleIndicator
===
'function'
)
{
return
this
.
options
.
scaleIndicator
.
call
(
this
,
choice
,
item
,
i
);
}
let
enabled
=
choice
.
scaleIndex
===
item
.
index
;
if
(
item
.
disabled
)
return
this
.
styles
.
hint
(
this
.
symbols
.
radio
.
disabled
);
if
(
enabled
)
return
this
.
styles
.
success
(
this
.
symbols
.
radio
.
on
);
return
this
.
symbols
.
radio
.
off
;
}
/**
* Render the actual scale => ◯────◯────◉────◯────◯
*/
renderScale
(
choice
,
i
)
{
let
scale
=
choice
.
scale
.
map
(
item
=>
this
.
scaleIndicator
(
choice
,
item
,
i
));
let
padding
=
this
.
term
===
'Hyper'
?
''
:
' '
;
return
scale
.
join
(
padding
+
this
.
symbols
.
line
.
repeat
(
this
.
edgeLength
));
}
/**
* Render a choice, including scale =>
* "The website is easy to navigate. ◯───◯───◉───◯───◯"
*/
async
renderChoice
(
choice
,
i
)
{
await
this
.
onChoice
(
choice
,
i
);
let
focused
=
this
.
index
===
i
;
let
pointer
=
await
this
.
pointer
(
choice
,
i
);
let
hint
=
await
choice
.
hint
;
if
(
hint
&&
!
utils
.
hasColor
(
hint
))
{
hint
=
this
.
styles
.
muted
(
hint
);
}
let
pad
=
str
=>
this
.
margin
[
3
]
+
str
.
replace
(
/\s+$/
,
''
).
padEnd
(
this
.
widths
[
0
],
' '
);
let
newline
=
this
.
newline
;
let
ind
=
this
.
indent
(
choice
);
let
message
=
await
this
.
resolve
(
choice
.
message
,
this
.
state
,
choice
,
i
);
let
scale
=
await
this
.
renderScale
(
choice
,
i
);
let
margin
=
this
.
margin
[
1
]
+
this
.
margin
[
3
];
this
.
scaleLength
=
colors
.
unstyle
(
scale
).
length
;
this
.
widths
[
0
]
=
Math
.
min
(
this
.
widths
[
0
],
this
.
width
-
this
.
scaleLength
-
margin
.
length
);
let
msg
=
utils
.
wordWrap
(
message
,
{
width
:
this
.
widths
[
0
],
newline
});
let
lines
=
msg
.
split
(
'\n'
).
map
(
line
=>
pad
(
line
)
+
this
.
margin
[
1
]);
if
(
focused
)
{
scale
=
this
.
styles
.
info
(
scale
);
lines
=
lines
.
map
(
line
=>
this
.
styles
.
info
(
line
));
}
lines
[
0
]
+=
scale
;
if
(
this
.
linebreak
)
lines
.
push
(
''
);
return
[
ind
+
pointer
,
lines
.
join
(
'\n'
)].
filter
(
Boolean
);
}
async
renderChoices
()
{
if
(
this
.
state
.
submitted
)
return
''
;
this
.
tableize
();
let
choices
=
this
.
visible
.
map
(
async
(
ch
,
i
)
=>
await
this
.
renderChoice
(
ch
,
i
));
let
visible
=
await
Promise
.
all
(
choices
);
let
heading
=
await
this
.
renderScaleHeading
();
return
this
.
margin
[
0
]
+
[
heading
,
...
visible
.
map
(
v
=>
v
.
join
(
' '
))].
join
(
'\n'
);
}
async
render
()
{
let
{
submitted
,
size
}
=
this
.
state
;
let
prefix
=
await
this
.
prefix
();
let
separator
=
await
this
.
separator
();
let
message
=
await
this
.
message
();
let
prompt
=
''
;
if
(
this
.
options
.
promptLine
!==
false
)
{
prompt
=
[
prefix
,
message
,
separator
,
''
].
join
(
' '
);
this
.
state
.
prompt
=
prompt
;
}
let
header
=
await
this
.
header
();
let
output
=
await
this
.
format
();
let
key
=
await
this
.
renderScaleKey
();
let
help
=
await
this
.
error
()
||
await
this
.
hint
();
let
body
=
await
this
.
renderChoices
();
let
footer
=
await
this
.
footer
();
let
err
=
this
.
emptyError
;
if
(
output
)
prompt
+=
output
;
if
(
help
&&
!
prompt
.
includes
(
help
))
prompt
+=
' '
+
help
;
if
(
submitted
&&
!
output
&&
!
body
.
trim
()
&&
this
.
multiple
&&
err
!=
null
)
{
prompt
+=
this
.
styles
.
danger
(
err
);
}
this
.
clear
(
size
);
this
.
write
([
header
,
prompt
,
key
,
body
,
footer
].
filter
(
Boolean
).
join
(
'\n'
));
if
(
!
this
.
state
.
submitted
)
{
this
.
write
(
this
.
margin
[
2
]);
}
this
.
restore
();
}
submit
()
{
this
.
value
=
{};
for
(
let
choice
of
this
.
choices
)
{
this
.
value
[
choice
.
name
]
=
choice
.
scaleIndex
;
}
return
this
.
base
.
submit
.
call
(
this
);
}
}
module
.
exports
=
LikertScale
;
Event Timeline
Log In to Comment