{
"name": "Alexandru PΔvΔloi",
"nickname": "PΔvΔ",
"age": 25,
"labPage": "iampava.com/tw",
"slides": "slides.com/iampava/tw-2020",
"e-mail": "pava@iampava.com"
}
{ about you }
π₯ will have acquired confidence to start basic Web projects on your own
π will have worked on a personal project which showcases your skills
π will have worked with multiple colleagues and thus grow your team-work skills
π will have learned the fundamentals of the Web
β Projects will be published soon on https://iampava.com/tw β‘ teams of 2 or 3
β If you don't like any of them, feel free to submit one yourselves
β Read more about the projects & evaluation here: https://profs.info.uaic.ro/~busaco/teach/courses/web/
β Skipping classes is ok, doesn't matter for the final grade
VS Code
Firefox
glitch.com
codepen.io
Every Friday I'll post in-advance exercises for the next lab!
OK, let's do this!
β JavaScript
β PhP
β C#
...
usually a browser, but not always!
built in pretty much any language we can think of
This
is
<img src="...">
<p> Lorem ipsum...</p>
Self-closing
Needs a closing tag!
<img src="/bob.png">
<p>
Hi!
<img src="bob.png">
</p>
Elements can have attributes
Or contain other elements
<button data-speed="1" type="button">
1x
</button>
... or custom attributes!
<!DOCTYPE html>
<html>
<head>
<!-- ... -->
</head>
<body>
<!-- ... -->
</body>
</html>
β OrganizingΒ most web pages
<header>
<main>
<footer>
<aside>
β If there's an <img>, let there be an alt
<img src="/images/avatar.png"
alt="Bob's avatar" />
β If it takes you to another page it's an anchor
<a href="/settings"> Settings </a>
β If it does something when clicking it, it's a button
<button type="button">
Save progress
</button>
β Always put labels on inputs
<label>
<span> Email or username*</span>
<input type="text" name="emailOrUsername">
</label>
β If there's an input, there should be a form
β Aaaand, if there's a form β‘ add a submit input/button
<form>
<label>
<span> Email or username*</span>
<input type="text" name="emailOrUsername">
</label>
<button type="submit"> Login </button>
</form>
β Keep HTML as minimalist as possible! NO, REALLY!
β Containers
header, main, footer, aside, section, div, ul, li
* personal stats
β Text
h1, h2, h3, p, span, strong, pre, code
β Media
img, picture, video, audio
β Forms
form, label, input, select, textarea
β Actions
a, button
PS: check DevDrive over the weekend for practice exercises
Week #2
??? {
border: 5px solid black;
background: blue;
}
value
property
selector
@media screen and (max-width: 500px) {
??? {
border: 5px solid black;
background: blue;
}
}
@media screen and (orientation: landscape) {
??? {
background: red;
}
}
@media (prefers-color-scheme: dark) {
body { background: black; }
h1, h2, h3 {
color: #fff;
}
}
@media (prefers-color-scheme: dark) {
??? { background: black; }
??, ??, ?? {
color: #fff;
}
}
β percentage (%)
β vh/vw
β em
β rem
β px
Β
Β
...
Try to avoid fixel px dimensions whenever
My favorite β€
<p style="font-weight: bold">
A simple styled paragraph...
</p>
* most
<html>
<head>
<style>
h1 {
text-align: center;
}
</style>
</head>
<body>
<h1> Smth </h1>
</body>
</html>
* most
<!-- index.html -->
<html>
<head>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<h1> Smth </h1>
</body>
</html>
/* style.css */
h1 {
text-align: center;
}
* most
Where to "position" an element inside the our Website.
Default position of all elements.
β from Top to Bottom
β from Left to Right
Position it based on some parent's/ancestor's position
The first one with a position other than static
{
top: 1em;
right: 10%;
bottom: 20px;
left: 2vh;
}
Position it relative to it's default static position
#1 Slightly adjust it's position by a couple of units
#2 To absolute position children according to itself
Usecases
Position it based on the viewport or the first ancestor with a transform property.
Scroll to top button on blogs
Fixed side content, ads, etc
Usecases
{
transform: scale(1.5);
/* transform: rotate(10deg); */
/* transform: translateX(5em); */
/* ... */
}
Default (static) position until the scroll reaches it. Then it sticks!
<main>
<div></div>
<section></section>
<div></div>
</main>
<main>
<div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</main>
<p>
Text
<span> Help info </span>
</p>
Help info
Which HTML element/elements we want to style?
* {
font-family: sans-serif;
}
h1,
h2,
h3 {
text-align: center;
}
<button type="button"> Log In </button>
<button type="button"> Register </button>
<button type="button"> Sign Out </button>
<button type="button" class="btn-round">
Log In
</button>
<button type="button" class="btn-round">
Register
</button>
<button type="button" class="btn-green">
Sign Out
</button>
.btn-round {
border-radius: 50%;
}
.btn-success {
color: #fff;
background: green;
}
<p id="hello">
A simple styled paragraph...
</p>
<style>
#hello {
font-weight: bold;
}
</style>
It's all about how specific you are!
<img
class="square-image round-image"
id="profile" src="user.jpg"
alt="user profile"/>
<style>
img {
border: 1px solid black;
}
.round-image {
border-radius: 50%;
border: 5px dotted red;
}
.square-image {
border-radius: 0;
border: 5px dashed green;
}
#profile {
border: 2px solid blue;
}
</style>
1)#ID
2).Class
3) TagName
π₯ !important
<style>
.red {
color: red;
}
.blue {
color: blue;
}
</style>
<p class="red blue"> Bob </p>
<p class="blue red"> Alice </p>
<style>
.red {
color: red;
}
.blue {
color: blue;
}
</style>
<p class="red blue"> Bob </p>
<p class="blue red"> Alice </p>
Hmmmmm...?!
Determines weather it's block or inline + the inner layout of itself.
all the available width. Next element will come below
just the width it needs. Next element comes inline
just like inline-block, only that width/height have no effect
PS: check DevDrive over the weekend for practice exercises
Week #3
flex
items
Flex Container
.gallery {
display: flex;
flex-flow: row wrap;
/* row no-wrap; column wrap; ... */
justify-content: space-between;
/* space-evenly; center; ... */
align-items: center;
/* space-between; space-evenly;... */
}
.raining .human {
/*
"human" class elements
inside "raining"-class elements
*/
display: hidden;
position: under-blanket;/
}
.valentines.in-love {
/*
both "valentines" & "in-love"
classes
*/
text-decoration: make-up;
}
main > .card {
/*
* Elements with class 'card' which
* are a direct child of a
* 'main' element
*/
}
BEM is naming pattern to keep our CSS clean and our minds sane! π
Elements that make sense on their own.
eg: image gallery, login form on home page...
<body>
<div class="gallery">
</div>
</body>
They make sense only as part of a block.
eg: image in an image gallery, form group in a form, etc
<body>
<div class="gallery">
<img class="gallery__image" />
</div>
</body>
An element or a block might have a certain state, like success, error, etc
<body>
<div class="gallery">
<img class="gallery__image" />
<img class="gallery__image gallery__image--seen" />
</div>
</body>
#logo {
tranform: scale(1.1) rotate(35deg);
transform-origin: center;
}
.5 sec
#logo {
transition: transform .5s ease-in;
}
#logo:hover {
transform: scale(1.1);
}
property
timing function
duration
A
A
A
A
#logo {
animation: rotate 1s linear infinite;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(180deg);
}
100% {
transform: rotate(360deg)
}
}
iteration count
PS: check DevDrive over the weekend for practice exercises
Week #4
about the essential project specs
about everything (also explain why you made certain choices)
- or -
PS: check the Website over the weekend for the timetable
Week #6
Download and install XAMPP if you've chosen PHP!
β we can have PHP only files or mix them with HTML for inserting content into the page
<!DOCTYPE html>
<html lang="en">
<head>
<title>PHP & HTML</title>
</head>
<body>
<h1> Some header </h1>
<?php
$today = date('d/m/Y');
echo "<h2> Today is " . $today . "</h2>";
?>
</body>
</html>
index.php
all variables must start with $
concatenate strings with . operator
β there are no type-declarations needed when we create new variables
<?php
$name = 'Bob';
$age = 31;
$isMarried = false;
// ...
β Arrays are actually key-value pairs & the keys don't necessarily have to be numbes, as we are used to
<?php
$phones = ['Bob' => 0740000000];
echo sizeof($phones); // 1
$loteryNumbers = [11, 5, 3];
$loteryNumber['smth'] = 'smth else';
echo sizeof($loteryNumbers); // 3
foreach($loteryNumbers as $element) {
echo $element;
}
β PHP has support for OOP style programming via Classes
<?php
class Human {
public function __construct($name, $age) {
$this -> name = $name;
$this -> age = $age;
}
public function greet() {
echo 'Hello! I am ' . $this -> name . '. Nice to meet you!';
}
}
class Programmer extends Human {
public function __construct($name, $age, $preferedLanguage) {
parent::__construct($name, $age);
$this -> preferedLanguage = $preferedLanguage;
}
public function code() {
echo 'Nom nom, I am coding in ' . $this -> preferedLanguage;
}
}
$fiiDeveloper = new Programmer('Bob', 31, 'PHP');
$fiiDeveloper -> greet();
echo '<br/>';
$fiiDeveloper -> code();
?>
β Add a action attribute to the form specifying the path the the PHP script handling the submit
β Add a method attribute to the form configuring what HTTP Verb to use (usually GET or POST)
On the client
On the server
β Use the global arrays $_GET or $_POST to read the submitted data
β Add the name attribute to all inputs/textareas/selects so that the server can read their values
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Adding two numbers</title>
</head>
<body>
<header>
<h1> Math.php </h1>
</header>
<form action="./math.php" method="GET">
<div>
<label for="no1">Number #1 </label>
<input name="no1" type="number" id="no1">
</div>
<div>
<label for="no2">Number #2 </label>
<input name="no2" type="number" id="no2">
</div>
<button type="submit" name="submit">Submit me! </button>
</form>
</body>
</html>
index.html
<?php
if(isset($_GET['submit'])) {
$no1 = $_GET['no1'];
$no2 = $_GET['no2'];
printResult($no1 + $no2);
}
function printResult($result) {
echo '<p> The answer is <strong>'.$result.'</strong>.</p>';
}
?>
math.php
JSON is one of the most popular data formats out there, used frequently on the Web to exchange data from client-server. - Working with JSON
<?php
$jsonAsText = file_get_contents("./gallery.json");
$galleryArr = json_decode($jsonAsText);
foreach($galleryArr as $image) {
echo '<div>
<img src="'. $image -> src. '">
<p>'. $image -> description .'</p>
</div>';
}
?>
index.php
[{
"src": "./images/barcelone.png",
"description": "Sunset in Barcelone",
"date": "22 June 2019"
}, {
"src": "./images/madrid.png",
"description": "Quiet street in Madrid",
"date": "23 June 2019"
}]
gallery.json
Week #7
MVC is one of the most popular back-end patterns out there, and the one I recommend when building your project. π₯
β this is where all the interaction with our database happens (storing & retrieving data) β consists of Classes/Objects/Functions depending on your app β is passed by the Controller to the View for Rendering
β what the User sees and interacts directly with β will render part of the model/models β should only contain very simple logic, like iterating through data and simple if-else
β where the logic happens β it connects the Model with the appropriate View based on the URL β it also responds to form submit and decides what view to render next
Β
Week #8
Information about a user stored on it's computer (in the browser).
Β
Primarily used to track us all over the internet... π
<?php
$preferredLang = 'RO';
setcookie("PreferredLanguage", $preferredLang, time() + 3600);
?>
<?php
if($_COOKIE['PreferredLanguage'] === 'RO') {
echo 'Salut';
} else {
echo 'Hello';
}
Setting up a cookie that expires in 1 hour regarding the language preference
Reading the cookie later in a different page
Similar to cookies but they store information about a user on the server.
How do they work? π€
β A cookie having a unique ID - calleΒ Session ID - is stored on the client (browser)
β On the server there's some data attached to that ID
β When the user goes back to the server, the cookie is read and thus the data attached to that ID is found and can be accessed
<?php
/**
START - Persist session for 2 hours,
even after closing the browser.
Needs to be called only once,
when starting the server.
*/
$TWO_HOURS = 60 * 60 * 2;
ini_set('session.cookie_lifetime', $TWO_HOURS);
ini_set('session.gc_maxlifetime', $TWO_HOURS);
session_start();
if(isset($_SESSION['count'])) {
$_SESSION['count'] ++;
} else {
$_SESSION['count'] = 1;
}
echo $_SESSION['count'];
?>
<?php
$CONFIG = [
'servername' => "localhost",
'username' => "root",
'password' => '',
'db' => 'test'
];
$conn = new mysqli($CONFIG["servername"], $CONFIG["username"], $CONFIG["password"], $CONFIG["db"]);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
} else {
echo "Successfully connected to DB";
}
?>
π Connecting to a MySQL database π
We're using Prepared Statement to prevent this π
<?php
$username = "Bob";
$pass = "12345";
$insertStatement = $conn -> prepare("INSERT INTO users VALUES(?, ?)");
$insertStatement -> bind_param("ss", $username, $pass);
$insertStatement -> execute();
$insertStatement -> close();
?>
<?php
$getUsersStatement = $conn -> prepare("SELECT * FROM users WHERE username = ?");
$getUsersStatement -> bind_param("s", $username);
$getUsersStatement -> execute();
$users = $getUsersStatement -> get_result();
foreach($users as $row) {
echo $row['username'];
echo ' -- ';
echo $row['password'];
echo '<br/>';
}
?>
Week #9
The DOM is a tree-like structure representing an XML document.
Β
Most often though, you'll hear about it in the context of HTML but it applies to any XML document.
The DOM provides us with an API (functions) through which we'll interact with it. And since it's a standard, those functions are the same in any programming language.
<?php
$dom = new DOMDocument();
$p = $dom -> createElement('p');
$p -> textContent = 'I am a paragraph';
$img = $dom -> createElement('img');
$img -> setAttribute('src', 'https://www.info.uaic.ro/wp-content/uploads/2019/05/cropped-engl-100x600v2.png');
$img -> setAttribute('alt', 'UAIC logo');
$p -> appendChild($img);
$dom -> appendChild($p);
echo $dom -> saveXML();
PHP example of using DOM
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM</title>
</head>
<body>
<script>
var p = document.createElement('p');
p.textContent = 'I am a paragraph';
var img = document.createElement('img');
img.setAttribute('src', 'https://www.info.uaic.ro/wp-content/uploads/2019/05/cropped-engl-100x600v2.png');
img.setAttribute('alt', 'UAIC logo');
p.appendChild(img);
document.body.appendChild(p);
</script>
</body>
</html>
JS example of using DOM
πSee, the exact same functions!
Week #10
DOM is just one way of parsingΒ an XML document. Let's look at two more: Simple XML & SAX
SimpleXML allows us to easily read an XML document and than iterate through it like a normal PHP data-structure.
<?xml version="1.0" encoding="utf-8"?>
<travel-list>
<country>
<name>Portugal</name>
<year>2022</year>
</country>
</travel-list>
Let's say we have the following XML document regarding travel destinations
<?php
$travelList = simplexml_load_file('travel.xml');
for ($index = 0; $index < sizeof($travelList); $index++) {
echo
"<p> I want to travel to " .
$travelList->country[$index]->name .
" in " . $travelList->country[$index]->year .
"</p>";
}
π This is how we would parse it to show that info in an HTML page π
However, since SimpleXML and DOM store the entire XML in memory, they cannot be used for huge XML files (GBs).
SAX is used to efficiently (from a memory perspective) parse huge XML docs.
It "iterates" through the XML and emits events whenever it stumbles upon a start tag, end tag, or content data.
Β
We "hook" into those events to read the data.
In the example below I've created a custom ParserΒ class to make things more readable.
<?php
$parser = new Parser('travel.xml');
$parser->parseAndPrint();
class Parser
{
private $xml_parser;
private $index = 0;
private $filename;
public function __construct($filename)
{
$this->filename = $filename;
$this->xml_parser = xml_parser_create();
xml_set_object($this->xml_parser, $this);
xml_set_element_handler($this->xml_parser, "startElement", "endElement");
xml_set_character_data_handler($this->xml_parser, "characterData");
}
public function parseAndPrint()
{
if (!($fp = fopen($this->filename, "r"))) {
die("Could not open XML input");
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($this->xml_parser, $data, feof($fp))) {
die(sprintf(
"XML error: %s at line %d",
xml_error_string(xml_get_error_code($this->xml_parser)),
xml_get_current_line_number($this->xml_parser)
));
}
}
xml_parser_free($this->xml_parser);
}
private function startElement($parser, $name, $attrs)
{
switch ($name) {
case 'COUNTRY':
echo '<p> I want to travel ';
break;
case 'NAME':
echo " to <strong>";
break;
case 'YEAR':
echo " in <strong>";
break;
default:
break;
}
}
private function endElement($parser, $name)
{
switch ($name) {
case 'COUNTRY':
echo '</p>';
break;
case 'NAME':
case 'YEAR':
echo '</strong>';
break;
default:
break;
}
}
private function characterData($parser, $data)
{
$data = preg_replace("/^\s+/", "", $data);
$data = preg_replace("/\s+$/", "", $data);
if (!($data == "")) {
echo $data;
}
}
}
β startElement function: gets called whenever the parser detects a start of an XML element. Depending on the tag we print a different message
β endElement function: gets called whenever the parser detects the end of an XML element. We're using to to close HTML tags.
β characterData function: gets called whenever the parser detects content inside an XML element. We use it to print the actual country name & year.
Week #11
A Web service is a software system designed to support machine-to-machine interaction over a network.
Web Services are similar to real-life services.
Β
For example: we have Food Delivery Services so that we don't have to drive to the store. Similarly, OpenWeatherMap offers weather information, or AWS S3 offers a Storage Service.
π What I love about Web Services is that you can combine them and create brand new products.
These types of products are called "mash-ups".
β Maps Service
β Weather Service
show realtime weather information on the Map so you can plan your trip
When creating a Web Service it is recommended to follow a set of patterns & best practices.
Β
Thus, in the following slides we're gonna be talking about 2 approaches: SOAP and REST.
βit can be adapted to any communication protocol, not just HTTP
βthe functionality provided by the Service (including data types) is described in WSDL
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header> </soap:Header>
<soap:Body>
<m:GetStockPrice xmlns:m="http://www.example.org/stock/Surya">
<m:StockName>IBM</m:StockName>
</m:GetStockPrice>
</soap:Body>
</soap:Envelope>
βtransfered information (for both request and response) must be in XML format and should respect a standard format of Envelope, Headers and Body
PHP already has two utility classes SoapServer and SoapClient for easily building and talking to SOAP Services.
Here's a demo of using them to build a dummy Game of Thrones Service (no spoilers π )
<?php
$client = new SoapClient(NULL, [
"location" => "http://localhost:1234/soap-live/got-service.php",
"uri" => "http://got-soap-service.com"
]);
// var_dump($client -> __getFunctions());
// var_dump($client -> __getTypes());
echo $client -> getEpisodesCount() . "<br/>";
echo $client -> getSynopsis(62) . "<br/>";
Client
<?php
$service = new SoapServer(NULL, [
"uri" => "http://got-soap-service.com"
]);
class Episode {
public function __construct($name)
{
$this -> episodName = $name;
}
}
class GotService
{
public function getSynopsis($args)
{
if ($args['seasonNo'] === 6 && $args['episodeNo'] === 3) {
return new Episode("Battle of the bastards: fight between good and evil!");
}
return "Episode not found!";
}
public function getEpisodesCount()
{
return 73;
}
}
$service->setObject(new GotService());
$service->handle();
Server
We haven't used Headers yet so let's modify our example by adding authentication
βthe Client will need to send a header named CustomAuthHeader with two propertis: username & pass
βthe Server will read this header and only allow access to the getSynopsis function if the credentials match
<?php
$client = new SoapClient(NULL, [
"location" => "http://localhost:1234/soap-live/got-service.php",
"uri" => "http://got-soap-service.com"
]);
// var_dump($client -> __getFunctions());
// var_dump($client -> __getTypes());
class CustomAuthHeader
{
public $username;
public $pass;
public function __construct()
{
$this->username = "bob";
$this->pass = "1234";
}
}
$header = new SoapHeader(
"http://got-soap-service.header.com",
"CustomAuthHeader",
new CustomAuthHeader()
);
echo $client->__soapCall("getSynopsis", [
[
"seasonNo" => 6,
"episodeNo" => 3
]
], NULL, [$header]) -> episodName;
Client
<?php
$service = new SoapServer(NULL, [
"uri" => "http://got-soap-service.com"
]);
class Episode {
public function __construct($name)
{
$this -> episodName = $name;
}
}
class GotService
{
private $isAuthenticated = false;
public function CustomAuthHeader($header)
{
if (
$header->username === "bob" &&
$header->pass === "1234"
) {
$this->isAuthenticated = true;
}
}
public function getSynopsis($args)
{
if (!$this->isAuthenticated) {
throw new Error("Must be authenticated!");
}
if ($args['seasonNo'] === 6 && $args['episodeNo'] === 3) {
return new Episode("Battle of the bastards: fight between good and evil!");
// return "Battle of the bastards: fight between good and evil!";
}
return "Episode not found!";
}
public function getEpisodesCount()
{
return 73;
}
}
$service->setObject(new GotService());
$service->handle();
Server