News:

Want to get involved in developing SMF, then why not lend a hand on our github!

Main Menu

Customising function constructPageIndex (nasty evil stuffz)

Started by Antechinus, July 03, 2014, 09:56:07 PM

Previous topic - Next topic

Antechinus

Ok all you back end geniuses, I am needing a bit of guidance here. :D

What I want to do is a better implementation of "Previous page" and "Next page" buttons for function constructPageIndex, as well as adding some decent styling hooks to the same, and turning the whole shebang into a proper list (which it really ought to be).

The way I want to do this is by assigning an extra class to the existing class="navPages" where I want it. This is better than just chucking in extra spans all over the place (ye olde 2.1 method) for two reasons. First it's cleaner markup. Second, it will make for cleaner and more versatile CSS, because you will be able to style all elements with one basic class, and change specific anchors rather than having to play with spans inside them. You know you want it (you can even steal it for 2.1 ;)).

At the moment the 2.0.x base link is generated as this:

$base_link = '<a class="navPages" href="' . ($flexible_start ? $base_url : strtr($base_url, array('%' => '%%')) . ';start=%d') . '">%s</a> ';


I can sort out turning it into a list, simply by changing the base link generation to this:

$base_link = '<li><a class="navPages" href="' . ($flexible_start ? $base_url : strtr($base_url, array('%' => '%%')) . ';start=%d') . '">%s</a></li>';


With template calling it as this:

<div class="pagesection">
<ul class="pagelinks"><li class="stupid_bloat_for_teh_extra_uglies">', $txt['pages'], '</li>', $context['page_index'], '</li>
</div>


Which will enable me to easily hide the redundant text that tells me something I already knew: that these are "Pages:". :P


The tricky bit (for me) is assigning an extra class to the base link anchor. This would have to be handled in a couple of places, and is going to require some conditionals. The basic way of doing it is to use this for the "Previous page" button:

// Show 'Prev'
if ($start >= $num_per_page)
$pageindex .= sprintf($base_link, $start - $num_per_page, ' <span class="previous_page">'. $txt['previous page']. '</span>');



I want to change that to this:

[code]// Show 'Prev'
if ($start >= $num_per_page)
$pageindex .= sprintf($base_link, $start - $num_per_page, $txt['previous page']);



And have the base link sorted out so that it will generate this:

$base_link = '<a class="navPages previous_page" href="' . ($flexible_start ? $base_url : strtr($base_url, array('%' => '%%')) . ';start=%d') . '">%s</a> ';


Obviously the base link also has to generate this for the "Next page" link:

$base_link = '<a class="navPages next_page" href="' . ($flexible_start ? $base_url : strtr($base_url, array('%' => '%%')) . ';start=%d') . '">%s</a> ';


Short version: I need an extra variable in the base link markup, like this:

$base_link = '<a class="navPages %stuffz" href="' . ($flexible_start ? $base_url : strtr($base_url, array('%' => '%%')) . ';start=%d') . '">%s</a> ';

And some way of getting the right class assigned to %stuffz.

Any takers? :D

Antechinus

Bumpity. :P Come on guys, someone here must know how to do this. :D

Antechinus

Bleh. So I RTFPHPM a bit, did a lot of breaking stuff and swearing, and got it working.

No, you can't have the code. My code. Get yer own. :P

* Antechinus goes to write mod now...............

kat


Antechinus

You should try it sometime. Plenty of entertainment to be had.


Antechinus

Yay! I have bugz!

Quite apart from my personal collection of arthropods and prokaryote fauna, there is also a bug in the effing page index stuff. This is the one relevant to this thread.

So, it mostly works perfectly, except when splitting topics. That causes an undefined error:

   http://127.0.0.1/SMF_20x/index.php?action=splittopics;sa=selectTopics;subname=Split+test+1;topic=1.0;start2=0;move=reset;msg=0;xml
8: Undefined index: next_page
File: K:/VertrigoServ/www/SMF_20x/Sources/Subs.php
Line: 721


The line in Subs is the last one here:

// Show 'Next'.
$display_page = ($start + $num_per_page) > $max_value ? $max_value : ($start + $num_per_page);
if (($display_page <= $tmpMaxPages)&&($tmpMaxPages > 1))
$pageindex .= sprintf($base_link, $display_page, $txt['next_page'], ' next_page');


There is also a "previous page" link in the modified page index, but that never causes an undefined error. It's only the "next page" link that is acting up. Note that it doesn't give an undefined anywhere else. It only happens when you are actually splitting a topic via SplitTopics.template.php. That's apparently down to how the javascript in that template calls the updated page index when you shunt posts from the not-selected to selected areas.

function onDocReceived(XMLDoc)
{
var i, j, pageIndex;
for (i = 0; i < 2; i++)
{
pageIndex = XMLDoc.getElementsByTagName("pageIndex")[i];
setInnerHTML(document.getElementById("pageindex_" + pageIndex.getAttribute("section")), pageIndex.firstChild.nodeValue);
start[i] = pageIndex.getAttribute("startFrom");
}


The js is default SMF. I haven't touched it (yet). Anyone got any ideas on how to tweak it to make it behave?

Complete code for the modified page index function goes like this:

function constructPageIndex($base_url, &$start, $max_value, $num_per_page, $flexible_start = false)
{
global $modSettings, $txt;

// Save whether $start was less than 0 or not.
$start = (int) $start;
$start_invalid = $start < 0;

// Make sure $start is a proper variable - not less than 0.
if ($start_invalid)
$start = 0;
// Not greater than the upper bound.
elseif ($start >= $max_value)
$start = max(0, (int) $max_value - (((int) $max_value % (int) $num_per_page) == 0 ? $num_per_page : ((int) $max_value % (int) $num_per_page)));
// And it has to be a multiple of $num_per_page!
else
$start = max(0, (int) $start - ((int) $start % (int) $num_per_page));

// Wireless will need the protocol on the URL somewhere.
if (WIRELESS)
$base_url .= ';' . WIRELESS_PROTOCOL;

$base_link = '<li><a class="navPages%3$s" href="' . ($flexible_start ? $base_url : strtr($base_url, array('%' => '%%')) . ';start=%1$d') . '">%2$s</a></li>';

// Compact pages is off or on?
if (empty($modSettings['compactTopicPagesEnable']))
{
// Show the left arrow.
$pageindex = $start == 0 ? ' ' : sprintf($base_link, $start - $num_per_page, '&#171;', ' previous_page');

// Show all the pages.
$display_page = 1;
for ($counter = 0; $counter < $max_value; $counter += $num_per_page)
$pageindex .= $start == $counter && !$start_invalid ? '<li><a class="navPages current_page">' . $display_page++ . '</a></li>' : sprintf($base_link, $counter, $display_page++, '');

// Show the right arrow.
$display_page = ($start + $num_per_page) > $max_value ? $max_value : ($start + $num_per_page);
if ($start != $counter - $max_value && !$start_invalid)
$pageindex .= $display_page > $counter - $num_per_page ? ' ' : sprintf($base_link, $display_page, '&#187;', ' next_page');
}
else
{
// If they didn't enter an odd value, pretend they did.
$PageContiguous = (int) ($modSettings['compactTopicPagesContiguous'] - ($modSettings['compactTopicPagesContiguous'] % 2)) / 2;
$pageindex = '<li><span class="navPages pages_text">' .$txt['pages']. '</span></li>';

// Show 'Prev'
if ($start > ($num_per_page - 1))
$pageindex = sprintf($base_link, $start - $num_per_page, $txt['previous_page'], ' previous_page');

// Show the first page. (>1< ... 6 7 [8] 9 10 ... 15)
if ($start > $num_per_page * $PageContiguous)
$pageindex .= sprintf($base_link, 0, '1', '');

// Show the ... after the first page.  (1 >...< 6 7 [8] 9 10 ... 15)
if ($start > $num_per_page * ($PageContiguous + 1))
$pageindex .= '<li><span class="navPages page_dots" style="cursor: pointer;" onclick="' . htmlspecialchars('expandPages(this, ' . JavaScriptEscape(($flexible_start ? $base_url : strtr($base_url, array('%' => '%%')) . ';start=%1$d')) . ', ' . $num_per_page . ', ' . ($start - $num_per_page * $PageContiguous) . ', ' . $num_per_page . ');') . '">...</span></li>';

// Show the pages before the current one. (1 ... >6 7< [8] 9 10 ... 15)
for ($nCont = $PageContiguous; $nCont >= 1; $nCont--)
if ($start >= $num_per_page * $nCont)
{
$tmpStart = $start - $num_per_page * $nCont;
$pageindex .= sprintf($base_link, $tmpStart, $tmpStart / $num_per_page + 1,'');
}

// Show the current page. (1 ... 6 7 >[8]< 9 10 ... 15)
if (!$start_invalid)
$pageindex .= '<li><a class="navPages current_page">' . ($start / $num_per_page + 1) . '</a></li>';
else
$pageindex .= sprintf($base_link, $start, $start / $num_per_page + 1, '');

// Show the pages after the current one... (1 ... 6 7 [8] >9 10< ... 15)
$tmpMaxPages = (int) (($max_value - 1) / $num_per_page) * $num_per_page;
for ($nCont = 1; $nCont <= $PageContiguous; $nCont++)
if ($start + $num_per_page * $nCont <= $tmpMaxPages)
{
$tmpStart = $start + $num_per_page * $nCont;
$pageindex .= sprintf($base_link, $tmpStart, $tmpStart / $num_per_page + 1,'');
}

// Show the '...' part near the end. (1 ... 6 7 [8] 9 10 >...< 15)
if ($start + $num_per_page * ($PageContiguous + 1) < $tmpMaxPages)
$pageindex .= '<li><span class="navPages page_dots" style="cursor: pointer;" onclick="expandPages(this, \'' . ($flexible_start ? strtr($base_url, array('\'' => '\\\'')) : strtr($base_url, array('%' => '%%', '\'' => '\\\'')) . ';start=%1$d') . '\', ' . ($start + $num_per_page * ($PageContiguous + 1)) . ', ' . $tmpMaxPages . ', ' . $num_per_page . ');">...</span></li>';

// Show the last number in the list. (1 ... 6 7 [8] 9 10 ... >15<)
if ($start + $num_per_page * $PageContiguous < $tmpMaxPages)
$pageindex .= sprintf($base_link, $tmpMaxPages, $tmpMaxPages / $num_per_page + 1, '');

// Show 'Next'.
$display_page = ($start + $num_per_page) > $max_value ? $max_value : ($start + $num_per_page);
if (($display_page <= $tmpMaxPages)&&($tmpMaxPages > 1))
$pageindex .= sprintf($base_link, $display_page, $txt['next_page'], ' next_page');
}

return $pageindex;
}


With the template just calling the output like this:

<ul class="pagelinks" id="pageindex_selected">', $context['selected']['page_index'], '</ul>

Antechinus

Meh. Turns out the problem is probably coming from Sources/SplitTopic.php. Specifically, this bit:

// Fix an oversized starting page (to make sure both pageindexes are properly set).
if ($context['selected']['start'] >= $context['selected']['num_messages'])
$context['selected']['start'] = $context['selected']['num_messages'] <= $context['messages_per_page'] ? 0 : ($context['selected']['num_messages'] - (($context['selected']['num_messages'] % $context['messages_per_page']) == 0 ? $context['messages_per_page'] : ($context['selected']['num_messages'] % $context['messages_per_page'])));

// Build a page list of the not-selected topics...
$context['not_selected']['page_index'] = constructPageIndex($scripturl . '?action=splittopics;sa=selectTopics;subname=' . strtr(urlencode($_REQUEST['subname']), array('%' => '%%')) . ';topic=' . $topic . '.%1$d;start2=' . $context['selected']['start'], $context['not_selected']['start'], $context['not_selected']['num_messages'], $context['messages_per_page'], true);
// ...and one of the selected topics.
$context['selected']['page_index'] = constructPageIndex($scripturl . '?action=splittopics;sa=selectTopics;subname=' . strtr(urlencode($_REQUEST['subname']), array('%' => '%%')) . ';topic=' . $topic . '.' . $context['not_selected']['start'] . ';start2=%1$d', $context['selected']['start'], $context['selected']['num_messages'], $context['messages_per_page'], true);


Obviously this means nobody will have a clue how it works. Go on, prove me wrong.

Arantor

So where is $txt['next_page'] defined?

Also, why use a language string instead of something like &raquo; ?

Antechinus

To answer the second question first, because for various reasons I hate &raquo;. ;)

The $txt is defined in ThemeStrings.english.php, and in Subs.php.

// Custom strings for previous/next pages.
$txt['previous_page'] = 'previous';
$txt['next_page'] = 'next';


And Subs:

function constructPageIndex($base_url, &$start, $max_value, $num_per_page, $flexible_start = false)
{
global $modSettings, $txt;

// Save whether $start was less than 0 or not.
$start = (int) $start;
$start_invalid = $start < 0;

// Make sure $start is a proper variable - not less than 0.
if ($start_invalid)
$start = 0;
// Not greater than the upper bound.
elseif ($start >= $max_value)
$start = max(0, (int) $max_value - (((int) $max_value % (int) $num_per_page) == 0 ? $num_per_page : ((int) $max_value % (int) $num_per_page)));
// And it has to be a multiple of $num_per_page!
else
$start = max(0, (int) $start - ((int) $start % (int) $num_per_page));

// Wireless will need the protocol on the URL somewhere.
if (WIRELESS)
$base_url .= ';' . WIRELESS_PROTOCOL;

$base_link = '<li><a class="navPages%3$s" href="' . ($flexible_start ? $base_url : strtr($base_url, array('%' => '%%')) . ';start=%1$d') . '">%2$s</a></li>';

// Compact pages is off or on?
if (empty($modSettings['compactTopicPagesEnable']))
{
// Show the left arrow.
$pageindex = $start == 0 ? ' ' : sprintf($base_link, $start - $num_per_page, '&#171;', ' previous_page');

// Show all the pages.
$display_page = 1;
for ($counter = 0; $counter < $max_value; $counter += $num_per_page)
$pageindex .= $start == $counter && !$start_invalid ? '<li><a class="navPages current_page">' . $display_page++ . '</a></li>' : sprintf($base_link, $counter, $display_page++, '');

// Show the right arrow.
$display_page = ($start + $num_per_page) > $max_value ? $max_value : ($start + $num_per_page);
if ($start != $counter - $max_value && !$start_invalid)
$pageindex .= $display_page > $counter - $num_per_page ? ' ' : sprintf($base_link, $display_page, '&#187;', ' next_page');
}
else
{
// If they didn't enter an odd value, pretend they did.
$PageContiguous = (int) ($modSettings['compactTopicPagesContiguous'] - ($modSettings['compactTopicPagesContiguous'] % 2)) / 2;
$pageindex = '<li><span class="navPages pages_text">' .$txt['pages']. '</span></li>';

// Show 'Prev'
if ($start > ($num_per_page - 1))
$pageindex = sprintf($base_link, $start - $num_per_page, $txt['previous_page'], ' previous_page');

// Show the first page. (>1< ... 6 7 [8] 9 10 ... 15)
if ($start > $num_per_page * $PageContiguous)
$pageindex .= sprintf($base_link, 0, '1', '');

// Show the ... after the first page.  (1 >...< 6 7 [8] 9 10 ... 15)
if ($start > $num_per_page * ($PageContiguous + 1))
$pageindex .= '<li><span class="navPages page_dots" style="cursor: pointer;" onclick="' . htmlspecialchars('expandPages(this, ' . JavaScriptEscape(($flexible_start ? $base_url : strtr($base_url, array('%' => '%%')) . ';start=%1$d')) . ', ' . $num_per_page . ', ' . ($start - $num_per_page * $PageContiguous) . ', ' . $num_per_page . ');') . '">...</span></li>';

// Show the pages before the current one. (1 ... >6 7< [8] 9 10 ... 15)
for ($nCont = $PageContiguous; $nCont >= 1; $nCont--)
if ($start >= $num_per_page * $nCont)
{
$tmpStart = $start - $num_per_page * $nCont;
$pageindex .= sprintf($base_link, $tmpStart, $tmpStart / $num_per_page + 1,'');
}

// Show the current page. (1 ... 6 7 >[8]< 9 10 ... 15)
if (!$start_invalid)
$pageindex .= '<li><a class="navPages current_page">' . ($start / $num_per_page + 1) . '</a></li>';
else
$pageindex .= sprintf($base_link, $start, $start / $num_per_page + 1, '');

// Show the pages after the current one... (1 ... 6 7 [8] >9 10< ... 15)
$tmpMaxPages = (int) (($max_value - 1) / $num_per_page) * $num_per_page;
for ($nCont = 1; $nCont <= $PageContiguous; $nCont++)
if ($start + $num_per_page * $nCont <= $tmpMaxPages)
{
$tmpStart = $start + $num_per_page * $nCont;
$pageindex .= sprintf($base_link, $tmpStart, $tmpStart / $num_per_page + 1,'');
}

// Show the '...' part near the end. (1 ... 6 7 [8] 9 10 >...< 15)
if ($start + $num_per_page * ($PageContiguous + 1) < $tmpMaxPages)
$pageindex .= '<li><span class="navPages page_dots" style="cursor: pointer;" onclick="expandPages(this, \'' . ($flexible_start ? strtr($base_url, array('\'' => '\\\'')) : strtr($base_url, array('%' => '%%', '\'' => '\\\'')) . ';start=%1$d') . '\', ' . ($start + $num_per_page * ($PageContiguous + 1)) . ', ' . $tmpMaxPages . ', ' . $num_per_page . ');">...</span></li>';

// Show the last number in the list. (1 ... 6 7 [8] 9 10 ... >15<)
if ($start + $num_per_page * $PageContiguous < $tmpMaxPages)
$pageindex .= sprintf($base_link, $tmpMaxPages, $tmpMaxPages / $num_per_page + 1, '');

// Show 'Next'.
$display_page = ($start + $num_per_page) > $max_value ? $max_value : ($start + $num_per_page);
if (($display_page <= $tmpMaxPages)&&($tmpMaxPages > 1))
$pageindex .= sprintf($base_link, $display_page, $txt['next_page'], ' next_page');
}

return $pageindex;
}

Arantor

ThemeStrings isn't loaded in XML mode and it's running in XML mode as per the ;xml URL you provided.

Either modify Subs.php to declare them if not otherwise declared or move the definition to index.language.php.

Antechinus

Ok, but the funny thing is that when I disabled that js by commenting it out, the problem still occurred. That's what led me to now think it's likely to be a Sources problem rather than a js problem.

I don't want to stick the strings in index.english.php since that's not doable for a mod (want to package the thing). So, how would you suggest modifying Subs?

Arantor

Well, the URL *clearly* says it's calling a ;xml URL and in that circumstance it won't be loaded because the theme doesn't get fully loaded. Whatever JS you commented out is almost certainly not the JS calling for segments of a topic via XML...

The simplest way of doing this in Subs.php is to have this after the global declaration:

if (!isset($txt['previous_page']))
    $txt['previous_page'] = 'previous';
if (!isset($txt['next_page']))
   $txt['next_page'] = 'next';

Antechinus

Ok, but that will be untranslatable. Is there a way of doing it that will allow various languages to use the right translation? What about Modifications.english.php? Does that get loaded in XML mode?

Arantor

Yes, Modifications is loaded in literally every scenario. It's the only thing that is.

The different possibilities:
* Wireless - loads index, Wireless and Modifications
* XML - loads index and Modifications
* no action specified or on the list of simple actions (which don't require much theme stuff, e.g. print page) - loads index and Modifications
* everything else, load Modifications and whatever the theme says it wants to load in $settings['theme_templates'], if not specified, use index. (So on a stock install, index is used anyway)

Antechinus

Ok cool. I'll give it a bash with the strings in that one then.

Antechinus

Yup, that works. Sorted. :D

(Actually they'd have to go in that file for a packaged version anyway. I just hadn't thought of trying it on the test theme, which has strings for Africa).

Arantor

And that's what you get for daring people to prove you wrong :P

Antechinus

Yeah well, the last time I asked for a bit of help in this thread no bugger answered, so I figured give them a bit of a dare and they'll want to prove me wrong. Bloody worked a treat. :D

Antechinus

Ay up. Was just going over this again and had a brainwave, which I should have thought of before. Pseudos. Ditch all the txt strings and just use pseudos. Easy to style, unlimited choice of content, and no translation issues. D'oh.

* Antechinus is using pseudos now, just in case you were wondering.

Advertisement: