Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F4121947
index.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
index.js
View Options
/*!
* Collapsing script for Special:LanguageStats in MediaWiki Extension:Translate
* @author Krinkle <krinklemail (at) gmail (dot) com>
* @author Niklas Laxström
* @license GPL-2.0-or-later, CC-BY-SA-3.0
*/
(
function
()
{
'use strict'
;
var
$columns
;
/**
* Add css class to every other visible row.
* It's not possible to do zebra colors with CSS only if there are hidden rows.
*
* @param {jQuery} $table
*/
function
doZebra
(
$table
)
{
$table
.
find
(
'tr:visible:odd'
).
toggleClass
(
'tux-statstable-even'
,
false
);
$table
.
find
(
'tr:visible:even'
).
toggleClass
(
'tux-statstable-even'
,
true
);
}
function
addExpanders
(
$table
)
{
var
$metaRows
=
$
(
'tr.AggregateMessageGroup'
,
$table
);
// Quick return
if
(
!
$metaRows
.
length
)
{
return
;
}
$metaRows
.
each
(
function
()
{
var
$parent
=
$
(
this
),
thisGroupId
=
$parent
.
attr
(
'data-groupid'
),
$children
=
$
(
'tr[data-parentgroup="'
+
thisGroupId
+
'"]'
,
$table
);
// Only do the collapse stuff if this Meta-group actually has children on this page
if
(
!
$children
.
length
)
{
return
;
}
// Build toggle link
var
$toggler
=
$
(
'<span>'
).
addClass
(
'groupexpander collapsed'
)
.
append
(
'['
,
$
(
'<a>'
)
.
attr
(
'href'
,
'#'
)
.
text
(
mw
.
msg
(
'translate-langstats-expand'
)
),
']'
)
.
on
(
'click'
,
function
(
e
)
{
var
$el
=
$
(
this
);
// Switch the state and toggle the rows
if
(
$el
.
hasClass
(
'collapsed'
)
)
{
$children
.
removeClass
(
'statstable-hide'
).
trigger
(
'show'
);
doZebra
(
$table
);
$el
.
removeClass
(
'collapsed'
).
addClass
(
'expanded'
);
$el
.
find
(
'> a'
).
text
(
mw
.
msg
(
'translate-langstats-collapse'
)
);
}
else
{
$children
.
addClass
(
'statstable-hide'
).
trigger
(
'hide'
);
doZebra
(
$table
);
$el
.
addClass
(
'collapsed'
).
removeClass
(
'expanded'
);
$el
.
find
(
'> a'
).
text
(
mw
.
msg
(
'translate-langstats-expand'
)
);
}
e
.
preventDefault
();
}
);
// Add the toggle link to the first cell of the meta group table-row
$parent
.
find
(
' > td'
).
first
().
append
(
$toggler
);
// Handle hide/show recursively, so that collapsing parent group
// hides all sub groups regardless of nesting level
$parent
.
on
(
'hide show'
,
function
(
event
)
{
// Reuse $toggle, $parent and $children from parent scope
if
(
$toggler
.
hasClass
(
'expanded'
)
)
{
$children
.
trigger
(
event
.
type
)[
event
.
type
]();
}
}
);
}
);
// Create, bind and append the toggle-all button
var
$allChildRows
=
$
(
'tr[data-parentgroup]'
,
$table
);
var
$allTogglesCache
=
null
;
var
$toggleAllButton
=
$
(
'<span>'
).
addClass
(
'collapsed'
)
.
append
(
'['
,
$
(
'<a>'
)
.
attr
(
'href'
,
'#'
)
.
text
(
mw
.
msg
(
'translate-langstats-expandall'
)
),
']'
)
.
on
(
'click'
,
function
(
e
)
{
var
$el
=
$
(
this
),
$allToggles
=
$allTogglesCache
||
$
(
'.groupexpander'
,
$table
);
// Switch the state and toggle the rows
// and update the local toggles too
if
(
$el
.
hasClass
(
'collapsed'
)
)
{
$allChildRows
.
removeClass
(
'statstable-hide'
);
$el
.
add
(
$allToggles
).
removeClass
(
'collapsed'
).
addClass
(
'expanded'
);
$el
.
find
(
'> a'
).
text
(
mw
.
msg
(
'translate-langstats-collapseall'
)
);
$allToggles
.
find
(
'> a'
).
text
(
mw
.
msg
(
'translate-langstats-collapse'
)
);
}
else
{
$allChildRows
.
addClass
(
'statstable-hide'
);
$el
.
add
(
$allToggles
).
addClass
(
'collapsed'
).
removeClass
(
'expanded'
);
$el
.
find
(
'> a'
).
text
(
mw
.
msg
(
'translate-langstats-expandall'
)
);
$allToggles
.
find
(
'> a'
).
text
(
mw
.
msg
(
'translate-langstats-expand'
)
);
}
doZebra
(
$table
);
e
.
preventDefault
();
}
);
// Initially hide them
$allChildRows
.
addClass
(
'statstable-hide'
);
doZebra
(
$table
);
// Add the toggle-all button above the table
$
(
'<p>'
).
addClass
(
'groupexpander-all'
).
append
(
$toggleAllButton
).
insertBefore
(
$table
);
}
function
applySorting
(
$table
)
{
var
sort
=
{},
re
=
/#sortable:(\d+)=(asc|desc)/
,
match
=
re
.
exec
(
location
.
hash
);
if
(
match
)
{
var
index
=
parseInt
(
match
[
1
],
10
);
sort
[
index
]
=
match
[
2
];
}
$table
.
tablesorter
(
{
sortList
:
[
sort
]
}
);
$table
.
on
(
'sortEnd.tablesorter'
,
function
()
{
$table
.
find
(
'.headerSortDown, .headerSortUp'
).
each
(
function
()
{
var
headerIndex
=
$table
.
find
(
'th'
).
index
(
$
(
this
)
),
dir
=
$
(
this
).
hasClass
(
'headerSortUp'
)
?
'asc'
:
'desc'
;
location
.
hash
=
'sortable:'
+
headerIndex
+
'='
+
dir
;
doZebra
(
$table
);
}
);
}
);
}
function
narrowTable
(
$table
,
enable
)
{
var
labelColumnCount
=
1
,
// 0-indexed
defaultValueColumn
=
2
;
if
(
$columns
===
undefined
)
{
$columns
=
$table
.
find
(
'thead > tr > th '
).
map
(
function
(
index
,
value
)
{
return
value
.
textContent
;
}
);
}
var
$select
=
makeValueColumnSelector
(
$columns
,
labelColumnCount
,
defaultValueColumn
);
// Prevent table sorter from making the select inaccessible
$select
.
on
(
'mousedown click'
,
function
(
e
)
{
e
.
stopPropagation
();
}
).
on
(
'change'
,
function
()
{
showValueColumn
(
$table
,
$select
,
labelColumnCount
);
}
);
if
(
enable
)
{
showValueColumn
(
$table
,
$select
,
labelColumnCount
);
}
else
{
// Restore original headings
$table
.
find
(
'thead > tr > th'
).
map
(
function
(
index
)
{
return
$
(
this
).
text
(
$columns
[
index
]
);
}
);
$table
.
find
(
'tr > *'
).
removeClass
(
'statstable-hide'
);
}
}
function
makeValueColumnSelector
(
headings
,
skip
,
def
)
{
var
$select
=
$
(
'<select>'
);
for
(
var
i
=
skip
;
i
<
headings
.
length
;
i
++
)
{
$
(
'<option>'
)
.
text
(
headings
[
i
]
)
.
val
(
i
)
.
prop
(
'selected'
,
i
===
def
)
.
appendTo
(
$select
);
}
return
$select
;
}
function
showValueColumn
(
$table
,
$select
,
skip
)
{
var
index
=
parseInt
(
$select
.
val
(),
10
);
var
cssQuery
=
'th:nth-child(_)'
.
replace
(
'_'
,
index
+
1
);
$table
.
find
(
cssQuery
).
html
(
$select
);
for
(
var
i
=
0
;
i
<
$select
.
children
().
length
;
i
++
)
{
cssQuery
=
'tr > *:nth-child(_)'
.
replace
(
'_'
,
i
+
skip
+
1
);
$table
.
find
(
cssQuery
).
toggleClass
(
'statstable-hide'
,
i
+
skip
!==
index
);
}
}
function
activateEntitySelector
(
$group
,
$messagePrefix
)
{
// hide the message group and prefix selector
var
$groupContainer
=
$
(
'.message-group-selector'
);
// Change the label, and update the for attribute, and remove the click handler
// which causes the entity selector to become un-responsive when triggered
$groupContainer
.
find
(
'label'
)
.
text
(
mw
.
msg
(
'translate-mgs-group-or-prefix'
)
)
.
attr
(
'for'
,
'mw-entity-selector-input'
)
.
off
(
'click'
);
// Determine what value was set, and set it on the entity selector
var
selectedGroup
=
$group
.
find
(
'select option:selected'
).
text
();
// load the entity selector and set the value
var
entitySelector
=
getEntitySelector
(
onEntitySelect
);
if
(
selectedGroup
)
{
entitySelector
.
setValue
(
selectedGroup
);
}
else
{
var
selectedMessage
=
$messagePrefix
.
val
();
if
(
selectedMessage
)
{
entitySelector
.
setValue
(
selectedMessage
);
}
}
$group
.
addClass
(
'hidden'
);
$group
.
after
(
entitySelector
.
$element
);
}
function
onEntitySelect
(
selectedItem
)
{
if
(
selectedItem
.
type
===
'group'
)
{
$
(
'select[name="group"]'
).
val
(
selectedItem
.
data
);
$
(
'input[name="messages"]'
).
val
(
''
);
}
else
{
$
(
'input[name="messages"]'
).
val
(
selectedItem
.
data
);
$
(
'select[name="group"]'
).
val
(
''
);
}
}
function
onSubmit
()
{
var
selectedGroupName
=
$
(
'select[name="group"]'
).
find
(
'option:selected'
).
text
();
var
selectedMessagePrefix
=
$
(
'input[name="messages"]'
).
val
();
var
currentVal
=
$
(
'.tes-entity-selector'
).
find
(
'input[type="text"]'
).
val
();
// Check if the user has selected an invalid entity.
if
(
currentVal
!==
selectedGroupName
&&
currentVal
!==
selectedMessagePrefix
)
{
mw
.
notify
(
mw
.
msg
(
'translate-mgs-invalid-entity'
),
{
type
:
'error'
,
tag
:
'invalid-selection'
}
);
return
false
;
}
}
function
getEntitySelector
(
onSelect
)
{
var
EntitySelector
=
require
(
'ext.translate.entity.selector'
);
return
new
EntitySelector
(
{
onSelect
:
onSelect
,
entityType
:
[
'groups'
,
'messages'
],
inputId
:
'mw-entity-selector-input'
}
);
}
$
(
function
()
{
var
$table
=
$
(
'.statstable'
);
activateEntitySelector
(
$
(
'#group'
),
$
(
'input[name="messages"]'
)
);
// Sometimes the table is not present on the page
if
(
!
$table
.
length
)
{
return
;
}
// Calculate absolute minimum table width
if
(
window
.
ResizeObserver
)
{
$table
.
css
(
'max-width'
,
'1px'
);
}
applySorting
(
$table
);
addExpanders
(
$table
);
$
(
'#mw-message-group-stats-form'
).
on
(
'submit'
,
onSubmit
);
if
(
!
window
.
ResizeObserver
)
{
return
;
}
var
minimumTableWidth
;
// Hopefully previous stuff have time to render by now to have accurate picture of the width
(
window
.
requestAnimationFrame
||
setTimeout
)(
function
()
{
minimumTableWidth
=
$table
.
outerWidth
();
$table
.
css
(
'max-width'
,
''
);
}
);
var
isNarrowMode
;
new
ResizeObserver
(
function
(
entries
)
{
var
shouldCollapse
=
entries
[
0
].
contentRect
.
width
<
minimumTableWidth
;
// Some fudge to avoid flapping
var
shouldExpand
=
entries
[
0
].
contentRect
.
width
-
20
>
minimumTableWidth
;
var
newMode
;
if
(
isNarrowMode
&&
shouldExpand
)
{
newMode
=
false
;
}
else
if
(
!
isNarrowMode
&&
shouldCollapse
)
{
newMode
=
true
;
}
else
{
newMode
=
isNarrowMode
;
}
if
(
newMode
!==
isNarrowMode
)
{
isNarrowMode
=
newMode
;
narrowTable
(
$table
,
isNarrowMode
);
}
}
).
observe
(
$table
.
parent
().
get
(
0
)
);
}
);
}()
);
File Metadata
Details
Attached
Mime Type
text/x-asm
Expires
Wed, Aug 19, 05:03 (1 d, 12 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
0d/69/70a2e2d6ab85de9981f75dddda90
Default Alt Text
index.js (9 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment