More title protection clean up. JS errors were being thrown calling the non-existent...
[lhc/web/wiklou.git] / skins / common / protect.js
1 /**
2 * Set up the protection chaining interface (i.e. "unlock move permissions" checkbox)
3 * on the protection form
4 *
5 * @param String tableId Identifier of the table containing UI bits
6 * @param String labelText Text to use for the checkbox label
7 */
8 function protectInitialize( tableId, labelText, types ) {
9 if( !( document.createTextNode && document.getElementById && document.getElementsByTagName ) )
10 return false;
11
12 var box = document.getElementById( tableId );
13 if( !box )
14 return false;
15
16 var tbody = box.getElementsByTagName( 'tbody' )[0];
17 var row = document.createElement( 'tr' );
18 tbody.appendChild( row );
19
20 row.appendChild( document.createElement( 'td' ) );
21 var col = document.createElement( 'td' );
22 row.appendChild( col );
23 // If there is only one protection type, there is nothing to chain
24 if( types > 1 ) {
25 var check = document.createElement( 'input' );
26 check.id = 'mwProtectUnchained';
27 check.type = 'checkbox';
28 col.appendChild( check );
29 addClickHandler( check, protectChainUpdate );
30
31 col.appendChild( document.createTextNode( ' ' ) );
32 var label = document.createElement( 'label' );
33 label.setAttribute( 'for', 'mwProtectUnchained' );
34 label.appendChild( document.createTextNode( labelText ) );
35 col.appendChild( label );
36
37 check.checked = !protectAllMatch();
38 protectEnable( check.checked );
39 }
40
41 setCascadeCheckbox();
42
43 return true;
44 }
45
46 /**
47 * Determine if, given the cascadeable protection levels
48 * and what is currently selected, if the cascade box
49 * can be checked
50 *
51 * @return boolean
52 *
53 */
54 function setCascadeCheckbox() {
55 // For non-existent titles, there is no cascade option
56 if( !document.getElementById( 'mwProtect-cascade' ) ) {
57 return false;
58 }
59 var lists = protectSelectors();
60 for( var i = 0; i < lists.length; i++ ) {
61 if( lists[i].selectedIndex > -1 ) {
62 var items = lists[i].getElementsByTagName( 'option' );
63 var selected = items[ lists[i].selectedIndex ].value;
64 if( !isCascadeableLevel(selected) ) {
65 document.getElementById( 'mwProtect-cascade' ).checked = false;
66 document.getElementById( 'mwProtect-cascade' ).disabled = true;
67 return false;
68 }
69 }
70 }
71 document.getElementById( 'mwProtect-cascade' ).disabled = false;
72 return true;
73 }
74
75 /**
76 * Is this protection level cascadeable?
77 * @param String level
78 *
79 * @return boolean
80 *
81 */
82 function isCascadeableLevel( level ) {
83 for (var k = 0; k < wgCascadeableLevels.length; k++) {
84 if ( wgCascadeableLevels[k] == level ) {
85 return true;
86 }
87 }
88 return false;
89 }
90
91 /**
92 * When protection levels are locked together, update the rest
93 * when one action's level changes
94 *
95 * @param Element source Level selector that changed
96 */
97 function protectLevelsUpdate(source) {
98 if( !protectUnchained() )
99 protectUpdateAll( source.selectedIndex );
100 setCascadeCheckbox();
101 }
102
103 /**
104 * Update chain status and enable/disable various bits of the UI
105 * when the user changes the "unlock move permissions" checkbox
106 */
107 function protectChainUpdate() {
108 if( protectUnchained() ) {
109 protectEnable( true );
110 } else {
111 protectChain();
112 protectEnable( false );
113 }
114 setCascadeCheckbox();
115 }
116
117 /**
118 * Are all actions protected at the same level?
119 *
120 * @return boolean
121 */
122 function protectAllMatch() {
123 var values = new Array();
124 protectForSelectors(function(set) {
125 values[values.length] = set.selectedIndex;
126 });
127 for (var i = 1; i < values.length; i++) {
128 if (values[i] != values[0]) {
129 return false;
130 }
131 }
132 return true;
133 }
134
135 /**
136 * Is protection chaining on or off?
137 *
138 * @return bool
139 */
140 function protectUnchained() {
141 var unchain = document.getElementById( 'mwProtectUnchained' );
142 return unchain
143 ? unchain.checked
144 : true; // No control, so we need to let the user set both levels
145 }
146
147 /**
148 * Find the highest-protected action and set all others to that level
149 */
150 function protectChain() {
151 var maxIndex = -1;
152 protectForSelectors(function(set) {
153 if (set.selectedIndex > maxIndex) {
154 maxIndex = set.selectedIndex;
155 }
156 });
157 protectUpdateAll(maxIndex);
158 }
159
160 /**
161 * Protect all actions at the specified level
162 *
163 * @param int index Protection level
164 */
165 function protectUpdateAll(index) {
166 protectForSelectors(function(set) {
167 if (set.selectedIndex != index) {
168 set.selectedIndex = index;
169 }
170 });
171 }
172
173 /**
174 * Apply a callback to each protection selector
175 *
176 * @param callable func Callback function
177 */
178 function protectForSelectors(func) {
179 var selectors = protectSelectors();
180 for (var i = 0; i < selectors.length; i++) {
181 func(selectors[i]);
182 }
183 }
184
185 /**
186 * Get a list of all protection selectors on the page
187 *
188 * @return Array
189 */
190 function protectSelectors() {
191 var all = document.getElementsByTagName("select");
192 var ours = new Array();
193 for (var i = 0; i < all.length; i++) {
194 var set = all[i];
195 if (set.id.match(/^mwProtect-level-/)) {
196 ours[ours.length] = set;
197 }
198 }
199 return ours;
200 }
201
202 /**
203 * Enable/disable protection selectors
204 *
205 * @param boolean val Enable?
206 */
207 function protectEnable(val) {
208 // fixme
209 var first = true;
210 protectForSelectors(function(set) {
211 if (first) {
212 first = false;
213 } else {
214 set.disabled = !val;
215 set.style.visible = val ? "visible" : "hidden";
216 }
217 });
218 }