Topic: [Tutorial] AJAXify your MODx site - and it degrades well, too!  (Read 31877 times)

Pages: 1 2 [3] 4   Go Down

#41: 12-Oct-2007, 07:40 AM

PHPVampire
Posts: 74

Where do i get the template switcher? OR even better, is it possible to do this without template switcher? (as ive alredy got my template setup and working and i dont really want to fiddle arround with it too much.

thnx for your help - and if this should work -> you rule! =)

#42: 15-Oct-2007, 08:21 AM

Moderators

AHHP
Posts: 397

Salut capitan,

WWW
Template Switcher Plugin

#43: 28-Nov-2007, 06:37 PM

numberblack
Posts: 8

WWW
Wow, this tutorial rocks! 

I have only question: How does google handle such ajax based sites? Is google bot able to index all those ajaxed pages?
modx is amazing and brilliant.  So is modx community!

#44: 22-Dec-2007, 05:15 PM

rav3n
Posts: 174

guys i just wanted to thank you for this tutorial!!!

Is google bot able to index all those ajaxed pages?
i think yes cause bot uses no js so it'll get actual links to pages

#45: 19-May-2008, 02:58 AM

andreasfruth
Posts: 5

This post is obsolete - please see http://modxcms.com/forums/index.php/topic,6743.msg157954.html#msg157954 for the tutorial.
« Last Edit: 20-May-2008, 08:02 AM by andreasfruth »

#46: 19-May-2008, 11:34 PM


Sylvaticus
Posts: 491

I think, therefor I am. But what I am, and why...?

WWW
I'm definitely interested in this. I need this on my site about the flora on Svalbard. Please make a tutorial if you can, and please continue any developement on this.  Cheesy

#47: 20-May-2008, 06:34 AM

Moderators

AHHP
Posts: 397

Salut capitan,

WWW
thank you very very much  Cheesy
I'm waiting for your complete tutorial!  Wink

the attached file (history.zip) is damaged!!  is it exactly file in this page? http://plugins.jquery.com/files/jquery.history.js_0.txt

#48: 20-May-2008, 06:40 AM

andreasfruth
Posts: 5

thank you very very much  Cheesy
I'm waiting for your complete tutorial!  Wink

the attached file (history.zip) is damaged!!  is it exactly file in this page? http://plugins.jquery.com/files/jquery.history.js_0.txt

Yes, just copy/paste what's in there into a file called histoy.js (or whatever you want).

I'm currently rewriting the above two posts, and i hope i'll have a more understable tutorial up today or tommorrow.

#49: 20-May-2008, 06:40 AM


Sylvaticus
Posts: 491

I think, therefor I am. But what I am, and why...?

WWW
Great news!

#50: 20-May-2008, 08:00 AM

andreasfruth
Posts: 5

Ok, so here is another method of getting your modX site Ajaxified, complete with history and bookmark capability.
You won’t need the template switcher for this.
Also, I found some problems between jquery and QuickEdit. I disabled QuickEdit (I don’t usually have a need for it). If someone could find why they don’t work together please share.

You can find an working example at: http://cumvreau.eu/test/

Requirements:

jQuery 1.2.3 – http://www.jQuery.com (1.2.3 is the version I used, it might work with newer versions also)
History plugin for jQuery: http://plugins.jquery.com/files/jquery.history.js_0.txt - copy all the text into a file named history.js

Crash course:

Step 1:

Include the two .js files (jquery.js, and history.js) in your template <head>.

Put the following code in the head also:
(You can put the code in a chunk, and then include the chunk in your template <head>)

Code:
<script>
var linkstyle = ".ajaxlink";
var content = "#content";
var toload = "#toload";
var uglyurl = "[(site_url)]"

function callback(hash)
{
if (hash != '') {
var loadstr = uglyurl + hash;
$(content).html("<div id='loader'><img src='assets/images/ajax-loader.gif' /><br /><p style='font-size:20px; color:red;'>Loading content <br />please wait!</p></div>");
$(content).load(loadstr+" "+toload);
}
}
$(document).ready(function() {
    $.history.init(callback);
    $(linkstyle).click(function(event){
        event.preventDefault();
        var str = this.href.replace(uglyurl, "");
        $.history.load(str.replace(/^.*#/, ''));
        $(content).html("<div id='loader'><img src='assets/images/ajax-loader.gif' /><br /><p style='font-size:20px; color:red;'>Loading content <br />please wait!</p></div>");
        $(content).load(this.href+" "+toload);
        return false;
    });
});
</script>

Little explainer for the first four variables in the script:

linkstyle: put the class that you will use for the links that trigger ajax.
content: id for the <div> that your content will be loaded into.
toload: id of the div that will be brought from the outside pages along with all it’s contents and placed into ‘content’.
uglyurl: part of the link url to be stripped in order to beautify your link. eg: when you click an ajaxified link you will get an url in your browser like this:

ht tp://yoursite.com/index#http://yoursite.com/page-two

If you set your ‘uglyurl’ variable to “ht tp://yoursite.com/” the above url will look like this:

ht tp://yoursite.com/index#page-two

It’s just for good looks.

Set your four variables how you like them. I’ll use:

var linkstyle = ".ajaxlink";
var content = "#content";
var toload = "#toload";
var uglyurl = "[(site_url)]"


Step 2:

Build your template with the following in mind:

Wrap ‘toload’ (or whatever you set the toload var to) around your [*content*] TV, and then wrap ‘content’ (or whatever you set the content var to)  around ‘toload’ like this:


Code:
…template code…
<div id="content">
<div id="toload">
[*content*]
</div>
</div>
…more template code…

Apply the ‘linkstyle’ (or whatever you set the linkstyle var to) class to any link you’d like to trigger Ajax like this:
Code:
<a class="ajaxlink" href="[~1~]">Link to main page</a>
<a class="ajaxlink" href="[~2~]">Link to page 1</a>
<a class="ajaxlink" href="[~3~]">Link to page 2</a>
<a class="ajaxlink" href="[~4~]">Link to page 3</a>

That’s it for the crash course, you should be good to go.


Thorough explanation:

How it works:

$(document).ready(function() {

When the page loads, the JS in the head activates.

$.history.init(callback);

This is a function that checks if the browser URL has a # in it. If it does, the function runs the callback function with anything that’s after # as a parameter.
The callback function prepends what’s in your ‘uglylink’ variable to the received parameter and loads into ‘content’ the ‘toload’ div from the specified url.
This allows you to have bookmarks and history on your site.

    $(linkstyle).click(function(event){

Puts an onclick function on every element with a class of ‘linkstyle’. This means that your browser will listen and intercept any click on a link with that class.
We use this instead of putting functions directly on the onclick event in the links because this way, if the user has JS off, he’ll still be able to navigate your site the traditional way.

        event.preventDefault();

We don’t want the browser to go to that link directly so we prevent that.

        var str = this.href.replace(uglyurl, "");


The above is a little string replacement to beautify your links. What it does: it takes the url from the clicked link, and substracts what you have defined in the ‘uglyurl’ var. This way we will have links like this: ht tp://yoursite.com/index#page-two instead of ht tp://yoursite.com/index#http://yoursite.com/page-two.

        $.history.load(str.replace(/^.*#/, ''));

We put the new address in the history stack, adding a # to it to trick the browser.

        $(content).html("<div id='loader'><img src='assets/images/ajax-loader.gif' /><br /><p style='font-size:20px; color:red;'>Loading content <br />please wait!</p></div>");
        $(content).load(this.href+" "+toload);


The first line puts a nice Loading image and text until the target page is loaded, and the second gets ‘toload’ div and all it’s contents from the target page, putting it into the ‘content’ div in our page (and replacing any existing content).


I hope this tutorial is more understandable than my previous posts Smiley.
« Last Edit: 20-May-2008, 08:52 AM by andreasfruth »

#51: 20-May-2008, 11:03 AM

Moderators

AHHP
Posts: 397

Salut capitan,

WWW
very nice.
thank you!

i tested on MODxHost template, it didn't work.
logged out to turning QuickEdit off, it worked well in IE7 but didn't worked on opera 9.21 and firefox 2.
remove mootools JSs from modxHost to test it, firefox problem solved but opera doesn't display result well.
ajax links work well, loading appears, new content appears but after a second content disappears.
i test your test-site in opera, works well probably it has problem with other JSs in MODxHost. (i use jQuery 1.2.4)

i only wanted to report it, your tutorial is very very good, useful, ....  Smiley

we created the Persian MODx support site (and forums) at http://modxcms.ir/forums,
i will share this great tutorial with other Persian users in Persian language, if you let me!  Wink

#52: 20-May-2008, 11:35 AM

andreasfruth
Posts: 5

very nice.
thank you!

i tested on MODxHost template, it didn't work.
logged out to turning QuickEdit off, it worked well in IE7 but didn't worked on opera 9.21 and firefox 2.
remove mootools JSs from modxHost to test it, firefox problem solved but opera doesn't display result well.
ajax links work well, loading appears, new content appears but after a second content disappears.
i test your test-site in opera, works well probably it has problem with other JSs in MODxHost. (i use jQuery 1.2.4)

i only wanted to report it, your tutorial is very very good, useful, ....  Smiley

we created the Persian MODx support site (and forums) at http://modxcms.ir/forums,
i will share this great tutorial with other Persian users in Persian language, if you let me!  Wink

Please do share.

I don't know about those problems, i'll try to look into it. For those with more JS knowledge: is it posible that if multiple JS libraries like jquery and mootools, are listening to the document.ready() event, one or more of them break?

« Last Edit: 20-May-2008, 01:09 PM by andreasfruth »

#53: 20-May-2008, 01:25 PM

Moderators

AHHP
Posts: 397

Salut capitan,

WWW
I did share!  Wink
you may visit it here, you can't understand anything because everything is Persian(farsi) but you can see your name well  Smiley

now other Persian users waits your updates too Wink


thanks again

#54: 20-May-2008, 09:44 PM

Moderators

MotSmart
MODx RTL Guru.
Posts: 923

WWW
Great job folks, Thanks for sharing andreasfruth & also to my friend, AHHP which has translated it to Persian.
Keep up a good work, it might worth adding to wiki or confluence :-]
[Search] [Add-ons] | [MODx Lovers Don't miss this link!]
[Documentation] [Wiki]
[Persian support forum]
[RoadMap] [SVN] [RTL SVN Branch] [Development] [Trac] [FishEye+Crucible] [Confluence] | [My Google Code]
[برای دسترسی به راهنمای فارسی به  » وبگاه مادایکس فارسی « و یا به » انجمنهای پشتیبانی فارسی مادایکس « مراجعه کنید]
A Person is Either your Brother in Faith or Your Equal in Humanity. - Imam Ali.  # Discover Islam. | # Discover Middle East @ PressTV.Creation of Earth and Sky and the birth of Adam
BBC, CNN, FOX, MSNBC: Israeli officials: We don't want to kill (AKA Genocide) innocent people of Gaza. ~ Stupid Me, Myself: So why don't you stop doing so?!

#55: 21-May-2008, 04:13 AM

andreasfruth
Posts: 5

Ok, the same result but this time using Mootools (QuickEdit still doesn't work Sad - see bottom for QE problem )

Requirements:

Mootools v. 1.11 - http://mootools.net
Pageloader plugin for mootools: http://www.phatfusion.net/pageloader/
History plugin for mootools: http://www.phatfusion.net/pageloader/

Include those three .js files in <head>

Use this code in the template:
Code:
<div id="content">
    <div id="toload">
           [*content*]
    </div>
</div>

Use a class on all your links that should trigger ajax (let's say .ajaxlink)

Put the following code into a chunk and include the chunk in your template:

Code:
<script>
window.addEvent('domready', function(){
new pageLoader({loadInTo:'content',
                                                           loadFrom:'toload',
                                                           links:'ajaxlink',
                                                           onStart: $(this.options.loadInTo).replaceWith("<div id='loader'><img src='assets/images/ajax-loader.gif' /><br /><p style='font-size:20px; color:red;'>Loading content <br />please wait!</p></div>");});
new History();
});
</script>

on http://www.phatfusion.net/pageloader/ you'll see explanations about the options you can use with pageloader.

a little explanation:
loadInTo:'content', - the div to load Into
loadFrom:'toload', - the div to load from
links:'ajaxlink', - class of the links that trigger ajax
onStart:'....' - code that shows the nice Loading image

If you want nice links, you have to hack the history.js file, look for the following code and add the line that begins with >>>:

Code:
set: function(str){
var url = this.formatURL(this.url);
str = this.formatHash(str);
   >>>     str = str.replace("replace this with your url that will be substracted", "");
this.url = url+'#'+str;
window.location.href = this.url;
if(window.ie){
this.iframe.setProperty('src', str);
}


EDIT: - by following these indications: http://modxcms.com/bugs/task/989 you can get QuickEdit to work.
Basically, QE included it's own version of mootools, and this tip prevents mootools to be included twice.
Downside: you have to include mootools manually or QE won't work.

Still i don't see this as an elegant solution. That's why i ask: is there any way to find out in a snippet if a module/pluggin is enabled/disabled?
That way i could check if QE is enabled and showing and load or not mootools based on this.
« Last Edit: 21-May-2008, 08:48 AM by andreasfruth »

#56: 28-Aug-2008, 08:07 PM


larsb
Posts: 73

Rock'n'roll

Hey, great tutorial, thanks for writing it.

I have a slight problem with it though. When I click on a link the loader icon begins to spin, but it just sits like that forever. No new content is displayed. Has anyone else experienced this?

Oh by the way I just noticed an error that firebug gave me:

Code:
Access to restricted URI denied" code: "1012
[Break on this error] xhr.open(type,s.url,s.async);try{if(s.da...[s.url]=modRes;if(!jsonp)success();}else

It is on line 28 in the assets/js/jQuery.js file:

Code:
28xhr.open(type,s.url,s.async);try{if(s.data)xhr.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xhr.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");xhr.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend&&s.beforeSend(xhr,s)===false){s.global&&jQuery.active--;xhr.abort();return false;}if(s.global)jQuery.event.trigger("ajaxSend",[xhr,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xhr&&(xhr.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xhr)&&"error"||s.ifModified&&jQuery.httpNotModified(xhr,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xhr,s.dataType,s.dataFilter);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xhr.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else

Unfortunately I don't have a clue what that means..

thanks, larsb
« Last Edit: 28-Aug-2008, 08:12 PM by larsb »
Signature on it's way

#57: 14-Nov-2008, 09:02 AM

Jul
Posts: 401

Hi,

I could AJAXify my MODx site by following the tutorial.

Now, I'm trying to do something more sophisticated :
1) loading in a div the summary (introtext) of a child document when the mouse is over a link (onmouseover event)
2) and load the content of this child document in another div when the link is clicked.

I thought that the first step for this was being able to add processing of mutiple events.
So, I tried to define the processing function externally to the addEvent call.
But this did not work. For the first call of the addEvent function, Firebug tells that evt is undefined. (code is below)

I really don't know how to implement this as (as long as I know) the class and rel attributes of my link only allow to define one target and one template. So, how to handle two types of events with two different targets ?

Maybe an idea could be to include some div within or around the anchor element and define class and rel for this div.
Then, define some action for onmouseover in Kudolink's code.

Does anyone have an idea for a flexible solution ?

Unsuccessful try to modify Kudolink's code :
Code:
function processEvent (evt)
{
 evt = evt || window.event;
 if (evt.which > 1 || evt.button > 1) return;
 var src = evt.target || evt.srcElement;
 if (src.nodeType && src.nodeType != 1) src = src.parentNode;
 while (src)
 {
  var srcName = (src.nodeName||src.tagName||'').toLowerCase();
  if (srcName == 'a' && src.className && src.className.match(/^(load|toggle)into-(.+)$/))
  {
   if (RegExp.$1 == 'load') return loadInto(src, RegExp.$2, evt);
   if (RegExp.$1 == 'toggle') return toggleInto(src, RegExp.$2, evt);
  }
  src = src.parentNode;
 }
};
addEvent(document, 'click', processEvent(evt), 1);
addEvent(document, 'mouseover', processEvent(evt), 1);

#58: 15-Nov-2008, 04:11 AM

Jul
Posts: 401

Summary : I want Ajax to retrieve different content and send it to different targets, depending on the event that occurs for an anchor (click or mouseover). See the first post of this thread (i.e. the tutorial) for an implementation that only handles the click event.
-----------------------------------------------------------------------------------------

I canceled my changes to the Kudolink's script (see my previous post) and had another approach.

As the class rel defines which template is used to format what Ajax returns,
and as the rel class defines the container where to send Ajax's output, I tried changing this dynamically in the row template chunk of the Wayfinder config file, using the onmouseover and onclick events.

Code below is wrong, because I mixed the roles of the class and rel attributes.
Code:
$rowTpl = '@CODE:<li><a
onmouseover="this.class=\'loadinto-resume_rubrique\';this.rel=\'Template_resume_rubrique\';"
onclick="this.class=\'loadinto-texte_rubrique\';this.rel=\'Template_texte_rubrique\';"
href="[+wf.link+]"
title="[+wf.pagetitle+]">
<div class="chapeau lettrine">[+wf.linktext+]</div><span></span>
</a></li>';
Using some javascript alert boxes, I could confirm that the "class" and "rel" attributes were correctly set.

Unfortunately, my code still does not work.
It worked when the class and rel were defined "statically", i.e. without basing on the onmouseover and onclick events.

Who can help ?
Thanks.


There are two other errors that I did :

1) The behaviour for the click is defined in kudolink's code, which is placed in the template for the "parent" page.
 So, I have to modify this code instead of Wayfinder's row chunk definition.

2) The click and mouseover events occurs for the div that is in the anchor and not for the anchor itself.

I'll have to alter kudolink's code.
Not obvious however...


« Last Edit: 15-Nov-2008, 04:59 AM by Jul »

#59: 15-Nov-2008, 05:54 AM

Jul
Posts: 401

Yoohooo ! Smiley I could change the code so that different contents are loaded by Ajax into different target containers depending on which event occurs: mouseover or click.

 Undecided There's however a problem with my the target for the template defined by the rel attribute: it's the parent document and not the content retrieved par Ajax.
The error comes most probably from the fact that I define the rel attribute for the src variable (src.rel) and I should do it for the target (target.rel) or something like this.

The code that I use is the one here : http://modxcms.com/forums/index.php?topic=6743
in the "3. Create 2 templates" section with the following changes :
1) Added an event handler for mouseover.
2) The class and rel attributes are defined dynamically (see code below)
Code:
addEvent(document, 'mouseover', function(evt){
 evt = evt || window.event;
 if (evt.which > 1 || evt.button > 1) return;
 var src = evt.target || evt.srcElement;
 src.rel='Template_resume_rubrique';
 src.className="loadinto-resume_rubrique";
 if (src.nodeType && src.nodeType != 1) src = src.parentNode;
 while (src)
 {
  var srcName = (src.nodeName||src.tagName||'').toLowerCase();
  if (srcName == 'a' && src.className && src.className.match(/^(load|toggle)into-(.+)$/))
  {
   if (RegExp.$1 == 'load') return loadInto(src, RegExp.$2, evt);
   if (RegExp.$1 == 'toggle') return toggleInto(src, RegExp.$2, evt);
  }
  src = src.parentNode;
 }
}
, 1);

addEvent(document, 'click', function(evt){
 evt = evt || window.event;
 if (evt.which > 1 || evt.button > 1) return;
 var src = evt.target || evt.srcElement;
 if (src.nodeType && src.nodeType != 1) src = src.parentNode;
 while (src)
 {
  var srcName = (src.nodeName||src.tagName||'').toLowerCase();
  src.rel='Template_texte_rubrique';
  src.className="loadinto-texte_rubrique";
  if (srcName == 'a' && src.className && src.className.match(/^(load|toggle)into-(.+)$/))
  {
   if (RegExp.$1 == 'load') return loadInto(src, RegExp.$2, evt);
   if (RegExp.$1 == 'toggle') return toggleInto(src, RegExp.$2, evt);
  }
  src = src.parentNode;
 }
}
, 1);
Chunk for the links that do the Ajax calls :
Code:
$rowTpl = '@CODE:<li><a 
href="[+wf.link+]"
title="[+wf.pagetitle+]">
<div class="chapeau lettrine" >[+wf.linktext+]</div><span></span>
</a></li>';
A possible improvement would be reducing code redundancy as the functions that handle the onclick and onmouseover events are 95% the same.

#60: 15-Nov-2008, 06:44 AM

Jul
Posts: 401

Well. I removed the src.rel definitions in the event handlers and changed the definition of variable "template" in the loadInto function. Like this:

Code:
function loadInto(src, destId, evt) // Function modified by Heliotrope to accept REL attr - kudo
{
template = 'template=' + 'OwnTemplates_' + destId;      // Changed this line
url =  src.href;
src.href = (url.indexOf('?')>0)? url + '&' + template: url + '?' + template;
...
As you can see the template to use has the same name as the id of the destination container in which the output from Ajax has to be formatted, plus some prefix (OwnTemplates_).

 Huh For a mysterious reason, the appearance of the clicked or mouseovered link also changes when an event occurs. Undecided
Any idea why ?
Pages: 1 2 [3] 4   Go Up
0 Members and 1 Guest are viewing this topic.