1
0
mirror of https://github.com/vichan-devel/vichan.git synced 2024-11-30 18:24:29 +01:00

- board-search.php Now properly calculates tag weight.

- boards.php Passes $search parameters into Twig.
- js/board-reictory.js Stores last search parameters and handles tag click events.
- Twig now passes old search parameters into the search form.
- Tags now link in such a way that they will preserve form data and other tags when clicked in a browser without JavaScript.

Signed-off-by: 8n-tech <8n-tech@users.noreply.github.com>
This commit is contained in:
8n-tech 2015-04-16 05:46:48 +10:00
parent 67bab31510
commit ec90c96459
6 changed files with 139 additions and 45 deletions

View File

@ -25,6 +25,7 @@ $languages = array(
$search = array(
'lang' => false,
'nsfw' => true,
'page' => 0,
'tags' => false,
'time' => ( (int)( time() / 3600 ) * 3600 ) - 3600,
'title' => false,
@ -37,6 +38,15 @@ if (isset( $_GET['sfw'] ) && $_GET['sfw'] != "") {
$search['nsfw'] = !$_GET['sfw'];
}
// Bringing up more results
if (isset( $_GET['page'] ) && $_GET['page'] != "") {
$search['page'] = (int) $_GET['page'];
if ($search['page'] < 0) {
$search['page'] = 0;
}
}
// Include what language (if the language is not blank and we recognize it)?
if (isset( $_GET['lang'] ) && $_GET['lang'] != "" && isset($languages[$search['lang']])) {
$search['lang'] = $_GET['lang'];
@ -44,7 +54,8 @@ if (isset( $_GET['lang'] ) && $_GET['lang'] != "" && isset($languages[$search['l
// Include what tag?
if (isset( $_GET['tags'] ) && $_GET['tags'] != "") {
$search['tags'] = $_GET['tags'];
$search['tags'] = explode( " ", $_GET['tags'] );
$search['tags'] = array_splice( $search['tags'], 0, 5 );
}
// What time range?
@ -73,6 +84,31 @@ foreach ($boards as $board) {
continue;
}
// Are we searching by title?
if ($search['title'] !== false) {
// This checks each component of the board's identity against our search terms.
// The weight determines order.
// "left" would match /leftypol/ and /nkvd/ which has /leftypol/ in the title.
// /leftypol/ would always appear above it but it would match both.
if (strpos("/{$board['uri']}/", $search['title']) !== false) {
$board['weight'] = 30;
}
else if (strpos($board['title'], $search['title']) !== false) {
$board['weight'] = 20;
}
else if (strpos($board['subtitle'], $search['title']) !== false) {
$board['weight'] = 10;
}
else {
continue;
}
unset( $boardTitleString );
}
else {
$board['weight'] = 0;
}
// Load board config.
$boardConfig = loadBoardConfig( $board['uri'] );
@ -101,7 +137,7 @@ $boardTags = fetchBoardTags( array_keys( $response['boards'] ) );
// Loop through each board and determine if there are tag matches.
foreach ($response['boards'] as $boardUri => &$board) {
// If we are filtering by tag and there is no match, remove from the response.
if ( $search['tags'] !== false && ( !isset( $boardTags[ $boardUri ] ) || !in_array( $search['tags'], $boardTags[ $boardUri ] )) ) {
if ( $search['tags'] !== false && ( !isset( $boardTags[ $boardUri ] ) || count(array_intersect($search['tags'], $boardTags[ $boardUri ])) !== count($search['tags']) ) ) {
unset( $response['boards'][$boardUri] );
}
// If we aren't filtering / there is a match AND we have tags, set the tags.
@ -145,13 +181,16 @@ foreach ($response['boards'] as $boardUri => &$board) {
// Sort boards by their popularity, then by their total posts.
$boardActivityValues = array();
$boardTotalPostsValues = array();
$boardWeightValues = array();
foreach ($response['boards'] as $boardUri => &$board) {
$boardActivityValues[$boardUri] = (int) $board['active'];
$boardTotalPostsValues[$boardUri] = (int) $board['posts_total'];
$boardWeightValues[$boardUri] = (int) $board['weight'];
}
array_multisort(
$boardWeightValues, SORT_DESC, SORT_NUMERIC, // Sort by weight
$boardActivityValues, SORT_DESC, SORT_NUMERIC, // Sort by number of active posters
$boardTotalPostsValues, SORT_DESC, SORT_NUMERIC, // Then, sort by total number of posts
$response['boards']
@ -159,8 +198,8 @@ array_multisort(
$boardLimit = $search['index'] ? 50 : 100;
$response['omitted'] = $search['index'] ? 0 : count( $response['boards'] ) - $boardLimit;
$response['boards'] = array_splice( $response['boards'], 0, $boardLimit );
$response['omitted'] = count( $response['boards'] ) - $boardLimit;
$response['boards'] = array_splice( $response['boards'], $search['page'], $boardLimit );
$response['order'] = array_keys( $response['boards'] );
@ -216,9 +255,14 @@ if (count($response['tags']) > 0) {
}
foreach ($tagUsage['users'] as $tagName => $tagUsers) {
if ($weightDepartureFurthest != 0) {
$weightDeparture = abs( $tagUsers - $tagsAvgUsers );
$response['tagWeight'][$tagName] = 75 + round( 100 * ( $weightDeparture / $weightDepartureFurthest ), 0);
}
else {
$response['tagWeight'][$tagName] = 0;
}
}
}
/* Include our interpreted search terms. */

View File

@ -36,6 +36,16 @@ $boards_omitted = (int) $searchJson['omitted'];
$posts_hour = number_format( fetchBoardActivity(), 0 );
$posts_total = number_format( $boardResult['posts_total'], 0 );
// This incredibly stupid looking chunk of code builds a query string using existing information.
// It's used to make clickable tags for users without JavaScript for graceful degredation.
// Because of how it orders tags, what you end up with is a prefix that always ends in tags=x+
// ?tags= or ?sfw=1&tags= or ?title=foo&tags=bar+ - etc
$tagQueryGet = $_GET;
$tagQueryTags = isset($tagQueryGet['tags']) ? $tagQueryGet['tags'] : "";
unset($tagQueryGet['tags']);
$tagQueryGet['tags'] = $tagQueryTags;
$tag_query = "?" . http_build_query( $tagQueryGet ) . ($tagQueryTags != "" ? "+" : "");
/* Create and distribute page */
$config['additional_javascript'] = array(
'js/jquery.min.js',
@ -45,17 +55,22 @@ $config['additional_javascript'] = array(
$boardsHTML = Element("8chan/boards-table.html", array(
"config" => $config,
"boards" => $boards,
"tag_query" => $tag_query,
)
);
$tagsHTML = Element("8chan/boards-tags.html", array(
"config" => $config,
"tags" => $tags,
"tag_query" => $tag_query,
)
);
$searchHTML = Element("8chan/boards-search.html", array(
"config" => $config,
"search" => $searchJson['search'],
"boards_total" => $boards_total,
"boards_public" => $boards_public,

View File

@ -22,6 +22,8 @@
'search-tag' : "#search-tag-input",
'search-title' : "#search-title-input",
'search-submit' : "#search-submit",
'tag-link' : ".tag-link"
},
// HTML Templates for dynamic construction
@ -50,6 +52,8 @@
}
},
lastSearch : {},
bind : {
form : function() {
var selectors = boardlist.options.selector;
@ -71,11 +75,17 @@
'searchSubmit' : $searchSubmit
};
if ($search.length > 0) {
// Bind form events.
$search.on( 'submit', searchForms, boardlist.events.searchSubmit );
$searchSubmit.prop( 'disabled', false ).on( 'click', searchForms, boardlist.events.searchSubmit );
boardlist.$boardlist
// Tag click
.on( 'click', selectors['tag-link'], searchForms, boardlist.events.tagClick )
// Form Submission
.on( 'submit', selectors['search'], searchForms, boardlist.events.searchSubmit )
// Submit click
.on( 'click', selectors['search-submit'], searchForms, boardlist.events.searchSubmit );
$searchSubmit.prop( 'disabled', false );
}
}
},
@ -83,6 +93,7 @@
build : {
boardlist : function(data) {
boardlist.build.boards(data['boards'], data['order']);
boardlist.build.lastSearch(data['search']);
boardlist.build.tags(data['tags']);
},
@ -101,12 +112,10 @@
boardlist.build.board( row, col ).appendTo( $row );
} );
if( index >= 100 ) return false;
$row.appendTo( $body );
} );
},
board : function( row, col ) {
board : function(row, col) {
var $col = $(col),
column = $col.attr('data-column'),
value = row[column]
@ -150,10 +159,10 @@
return $cell;
},
boardcell : {
'meta' : function( row, value ) {
'meta' : function(row, value) {
return $( boardlist.options.template['board-datum-lang'] ).text( row['locale'] );
},
'uri' : function( row, value ) {
'uri' : function(row, value) {
var $link = $( boardlist.options.template['board-datum-uri'] ),
$sfw = $( boardlist.options.template['board-datum-' + (row['sfw'] == 1 ? "sfw" : "nsfw")] );
@ -172,8 +181,18 @@
}
},
tags : function(data) {
lastSearch : function(search) {
return boardlist.lastSearch = {
'lang' : search.lang === false ? "" : search.lang,
'page' : search.page,
'tags' : search.tags === false ? "" : search.tags.join(" "),
'time' : search.time,
'title' : search.title === false ? "" : search.title,
'sfw' : search.nsfw ? 0 : 1
};
},
tags : function(data) {
}
},
@ -181,7 +200,33 @@
searchSubmit : function(event) {
event.preventDefault();
var $boardlist = event.data.boardlist,
boardlist.submit( {
'lang' : event.data.searchLang.val(),
'tags' : event.data.searchTag.val(),
'title' : event.data.searchTitle.val(),
'sfw' : event.data.searchSfw.prop('checked') ? 1 : 0
} );
return false;
},
tagClick : function(event) {
event.preventDefault();
var $this = $(this),
$input = $( boardlist.options.selector['search-tag'] );
$input
.val( ( $input.val() + " " + $this.text() ).replace(/\s+/g, " ").trim() )
.trigger( 'change' )
.focus();
return false;
}
},
submit : function( parameters ) {
var $boardlist = boardlist.$boardlist,
$boardbody = $( boardlist.options.selector['board-body'], $boardlist ),
$boardload = $( boardlist.options.selector['board-loading'], $boardlist );
@ -190,21 +235,12 @@
$.get(
"/board-search.php",
{
'lang' : event.data.searchLang.val(),
'tags' : event.data.searchTag.val(),
//'time' : event.data.searchTag.val(),
'title' : event.data.searchTitle.val(),
'sfw' : event.data.searchSfw.prop('checked') ? 1 : 0
},
parameters,
function(data) {
$boardload.hide();
boardlist.build.boardlist( $.parseJSON(data) );
}
);
return false;
}
},
init : function( target ) {
@ -217,7 +253,6 @@
if ($boardlist.length > 0 ) {
$( boardlist.options.selector['board-loading'], $boardlist ).hide();
boardlist.$boardlist = $boardlist;
boardlist.bind.form();
}

View File

@ -8,16 +8,16 @@
<div class="board-list">
<aside class="search-container col col-2">
<form id="search-form" class="box" method="get" target="/board-search.php">
<form id="search-form" class="box" method="get" action="/boards.php">
<h2 class="box-title">Search</h2>
<div class="board-search box-content">
<label class="search-item search-sfw">
<input type="checkbox" id="search-sfw-input" name="sfw" value="1" />&nbsp;Hide NSFW boards
<input type="checkbox" id="search-sfw-input" name="sfw" value="1" {% if not search.nsfw %}checked="checked"{% endif %} />&nbsp;Hide NSFW boards
</label>
<div class="search-item search-title">
<input type="text" id="search-title-input" name="title" name="title" value="" placeholder="Search titles..." />
<input type="text" id="search-title-input" name="title" name="title" value="{{search.title}}" placeholder="Search titles..." />
</div>
<div class="search-item search-lang">
@ -34,7 +34,7 @@
</div>
<div class="search-item search-tag">
<input type="text" id="search-tag-input" name="tags" value="" placeholder="Search tags..." />
<input type="text" id="search-tag-input" name="tags" value="{{ search.tags|join(' ') }}" placeholder="Search tags..." />
</div>
<div class="search-item search-submit">

View File

@ -9,6 +9,6 @@
<td class="board-pph"><div class="board-cell">{{board['pph']}}</td>
<td class="board-max"><div class="board-cell">{{board['posts_total']}}</td>
<td class="board-unique"><div class="board-cell">{{board['active']}}</td>
<td class="board-tags"><div class="board-cell">{% for tag in board.tags %}<a class="tag-link" href="#">{{ tag }}</a>{% endfor %}</div></td>
<td class="board-tags"><div class="board-cell">{% for tag in board.tags %}<a class="tag-link" href="{{ tag_query }}{{ tag }}">{{ tag }}</a>{% endfor %}</div></td>
</tr>
{% endfor %}

View File

@ -1,5 +1,5 @@
{% for tag, weight in tags %}
<li class="tag-item">
<a class="tag-link" href="#" style="font-size: {{weight}}%;">{{tag}}</a>
<a class="tag-link" href="{{ tag_query }}{{ tag }}" style="font-size: {{weight}}%;">{{tag}}</a>
</li>
{% endfor %}