Jul 05, 2009, 09:07 PM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
Search via SMF or Google: modx forums all of modxcms.com web
  MODxCMS.com   Forums   Help Login Register  
News:Read what MODx Developers say: MODx Dev. Blogs
Pages: 1 2 3 [4] 5   Go Down
  Print  
Author Topic: [Tutorial] AJAXify your MODx site - and it degrades well, too!  (Read 27028 times)
0 Members and 1 Guest are viewing this topic.
Sylvaticus
Sr. Member
****
Posts: 428


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


WWW
« Reply #45 on: May 19, 2008, 11:34 PM »

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
Logged
AHHP
Moderators
*
Posts: 341


Salut capitan,


WWW
« Reply #46 on: May 20, 2008, 06:34 AM »

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
Logged

andreasfruth
Jr. Member
*
Posts: 5


« Reply #47 on: May 20, 2008, 06:40 AM »

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.
Logged
Sylvaticus
Sr. Member
****
Posts: 428


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


WWW
« Reply #48 on: May 20, 2008, 06:40 AM »

Great news!
Logged
andreasfruth
Jr. Member
*
Posts: 5


« Reply #49 on: May 20, 2008, 08:00 AM »

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: May 20, 2008, 08:52 AM by andreasfruth » Logged
AHHP
Moderators
*
Posts: 341


Salut capitan,


WWW
« Reply #50 on: May 20, 2008, 11:03 AM »

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
Logged

andreasfruth
Jr. Member
*
Posts: 5


« Reply #51 on: May 20, 2008, 11:35 AM »

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: May 20, 2008, 01:09 PM by andreasfruth » Logged
AHHP
Moderators
*
Posts: 341


Salut capitan,


WWW
« Reply #52 on: May 20, 2008, 01:25 PM »

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
Logged

MotSmart
MODx RTL Guru.
Moderators
*
Posts: 910



WWW
« Reply #53 on: May 20, 2008, 09:44 PM »

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 :-]
Logged

[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?!
andreasfruth
Jr. Member
*
Posts: 5


« Reply #54 on: May 21, 2008, 04:13 AM »

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: May 21, 2008, 08:48 AM by andreasfruth » Logged
larsb
Member
**
Posts: 65



« Reply #55 on: Aug 28, 2008, 08:07 PM »

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: Aug 28, 2008, 08:12 PM by larsb » Logged
Jul
Full Member
***
Posts: 243


« Reply #56 on: Nov 14, 2008, 09:02 AM »

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);

Logged
Jul
Full Member
***
Posts: 243


« Reply #57 on: Nov 15, 2008, 04:11 AM »

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: Nov 15, 2008, 04:59 AM by Jul » Logged
Jul
Full Member
***
Posts: 243


« Reply #58 on: Nov 15, 2008, 05:54 AM »

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.
Logged
Jul
Full Member
***
Posts: 243


« Reply #59 on: Nov 15, 2008, 06:44 AM »

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 ?
Logged
Pages: 1 2 3 [4] 5   Go Up
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP

Copyright © 2005-2008 MODxCMS, All rights reserved. Contact Us
Styles by ziworks.com

Powered by SMF | SMF © 2006-2008, Simple Machines LLC

Valid XHTML 1.0! Valid CSS!