I'm using FPDI & FPDF to overlay new text on top of an existing PDF. It uses the useTemplate() method to achieve this.
Problem I'm having - it only applies the template to the first page. If the text is long, it will wrap to a second page, using the SetAutoPageBreak() method. How can I make it apply the template on every page?
I've cracked it. Looking into the code, I realised that even the SetAutoPageBreak() routine calls AddPage() internally, giving me the hook I needed to include my template on every page.
So, I extended the base FPDI class and over-rode the AddPage() method, including the useTemplate() stuff.
class BBPDF extends FPDI {
function AddPage($orientation='', $size='') {
parent::AddPage($orientation,$size);
$this->setSourceFile('templates/discover-community.pdf');
$template = $this->ImportPage(1);
$this->useTemplate($template);
}
}
Related
I would like to create a "cleanup" extension that replaces various characters (quotes by guillemets) in all kinds of textfields in TYPO3.
I thought about extending <f:format.html> or parseFunc, but I don't know where to "plug in" so I get to replace output content easily before it's cached.
Any ideas, can you give me an example?
If you don't mind regexing, try this:
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['cleanUpQuotes'][] = \NAMESPACE\Your\Extension::class;
Insert it into ext_localconf.php and this part is done.
The next step is the class itself:
public function cleanUpQuotes(TypoScriptFrontendController $parentObject)
{
$parentObject->content = DO_YOUR_THING_HERE
}
There also is another possibility which could replace any strings in the whole page - as it operates on the rendered page (and not only on single fields).
You even can use regular expressions.
Look at my answer -> here
Using the infos in this link:
https://docs.typo3.org/typo3cms/ExtbaseFluidBook/8-Fluid/9-using-php-based-views.html
I try to create an action to output a JSON.
I have a normal controller with the list action:
public function listAction()
{
$storelocators = $this->storelocatorRepository->findAll();
$this->view->assign('storelocators', $storelocators);
}
And in ext/my_storelocator/Classes/View/Storelocator I have a class List.php:
<?
class Tx_MyStorelocator_View_Storelocator_List extends Tx_Extbase_MVC_View_AbstractView {
public function render() {
return 'Hello World';
}
}
All I get is:
Sorry, the requested view was not found.
The technical reason is: No template was found. View could not be resolved for action "list" in class "My\MyStorelocator\Controller\StorelocatorController".
So I guess there is something wrong with the paths. Or where is the Problem?
Edit: Extensioninfos
Vendor: My
key: my_storelocator
controller: NOT SURE (I created it with the extension_builder so I guess my controllers name is Storelocator)
action: list
From my understanding a classname like Tx_MyStorelocator_View_Storelocator_List should be correct. But its not working
You will need to create an empty file for the HTML view for your controller, e.g. Resources/Private/Template/Storelocator/List.html, even if you do not plan to use the HTML view or if you just return the content yourself (which is perfectly fine).
The reason for this is simply technical limitation.
First of all, TYPO3 now has a built-in JSON view, described thoroughly here: https://usetypo3.com/json-view.html. It lets you easily define which properties you'd like to render.
The error message means that your Controller is still pointing to the TemplateView - because thats the error the TemplateView throws if it can't find the defined template file.
You can specify which view to use to render within your controller. You can either set a default view via the $defaultViewObjectName property, like so:
/**
* #var string
*/
protected $defaultViewObjectName = '\TYPO3\CMS\Fluid\View\TemplateView';
You can also set it from within the Controller inside initialization actions like so:
public function initializeExportPDFAction(){
$this->defaultViewObjectName = 'Vendor\Extension\View\FileTransferView';
}
(I have, however, not yet found a way to define the template from within actions, any tips in the comments would be appreciated)
Your path syntax is probably out of date. Instead of writing a render() function in Classes/View/Storelocator/List.php, try writing a listAction() function in a Classes/Controller/StorelocatorController.php file. Extension Builder should have created this file for you, if you made an aggregate model with the usual "list, create, edit ..." and such actions.
Review A journey through the Blog Example and the following chapter, Creating a first extension, for tips.
Keep in mind that there is a mismatch between the documentation and the Extension Builder generated PHP code files. Developing TYPO3 Extensions with Extbase and Fluid has some parts up to date, and other parts still using old syntax.
Pretty straight-forward question, but I can't find this anywhere. I'm using WicketStuff's TinyMCE to make a Rich Text Editor in my application, and can't find anywhere how to get the input from the text area. For brevity's sake, the following is a simplified version of the code I'm using.
private String input;
...
TinyMCESettings settings = new TinyMCESettings(TinyMCESettings.Theme.simple);
TextArea<String> textArea = new TextArea<String>("editor", new PropertyModel<String>(this, "input"));
textArea.add(new TinyMceBehavior(settings));
form.add(textArea);
Using this, I would expect the usual manner to simply use my String 'input' since it's set as the model. This always results in null as the model isn't being updated.
I tried using the auto-save plugin in case it was expecting the save button to be clicked (which doesn't update the model either), and neither worked. The only thing I've been able to do to get the user's input is to add a HiddenField, with a new model, and make a JavaScript call like
document.getElementById('hiddenField').value = tinyMCE.get('editor').getContent();
but this has led to other problems with trying to call the JS in the desired place and to get it to work properly. I feel this shouldn't be necessary anyways, as surely someone must have implemented a method to get the contents of the text area being used.
Any help would be greatly appreciated.
Thanks to a blog post at Nevermind Solutions, the way to get the model updated is to add the following JavaScript to the form's submitting button:
onclick="tinyMCE.triggerSave(true,true);"
My text area is inside a panel with the button outside of the panel, so it doesn't directly work for me. The trick was to add the JavaScript call to the button's onSubmit, move the logic into the onAfterSubmit, and to make the button MultiPart so that it could call the save trigger before doing the other logic associated to the model.
Hope this might help some others in the future.
You have to add a modifier to the submit button so that the model can update.
AjaxButton btnSubmit = new AjaxButton("btnSubmit", new Model()) {
#Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
doSomething();
}
};
btnSubmit.add(new TinyMceAjaxSubmitModifier());
Have a look here for more info
I am currently working on a project developed using Zend Framework, based on the structure of my web page design I have reached a point where I have to pass a small number of variables to my layout from each Controller/Action. These variables are:
<?php Zend_Layout::getMvcInstance()->assign('pageId', 'page1'); ?>
<?php Zend_Layout::getMvcInstance()->assign('headerType', '<header id="index">'); ?>
The reason for passing this information is firstly, I pass the page id as the multi column layout may change depending on the content being displayed, thus the page id within the body tag links the appropriate CSS to how the page should be displayed. Secondly I display a promotional jQuery slider only on the index page, but I need the flexibility to have it displayed on potentially multiple pages in case the wind changes and the client changes their mind.
My actual question: Is there a more appropriate method of passing this information to the Layout that I am overlooking?
I am not really questioning whether the information has to be sent, rather is there some Zend Framework feature that I have, in my haste, overlooked which would reduce the amount of repetitive redundant code which may very well be repeated in multiple Actions within the same controller?
You could turn that logic into an action helper than you can call from your controllers in a more direct way. You could also make a view helper to accomplish the same thing but view helpers usually generate data for the view rather than set properties.
// library/PageId.php
class Lib_PageId extends Zend_Controller_Action_Helper_Abstract
{
public function direct($title, $pageId, $headerType)
{
$view = $this->getActionController()->view;
$view->headTitle()->append($title);
$view->pageId = $pageId;
$view->headerType = $headerType;
}
}
In your controller actions you can now do this:
$this->_helper->PageId('Homepage', 'page1', 'index');
// now pageId and headerType are available in the view and
// Homepage has been appended to the title
You will also need to register the helper path in your Bootstrap like this:
protected function _initActionHelpers()
{
Zend_Controller_Action_HelperBroker::addPrefix('Lib');
}
Doing it like that can reduce the amount of repetitive code and remove needing to assign the values from the view. You can do it in the controller very quickly. You can also have default values in the case that the helper hasn't been called.
You shoudn't really be passing anything from the view to the layout, for a start the view should be included IN the layout, not the other way around.
So, setting your page title should be done using similar code to what you have, but inside the controller action being called:
$this->view->headTitle()->append('Homepage');
And the other two issues - you need to rethink as I stated to begin with. Maybe you're misunderstanding the layout/view principle? If you include the different views per action, then you simply change the div id when needed, and include the header for your banner only in the index.phtml file.
I want to add some javacsript to a Zend_Form_Element_Text .
At first I thought a decorator would be the best way to do it, but since it is just a script (the markup doesn't change) then maybe a view helper is better? or a view script?
It seems like they are all for the same purpose (regarding a form element).
The javascript I want to add is not an event (e.g. change, click, etc.). I can add it easily with headScript() but I want to make it re-usable , that's why I thought about a decorator/view helper. I'm just not clear about the difference between them.
What is the best practice in this case? advantages?
UPDATE: Seems like the best practice is to use view helpers from view scripts , so decorators would be a better fit?
Thanks.
You could create your own decorator by extending Zend_From_Decorator_Abstract and generate your snippet in it's render() method :
class My_Decorator_FieldInitializer extends Zend_Form_Decorator_Abstract {
public function render($content){
$separator = $this->getSeparator();
$element = $this->getElement();
$output = '<script>'.
//you write your js snippet here, using
//the data you have in $element if you need
.'</script>';
return $content . $separator . $output;
}
}
If you need more details, ask for it in a comment, i'll edit this answer. And I didn't test this code.
Use setAttrib function.
eg:-
$element = new Zend_Form_Element_Text('test');
$element->setAttrib('onclick', 'alert("Test")');
I'm not actually seeing where this needs to be a decorator or a view-helper or a view-script.
If I wanted to attach some client-side behavior to a form element, I'd probably set an attribute with $elt->setAttrib('class', 'someClass') or $elt->setAttrib('id', 'someId'), some hook onto which my script can attach. Then I'd add listeners/handlers to those targeted elements.
For example, for a click handler using jQuery , it would be something like:
(function($){
$(document).ready(function(){
$('.someClass').click(function(e){
// handle the event here
});
});
})(jQuery);
The benefit is that it is unobtrusive, so the markup remains clean. Hopefully, the javascript is an enhancement- not a critical part of the functionality - so it degrades gracefully.
Perhaps you mean that this javascript segment itself needs to be reusable across different element identifiers - someClass, in this example. In this case, you could simply write a view-helper that accepts the CSS class name as the parameter.
"the markup doesn't change", Yap,
but I like to add some javascript function throw ZendForm Element:
$text_f = new Zend_Form_Element_Text("text_id");
$text_f->setAttrib('OnChange', 'someFunction($(this));');
The best way is if you are working with a team, where all of you should use same code standard. For me and my team this is the code above.