Snippets

Create an account or login to be able to add, comment and rate snippets.

Navigation

Snippets by user Frank van Noorden Snippets by user Frank van Noorden

User friendly - Printing and Change Font Size

This snippet will allow the user of your application to a. Change the fontsize of a webpage dynamically and b. print a properly formatted part of the webpage or let the browser handle the printing.

The snippet will become available as a symfony plugin as soons as 1.1 is stable. Why? symfony 1.1 contains the RemoveStylesheet function, which will make things easier.

Font size

The interface exists of three buttons (Increase) (Decrease) (Default), will immediately change the fontsize in the main content area. That includes h1, h2 etc.

The new fontsize is stored in a cookie, you'll have to do some coding if you want to store it in a database. The new fontsize is always retrieved on loadtime of a page.

Some changes in your CSS, and also probably in the CSS in this snippet, are necessary. You will have to set a default fontsize in the main content area CSS-rule. You will have to remove fontsize from all rules inside the main content area.

Note: If you want to use a fixed size for a certain part of the screen, then simply leave in the fontsize, it will not be resized then.

Printing

The interface exists of a checkbox User friendly printing, Enable the checkbox option to print only the main content area. Disable the option to allow the browser to handle full page printing.

Idea behind the printing concept

Installation

Create file components.class.php in apps/frontend/modules/UserFriendly/actions with the following content

<?php 
 
class UserFriendlyComponents extends sfComponents
{
     public function executeDefault()
     {
   }
 
}
 

Create file _default.php in apps/frontend/modules/UserFriendly/templates with the following content

<?php use_helper('Javascript', 'I18N') ?>
<div id="fn_userfriendly_container">
    <h2><?php echo __('User options') ?></h2>
    <p><?php echo __('Change font size ')?><?php echo link_to_function(
  '(Help)',
  visual_effect('toggle_blind', 'help_font_div', array('duration' => 0.1))
    ) ?>
    </p>
    <div id="help_font_div" style="display:none">
        <?php echo __('With the three buttons below you can change the font size of the main content area.') ?><br /><?php echo __('From left to right: Increase, Decrease and back to Default font size.') ?>
    </div>
    <ul class="fn_userfriendly_actions">
    <?php use_helper('Javascript') ?>
        <li>
            <?php echo button_to_function("", "changeFontSize('td','plus')", array('href' => '#Size+','class' => 'fn_userfriendly_action_fontplus')) ?>
        </li>
        <li>
            <?php echo button_to_function("", "changeFontSize('td','min')", array('href' => '#Size-','class' => 'fn_userfriendly_action_fontmin')) ?>
        </li>
        <li>
            <?php echo button_to_function("", "changeFontSize('td','std')", array('href' => '#DefaultSize','class' => 'fn_userfriendly_action_fontstd')) ?>
        </li>
    </ul>
        <br />
        <p><?php echo __('User friendly printing ')?><?php echo link_to_function(
  '(Help)',
  visual_effect('toggle_blind', 'help_print_div', array('duration' => 0.1))
    ) ?><br />
    </p>
    <div id="help_print_div" style="display:none">
        <?php echo __('Enable the option below to print only the main content area.') ?><br /><?php echo __('Disable the option to allow the browser to handle full page printing.') ?>
    </div>
    <?php $cookiename = 'userfriendly_print' ?>
    <?php $cookie = sfContext::getInstance()->getRequest()->getCookie($cookiename) ?>
    <?php if ($cookie == '') : ?>
    <?php $cookie = 1 ?> 
    <?php endif; ?>
    <?php echo checkbox_tag('userfriendlyprint', 1, $cookie,array('onclick' => "setPrintMethod(); return false;")) ?>&nbsp;<label for="userfriendlyprint" class="small"><?php echo __('Print user friendly') ?></label>
</div>
 

Create file UserFriendlyHelper.php in directory apps/frontend/lib/helper with the following content

<?php
 
/**
 * User Friendly Helper 
 *
 * @author      Frank van Noorden <fnoorden@gmail.com> 
 * @license     will be released under the same LICENSE as symfony
 * @version     0.0.1
 */
/**
 * addition of js-files and stylesheet
 */  
function userfriendly_init()
{
  $response = sfContext::getInstance()->getResponse();  
  $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/prototype');
  $response->addJavascript(sfConfig::get('sf_prototype_web_dir').'/js/effects');
  $response->addJavascript('/js/UserFriendly');
 
  $request = sfContext::getInstance()->getRequest();
 
    // name of print cookie
    $print_cookie = 'userfriendly_print';
 
    // Retrieve print cookie, the cookie always overrides the default
    $cookie = $request->getCookie($print_cookie);
    if (isset($cookie) && $cookie <> '')
    {
        $print = $cookie;
  }
    else
    {
        $print = 1; // default is 1-friendly printing, 0-browser printing 
        $expire = time() + 31536000; // one year
        $response->setCookie($print_cookie, $print, $expire, '/');
  }
 
    // Add print stylesheet 
    if ($print == 1)
  {
      $response->addStylesheet('/css/userfriendlyprint','last', array('media' => 'print'));
  }
 
  return '';
 
}
 

Create UserFriendly.js in the js directory with the following content

/**
 * User Friendly js 
 * @author      Frank van Noorden <fnoorden@gmail.com> 
 * @license     will be released under the same LICENSE as symfony
 * @version     0.0.1
 */
 
var prefsLoaded = false;
var defaultFontSize = 100;
var currentFontSize = defaultFontSize;
 
/**
 * addLoadEvent: Add event handler to body when window loads 
 */
// Multiple onload function created by: Simon Willison
// http://simon.incutio.com/archive/2004/05/26/addLoadEvent
 
function addLoadEvent(func) {
    var oldonload = window.onload;
 
    if (typeof window.onload != "function") {
        window.onload = func;
    } else {
        window.onload = function () {
            oldonload();
            func();
        }
    }
}
 
/**
 * changeFontSize: Change font size
 */
function changeFontSize(rulename, newSize){
if(newSize == 'plus') currentFontSize = parseInt(currentFontSize) + 10;
if(newSize == 'min') currentFontSize = parseInt(currentFontSize) - 10;
if(newSize == 'std') currentFontSize = 100;
 
if(currentFontSize > 150){
currentFontSize = 150;
}else if(currentFontSize < 50){
currentFontSize = 50;
}
 
setFontSize(rulename, currentFontSize);
createCookie("fontSize", currentFontSize, 365);
}
 
/**
 * setFontSize: Set font size 
 */
function setFontSize(ruleName, newFontSize){
var rule = getCSSRule(ruleName);
rule.style.fontSize= newFontSize + '%';
}
 
/**
 * setUserOptions: Get cookie and set stored font size
 */
function setUserOptions(rulename){
    if(!prefsLoaded){
 
    cookie = readCookie("fontSize");
    currentFontSize = cookie ? cookie : defaultFontSize;
    setFontSize(rulename, currentFontSize);
 
    prefsLoaded = true;
    }
}
 
/**
 * createCookie: Create cookie, takes number of days as input
 */
function createCookie(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}
 
/**
 * readCookie: Read cookie
 */
function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
 
/**
 * getCSSRule: Get the CSS rule
 */
function getCSSRule(ruleName) { 
    ruleName=ruleName.toLowerCase(); 
    if (document.styleSheets) { 
        for (var i=0; i<document.styleSheets.length; i++) { 
            var styleSheet=document.styleSheets[i]; 
            var ii=0; 
            var cssRule=false; 
            do { // For each rule in the stylesheet
                if (styleSheet.cssRules) { 
                    cssRule = styleSheet.cssRules[ii]; // Mozilla
                } else { 
                    cssRule = styleSheet.rules[ii]; // IE style 
                } 
                if (cssRule) { // Rule found
                    if (cssRule.selectorText.toLowerCase()==ruleName) { 
                            return cssRule; // Return the style object
                    } // End found rule name
                } // end found cssRule
                ii++; 
            } while (cssRule) // end Do While loop
        } // end For loop
    } // end styleSheet ability check
    return false; // Nothing found
} // end getCSSRule 
 
/**
 * setPrintMethod: Set print method
 */
function setPrintMethod() { // Set print method
 
var x = readCookie("userfriendly_print")
if (x == 0) {
    x =1;
} else {
    x=0;
}
createCookie("userfriendly_print",x,365,"/");
 
window.location = document.location.href;
 
return false;
}
 

The file userfriendlyprint.css has to be matched with your own CSS. Create userfriendlyprint.css in the css directory with the following content

/* Remove unwanted elements, probably different for you */
#content_main_navtop, #content_main_navbottom, #content_bar, .noprint, .last
{
display: none;
}
 
/* Ensure the content spans the full width */
#header, #content_main
{
width: 100%; margin: 0; float: none;
}
 
/* Change text colour to black (useful for light text on a dark background) */
.lighttext
{
color: #000 
}
 
/* Improve colour contrast of links */
a:link, a:visited
{
color: #781351
}
 
/* Set color of image links to white (make them to disappear on print) */
a img, *:link img, *:visited img {
border:medium none;
color: #fff
}
 

Change the view.yml and add the following:

  components:
    UserFriendly: [UserFriendly, default]
 

Change your layout.php Initialize the print environment, place this before </head> tag:

<?php use_helper('UserFriendly') ?>
<?php userfriendly_init() ?>
 

The saved font size will be restored at load time of the page. Add after the <body> tag:

<?php use_helper('Javascript') ?>
<?php echo javascript_tag('
    addLoadEvent(function() {
              setUserOptions("td"); 
    });
') ?>
 

Note: the TD tag used in setUserOptions is the place where the font size is set in my case.

Include the component:

<?php include_component_slot('UserFriendly') ?>
 

Change your i18n file, if you use i18n

Demo at www.noorden.com

by Frank van Noorden on 2008-03-11, tagged change  dynamically  font  friendly  print  printing  set  size  user 

IP number to country

This snippet allows you to retrieve the country of the visitor using the IP number of the visitor. It will also become available as a symfony Plugin.

Very handy when you are developing a internationalized application. You can use the ISO code in lowercase to set the interface language. Like this:

$lang = strtolower(Country::getIso2WithIp(Country::getIpAddress()))
 

By passing the IP number to a function, you'll get the following information: - ISO 3166 Code, 2 characters, might be used to set the culture - Country, 20 characters

The IP data is imported from the webnet77 (http://software77.net/cgi-bin/ip-country/geo-ip.pl) database, probably the most frequently updated database on the web.

Data is stored on your server, that means that retrieving data is a lot faster compared to the already existing plugin sfIp2Country, which uses a web request.

config/schema.xml:

    <table name="YOURDB_country" phpName="Country">
      <column name="ipfrom" type="bigint" size="20" required="true" primaryKey="true" />
      <column name="ipto" type="bigint" size="20" />
      <column name="registry" type="varchar" size="7" />
      <column name="assigned" type="varchar" size="8" />
      <column name="iso2" type="varchar" size="2" />
      <column name="iso3" type="varchar" size="3" />
      <column name="country" type="varchar" size="20" />
    </table>
 

Do a build-model and whatever is needed.

Additions to lib/model/country.php

    static function getIpAddress()
    {
        // Get the ip v4 address
        if (getenv("HTTP_CLIENT_IP")) $ipaddr = getenv("HTTP_CLIENT_IP"); 
        else if(getenv("HTTP_X_FORWARDED_FOR")) $ipaddr = getenv("HTTP_X_FORWARDED_FOR"); 
        else if(getenv("REMOTE_ADDR")) $ipaddr = getenv("REMOTE_ADDR"); 
        else $ipaddr = "127.0.0.1"; // not found, make it localhost
 
        return $ipaddr;
    }
 
    static function retrievePkByIp($ipaddr)
    {
        // Make IP numerical
        $ipnum = sprintf("%u", ip2long($ipaddr));
 
      // lookup IP address 
        $c = new Criteria();
      $c->add(CountryPeer::IPFROM, "'$ipnum' >= ".CountryPeer::IPFROM." and "."'$ipnum' <= ".CountryPeer::IPTO, Criteria::CUSTOM);
        $rs = CountryPeer::doSelectRS($c);   
        $pk = 0;
    while ($rs->next()){
      $pk = $rs->getString(1);
        }
        return $pk;
    }
 
    static function getIso2WithIp($ipaddr)
    {
        // Make IP numerical
        $ipnum = sprintf("%u", ip2long($ipaddr));
 
      // lookup IP address 
        $c = new Criteria();
      $c->add(CountryPeer::IPFROM, "'$ipnum' >= ".CountryPeer::IPFROM." and "."'$ipnum' <= ".CountryPeer::IPTO, Criteria::CUSTOM);
        $rs = CountryPeer::doSelectRS($c);   
        $iso2 = "EN"; // initialize with your default country
    while ($rs->next()){
      $iso2 = $rs->getString(5);
        }
        return $iso2;
    }
 

Helper to demonstrate the works: \apps\frontend\lib\helper\CountryHelper.php

<?php 
 
function display_ipinfo()
{
        // Get IP address and make numeric
        $ipaddr = Country::getIpAddress();
        $ipnum = sprintf("%u", ip2long($ipaddr));
 
        // Retrieve from database
        $country = CountryPeer::retrieveByPk(Country::retrievePkByIp($ipaddr));
 
        // Output
        $o =  '<p>';
        $o .= 'Your IP number: '  . '&nbsp;&nbsp;&nbsp;' . $ipaddr . '<br />';
        $o .= 'Your IP numerical: ' . $ipnum . '<br />';
        $o .= 'Data retrieved from IP database:<br />';
 
        if ($country) // found
        {
            $o .= 'ISO code: ' . $country->getIso2() . '<br />';
            $o .= 'Country: ' . '&nbsp;&nbsp;' . $country->getCountry();
        }
        else                    // not found
        {
            $o .= 'Your IP number was not found in the IP-database';
        }
 
        $o .=  '</p>';
        echo $o;
}
 

Code to call the demo function in the helper:

<?php use_helper('Country'); ?>
<?php display_ipinfo() ?>
 

I load my data with a Cron job, the SQL statement is as follows:

LOAD DATA INFILE 'YOURPATH_IpToCountry.csv' REPLACE INTO TABLE YOURDB_country FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n'
 

Demo at http://www.noorden.com/en/my+symfony+php+projects/project-ip-number-to-country.html

by Frank van Noorden on 2008-03-02, tagged country  database  ip  iso  local  number 
(3 comments)

Avoid use of '

Sometimes the use of &apos; is recommended because single quotes (') and double quotes (") are used in a construction. However, use of &apos; in XHTML should generally be avoided for compatibility reasons. IE7 will give a runtime error on &apos;. You can use numeric character reference &#39; instead.

Following example shows the use of &#39 in combination with link_to_function:

<?php echo link_to_function(image_tag('printer.png', 'alt=Print page friendly') . ' Print', 'printUrl(&#39;/page/print/id/'.$page->getId().'&#39;)') ?>
 
by Frank van Noorden on 2008-01-21, tagged apos  character  linktofunction  numeric  references