dojo 1.1.1 to 1.6.1 Declarative Tag Update Script

This script performs the bulk of the upgrade translation to translate declarative tags from older versions of dojo up to the 1.6 format.

The script was written to work with tags in Smarty templates, so it includes a little extra logic to avoid confusion with Smarty syntax within the tags. If you’re not using Smarty, the script should still run fine, but you will need to change {ldelim} to { and {rdelim} to }.

Example of a simple translation performed by the tool.

Original

<label for="iDisplayMaxOffset">{#max_offset#}</label>
<input type="text" class="medium"
  name="iDisplayMaxOffset" id="iDisplayMaxOffset"
  dojoType="dijit.form.ValidationTextBox"
  readonly="true"
  value="{$iMaxOffset+1}" />

<label for="iDisplayMaxOffset">{#max_offset#}</label>
<input data-dojo-type="dijit.form.ValidationTextBox" data-dojo-props="'type':'text','class':'medium','name':'iDisplayMaxOffset','id':'iDisp
layMaxOffset','readonly':'true','value':'{$iMaxOffset+1}'">

Note that the attribute names are enclosed in single quotes. If there is a class attribute, for a custom CSS override, Internet Explorer (version 7, possibly others) requires the class attribute name to be quoted, or it may cause errors.

If a tag is too complex for this tool, it will output text recommending manual review, as well as the original tag, so you can fix any errors. In the translation below, the tool removed some of the message text.


{**** MANUAL REVIEW RECOMMENDED ****}
{**** 
<input type="text"
  name="sText" id="sText"
  regExp="{$sExtLngRegExp}"
  dojoType="dijit.form.ValidationTextBox"
  promptMessage="{#C_enter#} {#text#}"
  invalidMessage="{#C_invalid#} {#text#}"
  errorMessage="{#C_invalid#} {#text#} {#C_refer_to_documentation#}"
  value="{$sText}"
  onChange="setDataChanged()" />
****}
<input data-dojo-type="dijit.form.ValidationTextBox" data-dojo-props="'type':'text','name':'sText','id':'sText','regExp':'{$sExtLngRegExp}','promptMe
ssage':'{#C_enter#}','invalidMessage':'{#C_invalid#}','errorMessage':'{#C_invalid#}','value':'{$sText}','onChange':function(e){ldelim}setDataChanged(){rdelim}">

This is a command line script, run it with php dojo-tag.php old.file.html

<?php

$aEvents=array
('onblur'=>'onBlur',
'onchange'=>'onChange',
'onclick'=>'onClick',
'onclose'=>'onClose',
'ondblclick'=>'onDblClick',
'onfocus'=>'onFocus',
'onkeydown'=>'onKeyDown',
'onkeypress'=>'onKeyPress',
'onmousedown'=>'onMouseDown',
'onmouseenter'=>'onMouseEnter',
'onmouseleave'=>'onMouseLeave',
'onmousemove'=>'onMouseMove',
'onmouseout'=>'onMouseOut',
'onmouseover'=>'onMouseOver',
'onmouseup'=>'onMouseUp');

$aDeprecated=array('dijit.layout.AccordionPane'=>'dijit.layout.ContentPane');

$aDojoRequires=array();

$sFileText=file_get_contents($argv[1]);

$sNewText=preg_replace_callback('/(^\s*dojo\.require\s*\([\'"]([^\'^"]*)[\'"]\);[\r\n\s]*$)/m','requires',$sFileText);

$sUpdatedText=preg_replace_callback('/(<)(\w+) +([^>]*)(\/?>)/im','tags',$sNewText);

echo $sUpdatedText.PHP_EOL;

file_put_contents('/tmp/NEW',$sUpdatedText);

function requires($aMatches)
{
        global $aDeprecated,$aDojoRequires;
        $sDijit=trim($aMatches[2]);
        if (array_key_exists($sDijit,$aDeprecated))
                $sDijit=$aDeprecated[$sDijit];
        if (!in_array($sDijit,$aDojoRequires))
        {
                $aDojoRequires[]=$sDijit;
                return 'dojo.require("'.$sDijit.'");';
        }
        return '';
}

function tags($aMatches)
{
        global $aDeprecated;
        $sText=$aMatches[0];
        if (strpos($sText,'dojoType')!==false)
        {
                $sDataDojoType='';$aDojoText=array();$sDojoText='data-dojo-props=';$bFlagForReview=false;
                $sDataDojoId='';
                $aText=array();

                $sAttributeText=$aMatches[3];
                if (($iLeft=strpos($sAttributeText,'{'))!==false) 
                {
                        $iRight=strpos($sAttributeText,'}');
                        $iCountLeft=substr_count($sAttributeText,'{');
                        $iCountRight=substr_count($sAttributeText,'}');
                        if (($iLeft>$iRight) || ($iCountLeft>1) || ($iCountRight>1))
                                $bFlagForReview=true;
                }

                preg_match_all('/([a-zA-Z]+=[^>\s]+)/m',$sAttributeText,$aText);
                foreach ($aText[0] as $k => $v)
                {
                        if (stripos($v,'dojoType=')!==false)
                        {
                                $sDataDojoType=substr(str_replace(array('\'','"'),'',trim($v)),9);
                                $bDeprecated=array_key_exists($sDataDojoType,$aDeprecated);
                                if ($bDeprecated!==false)
                                {
                                        $bFlagForReview=true;
                                        $sDataDojoType=$aDeprecated[$sDataDojoType];
                                }
                                $sDataDojoType='"'.$sDataDojoType.'"';
                        }
                        else
                                if (stripos($v,'jsId=')!==false)
                                        $sDataDojoId='data-dojo-id='.substr($v,5);
                                else
                                        $aDojoText[]=pair($v,$bFlagForReview);
                }
                if (count($aDojoText)>0)
                        $sDojoText.='"'.implode(',',$aDojoText).'"';
                $sFlag=($bFlagForReview)?'{**** MANUAL REVIEW RECOMMENDED ****}'.PHP_EOL.
                        '{**** '.PHP_EOL.$sText.PHP_EOL.'****}'.PHP_EOL:'';
                $sClose=(strpos($sText,'/>')===false)?'>':' />';
                return $sFlag.$aMatches[1].$aMatches[2].' data-dojo-type='.$sDataDojoType.' '.$sDojoText.$sClose;
        }
        else
                return $sText;
}


function pair($value,&$bFlagForReview)
{
        global $aEvents;
        $iEqual=strpos($value,'=');
        $sProperty=substr($value,0,$iEqual);
        $sValue=substr($value,$iEqual+1);
        $sProperty=str_replace(array('\'','"'),'',trim($sProperty));
        $sValue=str_replace(array('\'','"'),'',trim($sValue));
        $bEvent=array_key_exists($sPropertyIndex=strtolower($sProperty),$aEvents);
        if ($bEvent===false)
                        $sRetVal='\''.$sProperty.'\':\''.$sValue.'\'';
        else
        {
                $bFlagForReview=true;
                $sRetVal='\''.$aEvents[$sPropertyIndex].'\':function(e){ldelim}'.$sValue.'{rdelim}';
        }

        return $sRetVal;
}

This is a simple tool, it is intended to be run on one file at a time, with the output reviewed carefully.

This script will upgrade most of the javascript, be sure to check the code carefully after it runs.

#!/bin/bash

# dojo 1.1.1 to dojo 1.6.1 javascript upgrade script

if [ $# -lt 1 ]
then
        echo 'Usage: dojo-js.sh <filename>'
        exit;
fi

NEW='/tmp/NEW'
cp $1 $NEW

sed --in-place "/attr([^\,^)]*)/s/attr/get/g" $NEW

# Must run AFTER the line above
sed --in-place "s/attr/set/g" $NEW
sed --in-place "s/\(\.set('value',[^\)]*\))/\1,false)/g" $NEW

sed --in-place "s/\.setValue\ *( *\([^\)]* *\))/.set('value',\1,false)/g" $NEW

sed --in-place "s/\.getValue\ *( *\([^\)]* *)\)/.get('value')/g" $NEW

sed --in-place "s/json-comment-filtered/json/" $NEW

sed --in-place "s/getDescendants\(.*\)$/getChildren\1 \/\/**** MANUAL REVIEW RECOMMENDED/" $NEW

sed --in-place "s/setHref(/set('href',/g" $NEW

sed --in-place "s/setAttribute/set/g" $NEW

sed --in-place "s/\.checked\s*\=\s*\(true\|false\)/.set('checked',\1)/g" $NEW
sed --in-place "s/\.checked/.get('checked')/g" $NEW

sed --in-place "s/getDisplayedValue()/get('displayedValue')/g" $NEW

sed --in-place "s/setLabel(/set('label',/g" $NEW

*** Make a backup before using these tools ***