Wednesday, 13 August 2008

PHP Copyright Year Trick

I found this snippet on a forum recently, it's so simple and obvious I wish I'd thought of it!

A lot of web pages have a copyright notice in the footer of the page with the year included. For server side scripts, instead of just writing the year in, you can replace it with code to dynamically write the year, so it's always up to date.

For PHP:

&copy;<?php print date("Y"); ?> My Company Ltd

You can use the same idea for other server side code, such as Java or Perl.

How Simple?

Tuesday, 12 August 2008

Generating Java Map List and Displaying with JSP

This example is to demonstrate recent investigations into outputting xml data to the page using a Java HTTPServlet and JSP with a Map List.

We want to output the id, description and size for each widget from the xml, to a form in html.
The id is stored in its own element but the description and size are name value pair properties.

<?xml version="1.0" encoding="UTF-8"?>
<widgetNode>
<widget>
<id>101</id>
<properties>
<property>
<name>description</name>
<value>Thingy Bolt</value>
</property>
<property>
<name>size</name>
<value>27</value>
</property>
</widget>
<widget>
<id>102</id>
<properties>
<property>
<name>description</name>
<value>Wotsit Nut</value>
</property>
<property>
<name>size</name>
<value>11</value>
</property>
</widget>
</widgetNode>


The Java extract here loops through each widget node, adding the values we want to Map, then adds that Map to a List.
The Map List is then added, as an attribute, to the request.

(Although unintended, this is also an example for XPath, which took a little investigation too)

...
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
...

private void processWidgetXml(HttpServletRequest request, String xml) {
List<Map<String,String>> widgets = new ArrayList<Map<String,String>>();
String expression = "/widgets/widget";
try {
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList)xPath.evaluate(expression, new InputSource(new StringReader(xml)),XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
Map<String,String> widgetMap = new HashMap<String,String>();
widgetMap.put("id", (String)xPath.evaluate("id", node));
widgetMap.put("description", (String)xPath.evaluate("properties/property[name='description']/value", node));
widgetMap.put("size", (String)xPath.evaluate("properties/property[name='size']/value", node));
widgets.add(widgetMap);
}
request.setAttribute("widgets", widgets);
} catch (XPathExpressionException e) {
System.err.println("XPath expression invalid: "+e.getMessage());
e.printStackTrace();
}
}

Coming to the JSP, the following extract highlights the syntax for the Map List. It loops through all of the widgets, creating a form, with unique name, for each widget.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
...
<% int lc = 0; %>
<c:forEach var="widget" items="${widgets}">
<form name="myWidget<%= lc %>" action="/myActionPage" method="post">
<input type="hidden" name="widgetId" value="${widget['id']}"/>
<input type="submit" value="Select"/>
${widget['description']} : ${widget['size']}
</form>
<% lc++; %>
</c:forEach>


Done... (finally)

Monday, 11 August 2008

Javascript to Pre Load Images

Normal behaviour for images on web pages is to load them when they are required. This can sometimes create an undesirable delay whilst the user navigates around the page. Not good, and annoying for the user. To get around this problem you can load the images you know you'll use as the page loads, giving the user a smoother experience.

The following Javascript loads images into an array. This forces the images to be downloaded, so that when the page requires them the browser will automatically get them from the cache. Add this code the head section.

<script type="text/javascript">

function preloadImages()
{
var images=[];
for(i=0; i<arguments.length; i++)
{
images[images.length]=new Image();
images[images.length-1].src=arguments[i];
}
}

preloadImages('your.jpg','list.jpg','of.jpg','images.jpg','goes.jpg','here.jpg');

</script>

Obviously (I hope), change the list of images passed in the call to the preloadImages function, to your own list of images.

Image Preload... Done.

Example: Preloaded images used for a slideshow

Friday, 8 August 2008

Javascript Simple Image Slideshow

This is a simple web page using HTML and Javascript. It displays an image with Next and Previous buttons.

When one of the buttons is pressed, the image is switched with the next or previous image.

As this is a simple example, the filenames for the images are expected to be the same but with incremental numbering. EG. image0.jpg, image1.jpg ... imageN.jpg.

<html>

<head>

<script type="text/javascript">
var img = 0; // Current image

function switchImage(i,d)
{
const imgs = 5; // Total number of images
img+=d;
if(img>=imgs){img=0;}
else if(img<0){img=imgs-1}
i.src = "image"+img+".jpg";
}
</script>

</head>

<body>

<h1>Switch Image Source</h1>

<input type="button" value="Prev" onClick="switchImage(document.getElementById('myImg'),-1);"/>
<input type="button" value="Next" onClick="switchImage(document.getElementById('myImg'),1);"/>
<br/><br/>
<img id="myImg" src="image0.jpg"/>

</body>

</html>

Change the imgs constant value to the total number of images you have in you slideshow.

Done.

See also: Progressed version preloading images and using any filename

Thursday, 7 August 2008

OOBasic Export Macro Part 2: CSV

Expanding on the last blog entry, See here, using a macro to create tab delimited text files, we can modify the code easily to create csv files instead.

Replace the following two lines in the code

FileProperties(2).Value = "9,0,ANSI,1"
sExt = ".txt"

With these

FileProperties(2).Value = "44,34,ANSI"
sExt = ".csv"

This then creates a comma seperated file with .csv extention for each tab within the spreadsheet.

CSV macro... Done

Wednesday, 6 August 2008

OpenOffice Basic Macro to Create Tab Delimited Text Files

This piece of code has proven most useful today...

It's a OpenOffice Basic macro that creates a tab delimited text file for each sheet in the document. Each sheet tab name is used to name the file.

Sub CreateText

  '----------------------------------------------------------------------
  ' Save document

  Dim document As Object
  Dim dispatcher As Object
  document = ThisComponent.CurrentController.Frame
  dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
  dispatcher.executeDispatch(document, ".uno:Save", "", 0, Array())

  '----------------------------------------------------------------------
  ' Export to text files

  Dim oDoc As Object ' The current Document
  Dim oSheets As Object ' A collection of all sheets
  Dim oSheet As Object ' One specific Sheet
  Dim sNewFilename As String ' New Filename
  Dim sExt As String ' The new extension to be applied
  Dim sURL As String ' Existing URL of file
  Dim sCurrDir As String ' Current Directory
  Dim oSaveSheet As Object
  Dim FileProperties(2) As New com.sun.star.beans.PropertyValue

  oDoc = thisComponent
  oSaveSheet = oDoc.CurrentController.getActiveSheet()
  oSheets = oDoc.Sheets()
  sURL = ConvertFromURL(oDoc.getLocation())
  sCurrDir = Mid(sURL,1,Len(sURL)-Len(Dir(sURL)))

  FileProperties(0).Name = "Overwrite"
  FileProperties(0).Value = True
  FileProperties(1).Name = "FilterName"
  FileProperties(1).Value = "Text - txt - csv (StarCalc)"
  FileProperties(2).Name = "FilterOptions"
  FileProperties(2).Value = "9,0,ANSI,1"
  sExt = ".txt"

  For i = 0 to (oSheets.getCount()-1)
    oSheet = oSheets.getByIndex(i)
    sNewFilename = oSheet.getName() & sExt
    oDoc.CurrentController.setActiveSheet(oSheet)
    oDoc.storeToURL(ConvertToURL(sCurrDir & sNewFilename),FileProperties())
  Next i

  oDoc.CurrentController.setActiveSheet(oSaveSheet) ' restores the original view

  MsgBox("Text Files Created")

End Sub


OOBasic Text File Export...Done

Friday, 1 August 2008

VBScript to Delete Files Older Than 14 Days

The VBScript can be run from the Windows command line or added to a windows script. It accepts a start directory as a parameter and searches through the directory and subdirectories deleting files older than 14 days.

(You can change the 14 in the code to any number of days)

Save this code in a file called DeleteOldFiles.vbs

Sub processFolder(ByRef folder, ByVal path)
  For Each file In folder.Files
    If DateDiff("d",file.datelastmodified,Date) > 14 Then
      Wscript.Echo "Deleting: "&path&"/"&file.Name
      file.Delete
    End If
  Next
  For Each subfolder In folder.SubFolders
    processFolder subfolder, path&"/"&folder.Name
  Next
End Sub
processFolder CreateObject("Scripting.FileSystemObject").GetFolder(WScript.Arguments(0)), WScript.Arguments(0)

To run the script from the command line issue the following statement, changing c:\temp to your starting directory:

cscript.exe DeleteOldFiles.vbs c:\temp


Or for the current directory

cscript.exe DeleteOldFiles.vbs .


Files Deleted Successfully.