# HG changeset patch # User Dan # Date 1217272389 21600 # Node ID 08a7875258b432936c49917e17392dd717b52229 # Parent 267c9f93b51f66cb51874de6cd86ea752479e8aa Added tab-based interface to userpage UI. Yes, it is plugin expansible, and yes, it breaks existing plugins that add code to the userpage (but that can be fixed with a "colspan=4") diff -r 267c9f93b51f -r 08a7875258b4 cron.php --- a/cron.php Mon Jul 28 13:10:22 2008 -0600 +++ b/cron.php Mon Jul 28 13:13:09 2008 -0600 @@ -45,7 +45,7 @@ $expiry_date = date('r', get_cron_next_run()); $etag = sha1($expiry_date); - + if ( isset($_SERVER['HTTP_IF_NONE_MATCH']) ) { if ( "\"$etag\"" == $_SERVER['HTTP_IF_NONE_MATCH'] ) diff -r 267c9f93b51f -r 08a7875258b4 includes/clientside/css/enano-shared.css --- a/includes/clientside/css/enano-shared.css Mon Jul 28 13:10:22 2008 -0600 +++ b/includes/clientside/css/enano-shared.css Mon Jul 28 13:13:09 2008 -0600 @@ -845,3 +845,55 @@ background-repeat: no-repeat; } +/* + * Userpage styles + * Note: The colors and such given here are very minimal. It's really best to copy the definitions to your + * theme's CSS, and remove all structure-related rules (margin, position, padding, etc.) + */ + +div.userpage_wrap { + position: relative; + top: 4em; + margin-bottom: 4em; + border: 1px solid #a0a0a0; +} + +ul.userpage_links { + position: absolute; + top: -3em; + padding-left: 10px; + list-style-type: none !important; + list-style-image: none !important; +} + +ul.userpage_links li { + float: left; + margin-right: 5px; + padding: 0 7px; + line-height: 1.9em; + list-style-type: none !important; + list-style-image: none !important; + border-style: solid; + border-color: #808080; + border-width: 1px 1px 0 1px; +} + +ul.userpage_links li.userpage_tab_active { + margin-top: -0.2em; + line-height: 2.1em; + border-width: 1px 1px 1px 1px; + border-bottom-color: #ffffff; + font-weight: bold; +} + +ul.userpage_links li:hover { + border-width: 1px 1px 1px 1px; + border-bottom-color: #ffffff; + cursor: pointer; +} + +div.userpage_block { + clear: both; + padding: 10px; +} + diff -r 267c9f93b51f -r 08a7875258b4 includes/clientside/jsres.php --- a/includes/clientside/jsres.php Mon Jul 28 13:10:22 2008 -0600 +++ b/includes/clientside/jsres.php Mon Jul 28 13:13:09 2008 -0600 @@ -102,6 +102,7 @@ 'pwstrength.js', 'flyin.js', 'rank-manager.js', + 'userpage.js', 'template-compiler.js', 'toolbar.js', ); diff -r 267c9f93b51f -r 08a7875258b4 includes/clientside/static/ajax.js --- a/includes/clientside/static/ajax.js Mon Jul 28 13:10:22 2008 -0600 +++ b/includes/clientside/static/ajax.js Mon Jul 28 13:13:09 2008 -0600 @@ -21,6 +21,12 @@ document.getElementById('ajaxEditContainer').innerHTML = ajax.responseText; selectButtonMajor('article'); unselectAllButtonsMinor(); + // if we're on a userpage, call the onload function to rebuild the tabs + if ( typeof(userpage_onload) == 'function' ) + { + window.userpage_blocks = []; + userpage_onload(); + } } }); } diff -r 267c9f93b51f -r 08a7875258b4 includes/clientside/static/editor.js --- a/includes/clientside/static/editor.js Mon Jul 28 13:10:22 2008 -0600 +++ b/includes/clientside/static/editor.js Mon Jul 28 13:13:09 2008 -0600 @@ -627,30 +627,38 @@ { if ( response.is_draft ) { - document.getElementById('ajaxEditArea').used_draft = true; - document.getElementById('ajaxEditArea').needReset = true; - var img = $dynano('ajax_edit_savedraft_btn').object.getElementsByTagName('img')[0]; - var lbl = $dynano('ajax_edit_savedraft_btn').object.getElementsByTagName('span')[0]; - if ( response.is_draft == 'delete' ) + try { - img.src = scriptPath + '/images/editor/savedraft.gif'; - lbl.innerHTML = $lang.get('editor_btn_savedraft'); - - var dn = $dynano('ajax_edit_draft_notice').object; - if ( dn ) + document.getElementById('ajaxEditArea').used_draft = true; + document.getElementById('ajaxEditArea').needReset = true; + var img = $dynano('ajax_edit_savedraft_btn').object.getElementsByTagName('img')[0]; + var lbl = $dynano('ajax_edit_savedraft_btn').object.getElementsByTagName('span')[0]; + if ( response.is_draft == 'delete' ) { - dn.parentNode.removeChild(dn); + img.src = scriptPath + '/images/editor/savedraft.gif'; + lbl.innerHTML = $lang.get('editor_btn_savedraft'); + + var dn = $dynano('ajax_edit_draft_notice').object; + if ( dn ) + { + dn.parentNode.removeChild(dn); + } + } + else + { + img.src = scriptPath + '/images/mini-info.png'; + var d = new Date(); + var m = String(d.getMinutes()); + if ( m.length < 2 ) + m = '0' + m; + var time = d.getHours() + ':' + m; + lbl.innerHTML = $lang.get('editor_msg_draft_saved', { time: time }); } } - else + catch(e) { - img.src = scriptPath + '/images/mini-info.png'; - var d = new Date(); - var m = String(d.getMinutes()); - if ( m.length < 2 ) - m = '0' + m; - var time = d.getHours() + ':' + m; - lbl.innerHTML = $lang.get('editor_msg_draft_saved', { time: time }); + console.warn('Exception thrown during save, error dump follows'); + console.debug(e); } } else @@ -670,6 +678,12 @@ ajaxEditorDestroyModalWindow(); document.getElementById('ajaxEditContainer').innerHTML = '
' + $lang.get('editor_msg_saved') + '
' + ajax.responseText; + // if we're on a userpage, call the onload function to rebuild the tabs + if ( typeof(userpage_onload) == 'function' ) + { + window.userpage_blocks = []; + userpage_onload(); + } opacity('ajaxEditContainer', 0, 100, 1000); } }); diff -r 267c9f93b51f -r 08a7875258b4 includes/clientside/static/functions.js --- a/includes/clientside/static/functions.js Mon Jul 28 13:10:22 2008 -0600 +++ b/includes/clientside/static/functions.js Mon Jul 28 13:13:09 2008 -0600 @@ -464,6 +464,11 @@ return position; } +function setScrollOffset(offset) +{ + window.scroll(0, offset); +} + // Function to fade classes info-box, warning-box, error-box, etc. function fadeInfoBoxes() @@ -568,7 +573,8 @@ blackout.style.backgroundColor = '#FFFFFF'; domObjChangeOpac(60, blackout); - blackout.style.backgroundImage = 'url(' + scriptPath + '/includes/clientside/tinymce/themes/advanced/skins/default/img/progress.gif)'; + var background = ( $(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 = getHighestZ() + 2; diff -r 267c9f93b51f -r 08a7875258b4 includes/clientside/static/userpage.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/includes/clientside/static/userpage.js Mon Jul 28 13:13:09 2008 -0600 @@ -0,0 +1,119 @@ +// Tabs on userpage + +var userpage_blocks = []; + +var userpage_onload = function() +{ + var wrapper = document.getElementById('userpage_wrap'); + var links = document.getElementById('userpage_links'); + + wrapper.className = 'userpage_wrap'; + links.className = 'userpage_links'; + + var blocks = wrapper.getElementsByTagName('div'); + var first_block = false; + for ( var i = 0; i < blocks.length; i++ ) + { + var block = blocks[i]; + if ( /^tab:/.test(block.id) ) + { + $(block).addClass('userpage_block'); + var block_id = block.id.substr(4); + userpage_blocks.push(block_id); + if ( !first_block ) + { + // this is the first block on the page, memorize it + first_block = block_id; + } + } + } + // init links + var as = links.getElementsByTagName('a'); + for ( var i = 0; i < as.length; i++ ) + { + var a = as[i]; + if ( a.href.indexOf('#') > -1 ) + { + var hash = a.href.substr(a.href.indexOf('#')); + var blockid = hash.substr(5); + a.blockid = blockid; + a.onclick = function() + { + userpage_select_block(this.blockid); + return false; + } + a.id = 'userpage_blocklink_' + blockid; + } + } + if ( $_REQUEST['tab'] ) + { + userpage_select_block($_REQUEST['tab'], true); + } + else + { + userpage_select_block(first_block, true); + } +} + +addOnloadHook(userpage_onload); + +/** + * Select (show) the specified block on the userpage. + * @param string block name + * @param bool If true, omits transition effects. + */ + +function userpage_select_block(block, nofade) +{ + // memorize existing scroll position, reset the hash, then scroll back to where we were + // a little hackish and might cause a flash, but it's better than hiding the tabs on each click + var currentScroll = getScrollOffset(); + + var current_block = false; + nofade = true; + for ( var i = 0; i < userpage_blocks.length; i++ ) + { + var div = document.getElementById('tab:' + userpage_blocks[i]); + if ( div ) + { + if ( div.style.display != 'none' ) + { + current_block = userpage_blocks[i]; + if ( nofade || aclDisableTransitionFX ) + { + div.style.display = 'none'; + } + } + } + var a = document.getElementById('userpage_blocklink_' + userpage_blocks[i]); + if ( a ) + { + if ( $(a.parentNode).hasClass('userpage_tab_active') ) + { + $(a.parentNode).rmClass('userpage_tab_active'); + } + } + } + if ( nofade || !current_block || aclDisableTransitionFX ) + { + var div = document.getElementById('tab:' + block); + div.style.display = 'block'; + } + /* + else + { + // do this in a slightly fancier fashion + load_component('SpryEffects'); + (new Spry.Effect.Blind('tab:' + current_block, { from: '100%', to: '0%', finish: function() + { + (new Spry.Effect.Blind('tab:' + block, { from: '0%', to: '100%' })).start(); + } + })).start(); + } + */ + var a = document.getElementById('userpage_blocklink_' + block); + $(a.parentNode).addClass('userpage_tab_active'); + + window.location.hash = 'tab:' + block; + setScrollOffset(currentScroll); +} diff -r 267c9f93b51f -r 08a7875258b4 includes/pageprocess.php --- a/includes/pageprocess.php Mon Jul 28 13:10:22 2008 -0600 +++ b/includes/pageprocess.php Mon Jul 28 13:13:09 2008 -0600 @@ -1300,6 +1300,42 @@ global $email; global $lang; + /** + * PLUGGING INTO USER PAGES + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Userpages are highly programmable and extendable using a number of + * hooks. These hooks are: + * + * - userpage_sidebar_left + * - userpage_sidebar_right + * - userpage_tabs_links + * - userpage_tabs_body + * + * You can add a variety of sections to user pages, including new tabs + * and new sections on the tables. To add a tab, attach to + * userpage_tabs_links and echo out: + * + *
  • YOUR TAB TEXT
  • + * + * Then hook into userpage_tabs_body and echo out: + * + *
    YOUR TAB CONTENT
    + * + * The userpage javascript runtime will take care of everything else, + * meaning transitions, click events, etc. Currently it's not possible + * to add custom click events to tabs, but any DOM-related JS that needs + * to run in your tab can be run onload and the effects will be seen when + * your tab is clicked. YOURTABID should be lowercase alphanumeric and + * have a short prefix so as to assure that it remains specific to your + * plugin. + * + * To hook into the "profile" tab, use userpage_sidebar_{left,right}. Just + * echo out table cells as normal. The table on the left (the wide one) has + * four columns, and the one on the right has one column. + * + * See plugins.php for a guide on creating and attaching to hooks. + */ + $page_urlname = dirtify_page_id($this->page_id); if ( $this->page_id == $paths->page_id && $this->namespace == $paths->namespace ) { @@ -1322,7 +1358,7 @@ if ( ( $page_name == str_replace('_', ' ', $this->page_id) || $page_name == $paths->nslist['User'] . str_replace('_', ' ', $this->page_id) ) || !$this->page_exists ) { - $page_name = $lang->get('userpage_page_title', array('username' => htmlspecialchars($target_username))); + $page_name = $lang->get('userpage_page_title', array('username' => $target_username)); } else { @@ -1367,9 +1403,13 @@ } else { + // get the rank data for the anonymous user (placeholder basically) $rank_data = $session->get_user_rank(1); } + // add the userpage script to the header + $template->add_header(''); + $this->header(); // if ( $send_headers ) @@ -1377,153 +1417,304 @@ // display_page_headers(); // } - // Start left sidebar: basic user info, latest comments - - if ( $user_exists ): - - echo ''; - echo ''; - - $code = $plugins->setHook('userpage_sidebar_left'); - foreach ( $code as $cmd ) - { - eval($cmd); } - echo '
    '; - - echo '
    - '; - // - // Main part of sidebar + // BASIC INFORMATION + // Presentation of username/rank/avatar/basic info // - // Basic user info - - echo ''; - - echo ''; - echo ''; - echo ''; - - if ( !empty($userdata['real_name']) ) - { - echo ''; - } - - // Administer user button - - if ( $session->user_level >= USER_LEVEL_ADMIN ) + if ( $user_exists ) { - echo ''; - } - - // Comments - - echo ''; - $q = $db->sql_query('SELECT page_id, namespace, subject, time FROM '.table_prefix.'comments WHERE name=\'' . $db->escape($target_username) . '\' AND user_id=' . $userdata['authoritative_uid'] . ' AND approved=1 ORDER BY time DESC LIMIT 5;'); - if ( !$q ) - $db->_die(); - - $comments = Array(); - $no_comments = false; - - if ( $row = $db->fetchrow() ) - { - do - { - $row['time'] = enano_date('F d, Y', $row['time']); - $comments[] = $row; - } - while ( $row = $db->fetchrow() ); - } - else - { - $no_comments = true; - } - - echo ''; + + // + // CONTACT INFORMATION + // + + echo ' '; + + // + // End of profile + // + + echo '
    ' . $lang->get('userpage_heading_basics', array('username' => htmlspecialchars($target_username))) . '
    '; - if ( $userdata['user_has_avatar'] == '1' ) - { - echo '' . $lang->get('usercp_avatar_image_alt', array('username' => $userdata['username'])) . '
    '; - } - // username - echo '' . htmlspecialchars($target_username) . '
    '; - // user title, if appropriate - if ( $rank_data['user_title'] ) - echo htmlspecialchars($rank_data['user_title']) . '
    '; - // rank - echo htmlspecialchars($lang->get($rank_data['rank_title'])); - echo '
    ' . $lang->get('userpage_lbl_joined') . ' ' . enano_date('F d, Y h:i a', $userdata['reg_time']) . '
    ' . $lang->get('userpage_lbl_num_comments') . ' ' . $userdata['n_comments'] . '
    ' . $lang->get('userpage_lbl_real_name') . ' ' . $userdata['real_name'] . '
    ' . $lang->get('userpage_btn_administer_user') . '
    ' . $lang->get('userpage_heading_comments', array('username' => htmlspecialchars($target_username))) . '
    '; - echo '
    '; - - echo ''; - $class = 'row1'; - $tpl = ' - '; + + echo '
    - class="wikilink-nonexistent">{PAGE}
    - {lang:userpage_comments_lbl_posted} {DATE}
    - {SUBJECT} + ?> +
    + + +
    + + +
    '; + + echo '
    + '; + + // heading + echo ' + + ' . ( + $session->user_level >= USER_LEVEL_ADMIN ? + '' + : '' + ) . ' + '; + + // avi/rank/username + echo ' + + '; + + // join date & total comments + echo ''; + echo ' - '; - $parser = $template->makeParserText($tpl); - - if ( count($comments) > 0 ) - { - foreach ( $comments as $comment ) + '; + echo ' + '; + echo ''; + + // real name + if ( !empty($userdata['real_name']) ) { - $c_page_id = $paths->nslist[ $comment['namespace'] ] . sanitize_page_id($comment['page_id']); - if ( isset($paths->pages[ $c_page_id ]) ) + echo ' + + + '; + } + + // latest comments + + echo ''; + $q = $db->sql_query('SELECT page_id, namespace, subject, time FROM '.table_prefix.'comments WHERE name=\'' . $db->escape($target_username) . '\' AND user_id=' . $userdata['authoritative_uid'] . ' AND approved=1 ORDER BY time DESC LIMIT 7;'); + if ( !$q ) + $db->_die(); + + $comments = Array(); + $no_comments = false; + + if ( $row = $db->fetchrow() ) + { + do { - $parser->assign_bool(array( - 'page_exists' => true - )); - $page_title = htmlspecialchars($paths->pages[ $c_page_id ]['name']); - } - else - { - $parser->assign_bool(array( - 'page_exists' => false - )); - $page_title = htmlspecialchars(dirtify_page_id($c_page_id)); + $row['time'] = enano_date('F d, Y', $row['time']); + $comments[] = $row; } - $parser->assign_vars(array( - 'CLASS' => $class, - 'PAGE_LINK' => makeUrlNS($comment['namespace'], sanitize_page_id($comment['page_id'])), - 'PAGE' => $page_title, - 'SUBJECT' => $comment['subject'], - 'DATE' => $comment['time'], - 'COMMENT_LINK' => makeUrlNS($comment['namespace'], sanitize_page_id($comment['page_id']), 'do=comments', true) - )); - $class = ( $class == 'row3' ) ? 'row1' : 'row3'; - echo $parser->run(); + while ( $row = $db->fetchrow() ); + } + else + { + $no_comments = true; + } + + echo ''; + + $code = $plugins->setHook('userpage_sidebar_left'); + foreach ( $code as $cmd ) + { + eval($cmd); } - } - else - { - echo ''; - } - echo '
    + ' . $lang->get('userpage_heading_basics', array('username' => htmlspecialchars($target_username))) . ' + » ' . $lang->get('userpage_btn_administer_user') . '
    + ' . ( + $userdata['user_has_avatar'] == 1 ? + '
    + ' . $lang->get('usercp_avatar_image_alt', array('username' => $userdata['username'])) . ' +
    ' + : '' + ) . ' + ' . htmlspecialchars($userdata['username']) . ' + ' . ( !empty($rank_data['user_title']) ? '
    ' . htmlspecialchars($rank_data['user_title']) : '' ) . ' + ' . ( !empty($rank_data['rank_title']) ? '
    ' . htmlspecialchars($lang->get($rank_data['rank_title'])) : '' ) . ' +
    + ' . $lang->get('userpage_lbl_joined') . '
    + ' . enano_date('F d, Y h:i a', $userdata['reg_time']) . ' + + ' . $lang->get('userpage_lbl_num_comments') . ' + + ' . $userdata['n_comments'] . ' +
    + ' . $lang->get('userpage_lbl_real_name') . ' + + ' . htmlspecialchars($userdata['real_name']) . ' +
    ' . $lang->get('userpage_heading_comments', array('username' => htmlspecialchars($target_username))) . '
    '; + echo '
    '; + + echo ''; + $class = 'row1'; + + $tpl = ' '; + $parser = $template->makeParserText($tpl); + + if ( count($comments) > 0 ) + { + foreach ( $comments as $comment ) + { + $c_page_id = $paths->nslist[ $comment['namespace'] ] . sanitize_page_id($comment['page_id']); + if ( isset($paths->pages[ $c_page_id ]) ) + { + $parser->assign_bool(array( + 'page_exists' => true + )); + $page_title = htmlspecialchars($paths->pages[ $c_page_id ]['name']); + } + else + { + $parser->assign_bool(array( + 'page_exists' => false + )); + $page_title = htmlspecialchars(dirtify_page_id($c_page_id)); + } + $parser->assign_vars(array( + 'CLASS' => $class, + 'PAGE_LINK' => makeUrlNS($comment['namespace'], sanitize_page_id($comment['page_id'])), + 'PAGE' => $page_title, + 'SUBJECT' => $comment['subject'], + 'DATE' => $comment['time'], + 'COMMENT_LINK' => makeUrlNS($comment['namespace'], sanitize_page_id($comment['page_id']), 'do=comments', true) + )); + $class = ( $class == 'row3' ) ? 'row1' : 'row3'; + echo $parser->run(); + } + } + else + { + echo ''; + } + echo '
    + class="wikilink-nonexistent">{PAGE}
    + {lang:userpage_comments_lbl_posted} {DATE}
    + {SUBJECT} +
    ' . $lang->get('userpage_msg_no_comments') . '
    '; + + echo '
    '; + echo '
    ' . $lang->get('userpage_msg_no_comments') . '
    '; + + echo '
    +
    '; + + echo '
    '; + + echo '
    + '; + + // + // Main part of sidebar + // + + // Contact information + + echo ''; + + $class = 'row3'; + + if ( $userdata['email_public'] == 1 ) + { + $class = ( $class == 'row1' ) ? 'row3' : 'row1'; + $email_link = $email->encryptEmail($userdata['email']); + echo ''; + } + + $class = ( $class == 'row1' ) ? 'row3' : 'row1'; + if ( $session->user_logged_in ) + { + echo ''; + } + else + { + echo ''; + } + + if ( !empty($userdata['user_aim']) ) + { + $class = ( $class == 'row1' ) ? 'row3' : 'row1'; + echo ''; + } + + if ( !empty($userdata['user_yahoo']) ) + { + $class = ( $class == 'row1' ) ? 'row3' : 'row1'; + echo ''; + } + + if ( !empty($userdata['user_msn']) ) + { + $class = ( $class == 'row1' ) ? 'row3' : 'row1'; + $email_link = $email->encryptEmail($userdata['user_msn']); + echo ''; + } + + if ( !empty($userdata['user_xmpp']) ) + { + $class = ( $class == 'row1' ) ? 'row3' : 'row1'; + $email_link = $email->encryptEmail($userdata['user_xmpp']); + echo ''; + } + + // Real life + + echo ''; + + if ( !empty($userdata['user_location']) ) + { + $class = ( $class == 'row1' ) ? 'row3' : 'row1'; + echo ''; + } + + if ( !empty($userdata['user_job']) ) + { + $class = ( $class == 'row1' ) ? 'row3' : 'row1'; + echo ''; + } + + if ( !empty($userdata['user_hobbies']) ) + { + $class = ( $class == 'row1' ) ? 'row3' : 'row1'; + echo ''; + } + + if ( empty($userdata['user_location']) && empty($userdata['user_job']) && empty($userdata['user_hobbies']) ) + { + $class = ( $class == 'row1' ) ? 'row3' : 'row1'; + echo ''; + } + + $code = $plugins->setHook('userpage_sidebar_right'); + foreach ( $code as $cmd ) + { + eval($cmd); + } + + echo '
    ' . $lang->get('userpage_heading_contact') . '
    ' . $lang->get('userpage_lbl_email') . ' ' . $email_link . '
    ' . $lang->get('userpage_btn_send_pm', array('username' => htmlspecialchars($target_username), 'pm_link' => makeUrlNS('Special', 'PrivateMessages/Compose/to/' . $this->page_id, false, true))) . '
    ' . $lang->get('userpage_btn_send_pm_guest', array('username' => htmlspecialchars($target_username), 'login_flags' => 'href="' . makeUrlNS('Special', 'Login/' . $paths->nslist[$this->namespace] . $this->page_id) . '" onclick="ajaxStartLogin(); return false;"')) . '
    ' . $lang->get('userpage_lbl_aim') . ' ' . $userdata['user_aim'] . '
    ' . $lang->get('userpage_lbl_yim') . ' ' . $userdata['user_yahoo'] . '
    ' . $lang->get('userpage_lbl_wlm') . ' ' . $email_link . '
    ' . $lang->get('userpage_lbl_xmpp') . ' ' . $email_link . '
    ' . $lang->get('userpage_heading_real_life', array('username' => htmlspecialchars($target_username))) . '
    ' . $lang->get('userpage_lbl_location') . ' ' . $userdata['user_location'] . '
    ' . $lang->get('userpage_lbl_job') . ' ' . $userdata['user_job'] . '
    ' . $lang->get('userpage_lbl_hobbies') . ' ' . $userdata['user_hobbies'] . '
    ' . $lang->get('userpage_msg_no_contact_info', array('username' => htmlspecialchars($target_username))) . '
    +
    '; + echo '
    '; + + echo '
    '; // tab:profile - echo ''; - echo '
    - '; - - echo ''; - - else: - - // Nothing for now - - endif; - // User's own content $send_headers = $this->send_headers; $this->send_headers = false; + echo ''; + + echo '
    '; + if ( $this->page_exists ) { $this->render(); @@ -1533,116 +1724,26 @@ $this->err_page_not_existent(true); } - // Right sidebar - - if ( $user_exists ): - - echo ''; - - echo '
    - '; - - // - // Main part of sidebar - // - - // Contact information - - echo ''; - - $class = 'row3'; - - if ( $userdata['email_public'] == 1 ) - { - $class = ( $class == 'row1' ) ? 'row3' : 'row1'; - $email_link = $email->encryptEmail($userdata['email']); - echo ''; - } - - $class = ( $class == 'row1' ) ? 'row3' : 'row1'; - if ( $session->user_logged_in ) - { - echo ''; - } - else - { - echo ''; - } - - if ( !empty($userdata['user_aim']) ) - { - $class = ( $class == 'row1' ) ? 'row3' : 'row1'; - echo ''; - } + echo ''; // tab:content - if ( !empty($userdata['user_yahoo']) ) - { - $class = ( $class == 'row1' ) ? 'row3' : 'row1'; - echo ''; - } - - if ( !empty($userdata['user_msn']) ) - { - $class = ( $class == 'row1' ) ? 'row3' : 'row1'; - $email_link = $email->encryptEmail($userdata['user_msn']); - echo ''; - } - - if ( !empty($userdata['user_xmpp']) ) - { - $class = ( $class == 'row1' ) ? 'row3' : 'row1'; - $email_link = $email->encryptEmail($userdata['user_xmpp']); - echo ''; - } - - // Real life - - echo ''; - - if ( !empty($userdata['user_location']) ) - { - $class = ( $class == 'row1' ) ? 'row3' : 'row1'; - echo ''; - } - - if ( !empty($userdata['user_job']) ) - { - $class = ( $class == 'row1' ) ? 'row3' : 'row1'; - echo ''; - } - - if ( !empty($userdata['user_hobbies']) ) - { - $class = ( $class == 'row1' ) ? 'row3' : 'row1'; - echo ''; - } - - if ( empty($userdata['user_location']) && empty($userdata['user_job']) && empty($userdata['user_hobbies']) ) - { - $class = ( $class == 'row1' ) ? 'row3' : 'row1'; - echo ''; - } - - $code = $plugins->setHook('userpage_sidebar_right'); + $code = $plugins->setHook('userpage_tabs_body'); foreach ( $code as $cmd ) { eval($cmd); } - echo '
    ' . $lang->get('userpage_heading_contact') . '
    ' . $lang->get('userpage_lbl_email') . ' ' . $email_link . '
    ' . $lang->get('userpage_btn_send_pm', array('username' => htmlspecialchars($target_username), 'pm_link' => makeUrlNS('Special', 'PrivateMessages/Compose/to/' . $this->page_id, false, true))) . '
    ' . $lang->get('userpage_btn_send_pm_guest', array('username' => htmlspecialchars($target_username), 'login_flags' => 'href="' . makeUrlNS('Special', 'Login/' . $paths->nslist[$this->namespace] . $this->page_id) . '" onclick="ajaxStartLogin(); return false;"')) . '
    ' . $lang->get('userpage_lbl_aim') . ' ' . $userdata['user_aim'] . '
    ' . $lang->get('userpage_lbl_yim') . ' ' . $userdata['user_yahoo'] . '
    ' . $lang->get('userpage_lbl_wlm') . ' ' . $email_link . '
    ' . $lang->get('userpage_lbl_xmpp') . ' ' . $email_link . '
    ' . $lang->get('userpage_heading_real_life', array('username' => htmlspecialchars($target_username))) . '
    ' . $lang->get('userpage_lbl_location') . ' ' . $userdata['user_location'] . '
    ' . $lang->get('userpage_lbl_job') . ' ' . $userdata['user_job'] . '
    ' . $lang->get('userpage_lbl_hobbies') . ' ' . $userdata['user_hobbies'] . '
    ' . $lang->get('userpage_msg_no_contact_info', array('username' => htmlspecialchars($target_username))) . '
    -
    '; - - echo ''; - - else: - - if ( !is_valid_ip($target_username) ) + if ( $user_exists ) + { + echo '
    '; // userpage_wrap + } + else { - echo '

    ' . $lang->get('userpage_msg_user_not_exist', array('username' => htmlspecialchars($target_username))) . '

    '; + if ( !is_valid_ip($target_username) ) + { + echo '

    ' . $lang->get('userpage_msg_user_not_exist', array('username' => htmlspecialchars($target_username))) . '

    '; + } } - endif; - // if ( $send_headers ) // { // display_page_footers(); @@ -1823,7 +1924,7 @@ global $db, $session, $paths, $template, $plugins; // Common objects global $lang; - header('HTTP/1.1 404 Not Found'); + @header('HTTP/1.1 404 Not Found'); $this->header(); $this->do_breadcrumbs(); @@ -1838,7 +1939,7 @@ { if ( $userpage ) { - echo '

    ' . $lang->get('page_msg_404_title') . '

    + echo '

    ' . $lang->get('page_msg_404_title_userpage') . '

    ' . $lang->get('page_msg_404_body_userpage'); } else diff -r 267c9f93b51f -r 08a7875258b4 language/english/core.json --- a/language/english/core.json Mon Jul 28 13:10:22 2008 -0600 +++ b/language/english/core.json Mon Jul 28 13:13:09 2008 -0600 @@ -156,8 +156,9 @@ lbl_password: 'Password:', msg_404_title: 'There is no page with this title yet.', - msg_404_body_userpage: 'This user has not created his or her user page yet.', msg_404_body: 'You have requested a page that doesn\'t exist yet.', + msg_404_title_userpage: 'No content', + msg_404_body_userpage: 'This user has not yet created any custom user page content.', msg_404_create: 'You can create this page, or return to the homepage.', msg_404_gohome: 'Return to the homepage.', msg_404_was_deleted: 'This page was deleted on %delete_time%. The stated reason was:

    %delete_reason%

    You can probably roll back the deletion.', diff -r 267c9f93b51f -r 08a7875258b4 language/english/user.json --- a/language/english/user.json Mon Jul 28 13:10:22 2008 -0600 +++ b/language/english/user.json Mon Jul 28 13:13:09 2008 -0600 @@ -128,6 +128,7 @@ msg_elev_timed_out: 'Your administrative session has timed out. Log in again', + reg_err_locked_out: 'Registration is disabled because you are currently locked out from logging in. Please wait %time% minutes before attempting to register again.', reg_err_captcha: 'The confirmation code you entered was incorrect.', reg_err_disabled_title: 'Registration disabled', reg_err_disabled_body: 'The administrator has disabled the registration of new accounts on this site.', @@ -620,9 +621,9 @@ ml_msg_matches: 'Search returned %matches% matches', }, userpage: { - page_title: '%username%\'s user page', + page_title: '%username|htmlsafe%\'s user page', heading_basics: 'All about %username%', - lbl_joined: 'Joined:', + lbl_joined: 'Member since:', lbl_num_comments: 'Total comments:', lbl_real_name: 'Real name:', btn_administer_user: 'Administer user', @@ -643,6 +644,8 @@ lbl_hobbies: 'Enjoys:', msg_no_contact_info: '%username% hasn\'t posted any real-life contact information.', msg_user_not_exist: 'Additional information: user "%username%" does not exist.', + tab_profile: 'Profile', + tab_content: 'User page', } } }; diff -r 267c9f93b51f -r 08a7875258b4 themes/oxygen/css/bleu.css --- a/themes/oxygen/css/bleu.css Mon Jul 28 13:10:22 2008 -0600 +++ b/themes/oxygen/css/bleu.css Mon Jul 28 13:13:09 2008 -0600 @@ -776,3 +776,29 @@ padding-right: 5px; } +/* + * Userpage styles + */ + +ul.userpage_links li { + background-image: url('../images/buttonbg.gif'); + background-repeat: repeat-x; +} + +ul.userpage_links li a { + color: #202020; +} + +ul.userpage_links li.userpage_tab_active { + background-image: url('../images/buttonbg-lite.gif'); +} + +ul.userpage_links li:hover { + background-image: url('../images/buttonbg-lite.gif'); + border-color: #404040 #404040 #ffffff #404040; + border-bottom-width: 0; +} + +ul.userpage_links li.userpage_tab_active:hover { + border-bottom-width: 1px; +} diff -r 267c9f93b51f -r 08a7875258b4 themes/oxygen/images/buttonbg-lite.gif Binary file themes/oxygen/images/buttonbg-lite.gif has changed