Styles

Sunday, April 25, 2010

Telerik Smarts

RAD Alerts

To convert the standard Javascript Alerts to the fancy RAD Alerts add this script within the <Head> tag.

<script type="text/javascript">
  window.alert = function(string)
  {
    radalert(string.replace(/-/g, "<br />•"), "auto", null, "Alert");
  }
</script>

Add the RadWindowManager in the page and configure it with the appropriate Telerik Skin.

<telerik:RadWindowManager runat="server" 
    ID="alertWindowManager" 
    Skin="Default" 
    AutoSize="true" 
    Animation="None" />

Themes and Demos

There are also plenty of pretty cool demos of all the controls that telerik have created:

http://demos.telerik.com/aspnet-ajax/window/examples/windowmanager/defaultcs.aspx

Thursday, April 15, 2010

HTML rules for Email clients

The following email clients are generally what need to be supported today:
  • Outlook 2003
  • Outlook 2007
  • Outlook 2010
  • Hotmail webmail
  • Yahoo webmail
  • Gmail webmail
  • MacMail
  • Lotus Notes
  • Eudora 
Since most email clients still use HTML 1.1 in one way or another, there are severe limitations to the look and feel of your email.

Here is a list of general rules you can remember when trying to create an email template:
  • Remove <style>.</style>
    • NOTE: This is not always the case and <style> is necessary in some specific cases
  • Remove <script>.<script>
  • Remove <noscript>.</noscript>
  • Remove <link>.</link>
  • Change anything with <.*? /> to <.*? > (e.g. <img /> should be <img>)
  • Change <td></td> to <td>&nbsp;</td>
    • NOTE: Please test as outlook might create a bigger gap in place of &nbsp;
  • There should not be spacing in between the following tags: <img.*? ></td> 
  • <img.*? > should have style="display:block"
    • NOTE: Please test as its not always the case
  • <img src="" needs to be an absolute path
  • <img src="" cannot contain the word "banner"(for spam protection!)
    • NOTE: ISP filters and other technology deployed across the internet have complicated rule sets designed to block banners, advertising and all other manner of communication deemed to be unsolicited commercial email. By naming the folder that contains your image "banner" you are increasing the likelihood that your image, if not your entire email will be outright blocked because you've declared it as a banner in so far as a spam filter is concerned.
  • Replace style="width:0" with width="0"
  • Use embedded style="font-family:." or <font face="."></font>
  • Use embedded style="color:." or <font color=".">.</font>
  • Use embedded style="font-size:." instead of <font size=".">.</font>
  • Replace style="font-style:italic" with <i>.</i>
  • Replace style="font-weight:bold" with <strong>.</strong>
  • Do not use style="padding:[0]"
  • Do not use style="margin:[0]"
  • Replace style="float:[0]" with <table align="[0]"><tr><td>[content here]</td></tr></table>
  • Replace <style> and <link> and replace all class attributes (class="") with corresponding simple class styles (.className)
  • Replace <style> and <link> and add all id attributes with corresponding simple id styles (#id)
  • Replace <style> and <link> and add all element attributes with corresponding simple element styles (elementTag) 
 Most of these can be created with an application that stream reads the HTML template and replaces them using Regular Expressions.

Thursday, April 8, 2010

Using Selenium

Client Setup


Initially, the developer would need to set up a project within the solution of the application they are working on called [ProjectName].UnitTests.

This project will need the following binary references: - nunit.framework.dll - ThoughtWorks.Selenium.Core.dll



Selenium Client Code


Once this is complete, the developer may create their own test cases from scratch or use the FireFox Plugin "Selenium IDE" to record interactions against a specific URL. (The IDE can be grabbed from the following location: http://selenium-ide.seleniumhq.org/)

The selenium code uses the Nunit framework to create unit tests that can be run either with the nunit standalone application, or via a function call in the application. The code will look similar to the following:

using NUnit.Framework;
using Selenium;
namespace MCN0002.UnitTests
{
    [TextFixture]
    public class PromoBuilder
    {
        private ISelenium selenium;
        private string location;
        [SetUp]
        public void SetupTest()
        {
            selenium = new DefaultSelenium("localhost", 5551,
           "*iexplore", Resources.Url);
            selenium.SetSpeed(Resources.Speed);
            selenium.Start();
        }
        [TearDown]
        public void Teardown()
        {
            try
            {
                Assert.IsFalse(location.Equals(selenium.GetLocation()),
               "Has not redirected to the success page.");
            }
            finally
            {
                selenium.Stop();
            }
        }
        [Test]
        public void DateValidation()
        {
            selenium.Click(
           "//a[@id='ctl00_ContentPlaceHolder1_ctlPromoEditor_btnEdit']/b");
            selenium.WaitForPageToLoad(Resources.PageLoadWaitTimeout);
            selenium.Select(
           "ctl00_ContentPlaceHolder1_ctlPromoEditor_ddlPromoStart_Day", "label=31");
            selenium.Select(
           "ctl00_ContentPlaceHolder1_ctlPromoEditor_ddlPromoStart_Month", "label=11");
            selenium.Click(
           "//a[@id='ctl00_ContentPlaceHolder1_ctlPromoEditor_btnSave']/b");
            location = selenium.GetLocation();
        }
    }
}

Server Setup


In order to run the Selenium Client successfully, the developer will need the server application running on a remote machine or their own local machine. The server application (Selenium Remote Control) is built in java and can be found at the following URL: http://selenium-rc.seleniumhq.org/

Once this is downloaded, and assuming the java runtime is installed on the server, the following batch file can be run to start the server:

java -jar "C:\[Selenium Server Location]\selenium-server.jar" 
-interactive -port 5551

Where the port number is decided by the developer. (By default the port number is 4444, however the Firefox Selenium IDE plugin has already taken that)

Recommendations


Page Load timing


Any page load actions (i.e. Click of a button that postbacks, link etc.) must precede the following line of code:

selenium.WaitForPageToLoad("30000");

Where the parameter is the number of miliseconds the process will timeout on while waiting for the page to load.

The reason for this is that the timing of any page load may be affected by many factors which include:
  • the amount of memory on the developer's machine which may take time to open the page using selenium
  • the website being tested is on a slow server
The above line of code will guarantee that if the next action is to check a checkbox, that checkbox will be found on the loaded page. This means that the developer could set the interval speed to as fast as they require.

Checking Error Messages


A common use of testing correct page behavior (especially for forms submission) requires testing whether appropriate error messages get displayed correctly or not. The problem is, however, that a validator on a form is displayed by javascript, which ultimately means that the error message is always on the web page even if it is visible or not. (i.e. the error message will not be an empty string if the validator is hidden).

Moreover, selenium doesnt read attributes for styling (i.e. display:none or visibility:visible).

The solution to this is to check the following:

selenium.GetElementHeight("countryValidator");

If this returns 0 then the error is not displayed, otherwise it is displayed.

Get Attribute


In order to get an attribute of an exact control, the HTML must be interrogated. This interogation is similar to XPaths for XML. The below code gets the "src" attribute of an "img" element that has an attribute "id" of value "imgCheckTraction".
selenium.GetAttribute("//img[@id='imgCheckTraction']@src");

Test Data


Developers should always have a list of testable data that will always be the same no matter how many times you run the unit tests. Any time there is an alteration on the data for validation testing, the data should always be reverted to its original state. This will allow developer to create a new unit test assuming the test data is the original data that was initialized.

Sunday, March 21, 2010

Opacity in IE, Firefox and Chrome

pngs and other images require separate styling attributes for IE and Firefox. Below are the two attributes that will allow transparency to be supported for both browsers:

.menu .hover .menuitems
{
 filter: progid:dximagetransform.microsoft.alpha(opacity=80);
 opacity: 0.8;
}

Note: the "filter" attribute is used for IE, and the "opacity" attribute is used for FF.

It must also be noted that this will actually make the entire image transparent so all text found within it will most likely not have the desired effect.

This is different from images that have transparency in it.

Thursday, March 4, 2010

Apache Configuration

XAMPP Server Configuration

When installing xampp, generally you wouldn't want to keep all your PHP applications nested within the installed folders incase you choose to uninstall it for a newer version. The following file will need to be configured to place php applications in your own project folder (e.g. D:\Projects\Php\)

C:\Program Files\xampp\apache\conf\httpd.con

DocumentRoot "D:/Projects/Php"
<Directory "D:/Projects/Php">
     Options Indexes FollowSymLinks Includes ExecCGI
     AllowOverride All
     Order allow,deny
     Allow from all
 </Directory>

DocumentRoot for phpMyAdmin

When changing the DocumentRoot as shown above, this will change the location of the mySQL admin console. Therefore a shortcut for "phpMyAdmin" must be created on D:/Projects/Php from C:\Program Files\xampp\phpMyAdmin. This will allow for access to mySQL via http://localhost/phpMyAdmin

Default Documents

If you don't want to specify the .php extension in the URL by having a default php load within any folder on your site, you can add any specific php file names to the following file:

C:\Program Files\xampp\apache\conf\httpd.conf

DirectoryIndex index.php

XAMPP mySQL databases location

Databases can generally be copied and pasted from the following location:

C:\xampp\mysql\data

Database Corruption

Sometimes the database can get corrupt from copying files from the \data\ directory. This will need a reboot of the xampp server. Once this happens there will be an error message on the site saying that "[table_name] has crashed or is corrupt and will need a repair". If that is the case you must run the following on the mySQL database:

REPAIR TABLE [table_name]

Default "root" User for mySQL databases

The default password for root is blank, however changing this can be done from the xampp control panel by click the "Shell" button and typing the following command

mysqladmin -u root -p password NEWPASSWORD

Where NEWPASSWORD is the password you want to specify

Default "root" password for phpMyAdmin


The following lines need to be updated in the file: C:\xampp\phpMyAdmin\config.inc.php

$cfg['Servers'][$i]['user']                 = 'root';
$cfg['Servers'][$i]['password']             = 'NEWPASSWORD';

Monday, February 15, 2010

Commonly used Regular Expressions

Here is a list I put together a while back to keep for reference whenever I do validation:

First Name or Last Name

^[a-zA-Z-'\s]*$

Email

^[a-zA-Z0-9]+[a-zA-Z0-9\'._%+-]*@[a-zA-Z0-9_-]+[.]%7b1%7d[a-zA-Z0-9_-]+
[a-zA-Z0-9._-]*[a-zA-Z0-9]+$">*@[a-zA-Z0-9_-]+[.]{1}[a-zA-Z0-9_-]+
[a-zA-Z0-9._-]*[a-zA-Z0-9]+$

Phone or Mobile

^[0-9\(\)\-+\s]*$

Postcode for Australia

^[0-9]{4}$

Postcode for the US

^[0-9]{5}$

Postcode for the UK

^[a-zA-Z]{1,2}[0-9]{1,2}[a-zA-Z]?[\s]*[0-9]{1}[a-zA-Z]{2}$

Date: Day

^([0-2]*[1-9]{1}|3[0-1]{1})$

Date: Month

^([0]*[1-9]{1}|1[0-2]{1})$

Date: Year

^(19[0-9][0-9]|20[0-9][0-9])$

CSV File with comma delimited text

,(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))
There is also an incredibly useful tool that a colleague of mine, Ross Donald, built that had helped me out so much in the past:
http://www.radsoftware.com.au/regexdesigner/

Saturday, February 13, 2010

Sitefinity CMS features

Rich Text Editor

In order for the WYSIWYG editor to contain the table editor as follows:



You must edit the [Web Root Folder]\Sitefinity\Admin\ControlTemplates\EditorToolsFile.xml file and add the following tool:

<root>
  <tools dockable="false">
    <tool name="InsertTable" />
  </tools>
</root>

Page Navigation


For certain properties you only want to navigate to pages within your own sitefinity application, the following property with its attribute definition is the most appropriate for this requirement:

[WebEditor("Telerik.Cms.Web.UI.CmsUrlWebEditor, Telerik.Cms")]
    public string StartingNodeUrl
    { 
        get; set;
    }



File System Navigation


Some properties may require selecting a file or folder within within your sitefinity application. The following attribute definition is the most appropriate for this requirement:

[WebEditor("Telerik.FileManager.UrlWebEditor, Telerik.FileManager")]
    public string EndNodeUrl
    { 
        get; set;
    }



General URL Navigation

The System.Web General attribute description for a Url type Property is demonstrated below. Sitefinity would detect this and realise that it is a Url type Property, and would therefore allow the selection of a page or file within the sitefinity application:

[Editor(typeof(UITypeEditor), typeof(UITypeEditor)), UrlProperty]
    public string RedirectUrl
    { 
        get; set;
    }



Image URL


Some images in sitefinity are stored in libraries and so the standard sitefinity dialog for selecting from either library or file system needs to be used as follows:

[Editor("System.Web.UI.Design.ImageUrlEditor, System.Design",
 typeof(UITypeEditor)), UrlProperty]
    public string ImageUrl
    { 
        get; set;
    }

Wednesday, February 10, 2010

Classic ASP - prevent SQL Injection hacks

Typically, a developer would be tempted to write the following to connect to a database.
<%@ Language=VBScript %>
<% option explicit %>
<%
    set cnn = server.CreateObject("ADODB.Connection")
    cnn.Open(ConnectionString)

    strSQL = "exec uspSQLInsertString " & customerID & "," & contactID

    dim result
    result = cnn.Execute(strSQL)

    cnn is nothing
%>

This is actually a bad use of ADO which allows a potential security threat using SQL Injection.
A more appropriate use of ADO in Classic ASP is as follows:

<%@ Language=VBScript %>
<% option explicit %>
<%
    set cmd = Server.CreateObject("ADODB.Command") 
    cmd.ActiveConnection = ConnectionString 
    cmd.CommandText = "uspSQLInsertString" 
    cmd.CommandType = adCmdStoredProc
    cmd.Parameters.Append(cmdInsert.CreateParameter("@date", 
    adDBDate, adParamInput, 6, cdate(Request.Form("hLive"))))

    dim result
    result = cmd.Execute() 

    set cmd = nothing 
%>

This is a more appropriate way using parameterised queries.

Thursday, January 28, 2010

Photoshop Glass Button

The following steps are required to give a glass effect to buttons:

  1. Select two appropriate colours (for gradient shades)



  2. Select Rounded Rectangular tool:



  3. Draw a simple ellipse:



  4. Create a new layer:



  5. Ctrl + Click on the vector mask in the first shape layer so that you can select only the ellipse:





  6. Select the Gradient Tool:



  7. Make sure that the gradient consists of the two colours you have already selected (you can find this in the top left corner under the menu):



  8. Select the new layer while the ellipse marquee is still highlighted, and draw a gradient from top to bottom:



  9. Optionally, an inner glow can give a nicer effect to the shape by right clicking the second layer, and selecting "Blending Options":



    You can tweek the above settings for colour, size, and opacity of the glow.

  10. Click OK, and review the effects of the blend:



    Note: the ellipse marquee selection should not be un-selected at this point.

  11. Create a new third layer:



  12. Select the Elliptical Marquee tool:



  13. From the top-left settings under the menu, select the intersect option:



  14. Draw an ellipse marquee selection outside the image to intersect with the top half of the image:



  15. Change your primary colour to white, then select the gradient tool with the white to transparent setting in the top-left corner under the menu:



  16. Draw a gradient on the new layer from top to bottom as shown below:



  17. Finally, deselect the marquee and review the image:




This can now work as a button image as shown in the below example:




Wednesday, January 20, 2010

Html and Javascript basic practices

Developers get tempted to embed <script> tags within their html or aspx pages as shown below:

<html>
    <head>
        <title>Test Page</title>
    </head>
    <body>
        <script type="text/javascript">

            function testFunction(element)
            {
                alert(element.id);
            }

        </script>
    </body>
</html>

This inevitably creates grief when trying to debug script code, and also makes it harder to find javascript code when a new developer starts working on your application. On top of all that, maintenance starts becoming an issue.
A better example would be to separate javascript code from your web page:


// javascript file testJavascript.js

    function testFunction(element)
    {
        alert(element.id);
    }


<!-- html file testHtml.html -->
<html>
    <head>
        <title>Test Page</title>
    </head>
    <body>
        <script type="text/javascript" src="include/testJavascript.js"></script>
    </body>
</html>

Friday, January 1, 2010

Back in action!

Fellow internet scrapers. I am back with a vengeance from the void of the online social networking in my life (having said that the next post will probably be in the next 3 years!).

I'll be making sure that I don't waste too much of my time spilling my guts out and writing a proverbial diary with the inner workings of my soul exposed through the bits and bytes in the digital world out there.

I mean who cares right!? So long as the information is useful to you, my devoted reader, then that is all that matters. Plus it would be good for me to keep track of all the little technical quirks and issues I've faced that could help me along the way whenever I face a problem and cannot remember for the life of me how I did it.

So it's almost like a reference manual for all the times I've smashed my head against the table trying to figure something out :)

It will definately be easier since I'm using a Laptop with roaming internet rather than my prehistoric desktop machine :)

Happy reading!!