Use Ajax in Prototype.js to load PART of an external page into a div - ajax

I'm looking for a way to load a part of an external page (possibly selected by an id in the external page) into a div. Something similar to Ajax.Updater, but with the option of specifying an id to look for in the external page.
Does anything like this exist in prototype. I've been googling for examples without luck. If I can't find it soon I'll have to do some "gymnastics" with Ajax.Request and some function tied to onSuccess.

You could do something like this, though it is by no means an elegant solution.
new Ajax.Updater("container", 'www.babes.com', {
onSuccess: function() {
$("container").update( $('idOfSomeLoadedElement') );
}
});
I don't think there is an actual elegant way of doing this purely in js. Ideally, you'd make your AJAX request only for what you need. You might be able to do some server-side stuff to lop out what you don't need (basically, offload the onsuccess functionality above to the server).

Instead of AJAX you might get by with an iframe.
// dollar function calls Element.extend
var iframe = $(document.createElement('iframe'));
// control how and what it loads
iframe.addEventListener('onLoad', function() {
$('container').update(iframe.contentDocument.select('#someID').first());
});
iframe.setAttribute('src', 'http://URL');
// add it as invisible, content isn't loaded until then
iframe.setAttribute('hidden', true);
document.body.appendChild(iframe);
From a minimal test it's clear that you'll have to be as concious about cross-origin policies as any AJAX method, that is, it's a PITA.

Related

Single page application with Rails 4 and AngularJS

Ok, this idea might seem quite a bit crazy and it kindo' is (at least for me at my level).
I have a fairly standarad rails app (some content pages, a blog, a news block, some authentication). And I want to make it into a single page app.
What I want to accomplish is:
All the pages are fetched through AJAX like when using turbolinks, except that the AJAX returns only the view part (the yield part in the layout) withought the layout itself, which stays the same (less data in the responces, quicker render and load time).
The pages are mostly just static html with AngularJS markup so not much to process.
All the actual data is loaded separately through JSON and populated in the view.
Also the url and the page title get changed accordingly.
I've been thinking about this concept for quite a while and I just can't seem to come up with a solution. At this point I've got to some ideas on how this actualy might be done along with some problems I can't pass. Any ideas or solutions are greatly appreciated. Or might be I've just gone crazy and 3 small requests to load a page are worse then I big that needs all the rendering done on server side.
So, here's my idea and known problems.
When user first visits the app, the view template with angular markup is rendered regularly and the second request comes from the Angular Resource.
Then on ngClick on any link that adress is sent to ngInclude of the content wrapper.
How do I bind that onClick on any link and how can I exclude certain links from that bind (e.g. links to external authentication services)?
How do I tell the server not to render the layout if the request is comming from Angular? I though about adding a parameter to the request, but there might be a better idea.
When ngInclude gets the requested template, it fires the ngInit functions of the controllers (usually a single one) in that template and gets the data from the server as JSON (along with the proper page title).
Angular populates the template with the received data, sets the browser url to the url of the link and sets the page title to what it just got.
How do I change the page title and the page url? The title can be changed using jQuery, but is there a way through Angular itself?
Again, I keep thinking about some kind of animation to make this change more fancy.
Profit!
So. What do you guys think?
OK, in case enyone ever finds this idea worth thinking about.
The key can be solved as follows.
Server-side decision of whether to render the view or not.
Use a param in the ngInclude and set the layout: false in the controller if that param is present.
Have not found an easier way.
Client-side binding all links except those that have a particular class no-ajax
Here's a directive that does it.
App.directive('allClicks', function($parse) {
return {
restrict: 'A',
transclude: true,
replace: true,
link: function(scope, element, attrs) {
var $a = element.find('a').not($('a.no-ajax')),
fn = $parse(attrs['allLinks']);
$a.on('click', function(event) {
event.preventDefault();
scope.$apply(function() {
var $this = angular.element(event.target);
fn(scope, {
$event: event,
$href: $this.attr('href'),
$link: $this
});
});
});
}
};
})
And then use it on some wrapper div or body tag like <body ng-controller="WrapperCtrl" all-links="ajaxLink($href)"> and then in your content div do <div id="content" ng-include="current_page_template">
In your angular controller set the current_page template to the document.URL and implement that ajaxLink function.
$scope.ajaxLink = function(path) {
$scope.current_page_template = path+"?nolayout=true";
}
And then when you get your JSON with your data from the server don't forget to use history.pushState to set the url line and document.title = to setr the title.

What is the right away to update a panel using AJAX?

In MVC4 applications, I would like to update a panel using AJAX but using jQuery methods instead using AjaxExtensions from MVC.
But my problem is the updatePanelId.
I've seen several people use this to update it when has success:
success: function (response) {
var $target = $("#target");
var $newHtml = response;
$target.replaceWith($newHtml);
}
But when I do this, it forces me to use in every partial view that includes the id="target" at the root level of my razor view, and I guess that's not a good practice; I said this because I've realized when I use AjaxExtensions it doesn't happens, replace the update and it does not remove the panelId. But using jQuery it does.
Any idea to port the AjaxExtensions feature to jQuery?
You can use just:
$("#target").html(response); // it will just update content of the $("#target") container
Use jQuery's .load function. This will load the contents of the URL you specify into the target element. You can optionally specify a selector after the URL in load to only grab part of the target page.
$(function() {
$("#target").load("/MyURL");
});
JavaScript same origin policy applies to this.

loading colorbox from within AJAX content

Firstly I am very new to all forms of javascript, particularly anything remotely AJAX. That said, over the course of the last day I have managed to code a script that dynamically refreshes a single div and replaces it with the contents of a div on another page.
The problem however is that several of my other scripts do not work in the ajax refreshed content. The most important of which being "colorbox".
I have spent several hours this evening researching this and am seeing lot's of stuff regarding .load, .live... updating the DOM on refresh etc...etc... But to be quite honest most of it is going over my head currently and I wouldn't know where to begin in terms of integrating it with the code I currently have.
My Ajax refresh code is as follows (My apologies if I haven't used best practice, it was my first attempt):-
$(function() {
$(".artist li.artist").removeClass("artist").addClass("current_page_item");
$("#rightcolumnwrapper").append("<img src='http://www.mywebsite.com/wp-content/images/ajax-loader.gif' id='ajax-loader' style='position:absolute;top:400px;left:190px;right:0px;margin-left:auto;margin-right:auto;width:100px;' />");
var $rightcolumn = $("#rightcolumn"),
siteURL = "http://" + top.location.host.toString(),
hash = window.location.hash,
$ajaxSpinner = $("#ajax-loader"),
$el, $allLinks = $("a");
$ajaxSpinner.hide();
$('a:urlInternal').live('click', function(e) {
$el = $(this);
if ((!$el.hasClass("comment-reply-link")) && ($el.attr("id") != 'cancel-comment-reply-link')) {
var path = $(this).attr('href').replace(siteURL, '');
$.address.value(path);
$(".current_page_item").removeClass("current_page_item");
$allLinks.removeClass("current_link");
$el.addClass("current_link").parent().addClass("current_page_item");
return false;
}
e.preventDefault();
});
$.address.change(function(event) {
$ajaxSpinner.fadeIn();
$rightcolumn.animate({ opacity: "0.1" })
.load(siteURL + event.value + ' #rightcolumn', function() {
$ajaxSpinner.fadeOut();
$rightcolumn.animate({ opacity: "1" });
});
});});
I was hoping someone might be kind enough to show me the sort of modifications I would need to make to the above code in order to have the colorbox load when the contents of #rightcolumn have been refreshed.
There is also a second part to this question. My links to the pictures themselves are now also being effected by the hashtag due to the above code which will in turn prevent the images themselves from loading correctly in the colorbox I should imagine. How can I prevent these images from being effected and just have them keep the standard URL. I only want the above code to effect my internal navigation links if at all possible.
Many thanks guys. I look forward to your replies.
That's a lot of code to review so I'll focus first on the conceptual side of things. Maybe that you will give you some clues...
It sounds like when you load content via Ajax the DOM is changed. No worries, that's kind of what we expect. However, scripts loaded before the Ajax calls may have difficulty if they are bound to elements that weren't there at page load time or are no longer there.
JQuery's live function is one solution to that. Instead of binding to a specific element (or collection of elements) at particular point in time, live lets you specify a binding to an element (or collection) of elements without regard to when they show up in the DOM (if ever).
ColorBox, however, in its default "vanilla" use abstracts that all away and, I believe, uses classic DOM binding - meaning the elements must be present at bind time. (Since you don't show your call to ColorBox I can't see how your using it.)
You may want to consider re-initalizing ColorBox after each content load by Ajax to be certain the binding happens the way you need it to.
Use $('selector').delegate() it watches the DOM of 'selector' and .live() is deprecated.
Use this to watch your elements AND fire the colorbox initilization. This way the colorbox is not dependent on the DOM element, but the other way around.
$("body").delegate("a[rel='lightbox']", "click", function (event) {
event.preventDefault();
$.colorbox({href: $(this).attr("href"),
transition: "fade",
innerHeight: '515px',
innerWidth: '579px',
overlayClose: true,
iframe: true,
opacity: 0.3});});
This should basically solve your problem and is cross browser tested.
The a[rel='lightbox'] in the delegate closure is the reference to what ever link you're clicking to fire the colorbox, whether it has been loaded with the initial DOM or with an AJAX request and has been added to the DOM in a live fashion. ie: any tag like this:
<a rel='lightbox' href="http://some.website.com">Launch Colorbox</a>

how to get information from php without refreshing the page

hi
sorry for the bad title but I'm not 100% sure what I need for this problem
I created a welcome page and then when you click on links you get more information, for example:
Click Me
And then the php would get the information based on the id.
so the information received is reloaded on the page after the pages refreshes
what I would like to be able to do is when user clicks on the link, use jquery to not allow the link to run but still run the url in the background (without refreshing the page)
I have no idea where to start from so I really hope you could help
thanks
In a nutshell, it's called Ajax: sending an HTTP request to your server through javaScript, and receiving a response which can contain results, data, or other information.
You mention jQuery, here are the docs about that:
http://api.jquery.com/jQuery.get/
http://api.jquery.com/jQuery.post/
are convenience methods, which encapsulate $.ajax with preset options.
http://api.jquery.com/category/ajax/ is an overview of the whole system in jQuery.
The basics go like
//include jquery, etc.
$(document).ready(function(){
$('#some_element').click(function(){
$.get('some_url_on_your_server.php',{'data':'whatever params'},function(data){
do_something();//
},'json');
});
This will bind an element to make an Ajax call on click, and then you use the function ('success' function, in $.ajax) to handle the json data.
Have your server send back the data in JSON by using json_encode in php. Be sure to send the right header back, like
<?php
header('Content-Type: application/json');
echo json_encode($some_array);
exit;
There's a lot of resources on the web and SO for learning about Ajax, it's a big topic. Best of luck.
Make a JavaScript function, like sendData(linkId) and then each tag would have an onclick event called sendData(this). SendData(linkId) can then do an HTTPRequest (also known as an asynchronous or AJAX request) to a php file, let's call it handler.php, which receives GET or POST methods. I prefer using the prototype framework to do this kind of thing (you can get it at prototypejs.org).
Okay, now that I have said all that, let's look into the nitty-gritty of how to do this (way simplified for illustrative purposes).
Download the prototype script, save it on your server (like prototype/prototype.js, for example) and then put somewhere in your html <script type='text/javascript' language='Javascript' src='prototype/prototype.js'></script>
Your tags would look like this:<a id='exampleLink' onclick = 'sendData(this)'>Click me!</a>
You need JavaScript to do this: function sendData(tagId){
var url = 'handler.php?' + 'id=' + tagId;
var request = new AJAX.Request(url, {method = 'get'});
}
Finally, you need a php file (let's call it handler.php) that has the following: <?php
$tag_to_get = $_GET['tagId'];
do_a_php_function($tag_to_get);
?>
That's it in a nutshell, but it's worth mentioning that you should give your user some sort of feedback that clicking link did something. Otherwise he will click the link furiously waiting for something to happen, when it is actually doing just what its supposed to but in secret. You do that by making your php script echo something at the end, like 'Success!', and then add an onSuccess parameter to your JavaScript's new Ajax.Request. I'll let you read how to do that on your own because the prototype website explains how to receive a response from the handler and put the feedback somewhere in your HTML without making the user refresh.
you can achieve that behavior with a jquery function called $.get ... you can get more information on how to use here http://api.jquery.com/jQuery.get/
If you really want to (and I don't think you really do), you can use XMLHTTPRequest (wrapped in jQuery.get) to facilitate loading content into the page without page refreshing. You want an id or class on that tag, i.e. Click Me, and then:
<script>
$(".fetch").bind("click", function(evt)
{
$.get(this.attr("href"), function(data)
{
$("#whereIWantMyContent").html(data);
});
evt.preventDefault();
});
</script>
I would recommend you use AJAX to start with. A good place to being is http://www.w3schools.com/Ajax/Default.Asp
The link comes with a handy AJAX ASP/PHP Example too =))
Good Luck.

jQuery: Can I automatically apply a plug-in to a dynamically added element?

I'm in the process of converting my web app to a fully AJAX architecture.
I have my master page that is initially loaded and a div container that is loaded with dynamic content.
I created a few jQuery plugins that I apply to certain elements in order to extend their functionality. I'd normally call the functions as follows during each page load:
$(document).ready(function () {
// Enable fancy AJAX search
$(".entity-search-table").EntitySearch();
});
This would find the appropriate div(s) and call the plugin to enable the necessary functionality.
In an AJAX environment I can't just apply the plugin during the page load since elements will be added and removed dynamically.
I'd like to do something like this:
$(document).ready(function () {
// Enable fancy AJAX search
$(".entity-search-table").live("load", function () {
$(this).EntitySearch();
});
});
Question: Is there any way that I can trigger an event when a <div> or other element that matches a selector is added to the DOM?
It seems incredibly wasteful to activate the plug-in every time an AJAX request completes. The plug-in only needs to be applied to the element once when it is first added to the DOM.
Thanks for any help!
Yes - take a look at liveQuery. Example:
$('.entity-search-table').livequery(function(){
$(this).EntitySearch();
});
It seems incredibly wasteful to activate the plug-in every time an AJAX request completes. The plug-in only needs to be applied to the element once when it is first added to the DOM.
You can get the best of both worlds here, for example:
$("#something").load("url", function() {
$(".entity-search-table", this).EntitySearch();
});
This way it's only applying the plugin to the .entity-search-table elements you just loaded, since we specified a context to $(selector, context) to limit it.
The DOM 2 MutationEvent is what you really want, but unfortunately it isn't supported by IE. You'll need to either use live()/ delegate() binding in the plug-in, or (as I did when I had to work around this) use callbacks from your AJAX loaders indicating the scope of what has changed.
Use the live binding in your plugin code directly
jQuery.fn.EntitySearch = function() {
this.live(..., function(){ your plugin code });
return this;
}

Resources