tag:blogger.com,1999:blog-7593205560200912002024-03-13T21:23:01.735+01:00CakePHP :: Tips, tutorials and solutionsCakePHP blog :: Tutorials, tips and solutionsChrupkahttp://www.blogger.com/profile/02023619836696438714noreply@blogger.comBlogger3125tag:blogger.com,1999:blog-759320556020091200.post-91098407141378319422012-02-06T14:56:00.002+01:002012-02-06T15:04:59.794+01:00CakePHP - AJAX observeField in JsHelper with PrototypeCreating an <b>equivalent of $ajax->observeField with the new JsHelper</b> is quite simple. With the help of JsHelper you can <b>retrive the value of single field to your AJAX action</b>, as well as <b>retrive the values of all fields in the form</b>.<br />
<br />
I will present it on example of registration form in which we want to check if given field is valid after the field is updated (so, it's kind of registration form with validation of user data on the fly).<br />
<br />
Let's assume that registration form is held by the "register" action in UsersController, and the action which validates the fields (and to which we make AJAX call) is "verify".<br />
<ol>
<li><b>Include JsHelper in your controller where you want to use it.</b> <br />You should also define which JavaScript library you want to use. Default is JQuery, I use Prototype.<br /><blockquote class="tr_bq">
public $helpers = array('Js'=>array('Prototype'));</blockquote>
</li>
<li><b>If you use Security component in your controller, you should disable validatePost and csrfCheck in the action to which you make an AJAX call.</b><br />In our example with validating registration form - we should turn off validatePost and csrfCheck for the "verify" action. This can be done in the beforeFilter() function inside our controller:<br /><blockquote class="tr_bq">
public function beforeFilter() {<br />
parent::beforeFilter();<br />
if($this->params['action']=='verify') {<br />
$this->Security->validatePost=false;<br />
$this->Security->csrfCheck=false;<br />
}<br />
}</blockquote>
</li>
<li><b>Next, you should include a JavaScript library which you use, in the top of the view where the form is displayed</b> (in our example - in "register" view).<br /><blockquote class="tr_bq">
<?php echo $this->Html->script('prototype',false);?></blockquote>
(If you set the second parameter to false, the script will be put into the <head> section).<br />Of course if the library has already been included in the layout for other purposes - you don't need to double it in the view.<br /></li>
<li><b>Next, in the layout</b> which holds the registration form, <b>you should add a
writeBuffer method</b>, which will output buffered scripts. The writeBuffer
method should be placed before the </body> tag.<br />
<blockquote class="tr_bq">
<?php if($this->params['action']=='register'):?><br />
<?php echo $this->Js->writeBuffer();?><br />
<?php endif;?></blockquote>
</li>
<li> <b>Now, let's create a simple registration form with empty message div's to update after field validation</b>:<br /><blockquote class="tr_bq">
<?php echo $this->Form->create('User',array('controller'=>'users','action'=>'register'))?><br />
<div><br />
Login: <?php echo $this->Form->text('login',array('id'=>'login'));?><br />
<div id="message-login"></div><br />
</div><br />
<div><br />
Password: <?php echo $this->Form->text('password',array('id'=>'password'));?><br />
<div id="message-password"></div><br />
</div><br />
<?php echo $this->Form->submit('Register',array('div'=>false))?></div><br />
<?php echo $this->Form->end();?></blockquote>
</li>
<li><b>Next, add JsHelper event "onchange" for both fields</b> (of course you can change the event from "change", which will update given element after you leave the input, to any other of the
normal DOM events, such as "keyup" for "onkeyup", "click" for "onclick" etc.):<blockquote class="tr_bq">
<?php echo $this->Form->create('User',array('controller'=>'users','action'=>'register'))?><br />
<div><br />
Login: <?php echo $this->Form->text('login',array('id'=>'input_login'));?><br />
<div id="message-login"></div><br />
<?php $this->Js->get('#input_login');?><br />
<?php <br />
echo $this->Js->event('change',<br />
$this->Js->request(<br />
'/users/verify/login',<br />
array(<br />
'method'=>'post', <br />
'async'=>true, <br />
'update'=>'#message-login', <br />
'dataExpression'=>true, <br />
'data'=>'$("input_login").serialize()',<br />
)<br />
)<br />
);<br />
?><br />
</div><br />
<div><br />
Password: <?php echo $this->Form->text('password',array('id'=>'input_password'));?><br />
<div id="message-password"></div><br />
<?php $this->Js->get('#input_password');?><br />
<?php <br />
echo $this->Js->event('change',<br />
$this->Js->request(<br />
'/users/verify/password', <br />
array(<br />
'method'=>'post', <br />
'async'=>true, <br />
'update'=>'#message-password', <br />
'dataExpression'=>true, <br />
'data'=>'$("input_password").serialize()',<br />
)<br />
)<br />
);<br />
?><br />
</div><br />
<?php echo $this->Form->submit('Register',array('div'=>false))?></div><br />
<?php echo $this->Form->end();?></blockquote>
</li>
<li><b>Your "verify" function could look like this:</b><br /><blockquote class="tr_bq">
public function verify($field) {<br />
$this->layout = 'blank';<br />
if($field!=NULL) {<br />
$fields=array('login','password');<br />
if(in_array($field,$fields)) {<br />
App::uses('Sanitize','Utility');<br />
Sanitize::clean($this->request->data['User'][$field]);<br />
$this->User->set($this->request->data);<br />
if(!$this->User->validates()) {<br />
$this->validateErrors($this->User);<br />
$errors=$this->validationErrors;<br />
$this->set('errors',$errors);<br />
}<br />
$this->set('field',$field));<br />
}<br />
}<br />
}</blockquote>
Of course you should define the <b>$validate</b> variable in the model to verify if the given field validates.<br /> <br />
</li>
<li><b>The AJAX view for "verify" could look like this:</b><br /><blockquote class="tr_bq">
<?php if(isset($errors[$field]) && !empty($errors[$field])):?><br />
<div class="error-message"><br />
<?php foreach($errors[$field] as $error):?><br />
<?php echo $error?><br/><br />
<?php endforeach;?><br />
</div><br />
<?php else:?><br />
OK<br />
<?php endif;?></blockquote>
</li>
</ol>
<br />
Above solution allows to retrieve the value of <b>only one field</b> from the form.<br />
If you need to retrive more than one field from a form (for example if you want to compare "password" and "repeat password" fields), you should set the<b> 'data'</b> option as follows:<br />
<blockquote class="tr_bq">
<?php $this->Js->get('#<i>id_of_field_to_observe</i>');?><br />
<?php <br />
echo $this->Js->event('change',<br />
$this->Js->request(<br />
array('controller'=>'<i>controller</i>','action'=>'<i>action</i>', <i>parameters</i>), <br />
array(<br />
'method'=>'post', <br />
'async'=>true, <br />
'update'=>'#<i>id_of_element_to_update</i>', <br />
'dataExpression'=>true, <br />
'data'=>$this->Js->serializeForm(array('isForm'=>false, 'inline'=>true))<br />
)<br />
)<br />
);<br />
?> </blockquote>
<br />
This will allow you to retrieve data from whole form.<br />
<br />
Have fun playing with JsHelper;-)Chrupkahttp://www.blogger.com/profile/02023619836696438714noreply@blogger.com0tag:blogger.com,1999:blog-759320556020091200.post-34060598635725924552012-02-03T11:19:00.000+01:002012-02-03T11:27:49.832+01:00CakePHP 2.x & JS scripts in AJAX viewSometimes, after making an AJAX request, we want to use JS scripts in the view of AJAX function.<br />
I was having a trouble with that after switching to 2.0.5 version - a simple AJAX view, including only a text message and a bit of JavaScript code - didn't render and run the script at all.<br />
<br />
The solution for this is an <i>evalScripts</i> option in JsHelper.<br />
If you want your AJAX view to display and run <script>'s, simply add this option to your AJAX call.<br />
<br />
For example:<br />
<br />
<?php<br />
echo $this->Js->link('update',<br />
array('controller' => <i>'controller</i>', 'action' -> <i>'action</i>'),<br />
array(<br />
'update' => '#<i>id_of_element_to_update</i>',<br />
<b>'evalScripts' => true,</b><br />
)<br />
);<br />
?><br />
<br />Chrupkahttp://www.blogger.com/profile/02023619836696438714noreply@blogger.com0tag:blogger.com,1999:blog-759320556020091200.post-24512508003336390652012-01-23T14:28:00.000+01:002012-01-25T21:43:28.673+01:00CKEditor + KCFinder integration with CakePHP - tutorialLately I have been developing an application based on the new version of CakePHP (I am currently switching from 1.3 to 2.0.5).<br />
<span class="short_text" id="result_box" lang="en"><span class="hps">Together</span> <span class="hps">with the change of CakePHP version, I also wanted to implement the new version of WYSIWYG editor - so far I've been using <i>FCKeditor</i>, which is no longer developed and which was replaced with <i>CKEditor</i>. I decided to move on with <i>CKEditor</i>.</span></span><br />
<span class="short_text" id="result_box" lang="en"><span class="hps"><i>CKEditor</i> is also free and open source like <i>FCKeditor</i>, but there is a small difference between these two editors. <i>FCKeditor</i> had a built-in option of file managment (for example browsing server or file upload in insert image file option), which <i>CKEditor</i> doesn't have in the free and open source version. The file manager which can be used along with <i>CKEditor</i> is <i>CKFinder</i> - but this software isn't free. You have to buy licence to use it.</span></span><br />
<span class="short_text" id="result_box" lang="en"><span class="hps">But there is a workaround - we can use a free <i>KCFinder</i> file manager, which can be easily integrated into <i>CKEditor</i> and other editors (<i>FCKeditor</i>, <i>TinyMCE</i>).</span></span><br />
<br />
For the purpose of tutorial let's assume that our Cake application is being stored on our localhost and the "webroot" of our application is under "http://localhost/".<br />
<br />
The following instructions were made based on a following versions of software:<br />
<ul>
<li>CakePHP 2.0.5</li>
<li>CKEditor 3.6.2</li>
<li>KCFinder <span id="version">2.51</span></li>
</ul>
<br />
<b>How to install and integrate CKEditor to CakePHP? </b><br />
<ol>
<li>Download <i>CKEditor</i> from <a href="http://www.ckeditor.com/" target="_blank">www.ckeditor.com</a></li>
<li>Copy files from the zipped folder to "webroot/js/ckeditor/"</li>
<li>In the view where you want to display the editor, put the following script on the top of the page (or somewhere before textarea which you want to contain editor):<br /><blockquote class="tr_bq" style="font-family: inherit;">
<?php echo $this->Html->script('ckeditor/ckeditor');?></blockquote>
This scipt will include the "webroot/js/ckeditor.js" file to your view. </li>
<li>Create the textarea and give it a class named "ckeditor"<br /><blockquote class="tr_bq">
<?php echo $this->Form->textarea('content',array('class'=>'ckeditor'))?></blockquote>
</li>
</ol>
Voila! The editor is now displaying instead of raw textarea.<br />
<br />
<br />
<b>How to install and integrate KCFinder to CakePHP?</b><br />
<ol>
<li>Download <i>KCFinder</i> from <a href="http://kcfinder.sunhater.com/" target="_blank">kcfinder.sunhater.com </a></li>
<li>Copy files from the zipped folder to "webroot/js/kcfinder/"</li>
<li>Open "webroot/js/kcfinder/config.php" file.<br />In this file you can set several configurations, but we will focus on the ones that are most important for our file manager to work.<br /><i>KCFinder</i> is disabled by default.<br />If you want to give the ability of using file manager to all users in your website (so with no restrictions), change the value of 'disabled' to false.<br /><blockquote class="tr_bq">
'disabled' => false,</blockquote>
But giving everyone access to managing files on the server is probably not a good idea. Instead of this, you can enable file managment only when a specified session variable is set. The name of the session variable is on the bottom of config.php file:<br /><blockquote class="tr_bq">
'_sessionVar' => &$_SESSION['KCEDITOR'],</blockquote>
So, this is what you should do to make the file manager available after an authenticated user logs in:<br /><ul>
<li>leave the "disabled" to "true"</li>
<li>in the controller where you do the user authentication, after user has successfully logged in, enter this code to override the "disabled" value:<br /><blockquote class="tr_bq">
$_SESSION['KCEDITOR']['disabled']=false;</blockquote>
Remember to destroy this session variable after user logs out. <br />
</li>
<li>on the top of the "webroot/js/kcfinder/core/autoload.php" file insert:<br /><blockquote class="tr_bq">
session_name('CAKEPHP');</blockquote>
</li>
</ul>
</li>
<li>Still in the "config.php" file define the folder for uploaded files. By default the folder is "upload" in "kcfinder" directory. <br />If you are developing an application on your localhost and the "webroot" is under a "http://localhost/" address, and you want to keep uploaded files in "webroot/upload" folder, the 'uploadURL' configuration should look like:<br /><blockquote class="tr_bq">
'uploadURL' => "/app/webroot/upload",</blockquote>
If you are developing your application under for example "http://localhost/my_app/" address, the uploadURL should look like:<br /><blockquote class="tr_bq">
'uploadURL' => "/my_app/app/webroot/upload",</blockquote>
</li>
</ol>
You can test if <i>KCFinder</i> displays and works correctly under the URL:<br />
http://<i>path_to_your_app</i>/js/kcfinder/browse.php<br />
<br />
<br />
<b>How to integrate KCFinder to CKEditor in CakePHP?</b><br />
Open the "webroot/js/ckeditor/config.js" file and modify editor config to contain following code:<br />
<blockquote class="tr_bq">
CKEDITOR.editorConfig = function( config )<br />
{<br />
config.filebrowserBrowseUrl = '/js/kcfinder/browse.php?type=files';<br />
config.filebrowserImageBrowseUrl = '/js/kcfinder/browse.php?type=images';<br />
config.filebrowserFlashBrowseUrl = '/js/kcfinder/browse.php?type=flash';<br />
config.filebrowserUploadUrl = '/js/kcfinder/upload.php?type=files';<br />
config.filebrowserImageUploadUrl = '/js/kcfinder/upload.php?type=images';<br />
config.filebrowserFlashUploadUrl = '/js/kcfinder/upload.php?type=flash';<br />
};</blockquote>
<br />
If your app is being developed under for example http://localhost/my_app/, remember to put the whole path in the URLs, for example:<br />
<blockquote class="tr_bq">
config.filebrowserBrowseUrl = '/my_app/js/kcfinder/browse.php?type=files';</blockquote>
After adding above six lines of code in the <i>CKEditor</i> configuration you should be able to see "Browse" button in image / link / Flash insert options.<br />
<br />
And that's it!:-)<br />
<br />Chrupkahttp://www.blogger.com/profile/02023619836696438714noreply@blogger.com40