# HG changeset patch # User Dan # Date 1239648208 14400 # Node ID c949e82b8f49e178ff25349fa98acc6bad6016f6 # Parent 1e40b33f2e3ecd3a1ea0686a1323280771734ce1 New page protection UI. Both miniPrompt and failsafe HTML. diff -r 1e40b33f2e3e -r c949e82b8f49 images/protect-icons.png Binary file images/protect-icons.png has changed diff -r 1e40b33f2e3e -r c949e82b8f49 includes/clientside/static/ajax.js --- a/includes/clientside/static/ajax.js Mon Apr 13 12:32:36 2009 -0400 +++ b/includes/clientside/static/ajax.js Mon Apr 13 14:43:28 2009 -0400 @@ -33,42 +33,134 @@ // Miscellaneous AJAX applets -window.ajaxProtect = function(l) { +window.ajaxProtect = function(existing_level) +{ // IE <6 pseudo-compatibility if ( KILL_SWITCH ) return true; - load_component('l10n'); + + // touch this variable to allow it to be used in child functions + void(existing_level); + + load_component(['messagebox', 'jquery', 'jquery-ui', 'l10n', 'fadefilter', 'flyin']); + + // preload language + $lang.get('meta_meta'); - if(shift) { - r = 'NO_REASON'; - } else { - r = prompt($lang.get('ajax_protect_prompt_reason')); - if(!r || r=='') return; + var mp = miniPrompt(function(parent) + { + var icon_full = gen_sprite_html(cdnPath + '/images/protect-icons.png', 22, 22, 0, 0); + var icon_semi = gen_sprite_html(cdnPath + '/images/protect-icons.png', 22, 22, 22, 0); + var icon_none = gen_sprite_html(cdnPath + '/images/protect-icons.png', 22, 22, 44, 0); + + $(parent).append('

' + $lang.get('onpage_protect_heading') + '

'); + $(parent).append('

' + $lang.get('onpage_protect_msg_select_level') + '

'); + + $(parent).append('
'); + $(parent).append('
' + $lang.get('onpage_protect_btn_full_hint') + '
'); + $(parent).append('
'); + $(parent).append('
' + $lang.get('onpage_protect_btn_semi_hint') + '
'); + $(parent).append('
'); + $(parent).append('
' + $lang.get('onpage_protect_btn_none_hint') + '
'); + + $(parent).append('
' + $lang.get('onpage_protect_lbl_reason') + '
' + $lang.get('onpage_protect_lbl_reason_hint') + '
'); + + $(parent).append('

' + $lang.get('onpage_protect_btn_submit') + ' ' + $lang.get('etc_cancel') + '

'); + + $('.protectlevel', parent).css('line-height', '22px'); + $('h3', parent).css('text-align', 'center'); + $('.protectlevel_hint', parent) + .css('font-size', 'smaller') + .css('margin-left', '52px') + .hide(); + $('p.buttons', parent).css('margin-top', '15px').css('text-align', 'center'); + + if ( typeof(existing_level) == 'number' ) + { + $('#protect_level_' + existing_level, parent).attr('checked', 'checked'); + $('#protect_level_' + existing_level + '_hint', parent).show(); + $('#protect_level_' + existing_level, parent).parent().append(' ' + $lang.get('onpage_protect_lbl_current') + ''); + } + + $('input:radio', parent).click(function() + { + var mp = miniPromptGetParent(this); + $('.protectlevel_hint:visible', mp).hide('blind', 150); + $('#' + this.id + '_hint').show('blind', 150); + $('#protect_reason').focus(); + }); + $('input:text', parent).keyup(function(e) + { + if ( e.keyCode == 13 ) + ajaxProtectSubmit(this); + }); + }); +} + +window.ajaxProtectSubmit = function(el) +{ + var mp = miniPromptGetParent(el); + + var reason = trim($('#protect_reason', mp).attr('value')); + if ( reason == '' ) + { + var oldbg = $('#protect_reason').css('background-color'); + if ( jQuery.fx.off ) + { + $('#protect_reason').css('background-color', '#a00'); + setTimeout(function() + { + $('#protect_reason').css('background-color', oldbg); + }, 1000); + } + else + { + $('#protect_reason').css('background-color', '#a00').animate({ backgroundColor: oldbg }, 1000); + } + return false; } - setAjaxLoading(); - document.getElementById('protbtn_0').style.textDecoration = 'none'; - document.getElementById('protbtn_1').style.textDecoration = 'none'; - document.getElementById('protbtn_2').style.textDecoration = 'none'; - document.getElementById('protbtn_'+l).style.textDecoration = 'underline'; - ajaxPost(stdAjaxPrefix+'&_mode=protect', 'reason='+ajaxEscape(r)+'&level='+l, function(ajax) { - if ( ajax.readyState == 4 && ajax.status == 200 ) { - unsetAjaxLoading(); - if(ajax.responseText == 'good') - return true; - // check for JSON error response - var response = String(ajax.responseText + ''); - if ( response.substr(0, 1) == '{' ) + + var level = 0; + if ( $('#protect_level_1', mp).attr('checked') ) + level = 1; + if ( $('#protect_level_2', mp).attr('checked') ) + level = 2; + + var whitey = whiteOutMiniPrompt(mp); + $.post(stdAjaxPrefix + '&_mode=protect', { level: level, reason: reason }, function(response, statustext) + { + if ( response.success ) { - response = parseJSON(response); - if ( response.mode == 'error' ) + whiteOutReportSuccess(whitey); + setTimeout(function() + { + miniPromptDestroy(mp); + }, 1250); + // update protect button + var btn = $('#tb_ajax_protect_btn').get(0); + btn.level = level; + btn.setAttribute('onclick', null); + btn.onclick = null; + $(btn).click(function() + { + ajaxProtect(this.level); + return false; + }); + var status = ''; + switch(level) { - alert(response.error); - return true; + case 1: status = $lang.get('onpage_btn_protect_on'); break; + case 0: status = $lang.get('onpage_btn_protect_off'); break; + case 2: status = $lang.get('onpage_btn_protect_semi'); break; } + $('#tb_ajax_protect_status').text(status); } - alert(ajax.responseText); - } - }, true); + else + { + whiteOutReportFailure(whitey); + alert($lang.get('page_err_' + response.error)); + } + }, 'json'); } window.ajaxRename = function() diff -r 1e40b33f2e3e -r c949e82b8f49 includes/clientside/static/functions.js --- a/includes/clientside/static/functions.js Mon Apr 13 12:32:36 2009 -0400 +++ b/includes/clientside/static/functions.js Mon Apr 13 14:43:28 2009 -0400 @@ -465,7 +465,7 @@ function gen_sprite(path, width, height, xpos, ypos) { var image = document.createElement('img'); - image.src = scriptPath + '/images/spacer.gif'; + image.src = cdnPath + '/images/spacer.gif'; image.width = String(width); image.height = String(height); image.style.backgroundImage = 'url(' + path + ')'; diff -r 1e40b33f2e3e -r c949e82b8f49 includes/clientside/static/messagebox.js --- a/includes/clientside/static/messagebox.js Mon Apr 13 12:32:36 2009 -0400 +++ b/includes/clientside/static/messagebox.js Mon Apr 13 14:43:28 2009 -0400 @@ -572,6 +572,39 @@ }); } +/** + * Identical to whiteOutElement(), but safe to call on miniPrompt divs. + */ + +function whiteOutMiniPrompt(el) +{ + var top = getScrollOffset(); + var left = ( getWidth() / 2 ) - ( 320 / 2); + var width = 320; + var height = $dynano(el).Height() - 58; + + var blackout = document.createElement('div'); + // using fixed here allows modal windows to be blacked out + blackout.style.position = ( el.style.position == 'fixed' ) ? 'fixed' : 'absolute'; + blackout.style.top = top + 'px'; + blackout.style.left = left + 'px'; + blackout.style.width = width + 'px'; + blackout.style.height = height + 'px'; + + blackout.style.backgroundColor = '#FFFFFF'; + domObjChangeOpac(60, blackout); + var background = ( $dynano(el).Height() < 48 ) ? 'url(' + scriptPath + '/images/loading.gif)' : 'url(' + scriptPath + '/includes/clientside/tinymce/themes/advanced/skins/default/img/progress.gif)'; + blackout.style.backgroundImage = background; + blackout.style.backgroundPosition = 'center center'; + blackout.style.backgroundRepeat = 'no-repeat'; + blackout.style.zIndex = '1000'; + + var body = document.getElementsByTagName('body')[0]; + body.appendChild(blackout); + + return blackout; +} + function testMPMessageBox() { miniPromptMessage({ diff -r 1e40b33f2e3e -r c949e82b8f49 includes/functions.php --- a/includes/functions.php Mon Apr 13 12:32:36 2009 -0400 +++ b/includes/functions.php Mon Apr 13 14:43:28 2009 -0400 @@ -2155,6 +2155,27 @@ } /** + * Generate HTML for a sprite image. + * @param string Path to sprite image + * @param int Width of resulting image + * @param int Height of resulting image + * @param int X offset + * @param int Y offset + * @return object HTMLImageElement + */ + +function gen_sprite($path, $width, $height, $xpos, $ypos) +{ + $html = 'get_permissions('read') && $session->check_acl_scope('protect', $local_namespace) && $paths->wiki_mode && $local_page_exists && $perms->get_permissions('protect')) { + switch($local_cdata['protected']) + { + case PROTECT_FULL: $protect_status = $lang->get('onpage_btn_protect_on'); break; + case PROTECT_SEMI: $protect_status = $lang->get('onpage_btn_protect_semi'); break; + case PROTECT_NONE: $protect_status = $lang->get('onpage_btn_protect_off'); break; + } $label = $this->makeParserText($tplvars['toolbar_label']); - $label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_protect'))); + $label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_protect') . ' ' . "$protect_status")); $t0 = $label->run(); - $ctmp = ''; - if ( $local_cdata['protected'] == 1 ) - { - $ctmp=' style="text-decoration: underline;"'; - } $menubtn->assign_vars(array( - 'FLAGS' => 'accesskey="i" onclick="if ( !KILL_SWITCH ) { ajaxProtect(1); return false; }" id="protbtn_1" title="' . $lang->get('onpage_tip_protect_on') . '"'.$ctmp, - 'HREF' => makeUrl($local_page, 'do=protect&level=1', true), - 'TEXT' => $lang->get('onpage_btn_protect_on') + 'FLAGS' => 'accesskey="p" onclick="ajaxProtect(' . $local_cdata['protected'] . '); return false;" id="tb_ajax_protect_btn" title="' . $lang->get('onpage_tip_protect') . '"', + 'HREF' => makeUrl($local_page, 'do=protect', true), + 'TEXT' => $lang->get('onpage_btn_protect_change') )); $t1 = $menubtn->run(); - $ctmp = ''; - if ( $local_cdata['protected'] == 0 ) - { - $ctmp=' style="text-decoration: underline;"'; - } - $menubtn->assign_vars(array( - 'FLAGS' => 'accesskey="o" onclick="if ( !KILL_SWITCH ) { ajaxProtect(0); return false; }" id="protbtn_0" title="' . $lang->get('onpage_tip_protect_off') . '"'.$ctmp, - 'HREF' => makeUrl($local_page, 'do=protect&level=0', true), - 'TEXT' => $lang->get('onpage_btn_protect_off') - )); - $t2 = $menubtn->run(); - - $ctmp = ''; - if ( $local_cdata['protected'] == 2 ) - { - $ctmp = ' style="text-decoration: underline;"'; - } - $menubtn->assign_vars(array( - 'FLAGS' => 'accesskey="p" onclick="if ( !KILL_SWITCH ) { ajaxProtect(2); return false; }" id="protbtn_2" title="' . $lang->get('onpage_tip_protect_semi') . '"'.$ctmp, - 'HREF' => makeUrl($local_page, 'do=protect&level=2', true), - 'TEXT' => $lang->get('onpage_btn_protect_semi') - )); - $t3 = $menubtn->run(); - $this->toolbar_menu .= ' - -
'.$t0.' '.$t1.''.$t2.''.$t3.'
'; } diff -r 1e40b33f2e3e -r c949e82b8f49 index.php --- a/index.php Mon Apr 13 12:32:36 2009 -0400 +++ b/index.php Mon Apr 13 14:43:28 2009 -0400 @@ -329,39 +329,92 @@ $template->footer(); break; case 'protect': - if (!isset($_REQUEST['level'])) die_friendly('Invalid request', '

No protection level specified

'); - require_once(ENANO_ROOT.'/includes/pageutils.php'); - if(!empty($_POST['reason'])) + if ( isset($_POST['level']) && isset($_POST['reason']) ) { - if(!preg_match('#^([0-2]*){1}$#', $_POST['level'])) die_friendly('Error protecting page', '

Request validation failed

'); - PageUtils::protect($paths->page_id, $paths->namespace, intval($_POST['level']), $_POST['reason']); + $level = intval($_POST['level']); + if ( !in_array($level, array(PROTECT_FULL, PROTECT_SEMI, PROTECT_NONE)) ) + { + $errors[] = 'bad level'; + } + $reason = trim($_POST['reason']); + if ( empty($reason) ) + { + $errors[] = $lang->get('onpage_protect_err_need_reason'); + } - die_friendly($lang->get('page_protect_lbl_success_title'), '

' . $lang->get('page_protect_lbl_success_body', array( 'page_link' => makeUrl($paths->page) )) . '

'); + $page = new PageProcessor($paths->page_id, $paths->namespace); + $result = $page->protect_page($level, $reason); + if ( $result['success'] ) + { + redirect(makeUrl($paths->page), $lang->get('page_protect_lbl_success_title'), $lang->get('page_protect_lbl_success_body', array('page_link' => makeUrl($paths->page, false, true))), 3); + } + else + { + $errors[] = $lang->get('page_err_' . $result['error']); + } } $template->header(); ?>
- - ' . $lang->get('page_protect_err_need_reason') . '

'; ?> -

get('page_protect_lbl_reason'); ?>

-


- get('page_protect_lbl_level'); ?> get('page_protect_lbl_level_none'); - break; - case '1': - echo $lang->get('page_protect_lbl_level_full'); - break; - case '2': - echo $lang->get('page_protect_lbl_level_semi'); - break; - default: - echo 'None; Warning: request validation will fail after clicking submit'; - } - ?>

-

+

get('onpage_protect_heading'); ?>

+

get('onpage_protect_msg_select_level'); ?>

+ +
  • ' . implode('
  • ', $errors) . '
  • '; + } + ?> + +
    + +
    +
    + get('onpage_protect_btn_full_hint'); ?> +
    + +
    + +
    +
    + get('onpage_protect_btn_semi_hint'); ?> +
    + +
    + +
    +
    + get('onpage_protect_btn_none_hint'); ?> +
    + + + + + + +
    + get('onpage_protect_lbl_reason'); ?> + +
    + get('onpage_protect_lbl_reason_hint'); ?> +
    + +

    + + get('etc_cancel'); ?> +

    footer(); diff -r 1e40b33f2e3e -r c949e82b8f49 language/english/core.json --- a/language/english/core.json Mon Apr 13 12:32:36 2009 -0400 +++ b/language/english/core.json Mon Apr 13 14:43:28 2009 -0400 @@ -71,13 +71,6 @@ protect_lbl_success_title: 'Page protected', protect_lbl_success_body: 'The protection setting has been applied. Return to the page.', - protect_err_need_reason: 'Error: you must enter a reason for protecting this page.', - protect_lbl_reason: 'Reason for protecting the page:', - protect_lbl_level: 'Protecion level to be applied:', - protect_lbl_level_none: 'No protection', - protect_lbl_level_semi: 'Semi-protection', - protect_lbl_level_full: 'Full protection', - protect_btn_submit: 'Protect page', rename_err_need_name: 'Error: you must enter a new name for this page.', rename_lbl: 'Please enter a new name for this page:', @@ -286,6 +279,7 @@ btn_protect_on: 'on', btn_protect_off: 'off', btn_protect_semi: 'semi', + btn_protect_change: 'change', btn_clearlogs: 'clear page logs', btn_deletepage: 'delete this page', btn_deletepage_votes: ' (%num_votes% vote%plural%)', @@ -303,9 +297,7 @@ tip_delvote: 'Vote to have this page deleted (alt-d)', tip_resetvotes: 'Clear the list of votes for deletion against this page (alt-y)', tip_printable: 'View a version of this page that is suitable for printing', - tip_protect_on: 'Prevents all non-administrators from editing this page. [alt-i]', - tip_protect_off: 'Allows everyone to edit this page. [alt-o]', - tip_protect_semi: 'Allows only users who have been registered for 4 days to edit this page. [alt-p]', + tip_protect: 'Change the protection level of this page (alt-p)', tip_flushlogs: 'Remove all edit and action logs for this page from the database. IRREVERSIBLE! (alt-l)', tip_deletepage: 'Delete this page. This is always reversible unless the logs are cleared. (alt-k)', tip_adminoptions: 'Administrative options for this page', @@ -329,7 +321,21 @@ filebox_heading_history: 'File history', filebox_btn_this_version: 'this ver', filebox_btn_revert: 'restore', - filebox_btn_current: 'current' + filebox_btn_current: 'current', + + protect_heading: 'Protect page', + protect_msg_select_level: 'Select a protection level:', + protect_btn_full: 'Full protection', + protect_btn_full_hint: 'Prevents everyone except moderators and administrators (by default) from editing the page.', + protect_btn_semi: 'Semi-protection', + protect_btn_semi_hint: 'Only users who have been members of this site for more than 4 days will be able to edit this page.', + protect_btn_none: 'No protection', + protect_btn_none_hint: 'Allows everybody to edit this page unless ACLs deny them.', + protect_lbl_current: 'current setting', + protect_lbl_reason: 'Reason:', + protect_lbl_reason_hint: 'Enter a short reason for protecting the page. The message you enter here will be displayed in the page\'s logs.', + protect_btn_submit: 'Protect page', + protect_err_need_reason: 'Please enter a reason for protecting this page.', }, editor: { err_server: 'There was a problem starting the editor',