Recently in technical Category

YUI Compressor in NANT

| No Comments | No TrackBacks
One of the items I have been looking at recently is managing and minifying Javascript and CSS files. One of the good practices for web developers is to create websites that load quickly and have minimal server calls. Using tools to combine CSS or Javascript and minify them is an essential best practice. I'm currently working on a website developed in .NET where the files have not been concatenated, and each page is loading more than a dozen Javascript files.

In the past, I've used YUI Compressor to concatenate and minify my files. (The latest version can be downloaded here: http://developer.yahoo.com/yui/compressor/.) I decided to see if there was a way that this could be used in .NET automatically at build time. I came across the following article and decided to test it myself: http://www.codeproject.com/Articles/141931/Combine-Multiple-CSS-Files-into-One-File-and-Minif.

These changes required editing the configuration (config) files for the project, and I've outlined some steps below. You''ll need to ensure that you download YUI Compressor from the above link and download NantContrib, if you have not already. This was already set up for me and used, but we will need to ensure that we point to the NAnt.Contrib.Tasks.dll file. (Download NAntContrib hereL http://nantcontrib.sourceforge.net/.)

  • Ensure that the variables are set for buildDirectory, etc. I added the nantContrib.Path, <property name="nantContrib.Path" value="${path::get-full-path(nant::get-base-directory()+'../bin/NAnt.Contrib.Tasks.dll')}" />
  • Point to the JAR file for YUI Compressor, <property name="YUI" value="C:\yuicompressor-2.4.7\build\yuicompressor-2.4.7.jar"/>
  • Set the property name to point to the location of the CSS files and Javascript files. On build, all Javascript files are bundled into one directory in 'wwwroot', called 'scripts', and the CSS is in 'styles'. 
    <property name="CssFileLocation"  value="styles"/> 
    <property name ="JsFileLocation" value="scripts"/>
  • The following code concatenates the files in the directory and names the file 'style.css'. However, you can specify which files to exclude, if you desire. In the example below, I excluded print.css.
<target name="css" description="Concatenate CSS source files">
    <loadtasks assembly="${nantContrib.Path}" />
    <echo message="Building ${buildDir}\wwwroot\${CssFileLocation}\*.css" />
    <concat destfile="${buildDir}\wwwroot\${CssFileLocation}\style.css" append="true">
      <fileset>
        <include name="${buildDir}\wwwroot\${CssFileLocation}\*.css" />
        <exclude name ="${buildDir}\wwwroot\${CssFileLocation}\print.css"/>
      </fileset>
    </concat>
    <echo message="${buildDir}\wwwroot\${CssFileLocation}\style.css built." />
    <echo message="delete other files except style.css" />
    <delete>
      <fileset>
        <include name="${buildDir}\wwwroot\${CssFileLocation}\*.css"/>
        <exclude name="${buildDir}\wwwroot\${CssFileLocation}\style.css"/>
        <exclude name ="${buildDir}\wwwroot\${CssFileLocation}\print.css"/>
      </fileset>
    </delete>
    <echo message="delete other files except style.css is done" />
  </target>


  • The next step is to minify the CSS style.css file and save it as style.min.css. This will minify the files in sub-directory too, and print.css (excluded above) will also be minified.
<target name="css.minify" depends="css" description="Minimize CSS files">
    <foreach item="File" property="filename">
      <in>
        <items>
          <include name="${buildDir}\wwwroot\${CssFileLocation}\**\*.css"/>
        </items>
      </in>
      <do>
        <echo message="${filename}" />
        <exec program="java">
          <arg value="-jar" />
          <arg value="${YUI}" />
          <arg value="-o" />
          <arg value="${filename}.min" />
          <arg value="${filename}" />
        </exec>
      </do>
    </foreach>
  </target>

 

  • The same method will need to be used for Javascript files, which may require a little more thought on the organisation of the code within the files.
  • For the way in which the build script was written, I added the 'css' and 'css.minify' commands (target name) to the <target name="build" depends="css, css.minify"> tag, and the same would be done with the Javascript-specific code.
  • The final step would be to update your HTML to point to the correct CSS/JS files, and to load the Javascript at the bottom on the HTML page. The website I used as a guide mentions automatically replacing the file names, but I'm dubious about that.


However, apparently Visual Studio .NET comes with its own built-in tools for minifying and concatenating Javascript and CSS files now, but I have yet to try this.
Over the past year, I have been developing websites with Adobe CQ5 as the CMS (Content Management System), including building components, so that content writers can populate the web pages. In some cases, the logical method of creating components did not work; with any CMS, there are limitations or bugs, and part of the 'fun' (if you could call it that) is discovering an alternative solution. This article describes and explains the accordion component development. This component was developed nearly one year ago now, so some of the particulars are not as fresh in my mind.

What The Heck is An Accordion in Web Terms?

For those who do not know, an 'accordion' in web terminology is a design element that can show or hide a panel of content (to save screen space or provide a consistent grouping of similar data), and the user can click onto the panel to expand the minimised view, or to minimise an expanded panel. The screenshot below shows an example of the component, which was the solution I implemented. Obviously, the styling (CSS) and Javascript required is beyond the scope of this. (For those who are interested, the functionality of the interaction is completed using the JQuery Javascript library.)

cq5accordion1.jpg

For setting this component up in CQ5 CMS for the content editors to use, I ideally wanted the content writer to be able to add a panel for each 'accordion' entry, which would consist of a title/subject and body text. The body text needed the ability to be styled, so the custom CQ5 rich text editor needed to be used. This would have been using a compositeField / MultiField component, but a bug was discovered while creating this, and the values did not save correctly. Unfortunately, Adobe CQ5 CMS cannot handle certain data types, even though it was meant to be supported. (Adobe CQ5 CMS does tend to have a lot of "TODO" comments in its code.)

Obviously, I needed to come up with an alternative and user-friendly solution. I read in forums online about using the column component and adapting it, but I wanted it to be more intuitive to the content writers. I'm mainly writing about my experience here as there seems to be many wanting to complete the same task, but the information does not exist.

My Accordion CQ5 Solution Explained

The alternative solution was to develop the accordion and accordion panel components separately, as a parsys, while providing a user-friendly interface to give the content writers direction. Simply, the content writer will drag and drop an accordion component from the Sidekick onto the screen. The accordion component will have a placeholder message to instruct the user to add accordion entries. The user will double-click the accordion component on the screen to add accordion entries. (The accordion entries are simply another component.) The accordion entries component is the only type of component that they will be able to add inside the accordion component parsys; no other components will be allowed to be placed.

This tutorial shows some of the steps to create an accordion component in Adobe CQ5 CMS. First of all, I will explain the structure of the set-up for the component. A visual representation of the structure is displayed below. As you can see, the accordion is organised into the 'accordion' and 'accordion-entry' (one panel, consisting of a heading and rich text) components.

cq5accordion2.jpg

The 'accordion' Component
The 'Accordion' component is simply the placeholder that encompasses the accordion entries.

_cq_editConfig.xml:
To ensure that the screen updates so that the editor can see the output on the screen, the page in author mode in the CMS needs to be refreshed. The file demonstrates refreshing after creation, after deletion, after insertion, and after moving.

<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
    cq:dialogMode="floating"
    jcr:primaryType="cq:EditConfig">
    <cq:listeners
        jcr:primaryType="cq:EditListenersConfig"
        aftercreate="REFRESH_PAGE"
        afterdelete="REFRESH_PAGE"
        afterinsert="REFRESH_PAGE"
        aftermove="REFRESH_PAGE"/>
</jcr:root>

.content.xml
The 'Accordions' .content.xml file specifies that the sling:resourceSuperType is the standard parbase component. This will allow us to drag and drop other components into it. However, we need to ensure that only a specific type of component can be put into that place - the 'accordion-entry'. The settings allowedChildren is set to be an 'accordion-entry' component type, and allowedParents is the parsys.

<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
    cq:isContainer="{Boolean}true"
    jcr:primaryType="cq:Component"
    jcr:title="Accordion"
    sling:resourceSuperType="foundation/components/parbase"
    allowedChildren="[*/accordion-entry]"
    allowedParents="[*/parsys]"
    componentGroup=".hidden"/>

dialog.xml
When the user drags and drops the 'Accordion' component into place, they have the option to enter a unique ID for the accordion. See the snippet of code below.

<items jcr:primaryType="cq:WidgetCollection">
        <title
            jcr:primaryType="cq:Widget"
            fieldDescription="Leave empty to use the page title."
            fieldLabel="Title"
            name="./jcr:title"
            xtype="textfield"/>
        <id
            jcr:primaryType="cq:Widget"
            fieldDescription="Enter a unique ID for the accordion"
            fieldLabel="ID"
            name="./id"
            xtype="textfield"/>
    </items>

accordion.jsp
The following shows the contents of the Accordion JSP and how it is rendered on the page. The resourceType is a parsys, since the content editor will be dragging and dropping the 'according-entries' components into place here.

<c:set var="accordionFlag" scope="request" value="yes"/>
<c:set var="accordionID" scope="request" value="1"/>
<div><cq:include path="entries" resourceType="myproject/components/my-accordion/components/parsys"/></div>

clientlibs folder
This folder holds the Javascript for the accordion. There's some configuirations here, such as defining the client libraries, such as the Javascript/jQuery file that will handle how the accordion should behave. The Javascript file is placed into the 'source' folder underneath the 'clientlibs' folder. Note that the name must match the name in the js.txt file.

  • .content.xml:
    <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
        jcr:primaryType="cq:ClientLibraryFolder"
        categories="[my.accordion-component]"/>
  • js.txt:
    #base=source
    jaccordion.congif.js

The 'accordion-entry' Component
The 'Accordion-entry' component is an actual entry or panel that sits inside the 'Accordion' component. This is a child of the 'Accordion' component.

.content.xml:
The 'accordion-entry' will only be allowed to be used if it is a child of the 'Accordion' component, so we set the allowedParents accordingly.

<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
    jcr:primaryType="cq:Component"
    jcr:title="Accordion Entry"
    sling:resourceSuperType="foundation/components/parbase"
    allowedParents="[*/my-accordion/components/*parsys]"
    componentGroup=".hidden"/>

dialog.xml:
The 'accordion-entry' dialog allows the user to enter a title for the accordion entry panel as well as rich text for the body text of the accordion.

<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
    jcr:primaryType="cq:Dialog"
    helpPath="en/cq/current/wcm/default_components.html#Text"
    title="Text"
    xtype="tabpanel">
    <items jcr:primaryType="cq:WidgetCollection">
        <tab1
            jcr:primaryType="cq:Widget"
            anchor="100%"
            title="Text"
            xtype="panel">
            <items jcr:primaryType="cq:WidgetCollection">
                <title
                    jcr:primaryType="cq:Widget"
                    defaultValue="enter a title"
                    fieldLabel="Title"
                    name="./title"
                    xtype="textfield"/>
                <isRichTextFlag
                    jcr:primaryType="cq:Widget"
                    ignoreData="{Boolean}true"
                    name="./textIsRich"
                    value="true"
                    xtype="hidden"/>
                <text
                    jcr:primaryType="cq:Widget"
                    defaultValue="Please enter some text"
                    fieldDescription="Text displayed in panel"
                    fieldLabel="Text"
                    hideLabel="{Boolean}true"
                    name="./text"
                    xtype="richtext"/>
            </items>
        </tab1>
    </items>
</jcr:root>

accordion-entry.jsp:
The JSP renders the accordion-entry's HTML. I'm not going to include all of the file's contents, but note that I use the lines below in order to obtain the title and text, set by the content editor by using the contents of the dialog.xml file above.

<%
final String title = properties.get("title", "");
final String text = properties.get("text","");
%>


The 'parsys'
The parsys is used for ensuring that the component has the same properties to behave like the foundation parsys component. This component is a copy of the component in the foundation library, with a change to a few of the files for the accordion. The changed files are mentioned below.

.content.xml:
The parsys component superResourceType is the foundation's parsys component, and the allowedChildren is 'accordion-entry'.

<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
    cq:isContainer="{Boolean}true"
    jcr:primaryType="cq:Component"
    jcr:title="Accordian Composite 1"
    sling:resourceSuperType="foundation/components/parsys"
    allowedChildren="*/*accordion-entry"
    componentGroup=".hidden"/>

.content.xml (in the 'new' folder)
The resourceType needs to point to the accordion's copy of the parsys file.

<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
    jcr:primaryType="cq:Component"
    jcr:title="New Paragraph"
    sling:resourceType="myprojectx/components/my-accordion/parsys/new"
    componentGroup=".hidden"/>

_cq_editConfig.xml (in the 'new' folder) 
Simply, we will tell the user to drag and drop accordion entries to this place. (So, we change the emptyText parameter here.)

<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
    cq:actions="[_clear,insert]"
    cq:emptyText="Drop Accordian entries here"
    jcr:primaryType="cq:EditConfig"/>

Conclusion

Hopefully, I hope I have not missed anything important out from these steps. (It was a while ago since this was developed, so it's not very fresh in my memory.) I hope that this will allow you to think of alternative solutions where some of the components in CQ5 do not work as expected or as documented. The most important point is to develop the CMS website customisation so that the user can intuitively add their content and be prevented from making changes that could 'break' the website.

One more tip: I also think it's important to note that you can switch off Javascript or JQuery from running in EditMode, and this was done so that the user can view and edit all panels in the accordion by clicking onto any panel (without the behaviours applied to expand and contract).

Happy programming! 
Using CSS3, developers can add icons to a website without using images. The way to accomplish this is to locate a font that contains icons and using the CSS3 @font-face rule, or by using another font-loading method - requiring Javascript - to load the font. (Of course, you will need to ensure that you have permission to use the font on the website.) However, this method is only supported with browsers that use CSS3 and have Javascript enabled to read the font, so it may not work in all browsers.

iconfonts.gif

The advantages of using this method include not being required to maintain icons in image files and potentially quicker loading times, depending on the size of the image file containing the icon and the size of the file containing the font. 

Disadvantages include the inability to use multiple colours as the icon, as the icon is rendered as a vector font.

Others have discussed this topic on the following websites below:

http://net.tutsplus.com/tutorials/html-css-techniques/quick-tip-ever-thought-about-using-font-face-for-icons/

http://somerandomdude.com/2010/05/04/font-embedding-icons/
One way to test and view how a website would look on different browsers and devices (such as mobile phones and devices or different browser-specific operating systems)  would be to use a specific User Agent within your browser of choice. This way, you do not need to jump from computer to computer or device to device to test your websites. (Firefox has a User Agent Switcher "add-on" feature, and this can be downloaded along with your other development tools. Simply go to the "Tools" option in Firefox, then select the "Add-ons" link from the drop-down menu to search.) 

The 'User Agent Switcher' allows you to trick your browser into thinking that it is a different type of device or a different browser or Operating System by passing a string to define the type of device/browser. 

Once the Firefox add-on has been downloaded, you will need to create your User Agent strings, as these have not been provided. The following URL provides some 'User Agent' strings: http://useragentstring.com

However, if you do not wish to type in and save each one individually, the work has been done for you if you simple search the Internet for an XML file that contains a list of these already defined; this XML file can be imported into your "User Agent Switcher" tool. I found an XML file of these user agent strings in the forum of Chris Pederick's (developer of the 'User Agent Switcher' add-on) website, http://chrispederick.com/.

The tool allows the user agent strings to be backed up (as XML) or imported, so it's easy to back up your development environment.

Although the 'User Agent Switcher' does give you a very good idea about how your website will look in other browsers and give you the ability to test browser-specific code, keep in mind that it is not always accurate. (For example, the iPhone does not display an <iframe>, though this appears to look fine when viewing the website in the 'User Agent Switcher' with the iPhone option selected.) 

The tool is very easy to install and use, and new user agent strings can be added whenever you wish. I guarantee that you'll be using this tool a lot while developing your websites.
Several years ago, I was checking through my website's web logs and discovered that another developer (I use the term loosely here) had decided to hotlink to one of my images, and they set my image as the background of their MySpace website. In fact, it was a MySpace website for their band.

I was not happy, so I swapped out the image for another one, which promptly tiled across their MySpace website. This was a highly amusing result, and within a week, they had taken the website down and relaunched it a couple of days later with a new background image. (At least they did not steal my image, but the fact that they were using it without permission and putting their web traffic through my website with requests to my image, was annoying.)

Instead of humiliating others, I wish that I had known that I could have prevented the developer from linking to my image through making changes to the .htaccess file.

This can be easily achieved by putting a few lines into the .htaccess file. First of all, however, you will need to create an image that the users will be redirected to if they do link to an image. This image can include some text that asks users not to link to your image.

After you have created the image, simply write your redirect rule to the image you created above. You will need to check the HTTP_REFERER of the request, and ensure that your website can link to the images. Afterwards, add your RewriteRule so that all other websites not mentioned in the RewriteCond will obtain the created image. An example is below (1).

RewriteEngine On

#Replace ?mysite\.com/ with your blog url

RewriteCond %{HTTP_REFERER} !^http://(.+\.)?mysite\.com/ [NC]

RewriteCond %{HTTP_REFERER} !^$

#Replace /images/nohotlink.jpg with your "don't hotlink" image url

RewriteRule .*\.(jpe?g|gif|bmp|png)$ /images/nohotlink.jpg [L]


The example above will prevent any websites besides your own from hotlinking to images, but you may want some websites to see your images. To allow Google or other search engine sites to continue linking to your image (so that it comes up in results), simply add the following lines:

RewriteCond %{HTTP_REFERER} !google\. [NC]

RewriteCond %{HTTP_REFERER} !msn\. [NC]

RewriteCond %{HTTP_REFERER} !yahoo\. [NC]

RewriteCond %{HTTP_REFERER} !search\?q=cache [NC]


The above code can be adapted to meet your own demands and goals. 



1) How to protect your wordpress blog from hotlinking. http://www.wprecipes.com/how-to-protect-your-wordpress-blog-from-hotlinking

Web Font Loading Using Typekit

| No Comments | No TrackBacks

In a recent website project that I have been working on, the designer used a non-standard web font for page headers and navigation. This required loading through one of the methods of font-loading that I mentioned in a previous post:. Upon further research, I discovered that the font is available on Typekit, so I did some research into the service before deciding to sign up to the service, taking into account the particular usage of the website and potentially shifting multiple fonts across different domains.


Speed of the service:

TypeKit state on their website that they 'minimize fonts as much as possible' to ensure that the files are the smallest size possible. They also ensure that fewer requests are made with multiple CDNs (Content Delivery Networks) across the world and use font caching. Despite many enablers put into place to ensure the speed is quick, there may be some issues, such as the following:

'In these cases, Typekit users are most often concerned about their visitors seeing an effect commonly know as the FOUT, or the flash of unstyled text. You may have noticed the FOUT before: it's that brief flash of text in a default font before the web fonts have finished loading.' (http://blog.typekit.com/2010/10/29/font-events-controlling-the-fout/)

While making the website look more visually attractive with a new font, it is always a good idea to ensure that the website looks good with the standard web-safe fonts (such as Arial). This is necessary, in my opinion, as the Typekit font only works if Javascript is enabled.


Reliability and SLA (Service Level Agreement)

While Typekit do claim to provide a reliable service and have a wide CDN, I noted that they had recently suffered a DOS (denial-of-service) attack, and this brought down their CDN. (After the service was signed up to and I was using Typekit, I noticed a couple of times that the fonts were not being loaded, and this was reported by a couple of other users as well.)

Typekit do have an SLA, and I believe that I read somewhere on their website that if their service suffered an outage, that the customers would not have to pay for that month's service. (That SLA only applied to enterprise plans.)


Plans:

There are a few different types of payment plans to choose from, depending on your needs. Each plan reflects the number of domains, pageviews, and the fonts available. Note that payment is on a monthly basis.


Pageviews

Each plan had a different pageview limit per month, and Typekit state that this is a 'basic  guideline'. In the case that pageviews are consistently higher each month than the plan allows, they will require that another plan be chosen. Typekit state that they will not 'turn off' the font service if the user has gone over their pageview limit. Before purchasing a plan, view your website's logs/statistics to determine how many pageviews are made each month, on average.


Positives:

TypeKit is used by big brands, such as Zynga, New York Times, WIRED, Wordpress, and Twitter - to name a few.

TypeKit is owned by Adobe.

If the SLA is not met (enterprise plans), the month's fee is returned. Typekit promise '99.9% uptime' on their website. (https://typekit.com/plans/business)


Negatives:

By using Typekit, you are signing up to rent the font on a month-by-month basis.

Typekit relies on Javascript, but there's no alternative in some cases, depending on font licensing costs. CSS @font-face can also be used, but this is determined by the font.



Typekit has a trial if you are unsure and would like to see the service working and to judge whether or not it is right for you and your company.

In the past, web designers have had to use the widely-distributed fonts (such as Arial and Times New Roman) so they could guarantee their users could read their website. This left little room for creating websites that looked a little more like print. In the past, non-standard fonts would have to be converted into images, and this generally was not good for page loading, SEO, or website maintainability.

Although we have come a little closer to being able to use non-web-standard fonts on our websites, we still need to use Javascript to render different fonts, until more advanced methods are widely-used and available in browsers. The @font-face tag can be used, but it requires advanced browsers using CSS3, though the idea was proposed in CSS2. 

Overall, I suggest using a combination of CSS @font-face and one of the Javascript methods to load the font. I also suggest using a custom font sparingly and only in certain HTML tags and instances, such as in header <H1> (or <H2> and <H3>) tags only, pull quotes, or in navigation menus. I certainly do not recommend using a non-web-standard font for all body text. In all instances, I recommend using a fallback method in case there is an issue with the custom font loading, such as making all custom fonts default to 'sans-serif' in the case that the custom font does not load.

@font-face
To embed the font using CSS @font-face, you must first have permissions to use the font in this way. (Fonts are copyright, just as images are.) If you have permission to use the font and there are no restrictions on the licensing, you can load the font file as below. The following loads the font depending on the browser requirements on varying types of font format. The method was reworked several times by multiple developers since 2009, and this method is devised by the website FontSpring.com (1). This solution works in all browsers that support @font-face and on Android phones.

@font-face: {
font-family: 'MyCustomFont';
src: url('/fontfolder/CustomFont.eot?') format('eot'), 
url('/fontfolder/CustomFont.woff?') format('woff'), 
url('/fontfolder/CustomFont.ttf?') format('truetype'),
url('/fontfolder/CustomFont.svg#svgFontName?') format('svg'), 
}

@font-face: {
font-family: MyCustomFont;
src: url('/fontfolder/CustomFontDark.eot?') format('eot'), 
url('/fontfolder/CustomFontDark.woff?') format('woff'), 
url('/fontfolder/CustomFontDark.ttf?') format('truetype'),
url('/fontfolder/CustomFontDark.svg#svgFontName?') format('svg'), 
weight:bold;
}

Once you have loaded the font following the method above, you can call it using the font-family tag, as below.

h1 {
font-family: 'MyCustomFont', serif;
}

The following websites below use the @font-face method:
http://www.codeslingerschallenge.com/
http://www.faciodesign.co.uk/blog/

Note how the websites restrict the custom font to the headers and, in the case of the faciodesign.co.uk website, the navigation.

fontface.jpg

The following methods that I will look at include: Typeface.js, Google Fonts, sIFR, TypeKit, and Cufon.

 
Typeface.js
This solution uses a Javascript file to render fonts.

Advantages:
Easy to implement.
Does not require Flash.
The Javascript file is small, and it has the ability to load quickly.

Disadvantages
The text rendered is output like an image, and each word is output into a <span> tag.
Uses the <canvas> tag for each word, and combined with separate <span> tags, it inserts a lot of HTML.
The solution cannot be read by screen readers.
Looks different in different browsers and does not render in all browsers.

To use Typeface.js, simply download the Javascript file from:
http://typeface.neocracy.org/download.html

You will need to select a font that you have permission to use, and you will need to convert the font into a Javascript file (available on the Typeface.js website). Simply load the two Javascript files after your CSS file is loaded. After this is completed, you should be able to reference the font name in the CSS 'font-family' tag.

I had some problems converting some fonts to Javascript, and some fonts that were converted had rendering problems.


Google Web Fonts
This solution is developed by Google and allows developers to use licensed web fonts on their websites through Javascript.

Advantages:
Google Web Fonts is free.
Easy to implement and only requires loading Javascript from Google onto your website.

Disadvantages
There are only a few fonts available to use.

To use this method, simply visit the website: 
http://www.google.com/webfonts#ChoosePlace:select 
Choose a font and import Google's Javascript that renders the font by using:
@import url(http://fonts.googleapis.com/css?family=MyFont+Serif&v1);
Simply add the font to the font-family tag in CSS.


sIFR (Scalable Inman Flash Replacement)
This solution uses Flash and Javascript to render the font and is an SEO-friendly method.

Advantages:
Text is selectable and SEO-friendly.
Screen readers will not have problems reading the fonts that use this method.

Disadvantages:
Requires the Flash plugin, so this cannot be seen on the iPhone.
Page loading is an initial problem as it needs to load CSS, Javascript, and Flash.
There seems to be a learning curve, and it takes extra time to configure setting up on secure websites.
It requires much testing and there may be problems with it rendering in certain visual instances.

See the credit for a tutorial on how to use this method on your website (2). 
To try this method, you can download sIFR from the developer's website: 
http://novemberborn.net/sifr3


Typekit
This solution uses Javascript to render fonts, which are then passed from TypeKit's servers and delivered to the website. This solution is a subscription plan, and the company is now owned by Adobe.

Advantages
Owned by big brand, Adobe, so I suspect that this will continue to be developed and supported.
Contains many fonts to select from, and all are available to use.

Disadvantages
You pay monthly to rent the font.
If you have a lot of fonts in your kit, the produced Javascript file can be large and slow.

To use this method:
Visit the website http://www.typekit.com. You can sign up for a trial to test before you purchase one of their plans.


Cufon
Cufon allows you to render your fonts into Javascript files to use on your websites.

Advantages
Easy to use.

Disadvantages
Although you can convert any type of font, you need to bear in mind the licensing restrictions on the fonts that you wish to use.
Renders fonts as not selectable, and creates extra HTML and uses <canvas>.
Is not good for SEO.

I tried this method, and some of the fonts would not convert. Others converted, but they did not convert the font correctly.

To use this method:
Download the Cufon Javascript and the font-specific Javascript. To generate your font's Javascript, simply visit: http://cufon.shoqolate.com/generate/
Use Cufon.replace to add the font to specific HTML tags and classes:
Cufon.replace('#cufon-text h1');


Other Methods
Many other methods exist, and these work similar to TypeKit's solution, though some of these methods are free, and others require a fee. Methods include: Webtype, FontDeck, FontsLive, TypeFront, FontSpring, Fonts.com, and WebINK. There are many more, and these can be researched to discover the correct method for you.

In conclusion, I am glad that some progress is being made in this area so that we can use custom fonts in our web designs without relying on images or compromising SEO. There is still some way to go in this area, but we have come a long way from the days when you were limited to only using Times New Roman or Arial in websites and images for headings or navigation menus. 


1) FontSpring. The New Bulletproof @font-face syntax. http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax [3 February, 2011].

2) Wake-up Later. sIFR Tutorial:Use your own fonts. http://www.wakeuplater.com/website-building/use-your-own-fonts-a-simple-sifr-guide.aspx [10 October, 2011].

Under the Site - Technologies Used

| No Comments | No TrackBacks
Here is a tool that may come in useful for web developers; in a click of a button (after typing or copying and pasting a URL, of course), developers can see what technologies any given website uses. (Of course, the same can be achieved with Firebug with some analysis.)

http://underthesite.com

Using CSS To Draw Shapes

| 2 Comments | No TrackBacks
Lately, I have been using CSS to draw various shapes for some designs that I have been working on instead of relying on images to create the relevant design elements, if possible.

Obviously, this technique will not work in older browsers, so I suggest using an alternative for specific browsers in the case that your website audience may have a variety of browsers and is accessible without Javascript. Normally, I would simply not use these techniques as I feel usability is important, but the audience for the websites I am working on requires newer browsers and enabled Javascript.

A common design element is the use of 'triangles' to create speech bubbles or arrows. Borders are rendered at angles, so assigning border colours and widths will create triangles. (More on this subject can be read on Jon Rohan's website (1).)

A quick example of this is demonstrated in the class below with setting the border colour as follows, from left to right in order - top: transparent, right: transparent, bottom: transparent, and right: violet. Changing the widths of the border sides controls the size and angle of the borders. For this example, I wanted a triangle to point to the right. The top and bottom angle needs to be the same to keep the angle 'straight', and I set it at 80px. Since we are only setting the right-hand size border, we need to give this a width, and this will influence the width of the triangle, which has been set to 40px. The code and screenshot is pictured below.

.css-arrow-multicolor {
  border-color: transparent transparent transparent violet;
  border-style:solid;
  border-width:80px 0px 80px 40px;
  width:0;
  height:0;
}

cssshapes1.jpg


(Please note that the 'transparent' colour setting does not work in some older browsers.)

Using these basics, a simple comment bubble (like the image below) can be made without the use of images. To create and adapt the following comment bubble to your own style, simply visit Jon Rohan's website (1) to get the code. 

cssshapes2.jpg


In addition to creating triangular shapes, circles and rounded corners can also be created. To create rounded corners, simply add a border radius. (Unfortunately, not all browsers work the same, so you will need to use these three different tags for this to work in all browsers.)

The following three tags will create rounded corners, and the shape achieved is dependent on the width and height of the <DIV>. (For a circle, the border radius needs to be half the height and width of the <DIV> element, otherwise you will simply achieve a rectangle with rounded corners.) 

-moz-border-radius: 50px;
-webkit-border-radius: 50px;
border-radius: 50px;

An oval shape can be achieved by slightly rounding the height and width. The width of the radius should be half of the height and half of the width. (The one in the screenshot below is 200px wide and 100px tall.)

-moz-border-radius: 100px / 50px;
-webkit-border-radius: 100px / 50px;
border-radius: 100px / 50px;

Three shapes created using the border radius are pictured below, along with the code.

cssshapes3.jpg

#circle {
width: 100px;
height: 100px;
background: cadetblue;
-moz-border-radius: 50px;
-webkit-border-radius: 50px;
border-radius: 50px;
}
#oval {
width: 200px;
height: 100px;
background: seagreen;
-moz-border-radius: 100px / 50px;
-webkit-border-radius: 100px / 50px;
border-radius: 100px / 50px;
}
#rounded {
width: 200px;
height: 100px;
background: orange;
-moz-border-radius: 30px;
-webkit-border-radius: 30px;
border-radius: 30px;
}


It may take a few tweaks to get exactly the shape and style you want, but that is part of the fun. Happy programming.


1) Rohan, Jon. Creating Triangles in CSS. http://jonrohan.me/guide/css/creating-triangles-in-css/ [22 October, 2011].

2) CSS Yard. Making Shapes in CSS3. http://www.cssyard.com/css-tutorials/making-shapes-in-css/ [18 February, 2011].
One of my recent tasks was integrating a Twitter feed onto a website. Upon researching the various methods to achieve this, I decided to use the Javascript written by seaofclouds, which uses the Twitter Search API, which you can read more about here: https://dev.twitter.com/docs/using-search.

Adding the code to print out the tweets is effortless. To do this, simply add your jQuery and the seaofclouds Javascript classes; download these scripts and include them in your page. (If you add these classes at the bottom of your web page, make sure that you load the following method to call your Twitter function after the page has loaded, of course.) 

Next, add your function to make the call to the Twitter class, which is printed below. The function will reference a <DIV>, and the ID of this should be set in your function. In the example below, the ID is called "tweet". You will then need to add a <DIV> tag with this ID to your web page, and the content will be added here.

function callTwitters() {
      jQuery(function($){
        $("#tweet").tweet({
           // ..... add your customisation here .....
       }).bind("loaded",
            function(){
               $(this).find("a").attr("target","_blank");
            }
       )
        .bind("empty",
                function(){
                    $(this).find("ul").append("<p>No tweets.</p>");
                }
           );
      });
 }


In the above example, I have included two 'bind' tags. I feel that this will always need to be used, but if you do not wish to use them for whatever reason, you can remove them. The first will add the property 'target=_blank' to all <A> tags. (This will ensure that all links will open in a new window so that users will not be navigated away from your website.) The second will display a message if no tweets were returned.

I have included some of the customisation options below. These will be added to the code above, in place of the comment in the code above. (Simply add each configuration item with a comma following it, but do not include a comma after the last item.)

avatar_size: 20, // Set the size of the avatar, in pixels.
count: 5, // Set the number of tweets you wish to be displayed
usernames: ["jenikya", "twitter"], // If you want tweets from more than one user, list all users.
username: "jenikya", // List the user you want to see tweets from
loading_text: "searching twitter...", // Set the text to display before tweets are loaded
refresh_interval: 60, // Set the refresh, which will look for new tweets every 60 seconds, in this case
template: "<div class=twitmain> {text} {avatar} </div> {time} {user}", //Set a template, which can include styling as well as the items received from Twitter      
filter: function(t){  // Set up a filter to filter any results. In this example, we filter out replies, designated by the '@' symbol.
                   return ! /^@\w+/.test(t["tweet_raw_text"]);
},   
join_text: "auto", // Automatically join the text
fetch: 100, // Fetch a sampling of results if you use a filter or a query. It will ignore all results that are filtered out.

Instead of specifying usernames individually, you can automatically view all tweets from users in a list. That way, you don't need to make a code change to add a new user. To do this, simply add a 'username' and a 'list' attribute. (Make sure that you set up the list on twitter first, and the list will need to be a public one.)

username: "jenikya",
list: "myPublicList"

The 'query' attribute can also be used to gather results. For example, if you wanted to return all results with a hashtag, you would use the 'query'. However, if you use the 'query' attribute, it will ignore the 'username', 'usernames', and 'list' settings. The query is set to null by default. The query below will return a list of tweets with the #London hashtag. Tweets will be from any user on Twitter that has used this hashtag.
query: "#London",

If you want to only specify tweets from your user when the #London hashtag has been used, simply complete the following:
query: "from:jenikya #London",

Fortunately, Twitter allows web developers access to their feeds without the glitches that Facebook had. (Last year at about this time, I added Facebook comments to a series of websites. The weekend that I worked on this, there was a glitch in Facebook which meant that none of the changes were making their way though; even the Facebook developers on the forums admitted the issues and it seemed that one developer was solely in charge of the task of fixing it. It took three days before Facebook's feed started to work again; meanwhile I'd wasted my weekend thinking that I got something wrong and spent countless hours going over my work and trying alternative methods.)

Twitter also allows web developers the ability to format the tweets in the manor that they see fit, whereas Facebook packages up the whole lot and send it in an iFrame, so customisation is limited.

For more information and for the code from seaofclouds and other examples, visit the website: http://tweet.seaofclouds.com/

About this Archive

This page is an archive of recent entries in the technical category.

review is the previous category.

travel is the next category.

Find recent content on the main index or look in the archives to find all content.

Monthly Archives

Pages

OpenID accepted here Learn more about OpenID
Powered by Movable Type 5.12