Cakephp with Ajax, this.element.setAttribute is not a function - ajax

I'm trying to make a stackoverflow like tags system.
I followed this tutorial (in French): http://www.formation-cakephp.com/34/autocomplete-en-ajax which uses Prototype and Scriptaculous. Of course, I adapted it to my project
I get the following error:
this.element.setAttribute is not a function : controls.js Line 86
which corresponds to
this.element.setAttribute('autocomplete','off');
in the control.js file
I'm really new to Ajax, so I don't have a clue on what I'm doing (wrong)...
If you need some code from any file, let me know!
view.ctp:
<div class="input">
<label>Tags :</label>
<?php e($ajax->autoComplete(
'Tag.tag',
'/tags/autocomplete',
array(
'minChars' => 3,
'indicator' => 'ajaxloader'
)
)); ?>
<div id="ajaxloader" style="display:none;">
Chargement...
</div>
Controller:
function autocomplete()
{
$recherche = utf8_decode($this->data['Tag']['tag']);
$tags = $this->Tag->find(
'all',
array(
'fields' => 'DISTINCT tag',
'conditions' => "tag LIKE '$recherche%'",
'order' => 'tag',
'limit' => 10
)
);
$this->set(compact('tag', 'recherche'));
}

jQuery, scriptaculous, & prototype don't play well together but you can resolve this issue by putting jQuery in no-conflict mode.
var $j = jQuery.noConflict();
// $j is now an alias to the jQuery function; creating the new alias is optional.
Now instead of using the $ to for jQuery use $j so for example:
$j(document).ready(function() {
$j( "div" ).hide();
});
For more information on avoiding jQuery conflicts refer to the following: https://learn.jquery.com/using-jquery-core/avoid-conflicts-other-libraries/

It appears that scriptaculous doesn't play well with j-query. When I removed the j-query link I stopped getting an error. This definitely isn't an ideal solution, but I thought I'd share my discovery.

Related

x-editable drop down from remote not working

I am using X-editable bootstrap version 2
I am using codeigniter . But the text area and text box is working fine for me but drop down is not working .
in my view
< a href="#" id="contract" data-type="select" data-pk="1" data-source="<?php echo base_url('property/contract_get_update')?>" data-title="Select Contract type" class="" >contract data </a>
$( document ).ready(function() {
$('#contract').editable();
});
in my controller
public function contract_get_update()
{
echo "{'M': 'male', 'F': 'female'}";
}
i just tested with this output not working i tried many tricks but it is not seems to be working.
i want to display details from table name contract how can i get that value as a drop down in x-editable
I answered you on gitHub too. The problem is with your json format.
Try this:
$contract_types = array();
$contract_types[] = array('value' => 'M', 'text' => 'male');
$contract_types[] = array('value' => 'F', 'text' => 'female');
echo json_encode($contract_types);
If you are looping through a db query of results try this in your function:
foreach($results AS $result){
$json_response[] = array('value' => $result['id_column'], 'text' => $result['your_column']);
}
echo json_encode($json_response);
You need to use a custom class with text and value members (case sensitive) to enumerate it as a List of type this class then use it to response after ajax call.

Drupal 7 ajax_command_* creates unwanted div

I'm populating a select box using an AJAX callback in Drupal 7. I've tried both ajax_command_append() and ajax_command_html() to set the new <option...> statements, but both these wrap the HTML that I create inside a <div>. This causes the <select> to not display any of the options.
Is there a way to tell Drupal "Hey stupid, this is exactly the HTML I want, don't mess with it"?
I can code some jQuery to remove the div I guess, but it would be a lot better if I can prevent it from being added in the first place.
Yes you can!
Declare your own custom js callback. In below example, I used a span instead of the divs. But you can obviously remove the wrapper alltogether.
PHP:
function my_ajax_callback() {
$data = 'saved!';
// instead of using ajax_command_html, we provide our own
// js custom callback function
$output = array(
'#type' => 'ajax',
'#commands' => array(
array('command' => 'myjscallback', 'data' => $data),
),
);
return $output;
}
JS:
$(function() {
Drupal.ajax.prototype.commands.myjscallback = function (ajax, response, status) {
$('#save-btn-message').html('<span>' + response.data + '</span>');
};
});
The answer is yes.
Just use this instead:
$commands[] = ajax_command_invoke('#mywrapper', 'html', array($output));
So it seems the answer is "no" (or at least not without hacking core, and I'll have no dead kittens on my conscience).
misc/ajax.js contains the following:
var new_content_wrapped = $('<div></div>').html(response.data);
The comments therein go on to explain why they require the first HTML element to be a top-level one. If it is, the <div> wrapper is not used. In my case, I'm replacing <option> elements, so I get the <div>.
Now I could just replace the entire <select>, but that causes other issues in my case due to scripts that style things at page load. Rather than find those and re-fire them, it looks like it'll be easier to just ajax_command_invoke a script to run after my options are loaded to remove the div wrapper.
EDIT: As a workaround, I found I can do ajax_command_invoke($selector, 'html', array('<option...>')); and it bypasses the div addition code. Kinda sneaky, but it works...
you can use seen on this link http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7#ajax
for more reference and example download this module http://drupal.org/project/examples
it has all the examples of custom code and "ajax_example" as well
It works for me!
$selector = '#my-select';
$method = 'append';
$opts = array('new option');
$commands[] = ajax_command_invoke($selector, $method, $opts);
return array('#type' => 'ajax', '#commands' => $commands);

CodeIgniter dropdown (Javascript?)

Is there any way I can make a dropdown submit a form without clicking a button to to submit it. I want to be able to change languages on the fly in my site. I have the languages all set up. Here's my dropdown:
<?php echo form_open('languages');
$language = array(
'select' => 'Select Language',
'english' => 'English',
'spanish' => 'Español',
'german' => 'Deutsch',
'french' => 'Français'
);
echo form_dropdown('language', $language);
echo form_hidden('current_page', uri_string());
echo form_submit('submit', $this->lang->line('header6'));
echo form_close();
?>
How do I get the form to work without the submit button?
The easiest way would be to use jQuery. Your form and dropdown should have IDs to make referencing them easier.
$attributes = array('id' => 'form1');
echo form_open('languages', $attributes);
...
echo form_dropdown('language', $language, null, 'mydropdown');
Also include the following javascript (you'll need to load jQuery on the page for this to work). I've included Google's hosted version but you could install it locally if you prefer.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#mydropdown").live("change keyup", function () {
$("#form1").submit();
});
});
</script>
You don't strictly need to bind to keyup, you could just bind to the change event (in which case you could replace live("change") with simply change() but keyup covers keyboard changes to the dropdown.
I use onchange with any live select menu... makes it very very easy to fire off other methods.
<select id="myID" onchange="alert('Fired!')"><option value="gold">Beer</option>

using ajax to post comments in cakephp results in 404 error, but no errors locally?

Using an ajax helper created for use with Jquery I've created a form that posts comments to "/comments/add", and this works as expected on my local wamp server but not on my production server. On my production server I get a '404 error, cannot find /comments/add'.
I've spent quite a bit of time searching for a resolution with no luck so far. I've focused on trying to identify a gap but nothing jumps out at me.
Here are some observations:
works as expected on local wamp server
requestHandler is listed as component
files on both local and production server are the same
controllers folder has write access
autoLayout and autoRender are both set to false
Here is the form in my view:
<div class="comments form">
<?php echo $ajax->form('/comments/add', 'tournament', array('url' => '/comments/add', 'update' => 'Comments', 'indicator' => 'commentSaved'));?>
<fieldset>
<legend><?php __('Add Comment');?></legend>
<div id="commentSaved" style="display: none; float: right;">
<h2>Loading...</h2>
</div>
<?php
echo $form->hidden('Comment.foreign_id', array('value' => $tournament['Tournament']['id']));
echo $form->hidden('Comment.belongs_to', array('value' => 'Tournament'));
echo $form->input('Comment.name');
echo $form->input('Comment.email');
echo $form->input('Comment.web', array('value' => 'http://'));
echo $form->input('Comment.content');
?>
</fieldset>
<?php echo $form->end('Submit');?>
</div>
And here is my 'comment's controller add action:
function add() {
if($this->RequestHandler->isAjax())
{
$this->autoLayout = false;
$this->autoRender=false;
$this->Comment->recursive =-1;
$commentInfos = $this->Comment->findAllByIp($_SERVER['REMOTE_ADDR']);
$spam = FALSE;
foreach($commentInfos as $commentInfo)
{
if ( time() - strtotime($commentInfo['Comment']['created']) < 180)
{
$spam = TRUE;
}
}
if ($spam === FALSE)
{
if (!empty($this->data)) {
$this->data['Comment']['ip'] = $_SERVER['REMOTE_ADDR'];
$this->Comment->create();
if ($this->Comment->save($this->data)) {
$this->Comment->recursive =-1;
$comments = $this->Comment->findAll(array('Comment.foreign_id' => $this->data['Comment']['foreign_id'], 'Comment.belongs_to' => $this->data['Comment']['belongs_to'], 'Comment.status' =>'approved'));
$this->set(compact('comments'));
$this->viewPath = 'elements'.DS.'posts';
$this->render('comments');
}
}
}
else
{
$this->Comment->recursive =-1;
$comments = $this->Comment->findAll(array('Comment.foreign_id' => $this->data['Comment']['foreign_id'], 'Comment.belongs_to' => $this->data['Comment']['belongs_to'], 'Comment.status' =>'approved'));
$this->set(compact('comments'));
$this->viewPath = 'elements'.DS.'posts';
$this->render('spam');
}
}
else
{
$this->Session->setFlash(__('Invalid Action. Please view a post to add a comment.', true));
$this->redirect(array('controller' => 'pages', 'action'=>'display', 'home'));
}
}
As you can see I've made sure that 'autoLayout' and 'autoRender' are set to false, but in Firebug I still get a 404 error stating /comments/add cannot be found on the production server.
I should also point out that I'm using jquery, jquery.form and jquery.editable as well as a ajax helper created to be used with jquery.
Any help or even suggestions about how to trouble shoot this is really appreciated.
Cheers,
Paul
Turns out that this was caused by the last few lines of code, calling a session that I don't use in comments.
else
{
$this->Session->setFlash(__('Invalid Action. Please view a post to add a comment.', true));
$this->redirect(array('controller' => 'pages', 'action'=>'display', 'home'));
}
Lesson learned, be careful with code you get from a tutorial. It might have something you don't use.
-Paul
Have you made sure your .htaccess files are present on the production server? If so, is mod_rewrite installed, and is .htaccess overriding allowed in the home directory? It seems like the problem must lie in some difference between your local environment and your production environment, and not in the code itself.

Cakephp 1.3, Weird behavior on firefox when using $this->Html->link

Greetings,
I am getting a very weird and unpredictable result in firefox when using the following syntax:
$this->Html->link($this->Html->div('p-cpt',$project['Project']['name']) . $this->Html->div('p-img',$this->Html->image('/img/projects/'.$project['Project']['slug'].'/project.thumb.jpg', array('alt'=>$project['Project']['name'],'width'=>100,'height'=>380))),array('controller' => 'projects', 'action' => 'view', $project['Project']['slug']),array('title' => $project['Project']['name'], 'escape' => false),false);
OK I know it is big but bear with me.
The point is to get the following output:
<a href="x" title="x">
<div class="p-ctp">Name</div>
<div class="p-img"><img src="z width="y" height="a" alt="d" /></div>
</a>
I'm not sure if this validates correctly both on cakephp and html but it works everywhere else apart from firefox.
You can actually see the result here: http://www.gnomonconstructions.com/projects/browser
To reproduce the result use the form with different categories and press search. At some point it will happen!!
Although most of the time it renders the way it should, sometimes it produces an invalid output like that:
<div class="p-cpt">
name
</div>
<div class="p-img">
<img src="x" width="x" height="x" alt="x" />
</div>
Looks like it repeats the link inside each element.
To be honest the only reason I used this syntax was because cakephp encourages it.
Any help will be much appreciated :)
I am guessing that the name of some projects is null. According to the documentation, if you pass null as the second argument to the div() method, it will not generate the closing tag (and the resulting markup will be invalid).
The example of invalid markup that you pasted above appear to have come from Firebug rather than Page Source. Use Page Source to view the actual markup sent to the browser. The anchor tag is not repeated.
I rewrote your code to better see what happens. Copy it into one of your views, change 'My Project' to null, and notice how it will affect the $name_div variable:
<div class="p-cpt">My Project</div> will turn into <div class="p-cpt">.
<?php
$project['Project']['name'] = 'My Project';
$project['Project']['slug'] = 'my-project';
$image = $this->Html->image(
'/img/projects/' . $project['Project']['slug'] . '/project.thumb.jpg',
array(
'alt' => $project['Project']['name'],
'width' => 100,
'height' => 380
)
);
$name_div = $this->Html->div('p-cpt', $project['Project']['name']);
$image_div = $this->Html->div('p-img', $image);
$link = $this->Html->link(
$name_div . $image_div,
array(
'controller' => 'projects',
'action' => 'view',
$project['Project']['slug']
),
array(
'title' => $project['Project']['name'],
'escape' => false
)
);
var_dump($image);
echo 'Notice what happens below if project name is null.';
var_dump($name_div);
var_dump($image_div);
var_dump($link);
echo $link;

Resources