First question using the site so please bear with me if I haven't followed every rule in the book.
I come from a C++ background and don't have a great deal of experience with php/AJAX so I know that I probably have approached some of the following coding tasks in a sub-optimal/ improper way for writing code in different languages but anyway...
I have a Web site which uses a member login system written in PHP (connected to a mysql database), and the site is written using .php files to accomodate for this login system.
I want to use AJAX and JS on my .php pages to make them have a better user experience and I know this is possible (as I have done it), but I wanted to know if there are any negative/technical reasons why I shouldn't (and whether there are any better ways of doing this) as php is server side and AJAX is Client side.
Any advice would be appreciated.
Thanks
EDIT
I've added some code to show the type of things I would like to add to my php site
<?php
require "class.loginsys.php";
$LS = new LoginSystem();
$LS->init();
?>
<!-- HTML page structure -->
<!DOCTYPE html>
<html>
<head>
<title>OnyxProjectsPage</title>
<link rel="stylesheet" type="text/css" href="style.css" />
<script type = "text/javascript">
function createTable()
{
var xhr;
if (window.XMLHttpRequest) // Mozilla, Safari, ...
{
xhr = new XMLHttpRequest();
}
else if (window.ActiveXObject) // IE 8 and older
{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
xhr.open("GET", "createDatabase.php");
//xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send();
xhr.onreadystatechange = display_data;
function display_data()
{
if (xhr.readyState == 4)
{
if (xhr.status == 200)
{
alert("Table Created");
}
else
{
alert('There was a problem with the request.');
}
}
}
}
</script>
</head>
<body>
<!-- Header background bar -->
<div id="container" style="width: 1920px">
<div id="header" style="background-color:#4c4c4c;">
<form class="well-home span6 form-horizontal" name="ajax-demo" id="ajax-demo">
<div class="controls">
<button type="button" onclick="createTable()">Create Testplan</button>
</div>
</form>
</body>
</html>
Using AJAX / JavaScript is not more dangerous than regular PHP. You can argue, that people can disable JavaScript and thus not be able to perform your expected result.
Usually, using AJAX will, as you mentioned, satisfy the user-experience, since they don't have to reload the page everytime a request is send.
The best solution, in my opinion, would be:
Check if the User enabled Javascript in his browser (keyword: noscript). If so, you can do use Frameworks like jQuery. Using this you can take advantage of the build-in ajax-function (take a look here). Otherwise prepare a fallback/failsafe mode for to serve every visitor.
LT;DR
Mix both of them. In any case, check and validate on serverside before inserting data in a database (or everything related to that kind of stuff), even if you checked it on the clientside already.
Personally, I prefer a combination of both, however not in same example as DasSaffe supplied.
I would write your PHP/HTML log-in page and when a user attempts to log in it runs your PHP script through an ajax request. If the PHP script returns success then ajax can redirect the user successfully.
The nice thing about this is that you can handle empty fields/invalid log-ins without ever leaving the page. If you use PHP only you will have to redirect the user to your script and then redirect back if there is an error.
Then you have to think, if I redirect my user back to the log-in page how do I tell the user that there was an error?
Related
First let me explain where I'm coming from.
I've got a great grasp of javascript, html and css, client sided stuff. Server sided code like php and server-client code like ajax are not my strong suits. From most of every single article I've read about extracting the metadata from the stream points to here.
http://www.smackfu.com/stuff/programming/shoutcast.html
And then someone says, just use php and ajax! It's not very helpful or direct since I'm just picking up both.
I've yet to learn anything really about headers and using get requests so I'm at a loss with this method.
I also found an article which said to look up shoutcast class php, this is what I've found most helpful so far, and this is what I'm working with now. This one assumes I know the password to the stream I'm looking for (not ideal) but luckily I do.
https://github.com/MaThGo/shoutcast-class/blob/master/shoutcast.class.php
Both of these I understand are different, the first is pseudo code for grabbing metadata as it passes by in the stream, the second is just pulling xml of the same metadata but off of the webserver.
I'm assuming it'd be an easy switch to change the class a bit to pull the same information from the 7.html instead, no password would be required.
Where I was originally stuck: after modifying the above shoutcast class script a bit I end up with the song and stream title in a variable. I've saved it (and tested it so I know it does output the right info using echo) as getInfo.php in the same folder as my index.html file.
<?php //shoutcast class script from above link followed by
$stream = shoutcast("ip","port","pass"); //constructing the class
$streamData = stream.getShoutcastData(); //getting array of shoutcast metadata
$streamTitle = streamData["SERVERTITLE"]; //gets the server's title
$streamSong = streamData["SONGTITLE"]; //gets the current song playing artist and track
$playerText = "You're listening to {$streamTitle} <br> Song: {$streamSong}"
echo $streamTitle;
?>
If I have an audio element and a div for the song information with an id "info" how can I run this script and have it only modify the content for that div every couple of seconds? Obviously I don't want to eat a ton of bandwidth requesting / or getting metadata that is not different than before. This is what I'm assuming the php and ajax combination is for.
Figured this out, look further below, this is a terrible example script:
<!DOCTYPE HTML>
<html>
<head>
<script>
//perhaps something like this?
function update()
{
document.getElementById("info").innerHTML= //not sure what do do here
}
//or a function which uses setTimeout()?
</script>
</head>
<body onload="getThingsStarted()">
<!--Where the magic should happen-->
<div id="info">Somewhere in here</div>
<div id="audio">
<audio autoplay="true" controls="controls" src="http://ip:port/;">
</div>
</body>
</html>
Fixed: My original code had bad syntax so the XMLHttpRequest inside my ajax code never executed, so no results were ever being returned (figures). Here's what got it working.
<!DOCTYPE HTML>
<html>
<head>
<script>
//php ajax sample code w/ one slight modification from w3schools.com
function loadXMLDoc()
{
var xmlhttp;
if (window.XMLHttpRequest)
{//IE7, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHtppRequest();
}
else
{//IE6, IE5 wow these are old
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if(xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("info").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","stream.php?q=1",true);
xmlhttp.send();
}
</script>
</head>
<body>
<div id="info">Stream info</div>
<audio autoplay controls="controls" src="http://ip:port/;" ontimeupdate="loadXMLDoc()">
</body>
</html>
Second Question: I'm wondering if anyone can point me to a good example of extracting the metadata using the method from the first link, or a modification of the shoutcast class so it doesn't require a password? Much appreciated.
Since the metadata from the server is a couple of seconds ahead of the stream (makes sense shoutcast uses a buffer so the audio is behind the webserver's changing metadata) I'm curious if I could compare the results (perhaps check for how large of a time delay between server and clients content?).
Just some thoughts...
What version of DNAS are you running? In 2.0+ you should be able to pull an XML output of all public stream statistics from http://ip:port/statistics. Here's a live example of (hopefully) what you're trying to accomplish using JS: http://subfocus.fm.
To work around cross domain/port restrictions in the XMLHttpRequest (80 vs 8000 in this case typically) I have a local server script running a wget every minute to download the ShoutCAST XML file to the web server root path (publicly: http://ip/stats.xml). This may not be feasible in your case but I thought I'd share my patchwork solution.
As long as you have the XML on your web server, you should be able to use something along the lines of this for a single stream station:
<head>
<script>
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest()
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP")
}
function scMetaData() {
xmlhttp.open("GET", "stats.xml", false);
xmlhttp.send();
xmlDoc = xmlhttp.responseXML;
document.getElementById("info").innerHTML = "<b>Now Playing:</b> " + xmlDoc.getElementsByTagName("STREAM")[0].getElementsByTagName("SONGTITLE")[0].childNodes[0].nodeValue
}
setInterval(scMetaData, 10000);
</script>
</head>
<body onload="scMetaData();">
<span id="info"></span>
</body>
After creating the XMLHttpRequest object the rest is stored in a function to be called at a specified interval in milliseconds by setInterval(scMetaData, 10000); at the end of the script and also upon loading with <body onload="scMetaData();">. The live example I linked adds a FOR loop to parse the XML track IDs for 2 ShoutCAST streams.
I have a page with php and other stuff in the code. What I need to do is a way to check with php if there is javascript enabled in the browser.
This way, the whole page source will be prevented to be loaded, instead of using that only prevents the page from loading, but allows the source code.
PHP is a server-side language. There is no way to do this with PHP since it is run on the server, and then the result is sent to the client. The server has no knowledge of whether the client has JavaScript enabled or not.
If you don't want to show the code in your .html file when JS is disabled, then you don't have to use PHP. You could put the essential stuff in the .html file and load the rest in with JavaScript. If JavaScript is disabled, the rest of the stuff never gets loaded in the first place. (This is called progressive enhancement.)
This example will use the <noscript></noscript> tag inside an echo directive.
<?php
echo "<noscript>You need JS enabled to view the text on this page.</noscript>";
?>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script>
document.write("<h1>Heading Text</h1>");
document.write("<p>This message appeared because you have JS enabled.</p>");
</script>
</body>
</html>
You could make JavaScript fire a request to a page, setting a session variable enabling access to the website, then reload the page. This is by no means secure.
In all files except enable.php (could be done via an include/etc) before anything is echoed.
...
if (!isset($_SESSION['enabled']) { ?>
<!doctype html>
<html>
<head>
...
<script>
var xhr = new XMLHttpRequest();
xhr.open('GET', '/enable.php', false);
xhr.send();
window.location.reload();
</script>
</head>
<body></body>
</html>
<?php die();
}
....
In enable.php, you would then do
$_SESSION['enabled'] = 1;
enable.php would only need to be hit once-per-session and if JavaScript was disabled afterwards, or it was hit manually by pointing the browser there, your server will not know the difference. The assumption is the client must have JavaScript enabled for this session if the page was reached this session.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function ShowFile(sFilePath){
var oFileSystem = new ActiveXObject("Scripting.FileSystemObject");
frmEditHTML.tarHTMLText.value = oFileSystem.OpenTextFile(sFilePath.value).ReadAll();
}
function SaveAfterEditing(sFilePath){
var oFileSystem = new ActiveXObject("Scripting.FileSystemObject");
var oFile = oFileSystem.CreateTextFile(frmEditHTML.filPath.value,1);
oFile.WriteLine(sFilePath.value);
oFile.Close();
}
</script>
</head>
<body>
<form name="frmEditHTML">
Select the File you want to Edit
<input type=file name="filPath" onchange="ShowFile(this)">
<textarea name="tarHTMLText" cols=60 rows=20></textarea>
<input type="button" value="Save" name="cmdSave" onclick="SaveAfterEditing(this.form['tarHTMLText'])">
</form>
</body>
</html>
I read this link and this link but they could not help!
I don't want to use ActiveX as then this function will be restricted to IE.
IE Tab in FireFox is also causes problems!
How can I replicate this whole function in PHP without using ActiveX ?
Please Help!
Short answer:
With PHP you can't convert this script exactly as it is, since ActiveX is client side and PHP is server side. Javascript can't do this for you either, since modern browsers are sandboxed, and JavaScript cannot access local file systems.
Not so short answer:
You have other options, however, depending on which behavior (and implementation method) you wish to mimic.
You can use a Java Applet that is able to do pretty much what you could do with ActiveX. Works consistently across browsers but user have to have installed Java Runtime Environment.
You can use a mix of PHP + Javascript (AJAX). You upload a file to the server and then control PHP actions with Javascript (HTTP Requests via Ajax).
Hackish way
There is an hackish simple way to handle this situation. Requires a server somewhere though.
Create a page that uploads a file to the server.
Then send the file back to the browser, via AJAX (or any request, doesn't matter).
Manipulate the file in the client side (browser) with javascript.
Give the file to the user to download.
I am thinking of writing a desktop HTA program.
However, at startup I would need to make 1 ajax php database call to a website, which will need a success element callback.
Is this possible? Would I need to overcome any crossbrowser issues? Would firewalls cause any problems?
Possible - yes. See code below. Crossbrowser is not applicable in HTA -- you're always using the IE rendering engine. But I think you may mean cross-domain issues, which are also not applicable in HTA. Microsoft chose to disable all of the Javascript cross-domain protection because an HTA (HTML-Application) is treated as an application not a web page.
There are lots of considerations for firewalls, but it's unlikely that a firewall would block HTA AJAX calls more restrictively than HTML AJAX. If you have a web page that calls your PHP page, it will probably also work in HTA. Good luck!
<html><head>
<script language="javascript" type="text/javascript">
var XHR = new ActiveXObject("Msxml2.XMLHTTP");
function callAjax(url){
XHR.onreadystatechange=(callback);
txtStatus.value += "opening: " + url + "\n";
XHR.open("GET",url,true); //"POST" also works
XHR.send(); // XHR.send("name1=value1&name2=value2");
}
function callback(){
if(XHR.readystate == 4) txtStatus.value += "DONE\n" + XHR.responseText;
}
</script>
</head>
<body onload="callAjax(txtURL.value)">
<textarea id=txtURL style="width:100%" rows=1>http://www.google.com</textarea>
<textarea id=txtStatus style="width:100%" rows=20></textarea>
</body></html>
I have a big problem with my website.
I have made it in a way that seems to stop be from doing anything.
I have a number of containers, the main part of the page has three small containers all on top of each other and then a bigger container next to them that has the main content. The content that is shown in this main container is pulled from other pages so I don't have to refresh the whole page ever time a link is pressed. So I have one main page (the index) and a bunch of other content filled pages.
Now, if a page were to need to post data to the server to process it and then confirm with the user, this can't be done with normal PHP like I'm used to because the whole page is refreshed and it goes back to the default.
So I thought, I know Ajax can do this. I can post data to the server, process it and then change something on that page without loading anything.....
But I was wrong, it seems that it still wants to refresh the whole page meaning I lose my data. Also with the Ajax I am using "post" not "get" but for some reason it's putting the data into the address bar.
Is there a way I can keep my current structure and be able to do this, or am I doomed?
Any help, tips, code or advice would be MORE than welcome and thank you for the time and help.
Oh yeah, if I view the content outside of the index page the script runs just fine, it's only when the index pulls it from another page.
Ajax:
unction pass()
{
// Real Browsers (chrome)
if (window.XMLHttpRequest)
{
xhr = new XMLHttpRequest();
}
// IE
else if (window.ActiveXObject)
{
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
var oldPass = document.getElementById('oldPass').value;
var newPass = document.getElementById('newPass').value;
var newPassCheck = document.getElementById('newPassCheck').value;
xhr.open("POST","changeSettings.php");
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
var obj = {oldPass: oldPass, newPass: newPass, newPassCheck: newPassCheck};
xhr.send("data=" + JSON.stringify(obj));
xhr.onreadystatechange=function()
{
if (xhr.readyState==4)
{
//grade = xhr.responseText;
document.getElementById("myDiv").innerHTML = xhr.responseText;
//document.write.grade;
//alert ("Nice essay. Your grade is " + grade);
}
}
return false;
}
Here is the original page:
<div id="content">
<form>
<h1>This page is still under construction please do not attempt to use it!</h1>
<p>
Old Password: <input type="password" name="oldPass" id="oldPass"><br />
new Password: <input type="password" name="newPass" id="newPass"><br />
Retype Password: <input type="password" name="newPassCheck" id="newPassCheck"><br />
<input type="submit" name="submit" value="Submit" onClick="return pass();">
</p>
</form>
<div id="myDiv" name="myDiv"> </div>
</div>
Just because you're supplying "POST not GET" in the form doesn't mean ajax will handle it this way.
What needs to be actually done is attach to the submit event of the form, then let AJAX handle it the rest of the way. On a confirmed submission (or even a failure) you can update content (or show errors).
To keep it simple with jQuery...
<div id="content-container">
<form method="post" action="/some/submission/page.php">
<!-- flag to let the landing page know it's an ajax request
this is optional, but IMHO it makes for a more seamless
experience -->
<input type="hidden" name="ajax" value="true" />
<!-- controls go here -->
</form>
</div>
So there's your form. Now, you need to attach to the submit event. Again, I use jQuery for simplicity, but feel free to use any method. I also am creating a very generic controller here so you could presumably use it for every form found on the page, but that's up to you. (And, because we still decorate the <form> an absence of javascript will still proceed, but when it IS there, it will use the nice ajax look and feel)
// use .live to catch current and future <form>s
$('form').live('submit',function(){
var target = $(this).prop('action'),
method = $(this).prop('method'),
data = $(this).serialize();
// send the ajax request
$.ajax({
url: target,
type: method,
data: data,
success: function(data){
//proceed with how you want to handle the returned data
}
});
});
The above will take a normal form found on the page and make it submit via AJAX. You may also want to bind to $.ajaxError so you can handle any failures.
Also, depending on the content you return from the AJAX call, you can either pass the entire response back to the container ($('#content-container').html(data); in the success call), or if it's JSON or plain text, display other data.
Oh, and using my example, you may want to have something like the following in your posted page:
<?php
$ajax_call = isset($_POST['ajax']);
if (!$ajax_call){
// not an ajax call, go ahead with your theme and display headers
}
// output content as usual
if (!$ajax_call){
// again, not ajax, so dump footers too
}
(That way when it's AJAX, only the info in your container is returned, otherwise display the page as usual because they probably don't support AJAX/JavaScript).
You need to put up the page or post a code example in order to get answers to this question.
If I were to take a guess, it would be that you are not preventing submission of the form, so it's firing off the ajax request like you asked, but also submitting the form. In order to prevent it, you need to select the submit button and have it return false. Here's a quick example with jquery of how you would do this
$('input[type=submit]').click(function(){
$.ajax({ ... request here ... });
return false
});
or you can also catch the click event and prevent default, as such
$('input[type=submit]').click(function(event){
event.preventDefault();
});
Since I can't see any of your code, this is not guaranteed to be right. If you post the code, I can revise this. In the meantime, hopefully I guessed it!