Merge "Type hint against LinkTarget in WatchedItemStore"
[lhc/web/wiklou.git] / resources / src / mediawiki.special.block.js
1 /*!
2 * JavaScript for Special:Block
3 */
4 ( function () {
5 // Like OO.ui.infuse(), but if the element doesn't exist, return null instead of throwing an exception.
6 function infuseIfExists( $el ) {
7 if ( !$el.length ) {
8 return null;
9 }
10 return OO.ui.infuse( $el );
11 }
12
13 $( function () {
14 var blockTargetWidget, anonOnlyWidget, enableAutoblockWidget, hideUserWidget, watchUserWidget,
15 expiryWidget, editingWidget, editingRestrictionWidget, preventTalkPageEditWidget,
16 pageRestrictionsWidget, namespaceRestrictionsWidget, createAccountWidget, data,
17 enablePartialBlocks, blockAllowsUTEdit, userChangedCreateAccount, updatingBlockOptions;
18
19 function preserveSelectedStateOnDisable( widget ) {
20 var widgetWasSelected;
21
22 if ( !widget ) {
23 return;
24 }
25
26 // 'disable' event fires if disabled state changes
27 widget.on( 'disable', function ( disabled ) {
28 if ( disabled ) {
29 // Disabling an enabled widget
30 // Save selected and set selected to false
31 widgetWasSelected = widget.isSelected();
32 widget.setSelected( false );
33 } else {
34 // Enabling a disabled widget
35 // Set selected to the saved value
36 if ( widgetWasSelected !== undefined ) {
37 widget.setSelected( widgetWasSelected );
38 }
39 widgetWasSelected = undefined;
40 }
41 } );
42 }
43
44 function updateBlockOptions() {
45 var blocktarget = blockTargetWidget.getValue().trim(),
46 isEmpty = blocktarget === '',
47 isIp = mw.util.isIPAddress( blocktarget, true ),
48 isIpRange = isIp && blocktarget.match( /\/\d+$/ ),
49 isNonEmptyIp = isIp && !isEmpty,
50 expiryValue = expiryWidget.getValue(),
51 // infinityValues are the values the SpecialBlock class accepts as infinity (sf. wfIsInfinity)
52 infinityValues = [ 'infinite', 'indefinite', 'infinity', 'never' ],
53 isIndefinite = infinityValues.indexOf( expiryValue ) !== -1,
54 editingRestrictionValue = enablePartialBlocks ? editingRestrictionWidget.getValue() : 'sitewide',
55 editingIsSelected = editingWidget.isSelected(),
56 isSitewide = editingIsSelected && editingRestrictionValue === 'sitewide';
57
58 enableAutoblockWidget.setDisabled( isNonEmptyIp );
59
60 anonOnlyWidget.setDisabled( !isIp && !isEmpty );
61
62 if ( hideUserWidget ) {
63 hideUserWidget.setDisabled( isNonEmptyIp || !isIndefinite || !isSitewide );
64 }
65
66 if ( watchUserWidget ) {
67 watchUserWidget.setDisabled( isIpRange && !isEmpty );
68 }
69
70 if ( enablePartialBlocks ) {
71 editingRestrictionWidget.setDisabled( !editingIsSelected );
72 pageRestrictionsWidget.setDisabled( !editingIsSelected || isSitewide );
73 namespaceRestrictionsWidget.setDisabled( !editingIsSelected || isSitewide );
74 if ( blockAllowsUTEdit ) {
75 // Disable for partial blocks, unless the block is against the User_talk namespace
76 preventTalkPageEditWidget.setDisabled(
77 // Partial block that doesn't block editing
78 !editingIsSelected ||
79 // Partial block that blocks editing and doesn't block the User_talk namespace
80 (
81 editingRestrictionValue === 'partial' &&
82 namespaceRestrictionsWidget.getValue().indexOf(
83 String( mw.config.get( 'wgNamespaceIds' ).user_talk )
84 ) === -1
85 )
86 );
87 }
88 }
89
90 if ( !userChangedCreateAccount ) {
91 updatingBlockOptions = true;
92 createAccountWidget.setSelected( isSitewide );
93 updatingBlockOptions = false;
94 }
95
96 }
97
98 // This code is also loaded on the "block succeeded" page where there is no form,
99 // so check for block target widget; if it exists, the form is present
100 blockTargetWidget = infuseIfExists( $( '#mw-bi-target' ) );
101
102 if ( blockTargetWidget ) {
103 data = require( './config.json' );
104 enablePartialBlocks = data.EnablePartialBlocks;
105 blockAllowsUTEdit = data.BlockAllowsUTEdit;
106 userChangedCreateAccount = mw.config.get( 'wgCreateAccountDirty' );
107 updatingBlockOptions = false;
108
109 // Always present if blockTargetWidget is present
110 editingWidget = OO.ui.infuse( $( '#mw-input-wpEditing' ) );
111 expiryWidget = OO.ui.infuse( $( '#mw-input-wpExpiry' ) );
112 createAccountWidget = OO.ui.infuse( $( '#mw-input-wpCreateAccount' ) );
113 enableAutoblockWidget = OO.ui.infuse( $( '#mw-input-wpAutoBlock' ) );
114 anonOnlyWidget = OO.ui.infuse( $( '#mw-input-wpHardBlock' ) );
115 blockTargetWidget.on( 'change', updateBlockOptions );
116 editingWidget.on( 'change', updateBlockOptions );
117 expiryWidget.on( 'change', updateBlockOptions );
118 createAccountWidget.on( 'change', function () {
119 if ( !updatingBlockOptions ) {
120 userChangedCreateAccount = true;
121 }
122 } );
123
124 // Present for certain rights
125 watchUserWidget = infuseIfExists( $( '#mw-input-wpWatch' ) );
126 hideUserWidget = infuseIfExists( $( '#mw-input-wpHideUser' ) );
127
128 // Present for certain global configs
129 if ( enablePartialBlocks ) {
130 editingRestrictionWidget = OO.ui.infuse( $( '#mw-input-wpEditingRestriction' ) );
131 pageRestrictionsWidget = OO.ui.infuse( $( '#mw-input-wpPageRestrictions' ) );
132 namespaceRestrictionsWidget = OO.ui.infuse( $( '#mw-input-wpNamespaceRestrictions' ) );
133 editingRestrictionWidget.on( 'change', updateBlockOptions );
134 namespaceRestrictionsWidget.on( 'change', updateBlockOptions );
135 }
136 if ( blockAllowsUTEdit ) {
137 preventTalkPageEditWidget = infuseIfExists( $( '#mw-input-wpDisableUTEdit' ) );
138 }
139
140 // When disabling checkboxes, preserve their selected state in case they are re-enabled
141 preserveSelectedStateOnDisable( enableAutoblockWidget );
142 preserveSelectedStateOnDisable( anonOnlyWidget );
143 preserveSelectedStateOnDisable( watchUserWidget );
144 preserveSelectedStateOnDisable( hideUserWidget );
145 preserveSelectedStateOnDisable( preventTalkPageEditWidget );
146
147 updateBlockOptions();
148 }
149 } );
150 }() );