While separating your HTML and Javascript is a good idea, generating a Javascript file may be overkill for achieving this and also be a lot harder to maintain than it should be.
The best way i've found is to add simple plugin functions to Smarty to allow you to generate all of the HTML and Javascript associated with 'widgets' that appear many times throughout your site.
These plugin functions should:
- Generate all the HTML for a widget, so that you don't have to repeat HTML between different Smarty templates.
- Generate all the Javascript that a widget requires, so that you don't have to be writing Javascript in a Smarty template (which is almost always a bad idea - you should just be calling functions).
- Separates the generating of Javascript from actually outputting in the page, to allow you to control where the Javascript is actually placed.
PHP code to add functions to Smarty
$GLOBALS['pageJavascript'] = array();
$smarty->registerPlugin("function", "addButton", "addButtonSmarty");
$smarty->registerPlugin("function", "displayPageJavascript", "displayPageJavascript");
//Outputs the HTML for a button, generates the associated Javascript and either
//outputs that Javascript or saves it for later.
function addButtonSmarty($params, &$smarty){
if(isset($params['operation']) == FALSE){
return "operation not set.";
}
if(isset($params['tabID']) == FALSE){
return "tabID not set.";
}
$tabID = $params['tabID']
$operation = $params['operation'];
$uniqueID = "buttonEditOperation_".$operation;
addButtonJavascript($tabID, $operation);
echo "<button id='buttonEditOperation_".$operation."' />";
}
function addButtonJavascript($tabID, $operation){
$javascript = "
$('#tabContent_".$tabID." [id^=\"buttonEditOperation_".$operation."\"]')
.click( function() { alert('CLICK !'); })
.button(blabla);";
if(FALSE){
//You can just add the Javascript directly to the web page, however in this case
//it may throw an error if the user clicks on something before jQuery is
//fully loaded.
echo "<script type="text/javascript">";
echo $javascript;
echo "</script>";
}
else{
//Much better is to save the Javascript to be included later.
$GLOBALS['pageJavascript'][] = $javascript;
}
}
function displayPageJavascript(){
echo "<script type="text/javascript">";
foreach($GLOBALS['pageJavascript'] as $pageJavascript){
echo $pageJavascript;
echo "\n";
}
echo "</script>";
}
Wherever you add a button, instead of adding it directly, do:
{addButton tabID=$uniqueId operation=$op}
So your Smarty template would look like:
Smarty Template
<script type="text/javascript" src="./js/buttonInit.js"></script>
<div id="tabContent_{$uniqueId}">
<table>
{foreach $operations as $op}
<tr><td>{addButton tabID=$uniqueId operation=$op}</td></tr>
{/foreach}
</table>
</div>
...
...
...
<!-- bottom of smarty template -->
{displayPageJavascript}
Before anyone jumps in and says that writing HTML and Javascript in PHP is ugly and shouldn't be done - I fully agree!
However in this case the benefits of writing widgets as plugins in Smarty so outweigh the uglyness:
- It makes the Javascript for manipulating a widget be within a few lines of the HTML for the widget, which makes it a lot easier to write and debug that widget, compared to having them in separate files.
- Having the implementation of a widget be hidden from the Smart template, means that you can change it's implementation once in one place, and be sure that every use of that widget will be updated.
- It makes the code be a lot more reliable as you template editors don't have to remember to separately add Javascript for any widget that they add, so there will be a lot fewer mistakes in editing the template.