• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1247
  • Last Modified:

Ajax Updater: The requested method POST is not allowed for the URL ...

Hi
I am using Ajax Updater to send html files into a div tag on my page.

In Firefox fine.  In IE6 I am getting the error: The requested method POST is not allowed for the URL ...

The prototype and external js file are both in a global directory which is not the same as the place where the html page is.  It is also being tested on a Web Server.

Actually, that's not quite true,  it refuses to work -AT ALL- when the function is in the external js file.  the error was actually happening when the script was moved into the head of the html.

Please help.

Here's the funciton in the external js file:

function populate (serverPage, obj){      
alert("hello");
   var objID = "text";  
   new Ajax.Updater(objID, serverPage);

//change tab color
  if(obj != null)
  {
   var links = document.getElementById('box').getElementsByTagName('A');
    for (var i=0; i<links.length; i++) {
      if (links[i].className=='highlighted' && links[i] != obj)  
           links[i].className='plain';  
    }
    obj.className='highlighted';
  }
}


here's the call in the head of the html file:
window.onload = function(){populate ('blah.html', null);};


Here's the html:

      <div id="box">
        <ul id="boxtabs">
                         <li><a href="#" onclick="populate('moreblah.html',this);return false">About</a></li>
        </ul>
        <div id="box">(LOADING...)</div>
            <br class="clearFloat" />
      </div>
0
Lady_M
Asked:
Lady_M
  • 10
  • 8
5 Solutions
 
bdichiaraCommented:
It appears you want all the 'A' tags inside the "boxtabs" element, not the "box" element (which is EVERYTHING, it appears). Also, you don't want to use onclick="function();return false" but instead onclick="return function();" Additioanlly, Prototype/Scriptaculous has a better onload observer, I would recommend using it:

Event.observe(window, 'load', function(){ populate('blah.html', null); });

Along with the dollar function $(id) = document.getElementById(id)

Also, in this case, you're not SENDING any data, you are GETTING it (plus it's an HTML file), so use GET:

new Ajax.Updater(objID, serverPage, {method:'get'});

so to sum up:

function populate (serverPage, obj){      
      var objID = "text";
      new Ajax.Updater(objID, serverPage, {method:'get'});
      
      //change tab color
      if(obj != null){
            var links = $('boxtabs').getElementsByTagName('A');
            for (var i=0; i<links.length; i++) {
                  //if (links[i].className=='highlighted' && links[i] != obj){
                        links[i].className='plain';  
                  //}
            }
            obj.className='highlighted';
      }
      return false;
}

Event.observe(window, 'load', function(){ populate('blah.html', null); });


/////   html code  /////


<div id="box">
      <ul id="boxtabs">
            <li><a href="#" onclick="return populate('blah.html',this);" class="highlighted">main</a></li>
            <li><a href="#" onclick="return populate('junk.html',this);">Other</a></li>
            <li><a href="#" onclick="return populate('moreblah.html',this);">About</a></li>
      </ul>
      <div id="text">(LOADING...)</div>
      <br class="clearFloat" />
</div>

hope that helps.
0
 
bdichiaraCommented:
Here are some other recommendations:
- I commented out an unnecessary line above. You can mark all links as plain, then mark the highlighted one in the end.
- Keeping slower internet connections in mind, change your tab class onComplete.
- use a "loading" animation/message to let the user know "something is happening" and not to click 100 times cause they didn't see anything change.

That being said, here's the updated function:

function populate (serverPage, obj){
      //display loading message/animation here
      
      var objID = "text";
      new Ajax.Updater(objID, serverPage, {method:'get', onComplete:function(){
                        //change tab color
                        if(obj != null){
                              var links = $('boxtabs').getElementsByTagName('A');
                              for (var i=0; i<links.length; i++) {
                                    links[i].className = 'plain';  
                              }
                              obj.className = 'highlighted';
                        }
                        
                        //hide loading message/animation here
                  }
            }
      );
      
      return false;
}
0
 
bdichiaraCommented:
You can also reduce "flickering" by setting a global variable in relation to each tab, then check to see if the user is trying to switch to a tab that is currently open.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
Lady_MAuthor Commented:
Thanks for going to all that trouble, and giving such clear instructions.  I've been trying to sort this out for several days now so it's very appreciated.  I have changed my code around as you say and I'm going to test it on a server shortly and will let you know how I get on.
0
 
Lady_MAuthor Commented:
Hi bdichiara
Sorry for taking a while to get back to you, I'm working on several projects.  
Quickish question:
I want to put the populate () function into an external js file, and then I guess I have to initialise it from my page.  So I did try adding this line to the head of my html to call it:
//Event.observe(window, 'load', function(){ populate ('mypage.html', null); });
but it's not working.
Is there a (simple) way other than putting the call in the body tag to initialise this function from a global js file please?
0
 
Lady_MAuthor Commented:
Another less important quick question:
Where you've got "//hide loading message/animation here" - what can I put in there?  I tried adding a document.write but that just obviously wrote it to the page and froze the function.  It would be nice to add a little "please wait" there, but not sure how to do it.  It's not a big deal though.
Thanks
0
 
bdichiaraCommented:
If you are referencing your file like this:
<script type="text/javascript" src="/js/blah.js"></script>

You can just include that line right under your function. Also, here's some updated code that gives you an example of how to use the "loading animation"

///////  included javascript file  ///////

function populate (serverPage, obj){
      //display loading message/animation here
      Element.show('loading');
      
      var objID = "text";
      new Ajax.Updater(objID, serverPage, {method:'get', onComplete:function(){
                        //change tab color
                        if(obj != null){
                              var links = $('boxtabs').getElementsByTagName('A');
                              for (var i=0; i<links.length; i++) {
                                    links[i].className = 'plain';  
                              }
                              obj.className = 'highlighted';
                        }
                        
                        //hide loading message/animation here
                        Element.hide('loading');
                  } // end function
            } // end options
      ); // end ajax.updater
      
      return false;
}


Event.observe(window, 'load', function(){ populate('blah.html', null); });


///////  html and css  ///////

<style type="text/css">
.highlighted { background:#FFFFCC; }
.plain { color:#333333; }
#boxtabs { list-style:none; margin:0; padding:0; }
#boxtabs li { float:left; margin:5px; padding:5px; }
#text { clear:both; }
#loading { float:right; }
</style>


<div id="loading">insert loading animation here</div>
<div id="box">
      <ul id="boxtabs">
            <li><a href="#" onclick="return populate('blah.html',this);" class="highlighted">main</a></li>
            <li><a href="#" onclick="return populate('junk.html',this);">Other</a></li>
            <li><a href="#" onclick="return populate('moreblah.html',this);">About</a></li>
      </ul>
      <div id="text">(LOADING...)</div>
      <br class="clearFloat" />
</div>


Also, here's a link, if you want to see a demo:

http://briandichiara.com/tabs
0
 
bdichiaraCommented:
I think yours wasn't working because it's commented out (// is a comment)
0
 
bdichiaraCommented:
Also, a nice place for an AJAX loading animation can be found at:

http://ajaxload.info/
0
 
Lady_MAuthor Commented:
I've figured out the problem with the external call thing.  I still had the script tags in the js file.  So that's sorted.
And thanks alot for the link.  Sounds good.
But if I didn't want an animation, what would I put in that line?  Would I just get the Div element and add some html to it?
0
 
bdichiaraCommented:
Alternatively you could write "loading..." into the content area, then when the AJAX is complete, overwrite "loading..." with the new content, but I wouldn't recommend that. You could do just like gmail and put the text "Loading..." in the top right corner, similar to my example. It's up to you.
0
 
Lady_MAuthor Commented:
Hiya bdichiara

I know I'm being extremely slow, but I don't get what syntax I have to use in that line so that the loader will appear in the right place in the page, I'd like it to actually appear in "infoboxtext".
Do I have to get that element first and then assign it some content?  And if so, shouldn't I really be accessing the variable varobjID that I assign in the next line down?

function  getInfo (serverPage, obj){
      //Don't know what to put here.....
      var objID = "infoboxtext";
      new Ajax.Updater(objID, serverPage, {method:'get', onComplete:function(){
                        //change tab color
                        if(obj != null){
                              var links = $('infoboxtabs').getElementsByTagName('A');
                              for (var i=0; i<links.length; i++) {
                                    links[i].className = 'plain';  
                              }
                              obj.className = 'highlighted';
                        }
                       
                        //or here...........
                  }
            }
      );
     
      return false;
}
0
 
bdichiaraCommented:
What is it exactly that you want to do? Are you talking about putting the "loading..." text in the content of "infoboxtext" or are you simply wanting it in the same area "physically". If the answer is physically, then you just need to style a new element that does not reside inside your updated infoboxtext element.

////// right: ////////
<div id="loading">Loading...</div>
<div id="infoboxtext">
blah.html content
</div>


////// wrong: ////////
<div id="infoboxtext">
<div id="loading">Loading...</div>
blah.html content
</div>

The problem with the example above is when your new content is inserted into you div "infoboxtext" it will overwrite the existing content, including the loading div.  Now, if you are trying to replace the entire contents of "infoboxtext" with the text "Loading..." before it loads in the new content, then you would only need to use one line:

Element.update('infoboxtext','Loading...');

However, like I mentioned before, I would recommend against this. You will be clearing out the contents of "infoboxtext" once to display loading, then again to display the new contents. I think that would be too much action on the page for the user.

I would go with my recommendation and show/hide a message that simply says that new content is loading please wait...  The first part shows it at the start of the request, then the 2nd part hides it at the end of the request.
0
 
Lady_MAuthor Commented:
Hi again
Well to be honest the content loads instantaneously anyway so it's not a big issue.  All I want to do is show, okay let's say an animation, in the area of the text div if there is a delay in loading the pages.  So the show/hide thing sounds best.  So to clarify, I should use a <div id="loading"> to do this and change the class in the function.  Is that right?
0
 
bdichiaraCommented:
you could change the class from ".hidden { display:none; }" to ".visibile { display: block; }", or you can just use inline styles (which is what I usually do) like

<div id="loading" style="display:none;"><img src="loading_animation.gif" border="0" alt="loading..." /></div>

But then again, in your case, even the inline style is not necessary because when your page loads, it will hide the loading element when it completes the first request to get the content.

Just make sure you do not have this set in your stylesheet:

#loading { display:'none'; }

That will cause the show/hide thing not to work at all. It has to be done inline, meaning using: style="" inside the <div>
0
 
Lady_MAuthor Commented:
Okay thanks.  I think I get it now.
Thanks alot for all your help.  You can have some points now.
0
 
Lady_MAuthor Commented:
Sorry bdichiara, that sounded really curt.  I'm a bit stressed, trying to do half a dozen things at once.

What I meant to say was "thanks ALOT for all your help, you've been really kind and it's VERY appreciated.
0
 
bdichiaraCommented:
Your welcome! Let me know if you need any other help.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 10
  • 8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now