Commit 3b0c2456 authored by Nigel McNie's avatar Nigel McNie
Browse files

More progress on the views frontend. There are stubs for several actions, and...

More progress on the views frontend. There are stubs for several actions, and javascript implementations of those actions.
parent 28af17a1
......@@ -9,7 +9,7 @@ function ViewManager() {
this.init = function () {
// Hide 'new block here' buttons
forEach(getElementsByTagAndClassName('input', 'newblockhere', 'bottom-pane'), function(i) {
forEach(getElementsByTagAndClassName('div', 'add-button', 'bottom-pane'), function(i) {
removeElement(i);
});
......@@ -24,12 +24,105 @@ function ViewManager() {
});
// Rewrite the links in the category select list to be ajax
self.rewriteCategorySelectList();
// Rewrite the delete buttons to be ajax
self.rewriteDeleteButtons();
// Rewrite the 'add column' buttons to be ajax
self.rewriteAddColumnButtons();
// Rewrite the 'remove column' buttons to be ajax
self.rewriteRemoveColumnButtons();
}
this.addColumn = function(id) {
alert('Adding a column before current column ' + id);
}
/**
* Removes a column from the view, sizes the others to take its place and
* moves the blockinstances in it to the other columns
*/
this.removeColumn = function(id) {
var addColumnLeftButtonContainer;
if (id == 1) {
// We are removing the first column, which has the button for adding a column to the left of itself. We want to keep this
addColumnLeftButtonContainer = getFirstElementByTagAndClassName('div', 'add-column-left', 'column_1');
}
// Save the blockinstances that are in the column to remove
var blockInstances = getElementsByTagAndClassName('div', 'blockinstance', 'column_' + id);
// Remove the column itself
removeElement('column_' + id);
// Get the existing number of columns
var numColumns = getFirstElementByTagAndClassName('div', 'column', 'bottom-pane').getAttribute('class').match(/columns([0-9]+)/)[1];
forEach(getElementsByTagAndClassName('div', 'columns' + numColumns, 'bottom-pane'), function(i) {
removeElementClass(i, 'columns' + numColumns);
addElementClass(i, 'columns' + (numColumns - 1));
});
// All columns above the one removed need to be renumbered
if (id < numColumns) {
for (var i = id; i < numColumns; i++) {
var oldID = i + 1;
var newID = i;
$('column_' + oldID).setAttribute('id', 'column_' + newID);
// Renumber the add/remove column buttons
getFirstElementByTagAndClassName('input', 'addcolumn', 'column_' + newID).setAttribute('name', 'action_add_column_before_' + oldID);
getFirstElementByTagAndClassName('input', 'removecolumn', 'column_' + newID).setAttribute('name', 'action_remove_column_' + newID);
}
}
// The last column needs the class of the header changed, the first column possibly too
if (addColumnLeftButtonContainer) {
insertSiblingNodesBefore(
getFirstElementByTagAndClassName('div', 'remove-column', 'column_1'),
addColumnLeftButtonContainer
);
}
var lastColumn = $('column_' + (numColumns - 1));
var addColumnRightButtonContainer = getFirstElementByTagAndClassName('div', 'add-column-right', lastColumn);
if (!addColumnRightButtonContainer) {
var addColumnRightButtonContainer = getFirstElementByTagAndClassName('div', 'add-column-center', lastColumn);
removeElementClass(addColumnRightButtonContainer, 'add-column-center');
addElementClass(addColumnRightButtonContainer, 'add-column-right');
}
// If there used to be two columns (and therefore now there is one), remove the only 'remove column' button left, people can't remove the last column
if (numColumns == 2) {
removeElement(getFirstElementByTagAndClassName('div', 'remove-column', 'column_1'));
}
// Put the block instances that were in the removed column into the other columns
var i = 1;
forEach(blockInstances, function(instance) {
appendChildNodes(getFirstElementByTagAndClassName('div', 'column-content', 'column_' + i), instance);
if (i < (numColumns - 1)) {
i++;
}
else {
i = 1;
}
});
}
/**
* Rewrites the category select links to be AJAX
*/
this.rewriteCategorySelectList = function() {
forEach(getElementsByTagAndClassName('a', null, 'category-list'), function(i) {
connect(i, 'onclick', function(e) {
var queryString = parseQueryString(i.href.substr(i.href.indexOf('?')));
removeElementClass(getFirstElementByTagAndClassName('li', 'current', 'category-list'), 'current');
addElementClass(i.parentNode, 'current');
sendjsonrequest('viewrework.json.php', {'action': 'blocktype_list', 'category': queryString['category']}, 'POST', function(data) {
sendjsonrequest('viewrework.json.php', {'view': $('viewid').value, 'action': 'blocktype_list', 'category': queryString['category']}, 'POST', function(data) {
if (!data.error) {
$('blocktype-list').innerHTML = data.data;
}
......@@ -37,12 +130,17 @@ function ViewManager() {
e.stop();
});
});
}
// Rewrite the delete buttons to be ajax
/**
* Rewrites the blockinstance delete buttons to be AJAX
*/
this.rewriteDeleteButtons = function() {
forEach(getElementsByTagAndClassName('input', 'deletebutton', 'bottom-pane'), function(i) {
connect(i, 'onclick', function(e) {
sendjsonrequest('viewrework.json.php', {'action': 'delete_blockinstance', 'data': e.src().getAttribute('name')}, 'POST', function(data) {
sendjsonrequest('viewrework.json.php', {'view': $('viewid').value, 'action': 'delete_blockinstance', 'data': e.src().getAttribute('name')}, 'POST', function(data) {
if (!data.error) {
// TODO: not happy with using .parentNode, it's fragile
removeElement(i.parentNode.parentNode);
}
else {
......@@ -54,6 +152,47 @@ function ViewManager() {
});
}
/**
* Rewrites the add column buttons to be AJAX
*/
this.rewriteAddColumnButtons = function() {
forEach(getElementsByTagAndClassName('input', 'addcolumn', 'bottom-pane'), function(i) {
connect(i, 'onclick', function(e) {
var name = e.src().getAttribute('name');
var id = parseInt(name.substr(-1));
sendjsonrequest('viewrework.json.php', {'view': $('viewid').value, 'action': 'add_column', 'column': id}, 'POST', function(data) {
if (!data.error) {
self.addColumn(id);
}
else {
// ?
}
});
e.stop();
});
});
}
/**
* Rewrite the remove column buttons to be AJAX
*/
this.rewriteRemoveColumnButtons = function() {
forEach(getElementsByTagAndClassName('input', 'removecolumn', 'bottom-pane'), function(i) {
connect(i, 'onclick', function(e) {
var name = e.src().getAttribute('name');
var id = parseInt(name.substr(-1));
sendjsonrequest('viewrework.json.php', {'view': $('viewid').value, 'action': 'remove_column', 'column': id}, 'POST', function(data) {
if (!data.error) {
self.removeColumn(id);
}
else {
// ?
}
});
e.stop();
});
});
}
addLoadEvent(self.init);
}
......
......@@ -3,6 +3,7 @@
{include file="columnfullstart.tpl"}
<form action="" method="post">
<input type="hidden" id="viewid" name="view" value="1">
<div id="page">
<div id="top-pane">
<div id="category-list">
......@@ -17,28 +18,30 @@
<div id="bottom-pane">
<div id="column-container">
{foreach from=$columns.columns key=colnum item=column}
<div class="column columns{$columns.count}">
<div id="column_{$colnum}" class="column columns{$columns.count}">
<div class="column-header">
{if $colnum == 1}
<div class="add-column-left">
<input type="submit" class="submit" name="add_column_before_1" value="Add Column">
<input type="submit" class="submit addcolumn" name="action_add_column_before_1" value="Add Column">
</div>
{/if}
<div class="remove-column">
<input type="submit" class="submit" name="remove_column_{$colnum}" value="Remove Column">
<input type="submit" class="submit removecolumn" name="action_remove_column_{$colnum}" value="Remove Column">
</div>
{if $colnum == $columns.count}
<div class="add-column-right">
<input type="submit" class="submit" name="add_column_before_{$colnum+1}" value="Add Column">
<input type="submit" class="submit addcolumn" name="action_add_column_before_{$colnum+1}" value="Add Column">
</div>
{else}
<div class="add-column-center">
<input type="submit" class="submit" name="add_column_before_{$colnum+1}" value="Add Column">
<input type="submit" class="submit addcolumn" name="action_add_column_before_{$colnum+1}" value="Add Column">
</div>
{/if}
</div>
<div class="column-content">
<input type="submit" class="submit newblockhere" name="blocktype_add_top_{$colnum}" value="Add new block here">
<div class="add-button">
<input type="submit" class="submit newblockhere" name="action_blocktype_add_top_{$colnum}" value="Add new block here">
</div>
{foreach from=$column.blockinstances item=blockinstance}
<div class="blockinstance" id="blockinstance_{$blockinstance.id}">
<div class="blockinstance-header">
......@@ -55,7 +58,9 @@
{$blockinstance.content}
</div>
</div>
<input type="submit" class="submit newblockhere" name="blocktype_add_after_{$blockinstance.id}" value="Add new block here">
<div class="add-button">
<input type="submit" class="submit newblockhere" name="action_blocktype_add_after_{$blockinstance.id}" value="Add new block here">
</div>
{/foreach}
</div>
</div>
......
......@@ -145,7 +145,7 @@ EOF;
$blocktypehtml = str_replace('{TITLE}', hsc($blocktype['title']), $blocktypehtml);
$blocktypehtml = str_replace('{DESCRIPTION}', format_whitespace(hsc($blocktype['description'])), $blocktypehtml);
$blocktypehtml = str_replace('{THUMBNAIL_PATH}', hsc($blocktype['thumbnail_path']), $blocktypehtml);
$radio = ($javascript) ? '' : '<input type="radio" class="blocktype-radio" name="blocktype" value="blocktype_{' . $blocktype['id'] . '">';
$radio = ($javascript) ? '' : '<input type="radio" class="blocktype-radio" name="blocktype" value="' . $blocktype['id'] . '">';
$blocktypehtml = str_replace('{RADIO}', $radio, $blocktypehtml);
$result .= $blocktypehtml;
......@@ -155,4 +155,125 @@ EOF;
return $result;
}
function view_process_changes() {
global $SESSION;
if (!count($_POST)) {
return;
}
log_debug($_POST);
$view = param_integer('view');
$action = '';
foreach ($_POST as $key => $value) {
if (substr($key, 0, 7) == 'action_') {
$action = substr($key, 7);
}
else {
$data[$key] = $value;
}
}
$value = view_get_value_for_action($action);
$result = null;
if (starts_with($action, 'blocktype_add_top')) {
// Done as "add_top" so that block instances can be added to columns with nothing in them
$blocktype = param_integer('blocktype', 0);
if (!$blocktype) {
$SESSION->add_info_msg('Please select a block type to add first');
return;
}
$result = view_blocktype_add_top($view, $blocktype, $value);
$okmsg = 'Added block type successfully';
$errmsg = 'Could not add the block to your view';
}
else if (starts_with($action, 'blocktype_add_after')) {
$blockinstance = view_get_value_for_action($action);
$blocktype = param_integer('blocktype', 0);
if (!$blocktype) {
$SESSION->add_info_msg('Please select a block type to add first');
return;
}
$result = view_blocktype_add_after($view, $blocktype, $value);
$okmsg = 'Added block type successfully';
$errmsg = 'Could not add the block to your view';
}
else if (starts_with($action, 'add_column_before')) {
$result = false;
$okmsg = '';
$errmsg = 'Not implemented yet';
}
else if (starts_with($action, 'remove_column')) {
$column = view_get_value_for_action($action);
log_debug("Remove column " . $column);
if (view_remove_column($view, $column)) {
$SESSION->add_ok_msg('Removed column successfully');
}
else {
$SESSION->add_ok_msg('Failed to remove column');
}
return;
}
if (!is_null($result)) {
if ($result) {
$SESSION->add_ok_msg($okmsg);
}
else {
$SESSION->add_error_msg($errmsg);
}
redirect('/viewrework.php');
}
throw new UserException('No valid action found');
}
function starts_with($haystack, $needle) {
return substr($haystack, 0, strlen($needle)) == $needle;
}
function view_get_value_for_action($action) {
$value = intval(substr($action, strrpos($action, '_') + 1));
if ($value == 0) {
throw new UserException('Value for action is not valid');
}
return $value;
}
function view_assert_data($data, $key) {
if (!isset($data[$key])) {
throw new UserException('The value for "' . $key . '" is not available for this action');
}
}
function view_blocktype_add_top($view, $blocktype, $column) {
// Stub
log_debug("Add block type " . $blocktype . ' to the top of column ' . $column);
return true;
}
function view_blocktype_add_after($view, $blocktype, $blockinstance) {
// Stub
log_debug("Add block type " . $blocktype . ' below blockinstance ' . $blockinstance);
return true;
}
function view_add_column($view, $column) {
// Stub
log_debug('Adding column before current column ' . $column);
return true;
}
function view_remove_column($view, $column) {
// Stub
log_debug('Removing column ' . $column . ' from view ' . $view);
return true;
}
?>
......@@ -30,6 +30,7 @@ define('PUBLIC', 1);
require(dirname(__FILE__) . '/init.php');
require(dirname(__FILE__) . '/viewlib.php');
$view = param_integer('view');
$action = param_alphanumext('action');
switch ($action) {
......@@ -42,25 +43,43 @@ case 'blocktype_list':
// TODO:
//
// Where I can get to:
// Static version: Clicking buttons = response, but no action. Category browser works, for hard coded block types
// Dynamic version: Actions = response, but no action performed. Category browser works with ajax for hard coded block types
// Static version: Clicking buttons = response, but no action.
// Dynamic version: Actions = response, but no action performed.
//
// What can be done:
// Category browser
// Add column: js should make room for it, put in the raw html (note: need to generate column raw html in a function then!)
// Remove column: js should destroy the existing column, hopefully moving the blocks to other columns (could be implemented as move move delete?)
// Moving block instances: js should drag+drop, do ajax stub request. static should send response
// Add block: js should be done by drag and drop. static should respond
//
//
//
//
// Where I'm up to:
// Doing 'add block' for the static version. This involves getting the basic action responder code in place and being as concise as possibly
// Skip the ajax version of this for now, the configuration thing needs thinking about.
//
//
$data = views_build_blocktype_list($category, true);
json_reply(false, array('message' => false, 'data' => $data));
break;
case 'add_column':
$column = param_integer('column');
if (view_add_column($view, $column)) {
json_reply(false, false);
}
else {
json_reply(true, 'Failed to add column');
}
case 'remove_column':
$column = param_integer('column');
if (view_remove_column($view, $column)) {
// Just do it - no message
json_reply(false, false);
}
else {
json_reply(true, 'Failed to remove column');
}
break;
}
json_reply(true, 'Unknown action "' . $action . '"');
?>
......@@ -31,6 +31,8 @@ require('init.php');
require('viewlib.php');
define('TITLE', 'Views Rework [DANGER construction site]');
view_process_changes();
$smarty = smarty(array('views'), array('<link rel="stylesheet" href="views.css" type="text/css">'));
// FIXME: we can't know the first category is 'aboutme'
......
......@@ -70,10 +70,10 @@
}
/* each column div will have a class matching one of these, the number is the number of columns in total, so widths can be made equal */
.columns1 {
width: 100%;
width: 98%;
}
.columns2 {
width: 50%;
width: 48%;
}
.columns3 {
width: 31%;
......@@ -82,12 +82,17 @@
.column {
vertical-align: top;
float: left;
margin: 0 0 0 2%;
margin: 0 1%;
}
/* An explicit height for when there is one column and no remove button */
.column-header {
width: 100%;
position: relative;
height: 30px;
}
.add-button {
text-align: center;
}
/* contains the left-most 'add column' button */
......@@ -116,6 +121,7 @@
text-align: center;
}
/* block instance styles */
.blockinstance {
border: 2px solid #cc9;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment