Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F5972615
ApiSandboxLayout.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
ApiSandboxLayout.js
View Options
const
ParamLabelWidget
=
require
(
'./ParamLabelWidget.js'
),
OptionalParamWidget
=
require
(
'./OptionalParamWidget.js'
),
ApiSandbox
=
require
(
'./ApiSandbox.js'
),
Util
=
require
(
'./Util.js'
);
/**
* PageLayout for API modules
*
* @class
* @private
* @extends OO.ui.PageLayout
* @constructor
* @param {Object} [config] Configuration options
*/
function
ApiSandboxLayout
(
config
)
{
config
=
Object
.
assign
(
{
prefix
:
''
,
expanded
:
false
},
config
);
this
.
displayText
=
config
.
key
;
this
.
apiModule
=
config
.
path
;
this
.
prefix
=
config
.
prefix
;
this
.
paramInfo
=
null
;
this
.
apiIsValid
=
true
;
this
.
loadFromQueryParams
=
null
;
this
.
widgets
=
{};
this
.
itemsFieldset
=
null
;
this
.
deprecatedItemsFieldset
=
null
;
this
.
templatedItemsCache
=
{};
this
.
tokenWidget
=
null
;
this
.
indentLevel
=
config
.
indentLevel
?
config
.
indentLevel
:
0
;
ApiSandboxLayout
.
super
.
call
(
this
,
config
.
key
,
config
);
this
.
loadParamInfo
();
}
OO
.
inheritClass
(
ApiSandboxLayout
,
OO
.
ui
.
PageLayout
);
ApiSandboxLayout
.
prototype
.
setupOutlineItem
=
function
()
{
this
.
outlineItem
.
setLevel
(
this
.
indentLevel
);
this
.
outlineItem
.
setLabel
(
this
.
displayText
);
this
.
outlineItem
.
setIcon
(
this
.
apiIsValid
||
ApiSandbox
.
suppressErrors
?
null
:
'alert'
);
this
.
outlineItem
.
setTitle
(
this
.
apiIsValid
||
ApiSandbox
.
suppressErrors
?
''
:
mw
.
message
(
'apisandbox-alert-page'
).
plain
()
);
};
/**
* Create a widget and the FieldLayouts it needs
*
* @private
* @param {Object} ppi API paraminfo data for the parameter
* @param {string} name API parameter name
* @return {Object}
* @return {OO.ui.Widget} return.widget
* @return {OO.ui.FieldLayout} return.widgetField
* @return {OO.ui.FieldLayout} return.helpField
*/
ApiSandboxLayout
.
prototype
.
makeWidgetFieldLayouts
=
function
(
ppi
,
name
)
{
const
widget
=
Util
.
createWidgetForParameter
(
ppi
);
if
(
ppi
.
tokentype
)
{
this
.
tokenWidget
=
widget
;
}
if
(
this
.
paramInfo
.
templatedparameters
.
length
)
{
widget
.
on
(
'change'
,
()
=>
{
this
.
updateTemplatedParameters
(
null
);
}
);
}
const
helpLabel
=
new
ParamLabelWidget
();
let
$tmp
=
Util
.
parseHTML
(
ppi
.
description
);
$tmp
.
filter
(
'dl'
).
makeCollapsible
(
{
collapsed
:
true
}
).
children
(
'.mw-collapsible-toggle'
).
each
(
(
i
,
el
)
=>
{
const
$el
=
$
(
el
);
$el
.
parent
().
prev
(
'p'
).
append
(
$el
);
}
);
helpLabel
.
addDescription
(
$tmp
);
if
(
ppi
.
info
&&
ppi
.
info
.
length
)
{
for
(
let
i
=
0
;
i
<
ppi
.
info
.
length
;
i
++
)
{
helpLabel
.
addInfo
(
Util
.
parseHTML
(
ppi
.
info
[
i
].
text
)
);
}
}
let
flag
=
true
;
let
count
=
Infinity
;
let
tmp
;
switch
(
ppi
.
type
)
{
case
'namespace'
:
flag
=
false
;
count
=
mw
.
config
.
get
(
'wgFormattedNamespaces'
).
length
;
break
;
case
'limit'
:
tmp
=
[
mw
.
message
(
'paramvalidator-help-type-number-minmax'
,
1
,
widget
.
paramInfo
.
min
,
widget
.
paramInfo
.
apiSandboxMax
).
parse
(),
mw
.
message
(
'apisandbox-param-limit'
).
parse
()
];
helpLabel
.
addInfo
(
Util
.
parseHTML
(
tmp
.
join
(
mw
.
msg
(
'word-separator'
)
)
)
);
break
;
case
'integer'
:
tmp
=
''
;
if
(
ppi
.
min
!==
undefined
)
{
tmp
+=
'min'
;
}
if
(
ppi
.
max
!==
undefined
)
{
tmp
+=
'max'
;
}
if
(
tmp
!==
''
)
{
helpLabel
.
addInfo
(
Util
.
parseMsg
(
'paramvalidator-help-type-number-'
+
tmp
,
Util
.
apiBool
(
ppi
.
multi
)
?
2
:
1
,
ppi
.
min
,
ppi
.
max
)
);
}
break
;
default
:
if
(
Array
.
isArray
(
ppi
.
type
)
)
{
flag
=
false
;
count
=
ppi
.
type
.
length
;
}
break
;
}
if
(
Util
.
apiBool
(
ppi
.
multi
)
)
{
tmp
=
[];
if
(
flag
&&
!
(
widget
instanceof
OO
.
ui
.
TagMultiselectWidget
)
&&
!
(
widget
instanceof
OptionalParamWidget
&&
widget
.
widget
instanceof
OO
.
ui
.
TagMultiselectWidget
)
)
{
tmp
.
push
(
mw
.
message
(
'api-help-param-multi-separate'
).
parse
()
);
}
if
(
count
>
ppi
.
lowlimit
)
{
tmp
.
push
(
mw
.
message
(
'paramvalidator-help-multi-max'
,
ppi
.
lowlimit
,
ppi
.
highlimit
).
parse
()
);
}
if
(
tmp
.
length
)
{
helpLabel
.
addInfo
(
Util
.
parseHTML
(
tmp
.
join
(
mw
.
msg
(
'word-separator'
)
)
)
);
}
}
if
(
'maxbytes'
in
ppi
)
{
helpLabel
.
addInfo
(
Util
.
parseMsg
(
'paramvalidator-help-type-string-maxbytes'
,
ppi
.
maxbytes
)
);
}
if
(
'maxchars'
in
ppi
)
{
helpLabel
.
addInfo
(
Util
.
parseMsg
(
'paramvalidator-help-type-string-maxchars'
,
ppi
.
maxchars
)
);
}
if
(
ppi
.
usedTemplateVars
&&
ppi
.
usedTemplateVars
.
length
)
{
$tmp
=
$
();
for
(
let
j
=
0
,
l
=
ppi
.
usedTemplateVars
.
length
;
j
<
l
;
j
++
)
{
$tmp
=
$tmp
.
add
(
$
(
'<var>'
).
text
(
ppi
.
usedTemplateVars
[
j
]
)
);
if
(
j
===
l
-
2
)
{
$tmp
=
$tmp
.
add
(
mw
.
message
(
'and'
).
parseDom
()
);
$tmp
=
$tmp
.
add
(
mw
.
message
(
'word-separator'
).
parseDom
()
);
}
else
if
(
j
!==
l
-
1
)
{
$tmp
=
$tmp
.
add
(
mw
.
message
(
'comma-separator'
).
parseDom
()
);
}
}
helpLabel
.
addInfo
(
Util
.
parseMsg
(
'apisandbox-templated-parameter-reason'
,
ppi
.
usedTemplateVars
.
length
,
$tmp
)
);
}
// TODO: Consder adding more options for the position of helpInline
// so that this can become part of the widgetField, instead of
// having to use a separate field.
const
helpField
=
new
OO
.
ui
.
FieldLayout
(
helpLabel
,
{
align
:
'top'
,
classes
:
[
'mw-apisandbox-help-field'
]
}
);
const
layoutConfig
=
{
align
:
'left'
,
classes
:
[
'mw-apisandbox-widget-field'
],
label
:
name
};
let
widgetField
;
if
(
ppi
.
tokentype
)
{
const
button
=
new
OO
.
ui
.
ButtonWidget
(
{
label
:
mw
.
msg
(
'apisandbox-fetch-token'
)
}
);
button
.
on
(
'click'
,
()
=>
{
widget
.
fetchToken
();
}
);
widgetField
=
new
OO
.
ui
.
ActionFieldLayout
(
widget
,
button
,
layoutConfig
);
}
else
{
widgetField
=
new
OO
.
ui
.
FieldLayout
(
widget
,
layoutConfig
);
}
// We need our own click handler on the widget label to
// turn off the disablement.
widgetField
.
$label
.
on
(
'click'
,
()
=>
{
if
(
typeof
widget
.
setDisabled
===
'function'
)
{
widget
.
setDisabled
(
false
);
}
if
(
typeof
widget
.
focus
===
'function'
)
{
widget
.
focus
();
}
}
);
// Don't grey out the label when the field is disabled,
// it makes it too hard to read and our "disabled"
// isn't really disabled.
widgetField
.
onFieldDisable
(
false
);
widgetField
.
onFieldDisable
=
function
()
{};
widgetField
.
apiParamIndex
=
ppi
.
index
;
return
{
widget
:
widget
,
widgetField
:
widgetField
,
helpField
:
helpField
};
};
/**
* Update templated parameters in the page
*
* @private
* @param {Object} [params] Query parameters for initializing the widgets
*/
ApiSandboxLayout
.
prototype
.
updateTemplatedParameters
=
function
(
params
)
{
const
pi
=
this
.
paramInfo
,
prefix
=
this
.
prefix
+
pi
.
prefix
;
if
(
!
pi
||
!
pi
.
templatedparameters
.
length
)
{
return
;
}
if
(
!
$
.
isPlainObject
(
params
)
)
{
params
=
null
;
}
let
toRemove
=
{};
// eslint-disable-next-line no-jquery/no-each-util
$
.
each
(
this
.
templatedItemsCache
,
(
k
,
el
)
=>
{
if
(
el
.
widget
.
isElementAttached
()
)
{
toRemove
[
k
]
=
el
;
}
}
);
// This bit duplicates the PHP logic in ApiBase::extractRequestParams().
// If you update this, see if that needs updating too.
const
toProcess
=
pi
.
templatedparameters
.
map
(
(
info
)
=>
(
{
name
:
prefix
+
info
.
name
,
info
:
info
,
vars
:
Object
.
assign
(
{},
info
.
templatevars
),
usedVars
:
[]
}
)
);
let
p
;
const
doProcess
=
(
placeholder
,
target
)
=>
{
target
=
prefix
+
target
;
if
(
!
this
.
widgets
[
target
]
)
{
// The target wasn't processed yet, try the next one.
// If all hit this case, the parameter has no expansions.
return
true
;
}
if
(
!
this
.
widgets
[
target
].
getApiValueForTemplates
)
{
// Not a multi-valued widget, so it can't have expansions.
return
false
;
}
const
values
=
this
.
widgets
[
target
].
getApiValueForTemplates
();
if
(
!
Array
.
isArray
(
values
)
||
!
values
.
length
)
{
// The target was processed but has no (valid) values.
// That means it has no expansions.
return
false
;
}
// Expand this target in the name and all other targets,
// then requeue if there are more targets left or create the widget
// and add it to the form if all are done.
delete
p
.
vars
[
placeholder
];
const
usedVars
=
p
.
usedVars
.
concat
(
[
target
]
);
placeholder
=
'{'
+
placeholder
+
'}'
;
const
done
=
$
.
isEmptyObject
(
p
.
vars
);
let
index
,
container
;
if
(
done
)
{
container
=
Util
.
apiBool
(
p
.
info
.
deprecated
)
?
this
.
deprecatedItemsFieldset
:
this
.
itemsFieldset
;
const
items
=
container
.
getItems
();
for
(
let
i
=
0
;
i
<
items
.
length
;
i
++
)
{
if
(
items
[
i
].
apiParamIndex
!==
undefined
&&
items
[
i
].
apiParamIndex
>
p
.
info
.
index
)
{
index
=
i
;
break
;
}
}
}
values
.
forEach
(
(
value
)
=>
{
if
(
!
/^[^{}]*$/
.
exec
(
value
)
)
{
// Skip values that make invalid parameter names
return
;
}
const
name
=
p
.
name
.
replace
(
placeholder
,
value
);
if
(
done
)
{
let
tmp
;
if
(
this
.
templatedItemsCache
[
name
]
)
{
tmp
=
this
.
templatedItemsCache
[
name
];
}
else
{
tmp
=
this
.
makeWidgetFieldLayouts
(
Object
.
assign
(
{},
p
.
info
,
{
usedTemplateVars
:
usedVars
}
),
name
);
this
.
templatedItemsCache
[
name
]
=
tmp
;
}
delete
toRemove
[
name
];
if
(
!
tmp
.
widget
.
isElementAttached
()
)
{
this
.
widgets
[
name
]
=
tmp
.
widget
;
container
.
addItems
(
[
tmp
.
widgetField
,
tmp
.
helpField
],
index
);
if
(
index
!==
undefined
)
{
index
+=
2
;
}
}
if
(
params
)
{
tmp
.
widget
.
setApiValue
(
Object
.
prototype
.
hasOwnProperty
.
call
(
params
,
name
)
?
params
[
name
]
:
undefined
);
}
}
else
{
const
newVars
=
{};
// eslint-disable-next-line no-jquery/no-each-util
$
.
each
(
p
.
vars
,
(
k
,
v
)
=>
{
newVars
[
k
]
=
v
.
replace
(
placeholder
,
value
);
}
);
toProcess
.
push
(
{
name
:
name
,
info
:
p
.
info
,
vars
:
newVars
,
usedVars
:
usedVars
}
);
}
}
);
return
false
;
};
while
(
toProcess
.
length
)
{
p
=
toProcess
.
shift
();
// eslint-disable-next-line no-jquery/no-each-util
$
.
each
(
p
.
vars
,
doProcess
);
}
// eslint-disable-next-line no-jquery/no-map-util
toRemove
=
$
.
map
(
toRemove
,
(
el
,
name
)
=>
{
delete
this
.
widgets
[
name
];
return
[
el
.
widgetField
,
el
.
helpField
];
}
);
if
(
toRemove
.
length
)
{
this
.
itemsFieldset
.
removeItems
(
toRemove
);
this
.
deprecatedItemsFieldset
.
removeItems
(
toRemove
);
}
};
/**
* Fetch module information for this page's module, then create UI
*/
ApiSandboxLayout
.
prototype
.
loadParamInfo
=
function
()
{
let
dynamicFieldset
,
dynamicParamNameWidget
;
const
removeDynamicParamWidget
=
(
name
,
item
)
=>
{
dynamicFieldset
.
removeItems
(
[
item
]
);
delete
this
.
widgets
[
name
];
},
addDynamicParamWidget
=
()
=>
{
// Check name is filled in
const
name
=
dynamicParamNameWidget
.
getValue
().
trim
();
if
(
name
===
''
)
{
dynamicParamNameWidget
.
focus
();
return
;
}
if
(
this
.
widgets
[
name
]
!==
undefined
)
{
ApiSandbox
.
windowManager
.
openWindow
(
'errorAlert'
,
{
title
:
Util
.
parseMsg
(
'apisandbox-dynamic-error-exists'
,
name
),
actions
:
[
{
action
:
'accept'
,
label
:
OO
.
ui
.
msg
(
'ooui-dialog-process-dismiss'
),
flags
:
'primary'
}
]
}
);
return
;
}
const
widget
=
Util
.
createWidgetForParameter
(
{
name
:
name
,
type
:
'string'
,
default
:
''
},
{
nooptional
:
true
}
);
const
button
=
new
OO
.
ui
.
ButtonWidget
(
{
icon
:
'trash'
,
flags
:
'destructive'
}
);
const
actionFieldLayout
=
new
OO
.
ui
.
ActionFieldLayout
(
widget
,
button
,
{
label
:
name
,
align
:
'left'
}
);
button
.
on
(
'click'
,
()
=>
{
removeDynamicParamWidget
(
name
,
actionFieldLayout
);
}
);
this
.
widgets
[
name
]
=
widget
;
dynamicFieldset
.
addItems
(
[
actionFieldLayout
],
dynamicFieldset
.
getItemCount
()
-
1
);
widget
.
focus
();
dynamicParamNameWidget
.
setValue
(
''
);
};
this
.
$element
.
empty
()
.
append
(
document
.
createTextNode
(
mw
.
msg
(
'apisandbox-loading'
,
this
.
displayText
)
),
new
OO
.
ui
.
ProgressBarWidget
(
{
progress
:
false
}
).
$element
);
Util
.
fetchModuleInfo
(
this
.
apiModule
)
.
done
(
(
pi
)
=>
{
const
items
=
[],
deprecatedItems
=
[],
buttons
=
[],
filterFmModules
=
(
v
)
=>
v
.
slice
(
-
2
)
!==
'fm'
||
!
Object
.
prototype
.
hasOwnProperty
.
call
(
ApiSandbox
.
availableFormats
,
v
.
slice
(
0
,
-
2
)
);
// This is something of a hack. We always want the 'format' and
// 'action' parameters from the main module to be specified,
// and for 'format' we also want to simplify the dropdown since
// we always send the 'fm' variant.
if
(
this
.
apiModule
===
'main'
)
{
pi
.
parameters
.
forEach
(
(
parameter
)
=>
{
if
(
parameter
.
name
===
'action'
)
{
parameter
.
required
=
true
;
delete
parameter
.
default
;
}
if
(
parameter
.
name
===
'format'
)
{
const
types
=
parameter
.
type
;
types
.
forEach
(
(
type
)
=>
{
ApiSandbox
.
availableFormats
[
type
]
=
true
;
}
);
parameter
.
type
=
types
.
filter
(
filterFmModules
);
parameter
.
default
=
'json'
;
parameter
.
required
=
true
;
}
}
);
}
// Hide the 'wrappedhtml' parameter on format modules
// and make formatversion default to the latest version for humans
// (even though machines get a different default for b/c)
if
(
pi
.
group
===
'format'
)
{
pi
.
parameters
=
pi
.
parameters
.
filter
(
(
p
)
=>
p
.
name
!==
'wrappedhtml'
).
map
(
(
p
)
=>
{
if
(
p
.
name
===
'formatversion'
)
{
// Use the highest numeric value
p
.
default
=
p
.
type
.
reduce
(
(
prev
,
current
)
=>
!
isNaN
(
current
)
?
Math
.
max
(
prev
,
current
)
:
prev
);
p
.
required
=
true
;
}
return
p
;
}
);
}
this
.
paramInfo
=
pi
;
let
$desc
=
Util
.
parseHTML
(
pi
.
description
);
if
(
pi
.
deprecated
!==
undefined
)
{
$desc
=
$
(
'<span>'
).
addClass
(
'apihelp-deprecated'
).
text
(
mw
.
msg
(
'api-help-param-deprecated'
)
)
.
add
(
document
.
createTextNode
(
mw
.
msg
(
'word-separator'
)
)
).
add
(
$desc
);
}
if
(
pi
.
internal
!==
undefined
)
{
$desc
=
$
(
'<span>'
).
addClass
(
'apihelp-internal'
).
text
(
mw
.
msg
(
'api-help-param-internal'
)
)
.
add
(
document
.
createTextNode
(
mw
.
msg
(
'word-separator'
)
)
).
add
(
$desc
);
}
items
.
push
(
new
OO
.
ui
.
FieldLayout
(
new
OO
.
ui
.
Widget
(
{}
).
toggle
(
false
),
{
align
:
'top'
,
label
:
$desc
}
)
);
if
(
pi
.
helpurls
.
length
)
{
buttons
.
push
(
new
OO
.
ui
.
PopupButtonWidget
(
{
$overlay
:
true
,
label
:
mw
.
msg
(
'apisandbox-helpurls'
),
icon
:
'help'
,
popup
:
{
width
:
'auto'
,
padded
:
true
,
classes
:
[
'mw-apisandbox-popup-help'
],
$content
:
$
(
'<ul>'
).
append
(
pi
.
helpurls
.
map
(
(
link
)
=>
$
(
'<li>'
).
append
(
$
(
'<a>'
)
.
attr
(
{
href
:
link
,
target
:
'_blank'
}
)
.
text
(
link
)
)
)
)
}
}
)
);
}
if
(
pi
.
examples
.
length
)
{
buttons
.
push
(
new
OO
.
ui
.
PopupButtonWidget
(
{
$overlay
:
true
,
label
:
mw
.
msg
(
'apisandbox-examples'
),
icon
:
'code'
,
popup
:
{
width
:
'auto'
,
padded
:
true
,
classes
:
[
'mw-apisandbox-popup-help'
],
$content
:
$
(
'<ul>'
).
append
(
pi
.
examples
.
map
(
(
example
)
=>
{
const
$a
=
$
(
'<a>'
)
.
attr
(
'href'
,
'#'
+
example
.
query
)
.
html
(
example
.
description
);
$a
.
find
(
'a'
).
contents
().
unwrap
();
// Can't nest links
return
$
(
'<li>'
).
append
(
$a
);
}
)
)
}
}
)
);
}
if
(
buttons
.
length
)
{
items
.
push
(
new
OO
.
ui
.
FieldLayout
(
new
OO
.
ui
.
ButtonGroupWidget
(
{
items
:
buttons
}
),
{
align
:
'top'
}
)
);
}
if
(
pi
.
parameters
.
length
)
{
const
prefix
=
this
.
prefix
+
pi
.
prefix
;
pi
.
parameters
.
forEach
(
(
parameter
)
=>
{
const
tmpLayout
=
this
.
makeWidgetFieldLayouts
(
parameter
,
prefix
+
parameter
.
name
);
this
.
widgets
[
prefix
+
parameter
.
name
]
=
tmpLayout
.
widget
;
if
(
Util
.
apiBool
(
parameter
.
deprecated
)
)
{
deprecatedItems
.
push
(
tmpLayout
.
widgetField
,
tmpLayout
.
helpField
);
}
else
{
items
.
push
(
tmpLayout
.
widgetField
,
tmpLayout
.
helpField
);
}
}
);
}
if
(
!
pi
.
parameters
.
length
&&
!
Util
.
apiBool
(
pi
.
dynamicparameters
)
)
{
items
.
push
(
new
OO
.
ui
.
FieldLayout
(
new
OO
.
ui
.
Widget
(
{}
).
toggle
(
false
),
{
align
:
'top'
,
label
:
Util
.
parseMsg
(
'apisandbox-no-parameters'
)
}
)
);
}
this
.
$element
.
empty
();
this
.
itemsFieldset
=
new
OO
.
ui
.
FieldsetLayout
(
{
label
:
this
.
displayText
}
);
this
.
itemsFieldset
.
addItems
(
items
);
this
.
itemsFieldset
.
$element
.
appendTo
(
this
.
$element
);
if
(
Util
.
apiBool
(
pi
.
dynamicparameters
)
)
{
dynamicFieldset
=
new
OO
.
ui
.
FieldsetLayout
();
dynamicParamNameWidget
=
new
OO
.
ui
.
TextInputWidget
(
{
placeholder
:
mw
.
msg
(
'apisandbox-dynamic-parameters-add-placeholder'
)
}
).
on
(
'enter'
,
addDynamicParamWidget
);
dynamicFieldset
.
addItems
(
[
new
OO
.
ui
.
FieldLayout
(
new
OO
.
ui
.
Widget
(
{}
).
toggle
(
false
),
{
align
:
'top'
,
label
:
Util
.
parseHTML
(
pi
.
dynamicparameters
)
}
),
new
OO
.
ui
.
ActionFieldLayout
(
dynamicParamNameWidget
,
new
OO
.
ui
.
ButtonWidget
(
{
icon
:
'add'
,
flags
:
'progressive'
}
).
on
(
'click'
,
addDynamicParamWidget
),
{
label
:
mw
.
msg
(
'apisandbox-dynamic-parameters-add-label'
),
align
:
'left'
}
)
]
);
$
(
'<fieldset>'
)
.
append
(
$
(
'<legend>'
).
text
(
mw
.
msg
(
'apisandbox-dynamic-parameters'
)
),
dynamicFieldset
.
$element
)
.
appendTo
(
this
.
$element
);
}
this
.
deprecatedItemsFieldset
=
new
OO
.
ui
.
FieldsetLayout
().
addItems
(
deprecatedItems
).
toggle
(
false
);
const
$tmp
=
$
(
'<fieldset>'
)
.
toggle
(
!
this
.
deprecatedItemsFieldset
.
isEmpty
()
)
.
append
(
$
(
'<legend>'
).
append
(
new
OO
.
ui
.
ToggleButtonWidget
(
{
label
:
mw
.
msg
(
'apisandbox-deprecated-parameters'
)
}
).
on
(
'change'
,
()
=>
{
this
.
deprecatedItemsFieldset
.
toggle
();
}
).
$element
),
this
.
deprecatedItemsFieldset
.
$element
)
.
appendTo
(
this
.
$element
);
this
.
deprecatedItemsFieldset
.
on
(
'add'
,
()
=>
{
$tmp
.
toggle
(
!
this
.
deprecatedItemsFieldset
.
isEmpty
()
);
}
);
this
.
deprecatedItemsFieldset
.
on
(
'remove'
,
()
=>
{
$tmp
.
toggle
(
!
this
.
deprecatedItemsFieldset
.
isEmpty
()
);
}
);
// Load stored params, if any, then update the booklet if we
// have subpages (or else just update our valid-indicator).
const
tmp
=
this
.
loadFromQueryParams
;
this
.
loadFromQueryParams
=
null
;
if
(
$
.
isPlainObject
(
tmp
)
)
{
this
.
loadQueryParams
(
tmp
);
}
else
{
this
.
updateTemplatedParameters
();
}
if
(
this
.
getSubpages
().
length
>
0
)
{
ApiSandbox
.
updateUI
(
tmp
);
}
else
{
this
.
apiCheckValid
();
}
}
).
fail
(
(
code
,
detail
)
=>
{
this
.
$element
.
empty
()
.
append
(
new
OO
.
ui
.
LabelWidget
(
{
label
:
mw
.
msg
(
'apisandbox-load-error'
,
this
.
apiModule
,
detail
),
classes
:
[
'error'
]
}
).
$element
,
new
OO
.
ui
.
ButtonWidget
(
{
label
:
mw
.
msg
(
'apisandbox-retry'
)
}
).
on
(
'click'
,
()
=>
{
this
.
loadParamInfo
();
}
).
$element
);
}
);
};
/**
* Check that all widgets on the page are in a valid state.
*
* @return {jQuery.Promise[]} One promise for each widget, resolved with `false` if invalid
*/
ApiSandboxLayout
.
prototype
.
apiCheckValid
=
function
()
{
if
(
this
.
paramInfo
===
null
)
{
return
[];
}
else
{
// eslint-disable-next-line no-jquery/no-map-util
const
promises
=
$
.
map
(
this
.
widgets
,
(
widget
)
=>
widget
.
apiCheckValid
(
ApiSandbox
.
suppressErrors
)
);
$
.
when
(
...
promises
).
then
(
(
...
results
)
=>
{
this
.
apiIsValid
=
!
results
.
includes
(
false
);
if
(
this
.
getOutlineItem
()
)
{
this
.
getOutlineItem
().
setIcon
(
this
.
apiIsValid
||
ApiSandbox
.
suppressErrors
?
null
:
'alert'
);
this
.
getOutlineItem
().
setTitle
(
this
.
apiIsValid
||
ApiSandbox
.
suppressErrors
?
''
:
mw
.
message
(
'apisandbox-alert-page'
).
plain
()
);
}
}
);
return
promises
;
}
};
/**
* Load form fields from query parameters
*
* @param {Object} params
*/
ApiSandboxLayout
.
prototype
.
loadQueryParams
=
function
(
params
)
{
if
(
this
.
paramInfo
===
null
)
{
this
.
loadFromQueryParams
=
params
;
}
else
{
// eslint-disable-next-line no-jquery/no-each-util
$
.
each
(
this
.
widgets
,
(
name
,
widget
)
=>
{
const
v
=
Object
.
prototype
.
hasOwnProperty
.
call
(
params
,
name
)
?
params
[
name
]
:
undefined
;
widget
.
setApiValue
(
v
);
}
);
this
.
updateTemplatedParameters
(
params
);
}
};
/**
* Load query params from form fields
*
* @param {Object} params Write query parameters into this object
* @param {Object} displayParams Write query parameters for display into this object
* @param {Object} ajaxOptions Write options for the API request into this object, in the format
* expected by jQuery#ajax.
*/
ApiSandboxLayout
.
prototype
.
getQueryParams
=
function
(
params
,
displayParams
,
ajaxOptions
)
{
// eslint-disable-next-line no-jquery/no-each-util
$
.
each
(
this
.
widgets
,
(
name
,
widget
)
=>
{
let
value
=
widget
.
getApiValue
();
if
(
value
!==
undefined
)
{
params
[
name
]
=
value
;
if
(
typeof
widget
.
getApiValueForDisplay
===
'function'
)
{
value
=
widget
.
getApiValueForDisplay
();
}
displayParams
[
name
]
=
value
;
if
(
typeof
widget
.
requiresFormData
===
'function'
&&
widget
.
requiresFormData
()
)
{
ajaxOptions
.
contentType
=
'multipart/form-data'
;
}
}
}
);
};
/**
* Fetch a list of subpage names loaded by this page
*
* @return {Array}
*/
ApiSandboxLayout
.
prototype
.
getSubpages
=
function
()
{
const
ret
=
[];
// eslint-disable-next-line no-jquery/no-each-util
$
.
each
(
this
.
widgets
,
(
name
,
widget
)
=>
{
if
(
typeof
widget
.
getSubmodules
===
'function'
)
{
widget
.
getSubmodules
().
forEach
(
(
submodule
)
=>
{
ret
.
push
(
{
key
:
name
+
'='
+
submodule
.
value
,
path
:
submodule
.
path
,
prefix
:
widget
.
paramInfo
.
submoduleparamprefix
||
''
}
);
}
);
}
}
);
return
ret
;
};
module
.
exports
=
ApiSandboxLayout
;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Oct 3, 16:02 (1 d, 17 h ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
7f/3e/64dcf2e7dee9594642464af7f7fc
Default Alt Text
ApiSandboxLayout.js (21 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment