I would like to build a form (VIA POST METHOD) with just one field (url - link shortening). Now the question is how and if is it possible to build a form that detects the value of the URL field is a link and automatically shortens it rather than waiting you click Send (for exmaple like the web of Bit.ly).
The main idea is once the field is an identifier that value is a proper Hyperlink is directly sends and shortens (And the field is replaced by a shortened link) it without waiting for the click on the SEND.
index.html
<html>
<head>
<script>
function showHint(str) {
if (str.length == 0) {
document.getElementById("txtHint").innerHTML = "";
return;
} else {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("txtHint").innerHTML = this.responseText;
}
};
xmlhttp.open("GET", "gethint.php?q=" + str, true);
xmlhttp.send();
}
}
</script>
</head>
<body>
<p><b>Start typing a url in the input field below:</b></p>
<form>
Url: <input type="text" onkeyup="showHint(this.value)">
</form>
<p><span id="txtHint"></span></p>
</body>
</html>
gethint.php
<?php
// get the q parameter from URL
$q = $_REQUEST["q"];
$hint = "";
if (!filter_var($q, FILTER_VALIDATE_URL) === FALSE) {
// short the link
$rand = rand(1,1000);
$hint = 'http://domain.com/'.$rand; }
echo $hint === "" ? "Not a valid URL" : $hint; ?>
I'd use jQuery for the event triggering/AJAX and https://gist.github.com/dperini/729294 for weburl regex.
I'm not that at home on pure JavaScript AJAX calls, but is
xmlhttp.open("GET")
the right way to go at it if you want to make a POST?
Anyway the main thing you're missing is
function isUrl(url){
var regex = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?#)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$/i;
if(regex.test(url)){
return regex.test(url);
}else{
return regex.test("http://"+url);
}
}
So this should be your new index.html
<html>
<head>
<script>
var extensions = [".aero",".biz",".cat",".com",".coop",".edu",".gov",".info",".int",".jobs",".mil",".mobi",".museum",".name",".net",".org",".travel",".ac",".ad",".ae",".af",".ag",".ai",".al",".am",".an",".ao",".aq",".ar",".as",".at",".au",".aw",".az",".ba",".bb",".bd",".be",".bf",".bg",".bh",".bi",".bj",".bm",".bn",".bo",".br",".bs",".bt",".bv",".bw",".by",".bz",".ca",".cc",".cd",".cf",".cg",".ch",".ci",".ck",".cl",".cm",".cn",".co",".cr",".cs",".cu",".cv",".cx",".cy",".cz",".de",".dj",".dk",".dm",".do",".dz",".ec",".ee",".eg",".eh",".er",".es",".et",".eu",".fi",".fj",".fk",".fm",".fo",".fr",".ga",".gb",".gd",".ge",".gf",".gg",".gh",".gi",".gl",".gm",".gn",".gp",".gq",".gr",".gs",".gt",".gu",".gw",".gy",".hk",".hm",".hn",".hr",".ht",".hu",".id",".ie",".il",".im",".in",".io",".iq",".ir",".is",".it",".je",".jm",".jo",".jp",".ke",".kg",".kh",".ki",".km",".kn",".kp",".kr",".kw",".ky",".kz",".la",".lb",".lc",".li",".lk",".lr",".ls",".lt",".lu",".lv",".ly",".ma",".mc",".md",".mg",".mh",".mk",".ml",".mm",".mn",".mo",".mp",".mq",".mr",".ms",".mt",".mu",".mv",".mw",".mx",".my",".mz",".na",".nc",".ne",".nf",".ng",".ni",".nl",".no",".np",".nr",".nu",".nz",".om",".pa",".pe",".pf",".pg",".ph",".pk",".pl",".pm",".pn",".pr",".ps",".pt",".pw",".py",".qa",".re",".ro",".ru",".rw",".sa",".sb",".sc",".sd",".se",".sg",".sh",".si",".sj",".sk",".sl",".sm",".sn",".so",".sr",".st",".su",".sv",".sy",".sz",".tc",".td",".tf",".tg",".th",".tj",".tk",".tm",".tn",".to",".tp",".tr",".tt",".tv",".tw",".tz",".ua",".ug",".uk",".um",".us",".uy",".uz", ".va",".vc",".ve",".vg",".vi",".vn",".vu",".wf",".ws",".ye",".yt",".yu",".za",".zm",".zr",".zw"];
var delay = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
function isUrl(url){
var regex = /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?#)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$/i;
if(regex.test(url)){
return regex.test(url);
}else{
return regex.test("http://"+url);
}
}
function showHint(str) {
delay(function(){
str = str.toLowerCase();
var dot = str.lastIndexOf(".");
var extension = str.substr(dot);
extension = extension.split('/')[0];
var found = $.inArray(extension, extensions) > -1;
if (!isUrl(str)||!found) {
document.getElementById("txtHint").innerHTML = "";
return;
} else {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("txtHint").innerHTML = this.responseText;
}
};
xmlhttp.open("GET", "gethint.php?q=" + str, true);
xmlhttp.send();
}
}, 500)
}
</script>
</head>
<body>
<p><b>Start typing a url in the input field below:</b></p>
<form>
Url: <input type="text" onkeyup="showHint(this.value)">
</form>
<p><span id="txtHint"></span></p>
</body>
</html>
edit: Say you will start typing in http://www.example.net.. The AJAX will trigger on "http://www.example.ne" and then again when you add the last letter. To avoid that, you might try "change" instead of "keyup" event.
edit2: Now checks against list of valid domain extensions
edit3: Now waits half a second before posting the result.
edit4: Small oversight while checking for extensions, fixed with
extension = extension.split('/')[0];
Also if you want to enable users to write URL's without "http://" and similar, you'll need an edited regex or write a small hack that adds that to your string before you send it into "isUrl()".
Current setting:
In the same PHP document I have a PHP randomizer function and the HTML that calls that function -- a separate txt document with strings that are called by the php function:
Function
<?php
function rand_line($fileName, $maxLineLength = 4096) {
$handle = #fopen($fileName, "strings.txt");
if ($handle) {
$random_line = null;
$line = null;
$count = 0;
while (($line = fgets($handle, $maxLineLength)) !== false) {
$count++;
if(rand() % $count == 0) {
$random_line = $line;
}
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
fclose($handle);
return null;
} else {
fclose($handle);
}
return $random_line;
}
}
?>
I call the function in the HTML using:
<?php echo rand_line("strings.txt");?>
<input type="button" value="Another String" onClick="window.location.reload()">
This tends to be slow when multiple users access the page and press the button to obtain a new status.
What I would like to achieve:
Improve the performance and make the whole thing not so heavy: maybe the randomizer is unnecessarily complicated and I could work with AJAX calls for example, but if possible keeping the string list inside the strings.txt file and separated from the PHP script and HTML.
Sorry if I don't know what I'm talking about... I'm not a proficient programmer. Just a guy that hacks stuff together once in a while :)
You really don't want to use window.location.reload();
That is terrible... You do not want to refresh a page...
location.reload() sends http request for a whole new page (whole HTML), and then not only that your browser needs to render whole HTML again, you have to transfer more duplicated data through a network, from point A to point B.
You should send HTTP request only for a data that you need (you don't need whole HTML again, you loaded it the 1st time you visited page).
Instead, use XMLHttpRequest javascript library (AJAX) to request only for a portion of data (in your case => random line string)
HTML:
<!DOCTYPE html>
<html>
<head lang="en">
<script type="text/javascript">
function loadDoc(url, cfunc) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (xhttp.readyState == 4 && xhttp.status == 200) {
cfunc(xhttp);
}
};
xhttp.open("GET", url, true)
xhttp.send();
}
function randomLine(xhttp) {
alert(xhttp.responseText);
}
</script>
</head>
<body>
<input type="button" value="Get random line" onClick="loadDoc('http://localhost:8080/myScript.php', randomLine)">
</body>
</html>
PHP:
myScript.php
<?php
function rand_line($fileName, $maxLineLength = 4096)
{
...
}
echo rand_line("strings.txt");
?>
*EDIT #2*
Fully-functioning script. Grabs initial strings via PHP, and stores in array for later JavaScript usage. Minimizes # of calls.
PHP to grab strings from file; generates a default (random) string, as well as an array of strings for later use with button.
/**
* #input array $file
* #return array (mixed) [0] => string, [1] => array
*/
$randomStringFromFile = function($file) {
if (!$file) return false;
/**
* #return Removes carriage returns from the file
* and wraps $val with single-quotes so as
* to not break JavaScript
*/
$add_quotes = function(&$val) {
return str_replace("\n", "", "'$val'");
};
return [$file[rand(0, count($file)-1)], array_map($add_quotes, $file)];
};
$randomString = $randomStringFromFile( #file('strings.txt') ) ?: false;
JavaScript
<div id="string_container"><?php echo $randomString[0]; // defaults random string to page ?></div><br>
<button onclick="getString();">Another String</button>
<script>
var getString = function() {
var arr = [<?php echo implode(',', $randomString[1]); ?>],
setString = document.getElementById('string_container').innerHTML = arr[Math.floor(Math.random() * arr.length)];
};
</script>
Place the above in your page and you should be good to go.
EDIT (ORIGINAL)
We can remove PHP from the equation entirely using the following (fastest method):
<div id="string_container"></div><br>
<button onclick="getString();">Another String</button>
<script>
var getString = function() {
var request = new XMLHttpRequest(),
file = 'strings.txt';
request.open('GET', file);
request.onload = function() {
if (request.status === 200) {
var arr = request.responseText.split("\n"), /** assuming line breaks in file are standard carriage returns (Unix); "\r" if Windows */
setString = document.getElementById('string_container').innerHTML = arr[Math.floor(Math.random() * arr.length-1)];
}
};
request.send();
};
</script>
ORIGINAL w/PHP
We can simplify the PHP even further, removing loops from the equation altogether.
$randomStringFromFile = function($file) {
if (!$file) return false;
return $file[rand(0, count($file)-1)];
};
echo $randomStringFromFile( #file('strings.txt') ) ?: 'No worky!';
Using file() will return the contents in an array, thus allowing you to simply select a key at random and return the value.
NOTE On average, $file[rand(0, count($file)-1)] outperformed array_rand() (E.g. $file[array_rand($file)];) when selecting a key at random. By negligible amounts, have you.. ~0.0002s vs ~0.0005s, respectively.
You can simplify your code
function rand_line($fileName, $maxLineLength = 4096) {
$f = file($fileName);
$length = $maxLineLength + 1;
do {
$line = $f[array_rand($f)];
$length = strlen($line);
} while ($length > $maxLineLength);
return $line;
}
I want to display a form with a script I adapted from this question. The script is in a file I wrote called queries.js, and its purpose is to print the content of a php form called "dbMinAlert.php" in a div like this <div id="recentExits" name="recentExits"></div> located in my project's index, I tried invoking getNewData(); in my index.php file using this tag <body onLoad="getNewData()"> but it doesn't seem to do anything at all.
var data_array = ''; // this is a global variable
function getNewData() {
$.ajax({
url: "dbMinAlert.php",
})
.done(function(res) {
data_array = res; // the global variable is updated here and accessible elsewhere
getNewDataSuccess();
})
.fail(function() {
// handle errors here
})
.always(function() {
// we've completed the call and updated the global variable, so set a timeout to make the call again
setTimeout(getNewData, 2000);
});
}
function getNewDataSuccess() {
//console.log(data_array);
document.getElementById("recentExits").innerHTML=data_array;
}
getNewData();`
---This php code works and it actually does what I expect it to do. The real problem is the javascript, for all I care the next php form could print a "Hello world" message, but I want it displayed inside the div I placed in my index, without having to post a thing to dbMinAlert.php.
define("HOST", "localhost");
define("DBUSER", "root");
define("PASS", "password");
define("DB", "mydb");
// Database Error - User Message
define("DB_MSG_ERROR", 'Could not connect!<br />Please contact the site\'s administrator.');
$conn = mysql_connect(HOST, DBUSER, PASS) or die(DB_MSG_ERROR);
$db = mysql_select_db(DB) or die(DB_MSG_ERROR);
$query = mysql_query("
SELECT *
FROM outputs, products
WHERE products.idProduct=outputs.idProduct
ORDER BY Date DESC, Time DESC limit 5
");
echo '<ul class="news">';
while ($data = mysql_fetch_array($query)) {
$date = date_create($data['Date']);
$time = date_create($data['Time']);
echo '<li><figure><strong>'.date_format($date,'d').'</strong>'.date_format($date,'M').date_format($date,'Y').'</figure>'.$data["idProduct"]." ".$data['prodName'].'</li>';
}
echo '</ul>';
You have to execute the function for the first time.
getNewData();
It could be the way you are returning the result from php. Instead of doing multiple echo, could you first assign your result in single php variable and finally do single echo.
$result = '<ul class="news">';
while ($data = mysql_fetch_array($query)) {
$date = date_create($data['Date']);
$time = date_create($data['Time']);
$result = $result + '<li><figure><strong>'.date_format($date,'d').'</strong>'.date_format($date,'M').date_format($date,'Y').'</figure>'.$data["idProduct"]." ".$data['prodName'].'</li>';}
$result = $result + '</ul>';
echo $result;
I found a solution in this question and my code ended up Like this.
I just had to invoke the function in my index by typing <body onload="return getOutput();">
JavaScript
//Min-Max Alerts
// handles the click event for link 1, sends the query
function getOutput() {
getRequest(
'dbMinAlert.php', // URL for the PHP file
drawOutput, // handle successful request
drawError // handle error
);
return false;
}
// handles drawing an error message
function drawError() {
var container = document.getElementById('recentExits');
container.innerHTML = 'Bummer: there was an error!';
}
// handles the response, adds the html
function drawOutput(responseText) {
var container = document.getElementById('recentExits');
container.innerHTML = responseText;
}
// helper function for cross-browser request object
function getRequest(url, success, error) {
var req = false;
try{
// most browsers
req = new XMLHttpRequest();
} catch (e){
// IE
try{
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
// try an older version
try{
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
return false;
}
}
}
if (!req) return false;
if (typeof success != 'function') success = function () {};
if (typeof error!= 'function') error = function () {};
req.onreadystatechange = function(){
if(req.readyState == 4) {
return req.status === 200 ?
success(req.responseText) : error(req.status);
}
}
req.open("GET", url, true);
req.send(null);
return req;
}
My problem I think is simple (but I am really simple), I am not using jquery or any other plugin just pure JavaScript and PhP.
I have a simple form with a select field in which multiple items can be selected such as :
<form id="test" name="test">
<input type="hidden" id="norman" value="bates"/>
<select multiple="multiple" name="fred[]" id="fred[]">
<option value="1">one</option>
<option value="2">two</option>
<option value="3">three</option>
<option value="4">four</option>
</select>
<input type="button" id="button" value="test" onclick="callAHAH('POST','my-page.php','container','loading...','modify-user')"/>
The callAHAH is the javaScript function that wraps up the data for the Ajax, the function is:
function callAHAH(method,url, pageElement, callMessage,form_name){
//window.location = url;
//document.getElementById(pageElement).innerHTML = callMessage;
try{
req = new XMLHttpRequest(); /* ff */
}
catch(e){
try{
req = new ActiveObject("Msxml2.XMLHTTP"); /* some ie */
}
catch(e){
try{
req = new ActiveXObject("Microsoft.XMLHTTP"); /*other ie */
}
catch(e){
req = false;
}
}
}
req.onreadystatechange = function(){responseAHAH(pageElement);};
var build_url=window.location.origin;
var url = "aj_scripts/"+url;
if(build_url=="http://localhost:8080"){
url=build_url+"/pitd_outer/pitd/"+url;
}
// Check request status
if(method=='POST'){
req.open("POST",url,true);
// adds a header to tell the PHP script to recognize the data as is sent via POST
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var the_data="";
///
var the_form=document.getElementById(form_name);
//alert(form_name);
for (var i=0;i<the_form.length;i++){
var the_type = the_form.elements[i].type;
var value;
if(the_type !="button"){
if(the_type =="checkbox"){
value = the_form.elements[i].checked
// alert("the array name is: "+the_array_name+" and it is checked:"+checked);
}else{
value=the_form.elements[i].value;
}
var id= the_form.elements[i].id;
the_data+=id;
the_data+="="+value+"&";
}
}
the_data=the_data.substring(0,the_data.length-1);//removing the last & symbol
// alert(the_data);
req.send(the_data); // calls the send() method with datas as parameter
}else if(method=="GET"){
req.open("GET",url,true);
req.send(null);
}
}
The JS handler has been working fine until I try and select multiple items and then the code only returns either the first or the last selected item.
I understand that the form is sending an array but I cannot seem to get the code to correctly test for an array I tried
var array_test=Array.isArray(the_form.elements[i]);
alert("array test:"+array_test);
But all I get is false so...
How can I get all of the select data that has been selected and then
How to I format it for the text string for the post is it
my_array[]=1$my_array[]=2 etc
thanks in advance for your help
Zen
OK I have the answer!
function callAHAH(method,url, pageElement, callMessage,form_name){
//window.location = url;
//document.getElementById(pageElement).innerHTML = callMessage;
try{
req = new XMLHttpRequest(); /* ff */
}
catch(e){
try{
req = new ActiveObject("Msxml2.XMLHTTP"); /* some ie */
}
catch(e){
try{
req = new ActiveXObject("Microsoft.XMLHTTP"); /*other ie */
}
catch(e){
req = false;
}
}
}
req.onreadystatechange = function(){responseAHAH(pageElement);};
var build_url=window.location.origin;
var url = "aj_scripts/"+url;
if(build_url=="http://localhost:8080"){
url=build_url+"/pitd_outer/pitd/"+url;
}
// Check request status
if(method=='POST'){
req.open("POST",url,true);
// adds a header to tell the PHP script to recognize the data as is sent via POST
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
var the_data="";
///
var the_form=document.getElementById(form_name);
//alert(form_name);
for (var i=0;i<the_form.length;i++){
var the_type = the_form.elements[i].type;
var value;
if(the_type !="button"){
if(the_type =="checkbox"){
value = the_form.elements[i].checked
var id= the_form.elements[i].id;
the_data+=id;
the_data+="="+value+"&";
}else if(the_form.elements[i].hasAttribute('multiple') == true){
var test_data = "";
var the_multiples = the_form.elements[i].options;
if((the_form.elements[i].hasAttribute('getall')==true)&&(the_form.elements[i].getAttribute('getall')=="get_all")){
//a multiple select that we need to get all values from and not just those that are selected
alert("hi");
console.log("inside the_form_elements has attributes");
for(var j=0;j<the_multiples.length;j++){
test_data += the_form.elements[i].id+"="+the_multiples[j].value+"&";
}//end of for var j
}else{
//a select list with potentially multiple selections and only want the selected ones
for(var j=0;j<the_multiples.length;j++){
if(the_multiples[j].selected == true){
test_data += the_form.elements[i].id+"="+the_multiples[j].value+"&";
}//end of if the_multiples
}//end of for var j
}//end of the if the_form inner
test_data=test_data.substring(0,test_data.length-1);//removing the last & symbol
the_data +=test_data;
alert(test_data);
}else{
value=the_form.elements[i].value;
var id= the_form.elements[i].id;
the_data+=id;
the_data+="="+value+"&";
}//end of if the_form outer
}
}
the_data=the_data.substring(0,the_data.length-1);//removing the last & symbol
// alert(the_data);
req.send(the_data); // calls the send() method with datas as parameter
}else if(method=="GET"){
req.open("GET",url,true);
req.send(null);
}
}
function responseAHAH(pageElement){
var output='';
if(req.readyState == 4){
if(req.status == 200){
output = req.responseText;
document.getElementById(pageElement).innerHTML = output;
}
}
}
The important bit of the code is:
if(the_type !="button"){
if(the_type =="checkbox"){
value = the_form.elements[i].checked
var id= the_form.elements[i].id;
the_data+=id;
the_data+="="+value+"&";
}else if(the_form.elements[i].hasAttribute('multiple') == true){
var test_data = "";
var the_multiples = the_form.elements[i].options;
if((the_form.elements[i].hasAttribute('getall')==true)&&(the_form.elements[i].getAttribute('getall')=="get_all")){
//a multiple select that we need to get all values from and not just those that are selected
alert("hi");
console.log("inside the_form_elements has attributes");
for(var j=0;j<the_multiples.length;j++){
test_data += the_form.elements[i].id+"="+the_multiples[j].value+"&";
}//end of for var j
}else{
//a select list with potentially multiple selections and only want the selected ones
for(var j=0;j<the_multiples.length;j++){
if(the_multiples[j].selected == true){
test_data += the_form.elements[i].id+"="+the_multiples[j].value+"&";
}//end of if the_multiples
}//end of for var j
}//end of the if the_form inner
test_data=test_data.substring(0,test_data.length-1);//removing the last & symbol
the_data +=test_data;
alert(test_data);
}else{
value=the_form.elements[i].value;
var id= the_form.elements[i].id;
the_data+=id;
the_data+="="+value+"&";
}//end of if the_form outer
Essentially I needed to sue the JavaScript hasAttribute function which I know is apparently not supported by every browser but it worked on IE10, and latest builds of FF O and C.
From there I had to use the .options subselect to cycle through each of select options to find the selected ones.
Those checking the code will notice I have a weird condition in there, the hasAttribute('getall') as I have a very weird situation where I needed to get all of the values out of the multiple select regardless of whether or not they had been selected again I know that non-standard attributes are not sup[ported by all browsers but were with the ones I was using.
regards
Zen