Wednesday, December 30

The File You're Looking for is...

/templates/system/html/modules.php

This is where you can change the module titles from h3 to h2. Also from tables to not tables. I tried to copy this like normal to the template/html folder, but I get some error that makes me angry, so just forget about that.

I changed all the tables to divs too cause tables make me sad. I think pretty much the one that my site uses is like this:

function modChrome_xhtml($module, &$params, &$attribs)
{
if (!empty ($module->content)) : ?>
<div class="moduletable->get('moduleclass_sfx'); ?>">
<?php if ($module->showtitle != 0) : ?>
<h2><?php echo $module->title; ?></h2>
<?php endif; ?>
<?php echo $module->content; ?>
</div>
}
<?php endif;
}

Wednesday, September 9

Literal... Interpreted... Quotes Matter

Something I never before (but probably should have) read that took hours to figure out:

If the string is enclosed in double-quotes ("), PHP will interpret more escape sequences for special characters. -via php.net
This really matters!!

For example. When you are sending mail, new lines are usually \r\n. If you have your message body in single quotes (') the \r\n will show up in the message!

Even more importantly. When using Pear mime, you have to define eol. Just remember $crlf = '\r\n' WILL NOT WORK!!! it has to be $crlf = "\r\n" If I had read to the bottom of the user comments on the pear page, it would have saved me a lot of time.

And yes, this post is actually about doing Mail_Mime with Pear :D

Resources:
PEAR Mail_Mime
PHP Maniac Examples

Tuesday, September 8

getdate() Without Time

I am rewriting the front end of a site, but can't change the back end or functionality. And so I must learn how to use an MSSql db via php. My first impression... they are not friends. Okay, moving on.

Problem:
Table has a datetime field, but the backend freaks out because of some 10yr old stored procedure. We traced it down to that the datetime can't contain the time.

Solution:
Now, I could have just used php date, but the day I found out that databases can insert their own date, I swore I'd never use it again for a current timestamp. So instead, my insert statement has this completely inelegent line:

convert(varchar(8), getdate(), 112)
That inserts the date with no time. Or more specifically, the time is 12:00AM. The actual contents is something like Sep 08 2009 12:00AM.

Wednesday, September 2

Buttons Change on Hover

First time I've done this (I think). Short sweet code.

<a href="link"><img src="images/button.jpg"
onmouseover="this.src='images/buttonhover.jpg';"
onmouseout="this.src='images/button.jpg';" /></a>
It would not surprise me if there were instances where this fails. But it's also pretty nice because you don't have to worry about a no js version; it just doesn't do anything without js.

If you're using large images, you might want to preload them.

Tuesday, July 14

Remove Extension PHP

I'm using a Joomla module called JX List Files. Simple, nice little module to list files in a directory. My only complaint was that it left the file extension in the name, so I added this little function I found.

function remext($strName){
$ext = strchr($strName, '.');
if($ext !== false){
$strName = substr($strName, 0, -strlen($ext));
}
return $strName;
}

Friday, July 10

Show/Hide with Select

This isn't complicated, but I forgot how I did it before, so I'm going to write it down this time.

The Case:
I have a form with a select box, if you select Yes, you get one set of options, and No gets another. The two pieces are in divs, both with style=display:none. The dropdown is a required field and it starts as a blank box.

The JavaScript:

function showHide(show, hide){
document.getElementById(show).style.display='block';
document.getElementById(hide).style.display='none';
}
The HTML:
<select id="yesno">
<option> </option>
<option value="yes" onclick="showHide('pickYes', 'pickNo')">Yes</option>
<option value="no" onclick="showHide('pickNo', 'pickYes')">No</option>
</select>
<div id="pickYes" style="display:none">
I display if Yes is selected
</div>
<div id="pickNo" style="display:none">
I display if No is selected
</div>


:UPDATE:
Oh man, I totally lied. That only works in Firefox. onclick isn't an option javascript event. Oops. Here's the real solution

Javascript:
function showHide(){
var sel = document.getElementById('yesno').value;
if (sel == 'yes'){
document.getElementById('pickYes').style.display='block';
document.getElementById('pickNo').style.display='none';
}
else if (sel == 'no'){
document.getElementById('pickNo').style.display='block';
document.getElementById('pickYes').style.display='none';
}else{
document.getElementById('pickYes').style.display='none';
document.getElementById('pickNo').style.display='none';
}
}
HTML:
<select id="yesno" onchange="showHide()">
<option> </option>
<option value="yes" onclick="showHide('pickYes', 'pickNo')">Yes</option>
<option value="no" onclick="showHide('pickNo', 'pickYes')">No</option>
</select>

So yeah... this isn't as pretty, but it works in other browsers.

ANOTHER UPDATE (from months in the future):
This whole ugliness can be completely avoided by just using JQuery :)

Wednesday, July 1

Random CSS Background

The Case:
We have a header background image on the top of the site. The customer wants it to rotate randomly between any number of images.

The Javascript:

var images=new Array();
images[0] = "header1.jpg";
images[1] = "header2.jpg";
images[2] = "header3.jpg";
images[3] = "header4.jpg";
images[4] = "header5.jpg";
var path = "http://example.com/images/";

function changeHeader(){
var rn=Math.floor(Math.random()*images.length);
document.getElementById('header').style.background = "url('"+path+images[rn]+"')";
}
And the HTML:
<script type="text/javascript">
window.onload=function(){
changeHeader();
setInterval("changeHeader()",5000);
}</script>
Don't forget to set a default image for those who don't use javascript.

Tuesday, June 9

Addendum about Sum()

It seems like it's totally okay if you're selecting just the sum to leave out the group by part. I needed to pull data and put it in rows, then show the total on the bottom. I don't know if I necessarily did this the _right_ way, but it worked.

My two queries:

$query1 = "SELECT * FROM table";
$query2 = "SELECT sum(amt) FROM table";
It was in a table so I used a while loop to add rows, then after the loop, added
<tr>
<td>TOTAL</td>
<td>$<?=number_format($row1['sum(pay_amt)'],2)?></td>
</tr>

of course, don't forget to define them. i defined row1 before the while loop.

Thursday, June 4

Notes to Self

Populating a table from csv:

  LOAD DATA LOCAL INFILE '/data.csv'
->INTO TABLE test_table
->FIELDS TERMINATED BY ','
->LINES TERMINATED BY '\r\n'
->(field1, filed2, field3);
Fields for money, use DECIMAL(N,2). N is however long the number will be and 2 is for the cents.

Then use PHP's number_format($number,2) to make it look pretty/readable.

Quick and dirty sum (via tizag):
<?php
$query = "SELECT type, SUM(price) FROM products GROUP BY type";

$result = mysql_query($query) or die(mysql_error());

// Print out result
while($row = mysql_fetch_array($result)){
echo "Total ". $row['type']. " = $". $row['SUM(price)'];
echo "<br />";
}
?>
Don't use & in your $_GET var. Do a str_replace to something else (no, not & amp; either), then change it back before the query

Gigundo tables will time out before loading the page

We are 2.6 parsecs from Sirius

Tuesday, June 2

Hacking QContacts

For the "Contact us" portion of our sites, we use QContacts instead of the plain Joomla contact module. The main reason is because it has the ability to add more fields to the email form. However, I decided a couple things needed to be changed.

  1. It uses a captcha type field using the php secureimage stuff. We need to use something that's ADA Compliant, so I wanted to use ReCaptcha.
  2. We have a big, complex site and every page has a "Contact Webmaster" link. Although it specifically says in bold print right at the top of the form to include the link of the page you're talking about, guess how many people do. Yes, about 1%. So, I wanted to add a referring link to the email.
Luckily, the code for QContacts is pretty straightforward. There were only two files I needed to change, and one I needed to add (for the ReCaptcha).

ReCaptcha Replacement

Using the recaptcha site as a reference, first we edit the file: /components/com_qcontacts/views/contact/tmpl/default_form.php. This is the page containing the actual form (and the hardest to find the first time). I put the recaptchalib.php file into the same place the original securimage.php file was (com_qcontacts/includes/secureimage). Down near the bottom, there will be the captcha code. it starts
if ($this->params->get('captcha')) {
which the following would replace the original code:
require_once JPATH_COMPONENT . DS . 'includes' . DS . 'securimage' . DS . 'recaptchalib.php';
$publickey = "..."; // you got this from the signup page
echo recaptcha_get_html($publickey);
}
Simple enough. Now, we need to validate the user input. This is in the file com_qcontacts/models/contact.php.

Near the top (around line 40 or so) will start the function __construct(). We need to add the following line:
$this->_data->captcha = JRequest::getString('recaptcha_response_field', '', 'post');
This gets the recaptcha_response_field as a post variable from the previous page. This should replace the existing captcha line. But wait, there's more!

Farther down in the code in this same file is the function __validateInputs and in here is where the captcha is validated. We need to replace the code after
if($sc) {
With
require_once JPATH_COMPONENT . DS . 'includes' . DS . 'securimage' . DS . 'recaptchalib.php';
$privatekey = "...";
$resp = recaptcha_check_answer ($privatekey,
$_SERVER["REMOTE_ADDR"],
$_POST["recaptcha_challenge_field"],
$captcha);

if (!$resp->is_valid) {
$this->setError( JText::_('Security code was incorrect, please try again', true));
return false;
}
So, fairly simple. In the Joomla backend, when you enable captcha, it will be replaced with ReCaptcha. None of the other parameters have any effect anymore. Now for #2.

Adding Referrer

This one is much simpler. We'll start with the same file as the last one (com_qcontacts/views/contact/tmpl/default_form.php).

At the end of the form, add:
<input type="hidden" name="refer" value="<?=$_SERVER['HTTP_REFERER']?>" />
Now on the other page (com_qcontacts/models/contact.php), add a line to function __construct again:
$this->_data->refer = JRequest::getString('refer', '', 'post');
Then find a line in the email creation section. I stuck the code after the show_ip param so it'd be at the end of the email.
$body .= "\r\n\r\n" . JText::_('Referring Page').': '.$this->_data->refer;
And that's it!

Wednesday, May 27

JCalPro Multiple Recent Events

This isn't even worth writing about, but it took me forever to figure out, so it's just a reminder.

Using JCalPro and the latest events module is pretty much easy. Just have to keep track of your category IDs and calendar IDs. I wanted mine pretty short, so I turned off everything but Start Time, Category Name and Event Date. I turned on Show Month Separators cause I think it looks nice. I used a <br /> to separate events.

One thing cool I found out was at the bottom, the box for "Specific Itemid for displaying the module" is what controls where the link goes that says "View Full Calendar." Put the calendar ID in there if it's not going to the right one.

So my main problem was, my events weren't showing up! It would just say "There are no upcoming events currently scheduled." I read support forums and almost all said it was a problem with versions. Well, that wasn't it; I'm using Joomla 1.5.10, PHP 5 and JCalPro 2.1.5. I put in some more test dates, and guess what, they showed up! After thinking about it a while, I noticed it was only the recurring events that weren't showing up. Not even the parent events. Hmmm. I looked through the module settings again and saw my problem. I don't know how I passed over it so many times before:

Friday, May 22

Speed Site Design

Today was a practice in speed design. We found out this morning a group needs a site by Wednesday. We have monday off. It needs to go through QA first so today's the day! 


It's almost done. I did mostly content and a coworker did design. We have 3 pages of content, one page of videos (ustream), photo gallery (Simple Image Gallery), a blog (IDoBlog) and a forum (Kunena).

I had some issues with Kunena, but finally figured them out. At first, I was using an old version with Legacy mode turned on. It sucked, but the beta version wouldn't allow me to post announcements. I upgraded anyway cause I was having some user issues. Registration link gave me a 403 error! It took me forever to find it, but finally I realized since I'm just using Joomla's user management, I probably needed to enable registration in the Global Configurations. D'oh!

Since we had a blog and a forum, I learned a bit about Joomla's ACLs. It seems special will give access only to author level or above. Perfect. 

Thursday, May 21

Get Your Head out of Your...

Department.

I just had a meeting with a HUGE group of people regarding their new website. I've put a lot of work into it, it's a pretty big department and their old site was so disorganized and convoluted. I've tried to find information myself on it in the past, and it was no easy task.

So at this meeting, these people could not get past the fact that the website wasn't designed the way their departments are. Every time I would show them a section, I was met with shaking heads and someone piping up "That's not how the department is organized." By the third or fourth time, I was ready to respond "You know what, lady, the user doesn't give two shits about your department! They just want their information." Luckily, I have an awesome boss who explained it to them in better terms.

Of the way too many people at that meeting, there was like on lady who gets it.

As a user of the internet, it was really hard for me. Have they never seen websites before? Have they never been frustrated because someone organized a website poorly. Apparently not.

On a related note, I've been following caseorganic on Twitter, who is/was at the webvisions conference tweeting about similar topics. It was pretty cool.

Thursday, May 14

Template Overriding

I wanted to do a category list layout for these couple pages, but I didn't want them to be numbered. It looked really bad, especially for a list of only 8 or so articles. I found some code to remove the numbers, but I really wanted a bulleted lists. That guy's code is a little different than the original default_items.php file, but not too much. I managed to find the foreach section and replaced the table pieces with li s. I'm pretty sure it'll only work correctly in the instance where your category only shows titles, but blah blah blah. That's not really the point of the story.

The real point is that in that forum article, I learned about template overrides. I've done a lot of hacking apart code since I started using Joomla. Now I've learend I can do it on a per template basis without touching the core Joomla code. Yay! 

Wednesday, May 13

Revelation (aka: duh *facepalm*)

Yesterday, I was complaining about the lack of a good php module/plugin for Joomla. Today I realized I'm a moron.

To use php code, what I have been doing is making it in an editor with syntax highlighting, then copy/pasting it into the Custom Code module. It worked, but it was a pain.

It may have taken a while, but I finally figured out: I can just use the Custom Code module to INCLUDE THE PHP FILE!!! I know, brilliant right.

Ok, I'm gonna go hide now *ducks in shame*

Tuesday, May 12

Long Hiatus

So yeah. I actually pretty much forgot about this blog. Then one day, I had to look up something and remembered I'd done it before and "Oh yeah! I made a blog!" Anywho.. I'm back now. I have a new job (after the unceremonious departure from my old job. You know, one of those "oh hey, it's your last day today" "What?! it's 3:30! You couldn't have told me this morning... or yesterday... or TWO WEEKS AGO.") No no, I'm not bitter. Water under the bridge. 


So yes. New job. It's fun. Not as much playing as my old job, but still enjoyable. I'm not all alone! And I'm like, a webmaster. That's it. No server administration. No support. It's like a real job :o oh yeah, AND I have a cubicle. And old hardware/os. Still trying to get a replacement keyboard. This one is gross and the ctrl and shift keys often stick. Ewwww.

We use Joomla. I like and hate it. Sometimes it's hard not having complete freedom over your pages. But it's cool. I can usually figure out ways around it. It's nice having something we can train the secretaries to use. 

I'm working on a big project right now. One thing cool about Joomla is that it (obviously) already has a database, so it's no work to add new tables for, you know, table stuff. I saved myself having to make 200 pages that way. Good thing I got here, or there would have been 200 pages on this site. 

One thing that would be nice would be to either a) be able to put php code into an article page,b) have some freaking syntax highlighting in the Custom Code module or c) be able to include a php file into an article page. I'm ok with any of those options. There are some plugins or modules to do stuff like it, but they either do it poorly or insecurely. 

Ok. Back to work.