Please login or register.

Login with username, password and session length
Advanced search  

News:

Latest sNews - sNews 1.7 - with its own forums - for discussion and user mods.

Author Topic: [Tutorial] Custom Template: Part 2a  (Read 2014 times)

centered

  • Guest
[Tutorial] Custom Template: Part 2a
« on: December 02, 2009, 04:33:31 PM »

If you haven't viewed the initial part of this tutorial series, please go here.

Now, if you followed Part 1, you should still sort of have a base sNews installation, slighted modded so far, but basically it is still kinda vanilla. Unfortunately, right now, the template look is going to stay vanilla.  Now I noted in Part 1 an idea for a admin template and since there are plenty of themes available, we can stray of course a tad.

Let's begin.

1. Let's open the root index.php and modify it to accommodate the admin and non-admin templates.
Code: [Select]
<?php
 
include(
'snews.php');

if (
check_category($categorySEF) ||
in_array$_GET['action'], explode','l('cat_listSEF') ) )
) {
// login and admin pages
include('sN_admin/index.php');
} else {
// everything else
include('sN_template/index.php'); 
}

?>


2. Go back to the sN_template folder and copy all of the inner contents and paste it in the sN_admin folder.  Now duplicate the base.php and name it login.php.  Don't forget to change the stylesheet path.

3. Open up the sN_admin/index.php file and change it to this:
Code: [Select]
<?php 
// For custom functions
include("functions.php");

if ($categorySEF == 'login') {
include( 'login.php' );
} else {
include( 'base.php' ); 
}

?>


4. Now let's create a custom login page. Open up login.php and add the following:
Code: [Select]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<?php title(); ?>
<meta name="robots" content="index,follow" />
<meta name="author" content="Solucija.com" />
<link rel="stylesheet" type="text/css" href="sN_admin/css/admin.css" />
<style type="text/css">
.adminpanel {
width: 450px;
margin: 0 auto;
border: 1px solid #ccc;
}

.adminpanel h2 {
display: block;
color: #fff;
font-weight: normal;
background: #487587;
padding: 10px 15px;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="header">
<ul id="topmenu" class="align-right">
<li>
<a href="<?php echo _SITE?>" title="<?php echo s('website_description'); ?>">
Back to the Homepage
</a>
</li>
</ul>
<div id="logo" class="align-left">
<h1><?php echo s('website_title'); ?></h1>
</div>
</div>

<div id="center">
<?php center(); ?>
</div>
</div>
</body>
</html>

Now open a new file under the sN_admin/css folder and call it admin.css. This will be the base for the regular admin template
Code: [Select]
* {
margin: 0;
padding: 0;
}

body {
font:.75em Verdana, Arial, Sans-Serif;
color:#272727;
line-height:1.6em;
background:#fff;
}

ul {
list-style:none;
}

.align-left { float: left; }
.align-right { float: right; }

#wrapper {
margin: 0 auto;
}

#header {
height:55px;
display:block;
background: #487587;
margin:0 auto;
padding:5px 0 10px 5px;

}

#topmenu {
float:right;
margin-top:35px;
}

#topmenu li {
display:inline;
padding:30px 15px 5px 0;
}

#topmenu a {
font-size:1em;
color:#eee;
padding: 5px;
margin: 0 auto;
}

#topmenu a:hover, #topmenu a:focus {
color: #ccc;
}

#logo h1 {
color: #fff;
font-weight: normal;
display:block;
margin: 33px 0 0 10px;
}

#center {
background:#fff;
overflow:hidden;
height:100%;
margin:30px auto;
padding:20px 20px 0;
}

.adminpanel {}

.adminpanel form {
padding: 10px 15px;
line-height: 2.0em;
}

.button {
    display:block;
    margin:10px 7px 0 0;
    background-color:#487587;
    border:1px solid #dedede;
    border-top:1px solid #eee;
    border-left:1px solid #eee;
    line-height:130%;
    font-weight:bold;
    color:#fff;
    cursor:pointer;
    padding:5px 10px 6px 7px;
}

.button:hover {
    background-color:#487587;
    color: #ccc;
}

You should end up with this:


Pretty basic and simple, but a clear separation of public and private viewings.

Nothing more today. So far, we have directed the engine to go to two separate paths for our templates, and even further if in one of the admin pages.  We created a basic custom login page with simple html and css, and with no hacking involved (other than file separation and modifying templates, which as mentioned before is redundant).  We can even go further and add some javascript for behavior, I will leave that up to you. 

Part 2 of 2 will be for the regular admin pages and I have a template picked out for the public view of the system.
Logged

centered

  • Guest
Re: [Tutorial] Custom Template: Part 2a
« Reply #1 on: December 03, 2009, 01:31:39 PM »

Just chiming in here with a few fixes.

First -
If you start styling up your login form, you will note that when you style the <label> the semi-colon gets all screwy.  The issue there is html_input (what else?).  To fix the <label> issue change the following:
Find:
Code: [Select]
$lbl = !empty($label) ? '<label for="'.$id.'">'.$label.'</label>' : '';

Replace:
Code: [Select]
$lbl = !empty($label) ? '<label for="'.$id.'">'.$label.':</label>' : '';

Find:
Code: [Select]
case 'password': $output = '<p>'.$lbl.':<br />'.$input.$val.' /></p>'; break;

Replace:
Code: [Select]
case 'password': $output = '<p>'.$lbl.'<br />'.$input.$val.' /></p>'; break;

Find:
Code: [Select]
$output = '<p>'.$lbl.':<br />
Replace:
Code: [Select]
$output = '<p>'.$lbl.'<br />
IMO this is a bug as it messes with css styling

Second -
If you notice if something goes wrong with logging in, you go to a different screen noting an error.  We can change the behavior with javascript, but for now, we will keep it at default and style it correctly:

Code: (Put in login.php in the header) [Select]
#center h3 {
background: red;
width: 450px;
margin: 0 auto;
display: block;
color: #fff;
padding: 10px 0;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
}

#center > p {
width: 450px;
margin: 0 auto;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
}

#center > p + p {
padding-bottom: 5px;
border-bottom: 1px solid #ccc;
}

#center a {
color: red;
font-weight: bold;
}

You should have this on error:


I also added/changed some CSS changes as well to the admin.css file to get the above picture.  You don't have to add these if you have your own styles.
Code: [Select]
body {
font:.75em "Lucida Grande", Tahoma, Arial, Verdana, sans-serif;
color:#272727;
line-height:1.6em;
background:#fff;
text-align:center;
}

.adminpanel {
text-align: left;
}

label {
font-size:95%;
padding:0 0 1px;
}

input[type=text], input[type=password] {
border-bottom:1px solid #ddd;
border-left:1px solid #c3c3c3;
border-right:1px solid #c3c3c3;
border-top:1px solid #7c7c7c;
color:#333;
font-size:100%;
margin:0;
padding:2px 0;
}

Third
Let's add some jquery validation to check if the fields are empty....
NOTE:
Quote
I wouldn't use this unless more testing was done.  If it breaks, I do apologize.  For now, it works for this purpose of just showcasing a how to.
a. Add the latest jquery in the head of the file
Code: [Select]
<script src="http://code.jquery.com/jquery-latest.js"></script>b. Add the error css to your login.php css
Code: [Select]
.error {
margin-left: 5px;
color: red;
font-weight: bold;
}
c. Before the closing body tag add the following:
Code: [Select]
<script type="text/javascript">
$(document).ready( function() {
$('#post').submit( function() {
// Error note
var note = '<span class="error">This field is empty or invalid</span>';
// No errors yet...
var error = false;
// define our field values
var uname = $('input#uname');
var pass = $('input#pass');
var calc = $('input#calc');
// Throw it all in a array
var fields = [uname, pass, calc];

// If the error is already present, remove it
$('.error').remove();

// Validate
for (var i in fields){
if (fields[i].val() == '') {
$(fields[i]).after(note);  // add the alert next to the noted element
$('.error').fadeTo(2000,0); // the error is now present, fade it out
error = true; // our error state is true
}
}
if (error === true){
return false; // the form is not submitted
}
});
});
</script>
You should have this after you hit the sumbit button with nothing in any or all of the fields:


You can also add your own rules if you prefer, but for now, let's just check if the fields are empty
« Last Edit: December 04, 2009, 11:11:41 AM by equilni »
Logged

centered

  • Guest
Re: [Tutorial] Custom Template: Part 2a
« Reply #2 on: December 04, 2009, 07:13:53 AM »

Just want to share something extra - a few more fixes and something HIGHLY EXPERIMENTAL.

First. I haven't seen alot of AJAX type mods that directly integrate with sNews.  Doing some research, there have been attempts but nothing finalized (or close to working) or published for testing.

I will do an attempt here - THIS IS AN ATTEMPT - DO NOT USE THIS IN A LIVE SETTING!:

First, some fixes for the above:

1. I have changed up the CSS some on the login page.  One fix is if you are logged in and go to the login page (now sure how...).  The notice class is for our ajax'd login note
Code: [Select]
<style type="text/css">
.adminpanel {
width: 450px;
margin: 0 auto;
border: 1px solid #ccc;
}

.adminpanel h2 {
display: block;
color: #fff;
font-weight: normal;
background: #487587;
padding: 10px 15px;
}

/* For login error */
#center a {
color: red;
font-weight: bold;
}

.error {
margin-left: 5px;
color: red;
font-weight: bold;
}

.notice {
background: #e6b561;
width: 420px;
margin: 0 auto;
display: block;
color: #fff;
padding: 10px 15px;
}
</style>
<?php if (!_ADMIN) {
// login error
echo '
<style type="text/css">
#center h3 {
background: red;
width: 450px;
margin: 0 auto;
display: block;
color: #fff;
padding: 10px 0;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
}

#center > p {
width: 450px;
margin: 0 auto;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
}

#center > p + p {
padding-bottom: 5px;
border-bottom: 1px solid #ccc;
}
</style>'
;
} else {
// we are logged in and accessing the login page
echo '
<style type="text/css">
#center h2 {
background: red;
width: 450px;
margin: 0 auto;
display: block;
color: #fff;
padding: 10px 0;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
}

#center > p {
width: 450px;
margin: 0 auto;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
</style>'
;
?>


2. Let's start our ajax'd login. 

Javascript - First thing is first, we need to add our validation check in our field check function form the previous post.  We remove any previous notices then make our array value into something that can be passed via GET POST, then show a response if there is one, if, not log us in. The request needs to be made to snews.php directly, everything else I tried didn't work (I didn;t try too much actually - it is late!!)  I will note, I DIDN'T TEST THIS SO DON'T USE IT UNLESS FOR TESTING - DO NOT GO LIVE WITH THIS CODE!!!:
Code: (Login.php) [Select]
<script type="text/javascript">
$(document).ready( function() {
$('#post').submit( function() {
// Error note
var note = '<span class="error">This field is empty or invalid</span>';
// No errors yet...
var error = false;
// define our field values
var uname = $('input#uname');
var pass = $('input#pass');
var calc = $('input#calc');
// Throw it all in a array
var fields = [uname, pass, calc];

// If the error is already present, remove it
$('.error').remove();

// Validate
for (var i in fields){
if (fields[i].val() == '') {
$(fields[i]).after(note); // Put the error note after the input element
$('.error').fadeTo(2000,0); // fade the error
error = true; // we have an error
}
}

if (error === true){
return false; // stop the form submitting
} else {
// all fields are entered, now let's validate it
loginCheck();
return false;  // if there is an error, we don't want the form submitting
}
});
});

function loginCheck() {
$('.notice').remove();  // if the notice is present, remove it!
var arg = $('#post').serialize();  // get the data ready for POST ie name=value
$.post( // post( url, data, callback, responseType)
'<?php echo _SITE?>administration/',
arg + '&callback=checkLogin', // we need this to check if AJAX or not
function( data ) {
if (data) { // we have an error, note it after the h2 block
$('h2').after('<span class="notice">' + data + '</span>');
} else { // we are logged in, redirect to the admin page
top.location.href = '<?php echo _SITE?>administration/';
}
},
'text'
);
}
</script>

PHP:
The goal here was not to mod up the core too much.... I think I accomplished it -
Find this block
Code: [Select]
<?php

if(isset(
$_POST['Loginform']) && !_ADMIN) {
$user checkUserPass($_POST['uname']);
$pass checkUserPass($_POST['pass']);
unset($_POST['uname'],$_POST['pass']);
if (md5($user) === s('username') && md5($pass) === s('password') && checkMathCaptcha()) {
$_SESSION[_SITE.'Logged_In'] = token();
notification(2,'','administration');
} else {
die( notification(2,l('err_Login'),'login'));
}
}

?>


Replace with:
Code: (UNTESTED CODE - USE FOR LOCAL TESTING ONLY!!) [Select]
<?php

if (isset($_POST['callback']) && !_ADMIN) {
function checkMathSum() {
$result 'false';
    $dig = isset($_SESSION[_SITE.'mathCaptcha-digit']) 
    $_SESSION[_SITE.'mathCaptcha-digit']
    '';
    $calc = isset($_POST['calc']) 
    $_POST['calc']
    '';
    if ($dig == $calc) {
     $result 'true';
    }
    return $result;
}
function checkLogin() {
if ( isset($_POST['callback']) ) {
$usr checkUserPass($_POST['uname']);
$pw checkUserPass($_POST['pass']);
$sum checkMathSum();
$error = array();
$val false;
if ( md5($usr) !== s('username') ) {
$val true;
$error['usr'] = "Username";
}
if ( md5($pw) !== s('password') ) {
$val true;
$error['pass'] = "Password";
}
if ( $sum == 'false' ) {
$val true;
$error['calc'] = "Sum";
}
if ($val === true) {
$err implode(', '$error);
echo $err .' is invaild. Please correct the below';
die(); // kill it, we don't the whole site coming in the response
} else {
$_SESSION[_SITE.'Logged_In'] = token();
die(); // same here, just set the token and let ajax do the redirect
}
}
}
checkLogin();
} else { 
if(isset($_POST['Loginform']) && !_ADMIN) {
$user checkUserPass($_POST['uname']);
$pass checkUserPass($_POST['pass']);
unset($_POST['uname'],$_POST['pass']);
if (md5($user) === s('username') && md5($pass) === s('password') && checkMathCaptcha()) {
$_SESSION[_SITE.'Logged_In'] = token();
notification(2,'','administration');
} else {
die( notification(2,l('err_Login'),'login'));
}
}
}

?>


What's going on here?  First, if Javascript is off, we default back to the original code. We then do a replicated checkMathCaptcha function.  I had some issues so I hacked it some, may be wrong, but for off the wall checking purposes, it works. 

Next we check our information.  This again, is a similar replica to the original function (or lines that could be a function).  To get where the error is we need to check each item and note if in error, then implode it and echo the result.  The echo is the response to the AJAX request.  No response? Then everything is good and set the session and let Javascript log us in.

If you followed me this far... then if you put the wrong items in the form, you will get a notice:
« Last Edit: December 04, 2009, 07:05:22 PM by equilni »
Logged

Keyrocks

  • Doug
  • ULTIMATE member
  • ******
  • Karma: 449
  • Posts: 6019
  • Semantically Challenged
    • snews.ca
Re: [Tutorial] Custom Template: Part 2a
« Reply #3 on: December 04, 2009, 05:19:21 PM »

I take that you are working on a new templating project for SN-1.7 as opposed to just providing a tutorial on templating with SN-1.7 as it currently exists in its default (downloadable) form. If so, I like what you have been doing so far Jason.  :)
« Last Edit: December 05, 2009, 08:51:03 PM by Keyrocks »
Logged
Do it now... later may not come.
-------------------------------------------------------------------------------------------------
sNews 1.6 MESU | sNews 1.6 MEMU

poppoll

  • Full Member
  • ***
  • Karma: 47
  • Posts: 199
    • Poppoll's sNews playground
Re: [Tutorial] Custom Template: Part 2a
« Reply #4 on: December 05, 2009, 02:03:53 AM »

I'm following this tut and so far everything works just fine. Even the ajax-part Equilni

One remark to have it validate add type="text/javascript" to
Code: [Select]
<script src="http://code.jquery.com/jquery-latest.js"></script>and before
Code: [Select]
$(document).ready( function() {add
Code: [Select]
//<![CDATA[and at the end before
Code: [Select]
</script>add
Code: [Select]
//]]>
PP
Logged