Does anyone have experience with ajax in drupal 7?
I'm a little stuck.
So, with my module, I output a link and map the path to a callback function with hook_menu()
In the callback function I used ajax_command_replace() and ajax_deliver() to update content.
Well, so far, so good. It all works. But turns out, for complicated reasons, that using links won't work.
So instead I decided to try the jQuery ajax way. So I attach a click event to a div so when it gets clicked something like this runs in a JavaScript file that I load:
jQuery.ajax({
type: 'POST',
url: 'http://path/etc',
});
Then, in my module, I use hook menu to map the path to a callback function that looks like this:
function the_callback($var) {
// a lot of code that gets the right nid to load. This all works...
// and eventually I end up here:
$node = node_load($nid, NULL, false);
if ($node) {
$node_view = node_view($node);
$output = theme("node",$node_view);
$commands = array();
$commands = ajax_command_replace('#content','<div id = "content">' . $output . '</div>';
$page = array('#type' => 'ajax', '#commands' => $commands);
ajax_deliver($page);
}
This is the exact same code that was sucessfully replacing content when I had the links. But for some reason this doesn't work when I try to invoke the ajax call with jQuery. The callback function gets called, the correct stuff gets loaded in $output, but the page isn't updating.
Does anyone know what is going on here?
Are you missing a closing parenthesis?
$c = ajax_command_replace('#content','<div id = "content">' .$output. '</div>';
Should be:
$c = ajax_command_replace('#content','<div id = "content">' .$output. '</div>');
probably there is some javascript code inside the $output returned by theme('node', $node_view) , which you need to strip(remove).
here's some code from my ajax function returning the node rendered content:
$n = node_load($nid, NULL, FALSE);
$output = drupal_render(node_view($n));
$output = preg_replace('~<script\s+type="text/javascript">.+</script>~is', '', $output);
Related
I am trying to generate generate Alternate JSON code for jstree in my PHP controller.
I am creating what looks like the correct data, however, jstree does not display it.
My javascript looks like this:
$this->registerJs("
$(function() {
$('#statustree').jstree({
'core' :
{
'data' :
{
'datatype' : 'json',
'url' : '/myaccount/buildstatustree',
}
}
});
$('#statustree').on('loaded.jstree', function()
{
$('#statustree').jstree('open_all');
});
})
", \yii\web\VIEW::POS_READY);
and my php looks like this:
// convert to JSON format for jstree
$tree = array();
$parent = new stdClass();
$parent->id = 'P1';
$parent->parent = '#';
$parent->text = $username;
$tree[] = $parent;
$student1 = new stdClass();
$student1->id = 'S1';
$student1->parent = 'P1';
$student1->text = 'Poly';
$tree[] = $student1;
$student1 = new stdClass();
$student1->id = 'S2';
$student1->parent = 'P1';
$student1->text = 'Bob';
$tree[] = $student1;
// convert to json and send
header('Content-type: application/json');
return json_encode( $tree );
My controller is getting called and is returning a string that looks like this:
[
{"id":"P1","parent":"#","text":"user2"},
{"id":"S1","parent":"P1","text":"Poly"},
{"id":"S2","parent":"P1","text":"Bob"}
]
The spinner spins while the call is made, but the spinner disappears, and my tree is not displayed...
I suspect that I am not forming my Alternate JSON response correctly, but nothing I try works....
Thanks
-John
The data you are generating looks fine (provided that is what you see in your dev tools as the response to the AJAX call that jsTree makes).
You might want to check if all the headers are OK - is it really served as JSON? You can also try adding the charset just in case:
header('Content-Type: application/json; charset=UTF-8');
I see you are already trying to force jQuery to treat the response as JSON regardless of headers, but use "dataType" instead of "datatype".
If this does not work - please share what you see in the net panel of your developer console - the headers and the response to the AJAX call jsTree makes.
I'm in a page called 'add.cpt' that has a list of images. The user has the option to remove the images but I can't make it work. In the event of click I try to call an ajax trying to pass the name of the image and id of the item (.../item/imageName) but it does delete the image and alerts what seems to be the content of delete_photo_file.ctp. It looks like the ajax is using the URL but it is not sending the data to delete the file wanted.
ItemsController:
App::uses('File', 'Utility');
class ItemsController extends AppController{
[...]
public function deletePhotoFile(){
//$this->autoRender = false; //did not tested but maybe I need to use this
$imgName = //don't know how to get it from ajax call
$itemId = //don't know how to get it from ajax call
$file = new File($dir.'/'.$itemId.'/'.$imgName);
$file->delete();
}
}
Ajax Call (from my ctp file):
$('#delete').click(function (){
[...]
var itemId=$('#itemId').val(); //comes from hidden input
var imgName = $('#imgName').val(); //comes from hidden input
$.ajax({
type: 'POST',
url:'http://localhost/html/Project/v5/CakeStrap/items/deletePhotoFile/',
data:{"itemId":itemId, imgName: imgName},
success: function(data){
alert(data); //alerts some HTML... seems to be delete_photo_file.ctp content
}
});
});
Can anyone help me? Thanks!
In your ItemsController, make sure you actually load the File utility class, by adding:
App::uses('File', 'Utility');
Just below the opening <?php tag before your class definition. In your action you can just use $this->request->data to get the data keys. Also, return the action of the delete() function, so you can trigger your AJAX success/error call accordingly.
public function deletePhotoFile() {
$imgName = $this->request->data['imgName'];
$itemId = $this->request->data['itemId'];
/**
* Where is the $dir below actually set? Make sure to pass it properly!
* Furthermore, it's always cleaner to use DS constant
* (short for DIRECTORY_SEPARATOR), so the code will work on any OS
*/
$file = new File($dir . DS . $itemId . DS . $imgName);
return $file->delete();
}
Finally, mind your quotes in the AJAX call:
data:{"itemId":itemId, imgName: imgName},
Should become:
data:{"itemId":itemId, "imgName": imgName},
As otherwise, you just call the imgName JS var twice.
In the php $imgName = $this->request->data('imgName'); $itemId = $this->request->data('imgId'); In the js you might want to put quotes around the variable name since it's the same as the name of the value being passed data: {'itemId': itemId, 'imgName': imgName},
To get the data out simply debug($this->request->data) in your deletePhotoFile() method and check the response in your browsers console, it should be a nicely formatted array with the data you POST`d over in your ajax request, you should be able to work out the rest from there.
You'll also want to look into using the RequestHandler component so you can assure the request is an ajax request.
I have a CJUIDialog where i load the content of another form using renderPartial. In that form there is an ajax button where it loads another form. That form contains another ajax button where i need to load the previous form inside the dialog itself. I have tried doing it like this. But it doesnt work.
In my controller i have two methods that prints out the two forms like this.
public function actionNewRecipients(){
$customer = new Customer;
$address = new Address;
$content = $this->renderPartial('_form_new',array('customer'=>$customer,'address'=>$address,'guest'=>true),true);
echo $content;
}
public function actionAddRecipients()
{ $content = $this->renderPartial('_form_inner',array(),true);
echo $content;}
And then in one form i have the ajax button like,
echo CHtml::ajaxSubmitButton(Yii::t('New','New Recipient'),CHtml::normalizeUrl(array('customer/newRecipients')),array('success'=>'js: function(data) {
alert("new");
$("#dialog_gift").html(data);
$("#dialog_gift").dialog("option","title","Select Recipient");
}'));
and in the other form i have the ajax button like,
echo CHtml::ajaxSubmitButton(Yii::t('New','New Recipient'),CHtml::normalizeUrl(array('customer/addRecipients')),array('success'=>'js: function(data) {
alert("select");
$("#dialog_gift").html(data);
$("#dialog_gift").dialog("option","title","Select Recipient");
//$("customer-form_inner").attr("action","'.CHtml::normalizeUrl(array('customer/newRecipients')).'")
}'));
And the CJUIDialog looks like,
$this->beginWidget('zii.widgets.jui.CJuiDialog', array(
'id'=>'dialog_gift',
// additional javascript options for the dialog plugin
'options'=>array(
'title'=>$title,
'autoOpen'=>false,
'modal'=>true,
'scrolling'=>'no',
'resizable'=>false,
'scrollable'=>false,
'closeOnEscape' => true,
),
));
echo '<div class="span-24">';
echo $content;
echo '</div>';
$this->endWidget('zii.widgets.jui.CJuiDialog');
Ill be initially loading one forms content.
The first transition happens properly. But after i replace the html content the second transition to load the other view does not happen.
Please let me know if anyone can help.
Thanks
Try setting the 4th parameter of the renderPartial(string $view, array $data=NULL, boolean $return=false, boolean $processOutput=false)-function. By setting $processOutput to true, all necessary scripts (including those to enable ajax-button-functionality) will be included and executed.
I'm running into trouble accessing global variables when I make an AJAX call to a php function in the MediaWiki framework.
My jQuery AJAX call looks like this:
jQuery.ajax({
url: 'GeneralFunctions.php',
type: 'GET',
dataType: 'json',
data: {
text: anchorText
},
success: function (data) {
alert("data: " + data);
}
});
My GeneralFunctions.php file looks like this:
<?php
if (isset($_GET['text'])) {
jsonInlineParse((string) $_GET['text']);
}
function jsonInlineParse($wikiText)
{
global $wgOut;
$return = $wgOut->parseInline($wikiText); //fails here
echo json_encode($return);
}
?>
When I run the jQuery call through a click event I get as far as the parseInline() function. The global variable is never defined in the scope and I get the error:
Fatal error: Call to a member function parseInline() on a non-object in /path/to/file/GeneralFunctions.php on line 54
I'm not sure how to make the parse call and define the global variable when the AJAX call is made?
UPDATE
$wgOut is the OutputPage object associated with MediaWiki. It holds all the HTML of the page and is used throughout the MediaWiki framework to add content to a page or article. It is used on the server side to create customized output for wiki articles. I use it to create forms or add HTML on many of our wikis.
More info here: http://www.mediawiki.org/wiki/Manual:$wgOut
UPDATE 2
#Juhana I changed my function to look like this which results in the same error as before. Each echo outputs "NULL".
<?php
function jsonInlineParse($wikiText)
{
include_once '/path/to/file/includes/OutputPage.php';
include_once '/path/to/file/includes/parser/Parser.php';
echo var_dump($wgOut);
global $wgOut;
echo var_dump($wgOut);
$return = $wgOut->parseInline($wikiText);
echo $return;
echo json_encode($return);
}
?>
I took a different approach after running into global variable problems. I changed the AJAX call I was making and the code below works very well for me. I'm using the editable jquery table you can find here.
PHP
function ajax_parse(){
global $wgRequest;
if($wgRequest->wasPosted()){
$text = $wgRequest->getVal("text");
wfDebug("Recieving::::".$text);
if(!strpos($text, "href")){
$text = myInlineParse($text);
$text = str_replace("<pre>", "", $text);
$text = str_replace("</pre>", "", $text);
}
wfDebug("Returning::::".$text);
echo $text;
}
exit;
}
function myInlineParse( $wikiText ) {
global $wgOut;
return $wgOut->parseInline( $wikiText );
}
JavaScript
// inject wikitext after hitting save
function postSave(o) {
var response = new Array("");
for(var i=0;i<o.row.length;i++){
new Ajax.Request(wgScript +'/Special:EditClass/ajax_parse',
{
asynchronous: false,
parameters: {'text': o.row[i].innerHTML},
onSuccess: function(text){
response.push(text.responseText);
}
}
);
}
return response;
}
For whatever reasons, extensions don't seem to have access to $wgOut. I solved this for my extension by using the hook: OutputPageParserOutput for the code I needed output (I needed to inject some scripts and stylesheets as well as using another hook to modify links and didn't want to bother with Resource_Loader though it is useful and recommended):
$wgHooks['OutputPageParserOutput'][] = array($this, 'doOutputPageParserOutput'); // 'doOutputPageParserOutput' defined as method in my class
As with other hooks, you can get rid of the array in favor of just a function name if you don't want to execute within a class.
i'm a little stuck with a jQuery. At the moment my function looks like this.
$(function(){
$(".url2").keyup(validNum).blur(validNum);
function validNum() {
var initVal = $(this).val();
outputVal = initVal.replace(/(https?:\/\/)?(www.)?[0-9A-Za-z-]{2,50}\.[a-zA-Z]{2,4}([\/\w\-\.,#?^=%&:/~\+#]*[\w\-\#?^=%&/~\+#]){0,250}(\s){1}$/
,"http://my.site/ref.php?id=<?php $code = unqiue-ref-id(); echo $unqiue-ref-id;?>");
if (initVal != outputVal) {
$(this).val(outputVal);
return false;
}}
});
So right now it rewrites a user typed url (in a textarea) to a redirection link with my own url (e.g. my.site?ref.php?id=unique12. What I need exactly is a POST Request to a php file (code below) where the valid user-url is given to the php file as a var and then the php file should give back a var with the generated unique unique-ref-id. I do of course know that the code above isn't working like that, it only shows how the final result should look like. The php file wich generates the unique-ref-id looks like this.
function unqiue-ref-id() {
$unqiue-ref-id = "";
$lenght=4;
$string="abcdefghijklmnopqrstuvwxyz123456789";
mt_srand((double)microtime()*1000000);
for ($i=1; $i <= $lenght; $i++) {
$shorturl .= substr($string, mt_rand(0,strlen($string)-1), 1);
}
return $unqiue-ref-id;
}
$user-url = // var send from jquery
do{
$unqiue-ref-id = unqiue-ref-id();
} while(in_array($unqiue-ref-id, $result));
// var send back to jquery function => final results of do function above
// Here i add the $user-url and $unique-ref-id to datebase (Dont need code for that)
?>
Would be so great if someone can help me out with that. Thanks a lot :)
Use the POST jQuery's method. Here's an example
$.post('URL-TO-POST-DATA', {'parameter1': 'value', 'parameter2': 'value'}, function(data_received){
/** Here goes your callback function **/ alert(data_received);
});
More information about POST method
Don't forget one thing. jQuery will not receive nothing if you don't use echo on PHP (instead of return). You MUST use echo in PHP, don't forget it.