I need to detect where the user has just clicked from - as my AJAX content needs to be displayed differently depending on the source page it is to be inserted into.
If it's to go into about.php it needs to be data only, but if it's to go into about-main.php it needs to be the whole middle column so needs a header/footer wrapper around the data.
The html called via AJAX is held in a php page which uses this code to see who's asking, and then formats the HTML response appropriately.
$array[] = "/cf/about.php";
$array[] = "/cf/about/about-main.php";
$array[] = "/cf/about/other-page.php";
$ispage = "";
foreach ($array as $value) {
if ($_SERVER['HTTP_REFERER'] != $value) {
$ispage = "";
} else {
$ispage = "woot";
}
}
if ($ispage == "woot") {
echo $content;
} else {
include_once 'about-header.php';
echo $content;
include_once 'about-footer.php';
}
The problem is... HTTP_REFERER seems to be a bit hit and miss. It works just fine while I'm at work on the network, but I've tried it out on my computer at home and it's obviously completely failing to work - the results are horrible :o
Is there another way of achieving this? I guess session variables could be used but then I've not got much experience of that!
Any and all hints/tips are appreciated ;)
Thanks!
edit:
The page is actually a staff profile page. Its normal location is about.php and the 2nd column div displays a grid of thumbnails which when clicked, load the profile in that place via AJAX. All nice and simple - back button reloads the grid of photos.
The problem is, each staff member also needs a static page. I've created these at about/staff-name.php. The content is THE SAME though. I want the server to detect if someone has come to the about/staff-name.php directly and if so, wrap a header/footer around it.
If the request has come from the grid of photos (ie AJAX) then it doesn't need the header/footer wrapper.
Is that clear? :o
1) If AJAX request - no wrapper
2) If not AJAX request - add header/footer wrapper
Wouldn't it be easier to just pass a flag in your AJAX call to tell the script which type of content to display?
Edit:
So about/staff-name.php displays the content. Call it via AJAX as about/staff-name.php?FromAjax=1
Then in the about/staff-name.php file:
if (isset($_REQUEST['FromAjax']) ) {
echo $content;
} else {
include_once 'about-header.php';
echo $content;
include_once 'about-footer.php';
}
No matter what, the Referer is not an information you should base your whole website upon : it is sent by the client, which means (at least) :
the client does not necessarily have to send it
it can be disabled in the browser
some firewall / antivirus remove it
it can be forged / altered (an easy way with firefox is to use an extension to do that)
You definitly must find a better/saffer/more reliable way to do what you need.
One solution (which you already discarded) would be to pass an additionnal information in all your links, saying which page the request comes from. In my opinion, this would probably be the best thing to do...
Maybe a simpler way would be to add a parameter to your Ajax request, saying where it comes from ? ie, instead of relying on the Referer in the PHP script, just have a look at a parameter in the request, which would act as some "kind of referer", but put by you ?
It will not be more secure (users could still forge request, with that parameter), but, at least, it would not be disabled / modified (except if the user does it by hand)
In the end, you also say this :
1) If AJAX request - no wrapper
2) If
not AJAX request - add header/footer
wrapper
Well, if it's only a matter of determining if the PHP script was called through an Ajax request, here too, two solutions :
Add a parameter to the Request when it's done through Ajax (you only add this parameter in the JS script doing the request ; and when the parameter is here, PHP knows it's an Ajax request)
Or, in the PHP script, look for an X-Requested-With HTTP header, which is often here with the value XMLHttpRequest when a request is made through an Ajax call. (But you should check that it's set with your JS Framework / or maybe it depends on the browser -- not sure about that :-( )
Why don't you just create the static pages on the server without using ajax at all, including the header and footer and the profile bit? If the page is static you shouldn't have any need to load content using javascript.
If you do need to load it using javascript, then Vex's solution is good. You could pass some optional parameters in the ajax call which control how the page is rendered - that way, the included page doesn't need to know about the pages that use it, it just needs to understand the parameters that tell it how to render itself. You can then reuse it more easily in future.
I did notice an error in your code however - this probably won't work as expected:
$ispage = "";
foreach ($array as $value) {
if ($_SERVER['HTTP_REFERER'] != $value) {
$ispage = "";
} else {
$ispage = "woot";
}
}
If a page name is matched, but then the next one isn't, $ispage will be set back to ''. You'd probably better off doing something like:
$ispage = "";
foreach ($array as $value) {
if ($_SERVER['HTTP_REFERER'] == $value) {
$ispage = "woot";
break;
}
}
or
$ispage = '';
if (in_array($_SERVER['HTTP_REFERER'], $array)) {
$ispage = 'woot';
}
Tai kucing -
If you format your links like this:
link
Then the php just needs to be this:
if (isset($_REQUEST['setvariablehere']) ) {
do something for when variable IS set
} else {
do something for when variable IS NOT set
}
Related
I have written a single page application in HTML5. I use JQuery and hash navigation to navigate between pages. This works fine so far. Now I have written a really simple php script that pulls blog entries from my database. Of course I want the user to be able to link those articles and navigate tags etc. How would I implement that?
I tried http://example.com/#blog?tag=news but somehow my php script is unable to catch that parameter.
do it like http://www.example.com?tag=news#blog in my opinion it looks nicer and also the # as #AbraCadaver stated is only used by the browser.
<?php echo $_GET['tag']; ?> //would output news
That is a fragment denoted by the # and is only used by the browser and not passed to the server. PHP will not receive $_GET['tag'] and not #blog as you have it constructed.
Try ?tag=news#blog but PHP will still not get the #blog.
you can catch using this var $_GET['tag']
you must use java scritp
eg:
var hash = location.hash;
it will return the hash value to you
but you will need send to server-side using
the post or get of java script
I have solved the problem and wanted to share here how.
The underlying problem here was the loading of all content with JQuery. While my initial URI was wrong, http://example.com/?tag=news#blog did not solve it either. The variable was never sent to the $_GET Array of PHP, because the index.html does not contain any PHP and the script is loaded into a div via JQuery/Ajax.
So the solution here was to modify my JQuery Function:
function navigate(theHash)
{
var parsed = theHash;
var tag = '';
if ( theHash.indexOf("/") != -1 ){ /* Check if there is a trailing slash in the string */
parsed = theHash.substr(0, theHash.indexOf("/"));
}
if ( theHash.indexOf(",") != -1 ){ /* Check for Parameters to send to PHP */
parsed = theHash.substr(0, theHash.indexOf(","));
tag = theHash.substr(theHash.indexOf(','), theHash.length);
}
if ( parsed.localeCompare("#!portfolio") == 0 ){
$('#content').load('portfolio.html');
}
else if ( parsed.localeCompare("#!blog") == 0 ){
if ( tag.localeCompare('') != 0 )
{
$("#content").load('blog.html?tag='+tag.substr(1, tag.length));
}
else{
$("#content").load('blog.html');
}
}
else{
$('#content').load('front.html');
}
}
So with the little change in the blog part of the if statement to load the html page with the parameter appended (which contains the php code), the variable gets transported correctly to PHP and I can read it via $_GET. While this is only a first draft and needs to get refined for more parameters and more robust behavior, it shows how I solved the issue.
My first contact with Ajax is happening right now, and I'm kind a confused. I've read many of questions asked, but I'm not able to read the answer, that is most likely here somewhere.
Situation is, I'm using OOP PHP approach, and all I do go through index.php with parameters. So I do not call any other .php file in form posts, button clicks..
I've created an HTML listbox (which I'd like to remove vertical scrollbar, but that's just a bonus to resolve), which feeds my categories in it.
Now, by clicking each category I'd like to call certain function that would then generate output for the other div.
function swapContent(){
$("#myPresentDiv").html('<img src="../../imgs/ajax-loader-big.gif"/>').show();
var cat = $('#listbox').val();
$("#action").change(alert(cat));
var url = "&s=".cat;
$.post(url, {contentVar: cat} ,function(data) {
$("#myPresentDiv").html(data).show();
});
}
So, my JQuery script picks up correct Category, I alert it to alert dialog, so I'm sure that's fine, and then with code as it is at the moment, I reload my whole page so I get, page in page in page in page...
I'm trying to figure out how to write JQ ajax call, that would return only the results, not the whole page.
can I put URL "index.php&s="cat, and then somehow tell to ajax "go through index, call function displayresults ($cat); ?
Hope everything I wrote make sense to you :)
Tnx.
The url's your ajax function call, must return only the page parts and not the whole html document.
If you have
$.post('ajax.php',data,function(d){
$('#responsediv').html(d).show();
});
The file ajax.php must only return the page parts,like
<div>This is the new content</div>
so you will not have page inside page.
If you look at the frameworks or cms out there, they basically have routes that map calls to your index.php function to methods of the controller.
This is a complex argument, you could try to start out reading this article
Yeah, that makes sense. Your question is basically: when you get a result of an AJAX op and insert it into your page, it inserts the whole layout again, rather than the template.
OK, so the solution is to make a call to a PHP script that is "unstyled" i.e. has no template data. Your PHP script should therefore just output a short HTML snippet rather than a page (you might have a 'header' and 'footer' that can be removed for this page). What action you need to take depends what you're using on the server side - framework? CMS? Custom PHP app?
I did the exact thing for a internal app quite some time ago....What happened was i was passing the class name, function name and the function parameters via ajax variables and reading the same in php at the backend and then call the appropriate function in the class with those paraeters.
The PHP code:
$option = trim($_GET['v']);
switch ( $option ) {
case 1:
$sid = trim($_GET['q']);
$page = trim($_GET['p']);
$method = trim($_GET['m']);
$class = new $page( $link );
echo $class->$method( $sid );
break;
case 2:
$page = trim($_GET['p']);
$method = trim($_GET['m']);
$class = new $page( $link );
echo $class->$method();
break;
default:
echo '';
break;
}
But this was an internal app, so there was no injection attacks, xss,xsrf,session hijack issues....things might differ for you
Hope this helps.
I think you are searching for a GENERAL strategy to handle ajax requests its upto you
for example Server Side Ajax
unless you are using a specific framework (CI , yii etc)
You might want to look into some frameworks, as they can make this for you infinitely easier to implement:
http://demo.atk4.com/demo.html?t=20
I have a PHP page where the header and footer are PHP includes.
I want to know if there is any possibility of the includes loading asynchronously - or does PHP gather all the files required, compile them and send them as one file?
The reason I ask is that I've seen an interesting PHP app that seemed to keep the connection open and do things in sequence before closing the connection - I wondered if that's what happens with includes.
PHP version is 5.3.6
EDIT:
What I actually want is for the page to load all at once, to prevent my layout mashing as each bit loads. Sorry to any who misunderstood this
PHP does gather and compile them; everything goes to the browser as a single document. If you don't want this, you'll have to do something with XMLHTTPRequest on the frontend
Generally any output will be output as it is generated.
echo 'A';
sleep(1000);
echo 'B';
sleep(1000);
echo 'C';
This slowly outputs "ABC". Includes are included when they are encountered, the same way echo outputs anything at that specific point. It's all in order, never asynchronously.
A web server may buffer all output before sending any of it to the client. In the above example, you'd receive "ABC" all together after 2 seconds of nothing.
If your objective is to receive all the page at once you need to use ob_start() and ob_end_flush(). Do something like:
ob_start();
...
write all your outputs
...
ob_end_flush();
This will force the server to buffer the output until the whole page is prepared.
Good luck!
I use the following architecture when loading a page on my application:
index.php
<script src="path/to/js/lib/jslib.js" type="text/javascript"></script>
window.addEvent('load', function()
{
BuildPg(PgStatus); //PgStatus is a variable I use in a state machine to build different pages
});
<form>
<div id="DivPgTop"></div>
<div id="DivPgMiddle"></div>
<div id="DivPgBottom"></div>
</form>
This is the entire index.php
In my jslib.js I have functions like:
function BuildPg(Pg) {
BuildPgTop(Pg);
BuildPgMiddle(Pg);
BuildPgBottom(Pg);
}
function BuildPgTop(Pg) {
var Content="";
if (Pg == 1) {
Content = function_a(); // function_a builds the top of the page
else if (Pg == 2) {
Content = function_b();
etc...
}
document.getElementById("DivPgTop").innerHTML = Content; //here is where I load the top of the page
}
And I do the same for the other parts of the page Middle and Bottom.
Using this framework, if you changed my BuildPg() function to something like:
function BuildPg(Pg) {
BuildPgTop(Pg);
sleep(foo);
BuildPgMiddle(Pg);
sleep(bar);
BuildPgBottom(Pg);
}
Your user would experience the top of the page loading first, a delay, the middle of the page, another delay, and the bottom.
And if you change the order of the function calls you could even have the bottom of the page load first, then the middle and the top.
I hope this makes sense. Good luck!
PHP sends a single document. What you want to do is achieved with something called AJAX (http://en.wikipedia.org/wiki/Ajax_%28programming%29)
Basically you write some JavaScript code that uses XMLHTTPRequest object to connect to the server and download some extra info.
So I have a site with a dozen pages on it using Drupal as a CMS. Wanted to know how to set/append all href links on any page with a dynamic attribute?
so here is an example URL:
http://www.site.com/?q=node/4
and I wanted to append to the URL like so:
http://www.site.com/?q=node/4&attr=1234
Now I have a nav bar on the site and when I hover over the link I see the url but I need to append the &attr=1234 string to the end of it. The string is dynamic so it might change from time to time.
I was thinking jQuery would be a good choice to do this but does Drupal have any functionality as well?
Now I've seen a couple of posts on Stack:
Post 1
Post 2
Problem is I'm learning my way around Drupal and have minimal experience with jQuery but getting better with both. I see the jQuery can replace a HREF but looks like they hard coded the HREF, could jQuery find all HREF's on a page and append the string to it? Also does Drupal have this functionality and what would be the best approach?
Also need this to work for clean or standard URL format, so I think Apache would handle this I just wanted to make sure.
Thanks for any help
EDIT:
Looks like the general consensus is the Drupal should handle this type of request. Just looking for the best implementation. Simple function call would be best but I would like it to dynamically add it to all existing href's as I want this to be dynamic instead of hard coding any url/href calls. So I could add/remove pages on the fly without the need to reconfigure/recode anything.
Thanks for the great tips though
EDIT #2:
Okay maybe I'm asking the wring question. Here is what I need and why it's not working for me yet.
I need to pass a value in the url that changes some of the look and feel of the site. I need it to be passed on just about every href tag on the page but not on User logout or Admin pages.
I see in my template code where the nav links get generated, so I though I could pass my code in the attributes array as the second parm to the function, but that is setting the tag attributes and not the URL attributes.
Now I see the bottom nav links use this Drupal function: menu_navigation_links() in menu.inc but the top nav uses a custom function.
This function in the template.php script looks to be the one creating the links
function lplus($text, $path, $options = array()) {
global $language;
// Merge in defaults.
$options += array(
'attributes' => array(),
'html' => FALSE,
);
// Append active class.
if (($path == $_GET['q'] || ($path == '<front>' && drupal_is_front_page())) &&
(empty($options['language']) || $options['language']->language == $language->language)) {
if (isset($options['attributes']['class'])) {
$options['attributes']['class'] .= ' active';
}
else {
$options['attributes']['class'] = 'active';
}
}
// Remove all HTML and PHP tags from a tooltip. For best performance, we act only
// if a quick strpos() pre-check gave a suspicion (because strip_tags() is expensive).
if (isset($options['attributes']['title']) && strpos($options['attributes']['title'], '<') !== FALSE) {
$options['attributes']['title'] = strip_tags($options['attributes']['title']);
}
return '<a href="'. check_url(url($path, $options)) .'"'. drupal_attributes($options['attributes']) .'><b>'. ($options['html'] ? $text : check_plain($text)) .'</b></a>';
}
not sure how to incorporate what I need into this function.
So on the home page the ?q=node/ is missing and if I append the ampersand it throws an error.
http://www.site.com/&attr=1234 // throws error
But if I mod it to the correct format it works fine
http://www.site.com/?attr=1234
Assuming that when you mean pages, you mean the content type of pages (will work for any other content type as long as it's really content and not something in a block or view).
You can easily replace the contents of any node that is about to be viewed by running a str_replace or with a regular expression. For instance, using str_replace:
function module_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
switch($op) {
case "view":
$node->body = str_replace($expected_link, $desired_link);
break;
}
}
where you define desired link somewhere else. Not an optimal solution, but non-Javascript browsers (yes, they still exist!) can't get around the forced, desired URLs if you try to change it with Javascript.
I think doing it in Drupal/PHP would be cleaner. Check out Pathauto module: http://drupal.org/node/17345
There is a good discussion on a related topic here:
http://drupal.org/node/249864
This wouldn't use jquery (instead you would overwrite a function using PHP) but you could get the same result. This assumes, however, that you are working with menu links.
I think you should consider exploring PURL ( http://drupal.org/project/purl ) and some of the modules it works with e.g. spaces and context.
I don't suggest you use jQuery to do this. It's a better practice to do this server side in PHP (Drupal).
You can overwrite the links dynamically into your preprocess page function.
On your template.php file:
function *yourtheme*_preprocess_page(&$vars, $hook){
//You can do it for the region that you need
$vars['content'] = preg_replace('/<a href="(.*?)"/i', '<a href="$1&attr=1234"', $vars['content']);
}
Note:
I did not try it, its only a hint.
It will add your parameters to the outside links too.
i am using ajax to load pages into a div
the page is loading fine
but i cant run the php and javascript
in that loaded page
in server i am loading the page like this
file_get_contents('../' . $PAGE_URL);
in the browser i am setting the content of the div
using
eval("var r = " + response.responseText);
and setting the innerHTML for that div
with the retrieve information
but when i get the new inner page
no php or java script is working
is that suppose to be like that ?
Well the php is not going to work I think because the way you are handling it, it is just text. I would suggest using something like include('../' . $PAGE_URL); and that should parse the php.
The javascript problem probably has to do with the fact that you are loading <html> <body> <head> tags in a div I'm not sure what happens when you do that, but it shouldn't work properly. Try using some type of <frame> tag.
In order for your javascript to be executed properly, you have to wait until the browser has finished to load the page.
This event is named onload(). Your code should be executed on this event.
<?php
$file = false;
if(isset($_GET['load'] && is_string($_GET['load'])) {
$tmp = stripclashes($_GET['load']);
$tmp = str_replace(".","",$tmp);
$file = $tmp . '.php';
}
if($file != false && file_exists($file) && is_readable($file)) {
require_once $file;
}
?>
called via file.php?load=test
That process the PHP file, and as long as you spit out HTML from the file simply
target = document.getElementById('page');
target.innerHTML = response.responseText;
Now, i'm fairly certain parts of that are insecure, you could have a whitelist of allowable requires. It should ideally be looking in a specific directory for the files also. I'm honestly not all too sure about directly dumping the responseText back into a DIV either, security wise as it's ripe for XSS. But it's the end of the day and I haven't looked up anything on that one. Be aware, without any kind of checking on this, you could have a user being directed to a third party site using file_get_contents, which would be a Very Bad Thing. You could eval in PHP a file_get_contents request, which... is well, Very Very Bad. For example try
<?php
echo file_get_contents("http://www.google.com");
?>
But I fear I must ask here, why are you doing it this way? This seems a very roundabout way to achieve a Hyperlink.
Is this AJAX for AJAXs sake?