I inadvertently sent this from the wrong email account earlier, and it seems to have vanished into a black hole. I'm resending again, from the correct email account. My apologies if the other turns up as a duplicate.

Hello,
For my work on Practical Plants (http://practicalplants.org/wiki), I needed to be able to control the HTML which was output by multiple template instances. Currently the HTML is hardcoded within the SF parser and there are no hooks available to modify it's output. While my need may be a fringe case, I think hardcoded HTML with no way to override it encourages hacking the core files: A Very Bad Thing. I'd like to submit my changes for inclusion into SF core, so I'm looking for feedback on the changes I'm proposing. I've attached a patch for SF_FormPrinter.php and SemanticForms.php and a new class file SF_MultipleTemplate.php, at the end of this email. 

I've made the following SF hooks available to modify the HTML output of a multiple template instance. In order to make these hooks flexible, I wanted to be able to supply an object instance which contained information about the Multiple Template Instance being parsed. To do this, I extracted most of the logic for outputting multiple template instances into a new class SFMultipleTemplate which is responsible for defining the default HTML (which is currently hardcoded in SFFormPrinter),  and for running the following hooks, which it passes the default html by reference to allow for modification, and the SFMultipleTemplate instance which is calling the hook, to give access to data about the Multiple Template Instance in question.

Here are the hooks I've created, based on the default HTML currently used.

sfMultipleInstanceTemplateBeforeHTML (String &$html, SFMultipleTemplate $template)
Allows the customisation of the HTML which is output before the list of template instances. 

sfMultipleInstanceTemplateAfterHTML (String &$html, SFMultipleTemplate $template)
Allows the customisation of the HTML which is output after the list of template instances.

sfMultipleInstanceTemplateHTML (String &$html, String $content, SFMultipleTemplate $template)
Allows the customisation of the html which wraps a multiple template instance item.

sfMultipleInstanceTemplateAdderHTML (String &$html, String $content, SFMultipleTemplate $template)
Same as above, except this sets the hidden multiple template instance item which is cloned by the frontend _javascript_ when the add button is clicked.

sfMultipleInstanceTemplateInnerHTML (String &$html, String $section, SFMultipleTemplate $template)
Allows the customisation of the html of the multiple template instance item. The html returned by this must contain the close and reorder icons. Passing some isolated default html for those icons, or providing get methods in SFMultipleTemplate might be a good idea.



Practical Plants Use Case
I use these hooks to render multiple template instance items as rows of a table for my references. You can see it in action here:





  //we have to str_replace some faux td elements since mediawiki doesn't allow <td> elements in wikitext without an enclosing table element




Attachment: SF_FormPrinter.patch
Description: Binary data



Patch for SemanticForms.php

Attachment: SemanticForms.php.patch
Description: Binary data



New class file SF_MultipleTemplate.php
<?php
class SFMultipleTemplate{

	public $template_name,
		   $disabled,
		   $section,
		   $add_button_text,
		   $instance = 0;

	public static $instances = array();

	public function getInstance($template_name){
		if(!isset(self::$instances[$template_name]))
			self::$instances[$template_name] = new self($template_name);
		return self::$instances[$template_name];
	}

	private function __construct($template_name){
		$this->template_name = $template_name;
		$this->add_button_text = wfMsg( 'sf_formedit_addanother' );
	}

	public function setDisabled($bool=true){
		$this->disabled = $bool;
	}
	public function setSection($section){
		// Add the character "a" onto the instance number of this input
		// in the form, to differentiate the inputs the form starts out
		// with from any inputs added by the Javascript.
		$this->section = str_replace( '[num]', '['.$this->instance.'a]', $section );
	}

	public function increment(){
		$this->instance++;
	}
		/**
	 * Creates the HTML for the inner table for every instance of a
	 * multiple-instance template in the form.
	 */
	public function innerHTML( ) {
		global $sfgTabIndex, $sfgScriptPath;

		$attributes = array(
			'tabindex' => $sfgTabIndex,
			'class' => 'remover',
		);

		$rearranger = 'class="rearrangerImage"';

		if ( $this->disabled ) {
			$attributes['disabled'] = 'disabled';
			$rearranger = '';
		}

		$removeButton = Html::input( null, wfMsg( 'sf_formedit_remove' ), 'button', $attributes );

		$html = <<<END
			<table>
			<tr>
			<td>$this->section</td>
			<td class="removeButton">$removeButton</td>
			<td class="instanceRearranger">
			<img src="$sfgScriptPath/skins/rearranger.png" $rearranger />
			</td>
			</tr>
			</table>
END;
		
		wfRunHooks( 'sfMultipleInstanceTemplateInnerHTML', array( &$html, &$this->section, $this ) );

		return $html;
	}

	/**
	 * Creates the HTML for a single instance of a multiple-instance template;
	 * plus the end tags for the full multiple-instance HTML.
	 */
	public function itemHTML() {

		//wrap the content in the inner html
		
		$content = $this->innerHTML();

		$html = "\t\t" . Html::rawElement( 'div',
			array(
				// The "multipleTemplate" class is there for
				// backwards-compatibility with any custom CSS on people's
				// wikis before SF 2.0.9.
				'class' => "multipleTemplateInstance multipleTemplate"
			),
			$content
		) . "\n";

		wfRunHooks( 'sfMultipleInstanceTemplateHTML', array( &$html, $content, $this ) );
		

		return $html;
	}

	public function adderHTML(){
		//wrap the content in the inner html
		$content = $this->innerHTML();

		$html = "\t\t" . Html::rawElement( 'div',
				array(
					'class' => "multipleTemplateStarter",
					'style' => "display: none",
				),
				$content
			) . "\n";
			
		wfRunHooks( 'sfMultipleInstanceTemplateAdderHTML', array( &$html, &$content, $this ) );

		return $html;
	}

	function addButtonHTML(){
		global $sfgTabIndex;

		$attributes = array(
			'tabindex' => $sfgTabIndex,
			'class' => 'multipleTemplateAdder',
		);
		if ( $this->disabled ) 
			$attributes['disabled'] = true;

		$html = Html::input( null, Sanitizer::decodeCharReferences( $this->add_button_text ), 'button', $attributes );

		wfRunHooks( 'sfMultipleInstanceTemplateAddButtonHTML', array( &$html, $this->add_button_text, $attributes, $this ) );

		return $html;
	}

	function beforeHTML(){
		$html = "\t" . '<div class="multipleTemplateWrapper">' . "\n"
				.  "\t" . '<div class="multipleTemplateList">' . "\n";

		wfRunHooks( 'sfMultipleInstanceTemplateBeforeHTML', array( &$html, $this ) );

		return $html;
	}

	function afterHTML(){
		$button = $this->addButtonHTML();

		$html = '</div>'
				. $button
				.'</div>';

		wfRunHooks( 'sfMultipleInstanceTemplateAfterHTML', array( &$html, $this ) );

		return $html;
	}

}



Any feedback would be appreciated. I'd love to have this included in the core so I can implement the functionality I need without having a custom core hack!

Thanks
Andru Vallance


------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_sfd2d_oct
_______________________________________________
Semediawiki-devel mailing list
Semediawiki-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/semediawiki-devel

Reply via email to