Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@

Empty file added assets/.gitkeep
Empty file.
Empty file added assets/css/.gitkeep
Empty file.
9 changes: 9 additions & 0 deletions assets/css/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
main {
margin-top: 25px;
}

img.flag {
width: 35px;
border: 1px solid #ccc;
margin-top: -2px;
}
9 changes: 9 additions & 0 deletions assets/css/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
</head>
<body>
<p>Directory access is forbidden.</p>
</body>
</html>
Empty file added assets/images/.gitkeep
Empty file.
Empty file added assets/images/flags/.gitkeep
Empty file.
Empty file.
Binary file added assets/images/flags/brazil/acre.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/alagoas.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/amapa.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/amazonas.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/bahia.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/brazil.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/ceara.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/distrito-federal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/espirito-santo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/goias.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions assets/images/flags/brazil/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
</head>
<body>
<p>Directory access is forbidden.</p>
</body>
</html>
Binary file added assets/images/flags/brazil/maranhao.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/mato-grosso-do-sul.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/mato-grosso.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/minas-gerais.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/para.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/paraiba.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/parana.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/pernambuco.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/piaui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/rio-de-janeiro.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/rio-grande-do-sul.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/rondonia.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/roraima.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/santa-catarina.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/flags/brazil/sao-paulo.png
Binary file added assets/images/flags/brazil/sergipe.png
Binary file added assets/images/flags/brazil/tocantins.png
9 changes: 9 additions & 0 deletions assets/images/flags/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
</head>
<body>
<p>Directory access is forbidden.</p>
</body>
</html>
9 changes: 9 additions & 0 deletions assets/images/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
</head>
<body>
<p>Directory access is forbidden.</p>
</body>
</html>
9 changes: 9 additions & 0 deletions assets/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
</head>
<body>
<p>Directory access is forbidden.</p>
</body>
</html>
Empty file added assets/js/.gitkeep
Empty file.
9 changes: 9 additions & 0 deletions assets/js/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
</head>
<body>
<p>Directory access is forbidden.</p>
</body>
</html>
70 changes: 70 additions & 0 deletions assets/js/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
+(function(window, document, $, undefined) {
"use strict";

$('#search-form').on('submit', function(e) {
// Prevent event' default behavior.
e.preventDefault();

// Get the search input.
var searchInput = $('#search-input');
// Get the value from the input trimming spaces from both beginning and the end.
var searchTerm = searchInput.val().trim();
// Let's check if the user typed something.
if (searchTerm.length > 0) {
// Configure and send the ajax request.
$.ajax({
'url' : "/handler-ajax.php",
'method': "GET",
'data' : {
'term': searchTerm
},
// This event is executed before the request is sent.
beforeSend: function(request, requestSettings) {
// Update the places where we show what the user is searching for.
$('code.search-term').text(searchTerm);
// Clean our output wrapper so we can append new results.
$('output').html('');
},
// This event is called if the request was able to be both sent and received by the url' (line 16) server.
success : function(response, textStatus, request) {
if (response.results > 0) {
var listGroup = $('<ul class="list-group"></ul>');
for (var resultIndex = 0; resultIndex < response.results; resultIndex++) {
var result = response.data[resultIndex];
var listGroupItem = $('<li class="list-group-item"></li>');

listGroupItem.text(result.title);

var stateFlagImage = $('<img/>', {
'class': "pull-right flag",
'src' : "/assets/images/flags/brazil/"+ result.alias +".png",
'alt' : result.title,
'title': result.title
});
listGroupItem.append(stateFlagImage);
listGroup.append(listGroupItem);
}

// Append the results list to the output wrapper.
$('output').append(listGroup);
}

// Update the results counter.
$('.results-count').text(response.message);
},
// This event is called if something weird happened while the request was being sent or the server rejected the connection.
error : function(request, textStatus, errorThrown) {
alert('Some nasty error occurred. Check console for more info.');
console.error(errorThrown);
},
// This event is called every time regardless if the request succeeded or not.
complete: function(request, textStatus) {
// do nothing for now.
}
});
}

// Force the browser to not submit the form.
return false;
});
})(window, document, jQuery);
5 changes: 5 additions & 0 deletions constants.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php
defined('DB_HOST') OR define('DB_HOST', "localhost");
defined('DB_USER') OR define('DB_USER', "root");
defined('DB_PASSWORD') OR define('DB_PASSWORD', "");
defined('DB_NAME') OR define('DB_NAME', "");
57 changes: 57 additions & 0 deletions handler-ajax.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php
header('Content-Type: text/html; charset=utf-8');

// Let's make sure we're recieving an Ajax request.
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtoupper($_SERVER['HTTP_X_REQUESTED_WITH']) === "XMLHTTPREQUEST" && strtoupper($_SERVER['REQUEST_METHOD']) === "GET") {
require_once './constants.php';
require_once './helper.php';

$response = array(
'data' => array(),
'results' => 0,
'message' => "",
'term' => ""
);

// Retrieves the searched term from the POST request sent by Ajax.
$searchedTerm = $_GET['term'];
// Let's make sure the string is trimmed.
$searchedTerm = trim($searchedTerm);
// We MUST ALWAYS sanitize user's inputs against XSS attacks before making queries in DB and etc with it.
//$searchedTerm = xss_clean($searchedTerm);

$db = getDatabase();

$query = $db->prepare(
'SELECT `state`.`title`, `state`.`alias`
FROM `country_states` AS `state`
LEFT JOIN `countries` AS `country` ON `country`.`id` = `state`.`country_id`
WHERE `country`.`alias` = ?
AND `state`.`title` LIKE ?
ORDER BY `state`.`title` ASC'
);

$query->execute(array(
"brazil",
"%{$searchedTerm}%"
));

$rowset = $query->fetchAll();
$rowsetCount = count($rowset);

$response['term'] = $searchedTerm;
$response['data'] = $rowset;
$response['results'] = $rowsetCount;
$response['message'] = $rowsetCount > 0 ? "Results: {$rowsetCount}" : "No results was found";

// Set up the response header to tell the browser we'll return a JSON instead of html/plain text etc.
header('Content-Type: application/json');
// Encodes our $response into JSON format.
echo json_encode($response);

// There's no more to do here with this request. We should stop any further execution after our response has been sent.
die();
}

// This will show up when someone tries to access this file directly through the browser or any other way than an Ajax request.
echo 'Not a json request.';
45 changes: 45 additions & 0 deletions helper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php
if (!function_exists('getPDOConnection')) {
/**
* Creates a new PDO connection based on the parameters.
*
* @link http://php.net/manual/en/class.pdo.php
*
* @param string $user // The db username
* @param string $pwd // The db user's password
* @param string $host // The host where the database is located in
* @param string $dbCharset // The db' charset
*
* @return PDO
**/
function getPDOConnection($user, $pwd, $dbName, $host = "localhost", $dbCharset = "UTF8")
{
$dsn = "mysql:host={$host};dbname={$dbName};charset={$dbCharset}";

$instanceOptions = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
);

$pdo = new PDO($dsn, $user, $pwd, $instanceOptions);

return $pdo;
}
}

if (!function_exists('getDatabase')) {
/**
* Creates and return a PDO connection based on the project default parameters.
*
* @return void
**/
function getDatabase()
{
if (empty(DB_NAME)) {
throw new Exception("Database name is missing.");
}

return getPDOConnection(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST, "UTF8");
}
}
89 changes: 89 additions & 0 deletions index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
/* * * * * * * ** * * * * * * * * * * * * * * * *
* IMPORTANT *
* After DB import you should configure *
* the constants in `constants.php` to reflect *
* your project environment variables. *
* * * * * * * * * * * * * * ** * * * * * * * * */

// This ensure that all errors/warnings will be displayed. This should be used only under development environments.
error_reporting(-1);
ini_set('display_errors', 1);

header('Content-Type: text/html; charset=utf-8');

require_once 'constants.php';
require_once 'helper.php';

// Tries to stablish connection with Database.
try {
getDatabase();
} catch (Exception $e) {
// Something went wrong.
echo "Make sure everything on the constants.php file is correct.</br></br>";

die($e->getMessage());
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">

<title>Ajax - Demo</title>

<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-T8Gy5hrqNKT+hzMclPo118YTQO6cYprQmhrYwIiQ/3axmI1hQomh7Ud2hPOy8SP1" crossorigin="anonymous">
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="/assets/css/index.css">
</head>
<body>
<main class="container">
<div class="row">
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Search > States of Brazil</h3>
</div>
<div class="panel-body">
<form id="search-form">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-search"></i></span>
<input type="search" class="form-control" id="search-input" name="search" placeholder="" autocomplete="false" autofocus>
<span class="input-group-btn">
<button class="btn btn-primary" type="submit">Send</button>
</span>
</div>
<p class="help-block">The searched <i>term</i> will be sent back to <code>handler.php</code> (as can be seen in <code>/assets/js/index.js</code>) which will query the DB and return possible results that contains <i>term</i> in its title. The requests can be seen an examined through browser's console if you have the option <strong>Log XMLHttpRequests</strong> enabled (you should always keep this checked).</p>
</div>
</form>
</div>
<div class="panel-footer">
<p>Searching for the term <code class="search-term">...</code></p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Search results</h3>
</div>
<div class="panel-body">
<output></output>
</div>
<div class="panel-footer">
<p class="results-count">No results was found</p>
</div>
</div>
</div>
</div>
</main>

<script src="https://code.jquery.com/jquery-3.1.0.min.js" integrity="sha256-cCueBR6CsyA4/9szpPfrX3s49M9vUU5BgtiJj06wt/s=" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="/assets/js/index.js"></script>
</body>
</html>
Empty file added misc/.gitkeep
Empty file.
Loading