Web Design / Development

05 December 2012 Generating PDFs and PNGs on Ubuntu

Ever needed to generate nicely formatted PDFs and/or PNGs on-the-fly? Check out wkhtmltopdf for PDF conversion using Webkit printing to PDF. From there you can conver the PDF to a PNG using pdftoppm.

Here's a very condensed run-down of the procedure on Ubuntu;

TCPDF is another widely used PDF conversion utility but I have found its layout and formatting options to be incredibly tedious. It makes a lot more sense to me to just print to PDF and let the Webkit browser do the heavy lifting .. with a helping hand from xvfb. You can invoke the xvfb command in PHP as follows:

<?php
$url = 'http://www.your-awesome-site.com/somepage.html;
$path = '/home/youraccount/somedir'; //path to where you want to write the file. Make sure the web user (www-data) owns this folder and has write permissions.
$pdfcommand = 'xvfb-run --server-args="-screen 0, 960x768x24" wkhtmltopdf '.escapeshellarg($url).' '.escapeshellarg($path).'some-awesome-file.pdf';
exec($pdfcommand);
//Then to convert the file to PNG:
$pngcommand = 'convert -density 300 '.escapeshellarg($path).'reminder.pdf '.escapeshellarg($path).'some-awesome-file.png';//imagemagick seems faster. 'convert' is the Imagemagick command. 
exec($pngcommand);
?>

   

22 July 2012 SFTP write access when files owned by www-data

Ubuntu users will recognize this common issue;

You have a user directory, e.g. /home/someuser, and you can SSH in and use 'sudo -s' to do super-usery things. Now try to SFTP (Dreamweaver, FileZilla, etc), and you can download, but if the files are 'owned' by www-data you probably can't upload anything except maybe new files. Many web applications (Drupal at least) need the files to be writable by the same user/group that Apache uses /... in the case of Ubuntu this is www-data.

You can't use 'sudo -s' within Dreamweaver or FileZilla.. yes, FileZilla has a custom command option, but it doesn't work with 'sudo -s'. 

You can "chown someuser:someuser * -R" inside the /home/someuser directory and make them writable by your user that way, but then you would need to chown them back to www-data to keep Drupal running well. 

A long-term solution is this:

sudo usermod -a -G www-data someuser

Then ... log that user out of the FTP client and try again. You have to log out for the new permissions to be recognized. 

   

30 December 2011 Google Checkout is now Google Wallet

Google Checkout has ... 'checked out' and change its name to Google Wallet. Google Wallet is essentially Google Checkout, but rebranded and targeted to mobile use as much as for use on regular sites (viewed from a personal computer). We look forward to working with wallet on some upcoming e-commerce projects.

   

15 December 2011 Get ready for Joomla 2.5!

Joomla 2.5 (formerly codenamed 1.8) is coming out any day now, short on the heels of winning 2011's Packt CMS award. 

This is the next major release in the series, which started with 1.0 in the Mambo days, progressed to the now very stable 1.5, and on to 1.6/1.7, which were intended as a stepping stone to 2.5. We have seen conflicting reports of an early January or late December release date. Either way, there will be a period of months in which Joomla users plan their migration to 2.5. If you are not using too many extensions you could probably migrate fairly painlessly (a migration tool is reportedly in the works). If you are using a number of extensions, make sure to check for Joomla 2.5 versions of those, or plan to use some alternative. Many extension developers do not update their extensions for new versions of Joomla until weeks or months after the official release, since that is when new bugs typically come to light and are ironed out. Since Joomla is open-source just like Drupal, WordPress and so many other packages, it is always a work in progress. That's not to say it isn't a great tool for building a robust site!

   

15 December 2011 Search Engine Optimization Successes

We have been focusing on our search engine optimization efforts lately, and updated our SEO page to include some more success stories and examples.

Many of our customers' sites are doing quite well in search results, with some in first place (not just page one) of Google. Our own site is on page one for "award winning web design", and beats out the Web Association Awards site. We won a Web Award in September for our work on the Vineyard Arts Project site, done using the Joomla CMS (content management system).

Have a look at our SEO page and let us know if you could use some help on your site. We offer no-obligation free initial SEO consultations.

   

25 October 2011 Multilingual Moodle

We're working on two Joomla-Moodle multilingual e-learning sites for a non-profit customer of ours, in English and Persian.

Moodle used to have no built-in translation capability as best I can remember (back in 2003 ...) but the text filter plugins in Moodle have changed that. Now you can enter <span> tags with lang attributes and a "multilang" class to enter content as follows:

<span lang="en" class="multilang">Some English text here</span><span lang="fa" class="multilang">Some Persian text here</span>

I purposely didn't type in Persian above, since it may not display properly for everyone.

The idea with the above is that Moodle will then only show the currently selected language. That works, except for the course names, which are still untranslatable. For sites with just two or three languages you can just include both language versions in the course name, e.g. "Management 101 - Persian Translation Here". Not ideal, but gets the job done.  This was our solution in our 2003 run-in with Moodle and is still our solution today. There probably is a way to do this properly but it would involve much programming and redoing of Moodle's title fields.

We'll be using/building a Moodle theme that supports left-to-right as well as right-to-left languages. We are doing the same in Joomla.

We are using Joomdle to connect Moodle with Joomla. This works great for Joomla 1.5 and JoomFish 2. Joomdle has a development version that's compatible with Joomla 1.7, but does not yet offer multilingual support, so we are stuck with Joomla 1.5 and JoomFish for now.

Joomla by default will show both <span> tags, so the template needs a little PHP love to hide the non-relevant language content. Here is what we came up with, which works great for just two languages:

<?php //plethora mod
$registry = JFactory::getConfig();
$jfLang = $registry->getValue("joomfish.language", false); 
if($jfLang->shortcode == 'fa'){ 
?> 
<style type="text/css"> 
span[lang|="en"]{ 
 display:none!important; 
} 
</style> 
<?php 
} 
if($jfLang->shortcode == 'en'){ 
?> 
<style type="text/css"> 
span[lang|="fa"]{ 
 display:none!important; 
} 
</style> 
<?php 
} 
//end ?>

We just inserted this at the end of the <head> portion of our template's index.php file.

   

18 May 2011 Selecting HTML tag(s) by CSS Class using JavaScript

Often web developers like to use:

document.getElementById('yourelement').style.display = 'none';

With jQuery there are easier ways to do this, but I'm talking just about plain JavaScript. 

But suppose you're using some script that's encoded and prevents you from adding unique IDs into <div> tags, for example. This is the case with CBSubs, for Joomla. The files are encoded and for most DIVs there are no IDs, so we're left having to select them based on the CSS classes (in CBSubs you can assign each plan a unique CSS class). 

Here's one way of doing it;

 

/*
	Developed by Robert Nyman, http://www.robertnyman.com
	Code/licensing: http://code.google.com/p/getelementsbyclassname/
*/
var getElementsByClassName = function (className, tag, elm){
	if (document.getElementsByClassName) {
		getElementsByClassName = function (className, tag, elm) {
			elm = elm || document;
			var elements = elm.getElementsByClassName(className),
				nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
				returnElements = [],
				current;
			for(var i=0, il=elements.length; i<il; i+=1){
				current = elements[i];
				if(!nodeName || nodeName.test(current.nodeName)) {
					returnElements.push(current);
				}
			}
			return returnElements;
		};
	}
	else if (document.evaluate) {
		getElementsByClassName = function (className, tag, elm) {
			tag = tag || "*";
			elm = elm || document;
			var classes = className.split(" "),
				classesToCheck = "",
				xhtmlNamespace = "http://www.w3.org/1999/xhtml",
				namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
				returnElements = [],
				elements,
				node;
			for(var j=0, jl=classes.length; j<jl; j+=1){
				classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
			}
			try	{
				elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
			}
			catch (e) {
				elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
			}
			while ((node = elements.iterateNext())) {
				returnElements.push(node);
			}
			return returnElements;
		};
	}
	else {
		getElementsByClassName = function (className, tag, elm) {
			tag = tag || "*";
			elm = elm || document;
			var classes = className.split(" "),
				classesToCheck = [],
				elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
				current,
				returnElements = [],
				match;
			for(var k=0, kl=classes.length; k<kl; k+=1){
				classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
			}
			for(var l=0, ll=elements.length; l<ll; l+=1){
				current = elements[l];
				match = false;
				for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
					match = classesToCheck[m].test(current.className);
					if (!match) {
						break;
					}
				}
				if (match) {
					returnElements.push(current);
				}
			}
			return returnElements;
		};
	}
	return getElementsByClassName(className, tag, elm);
};

This is from http://robertnyman.com/2008/05/27/the-ultimate-getelementsbyclassname-anno-2008/, so kudos to Robert Nyman on that.

Call Examples

To get all elements in the document with a “info-links” class:

getElementsByClassName("info-links");

To get all div elements within the element named “container”, with a “col” class.

getElementsByClassName("col", "div", document.getElementById("container"));

To get all elements within in the document with a “click-me” and a “sure-thang” class.

getElementsByClassName("click-me sure-thang");

That last one is very handy, because if your DIV contains multiple classes, you can use this to select the DIV you want even if it has no ID set.

   

15 May 2011 iPad / iPhone Browser Testing Tool

There's a very handy utility called iBBDemo2 that lets you test websites using an iPhone / iPad emulator. We used it with vineyardartsproject.org. It does not do a great job emulating video. For example, using standard YouTube embed code (an iframe), it renders a black box where the video would actually be, even though the video *will* run correctly on a physical iPhone. Other videos (e.g. locally hosted video) would be much harder to troubleshoot reliably using this tool.

It also seems that targeting for iPhone using CSS doesn't really work with iBBDemo2. For example:

@media only screen and (max-device-width: 480px) {
#somedivtag{
width:300px;
}
}

   

22 March 2011 Internet Explorer 9 and Firefox 4, Finally!

It's been a long time coming, but Internet Explorer 9 and Firefox 4 are finally out. There is no doubt that these both represent major improvements to each respective browser.

For IE9, it means much better and more reliable web page rendering, including support for CSS3 effects like rounded corners.

For Firefox 4, it means tabbed browsing and hardware acceleration á la Chrome (for faster browsing). Firefox was starting to be eclipsed by Google Chrome on those fronts, and now has a shot at maintaining its lead. One reason for that is that Firefox has loads more addons that are also more mature than the ones Chrome offers. In addition - and this is admittedly a minor thing - Firefox has Print Preview and Chrome STILL doesn't. Let's give Google the benefit of the doubt and assume it's because they want to save the environment ... but if that were the case they should remove the Print function altogether!

You can install Firefox 4 alongside a previous version of Firefox by installing it into a separate Program Files folder (for those of you using Windows). 

The Web Developer Toolbar extension for Firefox is already available for Firefox 4.

   

28 February 2011 Concrete5 Theme Installation Issues

Our original review of Concrete5 has gotten quite a response from the Concrete5 community, and I felt it was time for a closer look.

Some quick observations:

There are some really nice themes in the Concrete5 Marketplace

Installing themes could be made clearer. Here are some problems I had while trying to install a theme downloaded from the marketplace:

  • Currently, you supposedly (according to many posts on the Concrete5 forums) have to unzip a theme's zip file and FTP the resulting folder to the /themes directory. Trouble is, if you download a theme from the marketplace using Add to Cart, many of them are actually "packages" containing some other stuff as well as a theme - in a sub-folder. If you follow the normal instructions, you would end up FTPing it to /themes rather than /packages, and then when you go to the theme admin area in Concrete5, you won't be able to install your new themes.
  • I was trying to install a theme called Innovation, which I downloaded from the Marketplace. Unzipped, it creates a folder called 'cannonf700_innovation' which itself contains a folder called /themes/innovation. The contents of /cannonf700_innovation/themes/innovation should ACTUALLY go in /themes/innovation, which begs the question: where should the controller.php file in /root/themes/cannonf700_innovation/ go? The root directory? If that's the case, each time you install a new theme, controller.php gets overwritten.
  • Zip files should be standardized so when unzipped, no additional work is needed beyond simply FTPing to /themes; perhaps with non-marketplace themes this works fine. Ideally, you'd be able to install via a web interface with no FTP at all.

As it turns out, the themes you download from the Marketplace are in fact zipped up as packages, so you must upload them to the /root/packages/ directory, then login to your site, go to your dashboard and go to Add Functionality. Then you can install your newly available themes. It's easy, but you have to know it. I had looked in various places on the Concrete5 including in the forums before I stumbled upon this explanation. I really like the idea of packages, but wonder why there is a separate way of installing themes at Pages and Themes. For the Concrete5 neophyte, this seems contradictory. There should be just one place to do that.

Nice Features:

  • When creating a new page, the page alias is created on the spot. In Joomla, you have to click save the article first. 
  • If you don't want to enter text in your new page just yet, Concrete5 won't force you, whereas Joomla does.

Concrete5 is very user-friendly for editors and site owners, and with a bit clearer documentation in the How-to's area of the Concrete5 site, it will see even faster adoption by those of us using Joomla and Drupal. I really wish Joomla had the kind of user-friendliness Concrete5 has. There are in fact some Joomla "alpha" projects that seek to do much of what Concrete5 already does, and does very well. I don't believe Drupal has any aspirations to emulate Concrete5's editing interface, either, though they should.

   
request-a-quote

© 2003-2012 Plethora Design, LLC · Contact Us · Make a Payment · Search

877-51_Skype5-6682 / 703-291-8022. Northern Virginia web design company convenient to Washington, D.C. and Maryland.