[gelöst]Ajax implementierung mal anders
am 01.05.2011 - 17:26 Uhr in
Hallo liebe Drupal Fans,
ich versuche nun schon länger meine Homepage mit ajax zu erweitern - bisher leider ohne Erfolg.
http://www.drupalcenter.de/node/34774
Ich habe schon verschiedene Beiträge zu dem Thema erstellt, die auch sehr hilfreich waren, aber leider noch nicht den "Durchbruch" brachten.
Deshalb habe ich mir eine andere Vorgehensweise überlegt.
Ich denke, wenn folgendes JS Script immer die komplette Website lädt
Drupal.behaviors.my_ajax = function (context) {
$('#content-group-inner .node a').live('click', function (e) {
var url = $(this).attr('href');
//$('#content-region-inner').slideUp('slow');
$('#content-region-inner').empty().html('<img src="ajax-loader.gif" style="margin-left:50%;"/>');
xhr = $.ajax({
data: 'ajax=1', //hierauf lauschen die preprocess Funktionen(funktioniert auch)
type: 'GET',
url: url,
success: function (data) {
$('#content-region-inner').replaceWith(data);
Drupal.attachBehaviors(context);
}
});
return false;
});
};
könnte ich vielleicht versuchen Drupal bei einer Ajax Anfrage dazu zu bringen nur den Content auszugeben.
Also habe ich in mein Modul 2 hook_preprocess eingebaut, die auf eine Anfrage über Ajax, 2 andere tpl.php Dateien für die Ausgabe verwenden:
node-ajax.tpl.php und page-ajax.tpl.php.
So habe ich es gemacht:
function my_ajax_preprocess_page(&$vars, $hook) {
if ( isset($_GET['ajax']) && $_GET['ajax'] == 1 ) {
$vars['template_file'] = 'page-ajax';
}
}
function my_ajax_preprocess_node(&$vars, $hook) {
if ( isset($_GET['ajax']) && $_GET['ajax'] == 1 ) {
$vars['template_file'] = 'node-ajax';
}
}
Jetzt dachte ich, ich könnte in der node-ajax.tpl.php nur ein
print $content
einfügen, und damit nur content ausgeben.Aber weit gefehlt.
Eigenartigerweise kann ich meine node-ajax und page-ajax.tpl.php als 1:1 Kopie, wie die original Dateien meines Themes verwenden, wenn ich nur das
print $content
aus meiner node-ajax.tpl entferne.Zumindest lädt sich dann nicht die ganze Seite neu, sondern alle benötigten JS und CSS Scripte, und natürlich, wie nicht erwünscht, aber erstmal egal, die komplette Seitenstruktur. Sobald ich aber den Content mit ausgebe, habe ich wieder eine kompletten reload meiner Seite.
Wie kann das sein, da ich mir den Inhalt meiner $content Variable angeschaut habe, und diese definitiv nur den Inhalt hat, den ich benötige.
Ich bitte um eure Erkärung bzw. Hilfe um zu verstehen, wie sich dieses Verhalten erklären lässt.
Anbei poste ich nochmal den kompletten Code meines Moduls, aber ohne die tpl.php Dateien, um den Post nicht unnötig aufzublähen, da die sich von anderen wohl wenig unterscheiden:
my_ajax.module:
<?php
function my_ajax_init()
{
drupal_add_js(drupal_get_path('module', 'my_ajax') . '/my_ajax.js');
}
function my_ajax_preprocess_page(&$vars, $hook)
{
if (isset($_GET['ajax']) && $_GET['ajax'] == 1) {
$vars['template_file'] = 'page-ajax';
}
}
function my_ajax_preprocess_node(&$vars, $hook)
{
if (isset($_GET['ajax']) && $_GET['ajax'] == 1) {
$vars['template_file'] = 'node-ajax';
}
}
my_ajax.js:
Drupal.behaviors.my_ajax = function (context) {
$('#content-group-inner .node a').live('click', function (e) {
var url = $(this).attr('href');
//$('#content-region-inner').slideUp('slow');
$('#content-region-inner').empty().html('<img src="ajax-loader.gif" style="margin-left:50%;"/>');
xhr = $.ajax({
data: 'ajax=1',
type: 'GET',
url: url,
success: function (data) {
$('#content-region-inner').replaceWith(data);
Drupal.attachBehaviors(context);
}
});
return false;
});
};
- Anmelden oder Registrieren um Kommentare zu schreiben
Du müsstest in deiner
am 01.05.2011 - 19:46 Uhr
Wie schon korrekt von dir gepostet, musst du in deiner preprocess_page ein neues Template definieren - in dieses Template kommt dann der folgende Inhalt.
<?php
print $content;
?>
Um Ajax-Calls zu prüfen kannst du auch über die globale $_SERVER Variable gehen:$_SERVER['HTTP_X_REQUESTED_WITH'] - https://gist.github.com/909642
Wenn du dies in der node.tpl machst, bringt das nicht viel, da du hier ja nur die Darstellung der Node-Types steuern kannst. In der Page.tpl nimmst du Einfluss auf die komplette Seite - sprich die Regionen etc..
Genau diese Antwort hatte ich dir auch schon einmal in einem alten Posting von dir gegeben ( da Thema scheint dich nun ja schon ne ganze Weile zu beschäftigen )...
Schlanke Ajax Requests mit Drupal.
SteffenR
Hi SteffenR danke für Deine
am 01.05.2011 - 22:20 Uhr
Hi SteffenR danke für Deine Antwort,
du hast recht das beschäftigt mich wirklich schon sehr, sehr lange.
Die Überprüfung, die du angesprochen hast mache ich doch aber in meiner my_ajax.module datei nicht in einer node- oder page-ajax-tpl.php.
Macht das einen Unterschied? Ich finde es einfach übersichtlicher, wenn ich solche Funktionen in meinem Modul und nicht in der template.tpl.php auslagere, außerdem bleiben diese Funktionen bei einem Theme Update bestehen.
Zudem ist es ja so, wenn ich Änderungen in meiner node-ajax-tpl.php oder page-ajax-tpl.php vornehme, zeigen die sich bei einer Ajax Anfrage
auch in meinem Layout, d.h. ja, denke ich, dass meine Überprüfung funktioniert Nur, dass die Ausgabe von nur $content nicht zum gewünschten Ergebnis führt, hier wird dann komischerweise Alles ausgegeben. Wenn du meinst, dass das daran liegt, dass die preprocess Funktion nicht in mein Modul, sondern in template.php implementiert werden muss, werde ich das natürlich versuchen.
Wäre schön, wenn du mir noch einmal schreiben würdest, ob es einen Unterschied macht.
Danke schon im Voraus.
Ich habe den Vorschlag eurer
am 01.05.2011 - 23:37 Uhr
Ich habe den Vorschlag eurer Seite (danke dafür)
http://www.hopper-intermedia.de/webdesignblog/drupal-schlanke-ajax-reque...
1:1 nachgebaut auch die preprocess Funktion in template.php eingebunden und aus meinem Modul entfernt, den cache geleert, und es kommt aber das selbe Ergebnis.
Ein kompletter Page reload.
Ich habe es nur auf die page-ajax.tpl.php abgeändert, dran kann es aber nicht liegen.
Ich bin wirklich bald am verzweifeln.
Ich weis nicht, wie Ihr euren Ajax request absetzt. Aber wie wie oben erwähnt mache ich es so:
Drupal.behaviors.my_ajax = function (context) {
$('#content-group-inner .node a').live('click', function (e) {
var url = $(this).attr('href');
//$('#content-region-inner').slideUp('slow');
$('#content-region-inner').empty().html('<img src="ajax-loader.gif" style="margin-left:50%;"/>');
xhr = $.ajax({
data: 'ajax=1',
type: 'GET',
url: url,
success: function (data) {
$('#content-region-inner').replaceWith(data);
Drupal.attachBehaviors(context);
}
});
return false;
});
};
Ich denke so,oder so ähnlich macht Ihr es bestimmt auch.
Woran kann es denn noch liegen?
Ich mach echt schon zu lange an dem Problem rum, aber es ist mir wirklich wichtig.
Hast du denn mal geprüft, ob
am 02.05.2011 - 08:04 Uhr
Hast du denn mal geprüft, ob überhaupt die korrekten Templates gezogen werden und ob die Preprocess Funktion korrekt ausgeführt wird (einfach ein
<?php
echo "test"
?>
Das hat mit dem Javascript jetzt erstmal nix zu tun .. ( müsstest dann halt die Überprüfung des Headers "rausnehmen" und das Template testweise komplett überschreiben )..
SteffenR
Schön von Dir zu hören. Wenn
am 02.05.2011 - 11:50 Uhr
Schön von Dir zu hören.
Wenn ich es so mache, wie du gesagt hast, und in Firebug den Ajax request verfolge, erhalte unter Konsole als Html Ausgabe den "test" String.
Somit sollte es ja eigentlich funktionieren.
Ich lade anbei einfach mal mein Modul und meine Template hoch, um den Post nicht unnötig aufzublähen.
Vielleicht könntest du da mal kurz darüber schauen, ob Dir etwas relevantes auffällt.
Ich musste den .php und .js Dateien aus Sicherheitsgründen ein ".txt" anhängen, ich verwende die so natürlich nicht.
Da wäre sehr nett.
Ich habe in der Zwischenzeit
am 02.05.2011 - 13:02 Uhr
Ich habe in der Zwischenzeit mal statt
print $content
einfach durch
print $head
ersetzt.
Und siehe da, in #content-region-inner wird tatsächlich der Head der angeforderten Seite eingefügt.
Hat natürlich keine wirklichen Sinn, nur zu Testzwecken.
Nur mit dem Content funktioniert es nicht.
Kann das irgendwie von einem anderen Modul beeinträchtigt werden?
Ich weis leider keinen Rat mehr.
Auch in keinem Forum kann ich einen Hinweis auf dieses Problem finden.
Also bitte, bitte, ich bin für jede Hilfe mehr als dankbar.
Ich habe noch etwas
am 02.05.2011 - 20:49 Uhr
Ich habe noch etwas merkwürdiges herausgefunden.
Wenn ich
$('#content-group-inner .node a').live('click', function (e) {
in
$('#content-group-inner a').live('click', function (e) {
abändere, um die Auswahl nicht nur auf die Klasse "node" zu beschränken,
funktioniert die Ausgabe mit
print $content
,wenn ich einen Tab Link im Tabmenu anklicke.
Das heißt, daß dieses merkwürdige Verhalten nur beim Öffnen eines Nodes
auftritt, nicht aber bei Menüeinträgen.
Außerdem ist es so, wenn ich meine Nodes mit Ajax versuche zu laden,
wird wie gewollt nor der Inhalt ausgegeben, und dann erfolgt der komplette Reload.
Obwohl ich einen Menupunkt "Forum" habe, und ich in diesem mit Ajax ohne
Probleme navigieren kann, und Forumeinträge ja eigentlich auch Nodetypen sind.
Kannst du dir das vielleicht erklären?
Ich hoffe, dass dir dieses eigenartige Verhalten
vielleicht auf Anhieb sagt, woran das liegen kann.
Vielen Dank für deine Hilfe bis jetzt.
Bitte lasse mich nicht alleine.
Das was ich die ganze Zeit,
am 03.05.2011 - 08:05 Uhr
Das was ich die ganze Zeit, als erfolglosen Page reload interpretiert hatte, stellt sich bei genauerer Betrachtung
als Laden eines Scriptes mit dem merkwürdigen Namen heraus:
wyciwyg://7/http://www.beispiel.de//event/seq/1, das folgenden Inhalt hat:
function onload(event) {
2 var i = this.id, s = window.google_iframe_oncopy, H = s && s.handlers, h = H && H[i], w = this.contentWindow, d;
3 try {
4 d = w.document;
5 } catch (e) {
6 }
7 if (h && d && (!d.body || !d.body.firstChild)) {
8 if (h.call) {
9 i += ".call";
10 setTimeout(h, 0);
11 } else if (h.match) {
12 i += ".nav";
13 w.location.replace(h);
14 }
15 s.log && s.log.push(i);
16 }
17 }
Die generierte Html hat folgende Struktur:
<ins style="display:inline-table;border:none;height:90px;margin:0;padding:0;position:relative;visibility:visible;width:728px"><ins id="aswift_0_anchor" style="display:block;border:none;height:90px;margin:0;padding:0;position:relative;visibility:visible;width:728px"><iframe allowtransparency="true" frameborder="0" height="90" hspace="0" marginwidth="0" marginheight="0" onload="var i=this.id,s=window.google_iframe_oncopy,H=s&&s.handlers,h=H&&H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&&d&&(!d.body||!d.body.firstChild)){if(h.call){i+='.call';setTimeout(h,0)}else if(h.match){i+='.nav';w.location.replace(h)}s.log&&s.log.push(i)}" scrolling="no" vspace="0" width="728" id=aswift_0 name=aswift_0 style="left:0;position:absolute;top:0;" ></iframe></ins></ins>
.Irgendwo muss doch dieser Code herkommen,oder?
Wie gesagt, der $content erscheint erst völlig korrekt, und wird in das entsprechende div eingesetzt, nach einem kurzen Augenblick aber kommt dann das,
was ich anfangs fälschlicherweise als einen unendlichen reload interpriert hatte.
Ich bitte um Hilfe.
Das riecht doch nach dem
am 03.05.2011 - 09:08 Uhr
Das riecht doch nach dem Sript eines Wysiwyg-Editors, der gemäß seiner definierten Handler für die verschiedenen Elemente die Drupal-Ausgabe umformatiert. Vieleicht solltest Du den mal deaktivieren.
Beste Grüße
Werner
Mir sieht das auch stark nach
am 03.05.2011 - 09:24 Uhr
Mir sieht das auch stark nach google maps
aus wegen dem google iframe und
location.replace.
LG
Danke für eure Hinweise. Ich
am 03.05.2011 - 20:15 Uhr
Danke für eure Hinweise. Ich bin leider gerade unterwegs. Ich werde das prüfen, und mich dann zurück melden. Deswegen fasse ich mich so kurz.
Aber vielen Dank nochmal.
Lg
Dennis605
Endlich, ich habe den
am 05.05.2011 - 13:39 Uhr
Endlich, ich habe den Bösewicht.
Vielen Dank für all eure Hilfe und Unterstützung.
Der Fehler wurde durch ein Google AdSense Script verursacht, das normal in dem Node angezeigt werden soll.
So wie es aber aussieht verträgt sich dieses Script nicht sehr gut mit Ajax Anfragen.
Danke nochmal an alle.
Aber schon tut sich ein neues
am 05.05.2011 - 14:49 Uhr
Aber schon tut sich ein neues Problem auf.
Vielleicht sollte ich einen neuen Post dafür eröffnen, was mein Ihr?
Hier mein Problem:
"Drupal.attachBehaviors" funktioniert nicht zufriedenstellend in meinem Fall.
Kennt jmd. eine adäquate Lösung, wie man benötigtes Css und JS Scripte, für Inhalt, der durch eine Ajax Anfrage angefordert wurde, nachlädt bzw. nachladen lässt.
Im Moment mache ich es so, daß ich in meiner page-ajax.tpl.php nicht nur den $content, sondern auch den 'Head' samt Css und JS Scripten ausgebe.
Ist aber eine wirklich unsaubere Lösung, da der Head im Body des eingefügten Bereichs eingesetzt wird, und nicht in
<html><head></head></html>
, wie es eigentlich sein soll.Zum anderen habe ich es mit 2 versch. Ajax Anfragen versucht, eine für den $content, und die andere für die Css und JS Scripte, die dann über eine andere tpl.php Datei ausgebe.
Bringt aber leider, wie sich jeder vielleicht denken kann, auch nicht den gewünschten Erfolg.
Wundert mich, dass ich hier oder auf Drupal.org im forum fast nichts über dieses Problem lese, denn ich kann mir nicht vorstellen, dass ich der Einzige bin, der dieses Problem hat.
Es gibt zwar verschiedene Module, die dieses Problem versuchen zu beheben , funktionieren bei mir aber nicht so richtig.
Würdet Ihr mir vielleicht mitteilen, wie Ihr dieses ganz generelle Problem angeht, oder löst.
Vielen Dank für eure Beiträge.
Ich habe einen neuen Post
am 05.05.2011 - 20:48 Uhr
Ich habe einen neuen Post eröffnet, da jmd. der das gleiche Problem hat, unter diesem Thema nicht suchen würde.
http://www.drupalcenter.de/node/35200