Webprogramozás
Horváth Győző
egyetemi docens
horvath.gyozo@inf.elte.hu
1117 Budapest, Pázmány Péter sétány 1/c., 4.725
// Adatszerkezetek
const books = [
{ title: 'Anna Karenina', year: 1877 },
{ title: 'Harry Potter és a bölcsek köve', year: 1997 },
];
// Függvények
function getBooksOf1800(books) {
const result = [];
for (const book of books) {
if (book.year >= 1800 && book.year < 1900) {
result.push(book);
}
}
return result;
}
const booksOf1800 = getBooksOf1800(books)
// Tömbfüggvények
const booksOf1900 = books.filter(book => book.year >= 1900 && book.year < 2000)
class Library {
books = [
{title: 'A case for Christ', author: 'Lee Strobel'},
// ...
]
booksByAuthor(author) {
return this.books.filter(book => book.author === author)
}
}
const lib = new Library()
const strobels = lib.booksByAuthor('Lee Strobel')
for (const b of strobels) {
console.log(b.title);
}
<form>
Name: <input type="text" id="name">
<input type="button" value="Say hello!" id="hello">
<span id="output"></span>
</form>
<form>
Name: <input type="text" id="name">
<input type="button" value="Say hello!" id="hello">
<span id="output"></span>
</form>
function greet(name) {
return `Hello ${name}!`;
}
A forrás és a DOM eltérhet egymástól.
document
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<p>Lorem ipsum.</p>
<p class="active">
Dolor sit amet.
</p>
</body>
</html>
┣ DOCTYPE: html
┣ HTML
┣━━ #text:
┣━━ META charset="utf-8"
┣━━━━ #text:
┣━━━━ TITLE
┣━━━━ #text:
┣ #text:
┣ BODY
┣━━ #text:
┣━━ P
┣━━ #text: Lorem ipsum.
┣━━ P class="active"
┣━━ #text: Dolor sit amet.
┗ #text:
CSS szelektorral:
Egy elem: | document.querySelector(sel) |
Több elem: | document.querySelectorAll(sel) |
<form>
Név:
<input id="name" value="Luke">
<button>Click me!</button>
</form>
<script>
console.log( document.querySelector("#name") );
console.log( document.querySelectorAll("form > *") );
</script>
névvel | button |
azonosítóval | #navbar |
stílusosztállyal | .important |
attribútummal | [name=password] |
univerzális | * |
kombinálva | input.error[type=text] |
közvetlen gyerek | form > input |
leszármazott | #wrapper div |
következő testvér | ul + p |
utána jövő testvérek | ul ~ p |
<ul>
<li>First</li>
<li>Second</li>
<li>Third</li>
</ul>
const listItems = document.querySelectorAll('ul > li')
// Array-like object (NodeList)
for (const li of listItems) { /*...*/ } // OK
listItems.forEach(li => { /*...*/ }) // OK
listItems.map(li => { /*...*/ }) // Wrong: not an array
// Transforming to array
const listItemsArray = Array.from(listItems);
listItemsArray.map(li => { /*...*/ }); // OK
elem.querySelector(sel)
elem.querySelectorAll(sel)
<div class="first">
<span>Apple</span>
</div>
<div class="second">
<span>Pear</span>
</div>
const firstDiv = document.querySelector('div.first')
const spanInFirstDiv = ✒>firstDiv<✒.querySelector('span')
<form>
Name: <input type="text" id="name">
<input type="button" value="Say hello!" id="hello">
<span id="output"></span>
</form>
const nameInput = document.querySelector('#name')
const nameInput = document.querySelector('form input[type=text]')
HTML attribútum | DOM tulajdonság |
---|---|
type |
type |
value |
value |
readonly |
readOnly |
maxlength |
maxLength |
innerHTML
, innerText
: az elem nyitó- és
záróelem közötti HTML vagy szöveg<p>This is a <span>text</span></p>
const p = document.querySelector('p');
// reading
p.innerHTML; // 'This is a <span>text</span>'
p.innerText; // 'This is a text'
// writing
p.innerHTML = 'This is a <strong>new</strong> text';
<form>
Name: <input type="text" id="name">
<input type="button" value="Say hello!" id="hello">
<span id="output"></span>
</form>
// Reading
const input = document.querySelector('#name');
const name = input✒>.value<✒;
// Writing
const output = document.querySelector('#output');
output✒>.innerHTML<✒ = greet(name);
// Reading
const input = document.querySelector('#name');
const name = input✒>.value<✒;
// Writing
const output = document.querySelector('#output');
output✒>.innerHTML<✒ = greet(name);
elem.addEventListener('eventType', eventHandler)
const button = document.querySelector('button');
button.addEventListener('click', handleButtonClick);
function handleButtonClick() {
console.log('clicked');
}
<form>
Name: <input type="text" id="name"> <br>
<input type="button" value="Say hello!" id="hello">
<br>
<span id="output"></span>
</form>
function greet(name) {
return `Hello ${name}!`;
}
function handleHelloClick() {
const name = input.value;
const greeting = greet(name);
output.innerHTML = greeting;
}
const input = document.querySelector('#name');
const output = document.querySelector('#output');
const hello = document.querySelector('#hello');
hello.addEventListener('click', handleHelloClick);
// Typical JavaScript program:
// Reading (from DOM)
// Processing (independent from I/O)
// Writing (to DOM)
<!-- Reading -->
<input type="checkbox" id="accept" checked>
<script>
const elfogad = document.querySelector("#accept").checked;
</script>
<!-- Writing -->
<img src="" id="image">
<script>
const url = "http://images.io/example.png";
const image = document.querySelector("#image");
image.src = url;
</script>
<input type="radio" name="gender" value="male" checked> Male
<input type="radio" name="gender" value="female"> Female
Maiden name: <input id="maidenName">
<script>
// Reading
const femaleRadio =
document.querySelector("[name=gender][value=female]");
const isFemale = famaleRadio.checked;
// Writing
document.querySelector("#maidenName").hidden = !isFemale;
</script>
innerHTML
tulajdonság írása<div id="output"></div>
<script>
const greeting = "<h1>Hello <em>World</em></h1>";
const output = document.querySelector("#output");
output.innerHTML = greeting;
</script>
// Rövid statikus szöveg megadása
const html1 = `<h1>Hello there!</h1>`;
// Többsoros statikus szöveg megadása
const html2 = `
<div>
<p>No, <strong>I</strong> am your father!</p>
</div>
`;
// Változók behelyettesítése
const callsign = 'Red 5';
const html3 = `${callsign}, standing by.`;
// Tömbök kiírása leképezéssel
const callsigns = ["Red 10", "Red 7", "Red 3", "Red 6", "Red 9"];
const html4 = `
<p>All wings, report in.</p>
<ul>
${callsigns.map(callsign => `
<li>${callsign}, standing by.</li>
`).join("")}
</ul>
`;
// Feltételes kiírás (elágazás)
const chanceOfSuccess = 0.4;
const html5 = `
<span>
I have a
${chanceOfSuccess < 0.5 ? "bad" : "good"}
feeling about this.
</span>
`;
// Függvényekkel
function hanDescription(properties) {
return `
You
<ul>
${properties.map(hanProperty).join("")}
</ul>
Nerf Herder!
`;
}
function hanProperty(property) {
return `<li>${property}</li>`;
}
const hanProperties = [
"stuck up",
"half witted",
"scruffy looking"
];
const html6 = hanDescription(hanProperties);
Programozottan:
document.createElement(elem)
parent.appendChild(child)
: szülő gyerekeihez utolsóként
hozzáadja az új elemetparent.insertBefore(newChild, refChild)
: referencia elé
beszúrja az új elemet<body>
<ul>
<li>First</li>
<li>Second</li>
✒> <✒
<li>Third</li>
</ul>
✒> <✒
</body>
const p = document.createElement('p');
document.body.appendChild(p);
const newLi = document.createElement('li');
const ul = document.querySelector('ul');
const refLi =
ul.querySelector('li:nth-of-type(3)');
ul.insertBefore(newLi, refLi);
Stílusattribútum, stílusosztály, stíluslap
<div class="rodian bounty-hunter" style="bottom: 72in">
Greedo
</div>
style
tulajdonság olvasása/írása
CSS stílustulajdonság | style objektum tulajdonsága |
---|---|
left |
left |
background-color |
backgroundColor |
border-bottom-width |
borderBottomWidth |
border-top-left-radius |
borderTopLeftRadius |
<div style="position: absolute" id="movingElement"></div>
<script>
document.querySelector("#movingElement").style.top = "25px";
document.querySelector("#movingElement").style.left = "42px";
</script>
elem.style
: CSSStyleDeclaration
objektumstyle
attribútumon keresztül voltak megadva;<style>
.box {
position: absolute;
width: 100px; height: 100px;
}
</style>
<div class="box" style="left: 20px"></div>
const box = document.querySelector("div");
box.style.top = "30px";
box.style.top; // "30px" <-- JS
box.style.left; // "20px" <-- style attribute
box.style.width; // ""
box.style.position; // ""
window.getComputedStyle(elem)
border
, background
,
stb.) nem érhető el, csak az elemi tulajdonságok.<style>
.box {
position: absolute;
width: 100px; height: 100px;
}
</style>
<div class="box" style="left: 20px"></div>
const box = document.querySelector("div");
box.top = "30px";
const computedStyle = window.getComputedStyle(box);
computedStyle.top // "30px"
computedStyle.left // "20px"
computedStyle.width // "100px"
computedStyle.position // "absolute"
classList
tulajdonság
add(osztály)
remove(osztály)
toggle(osztály)
contains(osztály)
<div class="rodian bounty-hunter">Greedo</div>
add
, remove
, toggle
,
contains
<div class="red green blue">
const div = document.querySelector('div');
div.classList.remove("green");
div.classList.add("pink");
// váltogatás
div.classList.toggle("pink");
// feltételes megjelenítés
div.classList.toggle("pink", i < 10);
// van-e adott stílusosztály
div.classList.contains("red"); // true
// több hozzáadása egyszerre
div.classList.add("orange", "yellow");
document.styleSheets
→ tömb
(StyleSheet
)type
disabled
(stíluslap dinamikus ki-bekapcsolása)href
title
cssRules
: szabályok módosítása
cssText
: a szabály szöveges formájaselectorText
(nem szabványos)style
: az adott szabály stíluslistája (mint az inner
style)getAttribute(name)
setAttribute(name, value)
hasAttribute(name)
removeAttribute(name)
toggleAttribute(name[, predicate])
<button type="submit" data-id="10" disabled>A button</button>
const b = document.querySelector('button')
// reading
b.getAttribute('type') // 'submit'
b.getAttribute('data-id') // '10'
b.getAttribute('disabled') // ''
b.getAttribute('foo') // null or ''
b.hasAttribute('disabled') // true
// writing
b.setAttribute('name', 'send')
b.setAttribute('hidden', '') // boolean attribute
b.toggleAttribute('disabled') // toggle boolean attribute
data-*
attribútum → dataset
tulajdonság
<div
data-id="10"
data-some-text="foo"
></div>
const div = document.querySelector('div')
// reading
div.dataset.id // "10"
div.dataset.someText // "foo"
// writing
div.dataset.someText = "bar"
div.dataset.user = "John" // --> data-user="John"
div.dataset.dateOfBirth = "2000-12-12" // --> data-date-of-birth="2000-12-12"
// removing
delete div.dataset.id
// checking
'someText' in el.dataset // true
'id' in el.dataset // false
attributes
: élő lista, tömbszerű objektumgetAttributeNames()
: szövegtömbchildNodes
, firstChild
,
lastChild
children
, firstElementChild
,
lastElementChild
parentNode
, parentElement
closest(cssSelector)
nextSibling
, previousSibling
nextElementSibling
,
previousElementSibling
Csomópont típusa
nodeType === 1
: elemnodeType === 3
: szöveges csomópontparent.appendChild(elem)
: beszúrásparent.insertBefore(elem, ref)
: beszúrásparent.removeChild(elem)
: törlésparent.replaceChild(elem, oldElem)
: csereelem
létezik, akkor mozgatásparent.contains(element)
: tartalmazza-e<ul>
<li>első</li>
<li>második</li>
<li>harmadik</li>
<li>negyedik</li>
<li>ötödik</li>
</ul>
function getPosition(element) {
let count = 0;
while ( null != el ) {
el = el.previousElementSibling;
count++;
}
return count;
}
const secondChild = document.querySelector('ul > li:nth-child(2)');
const position = getPosition(secondChild); // 2
<ul>
<li>első</li>
<li>második</li>
<li>harmadik</li>
<li>negyedik</li>
<li>ötödik</li>
</ul>
function getPosition(element) {
const parent = element.parentNode;
const children = Array.from(parent.children);
return children.indexOf(element) + 1;
}
const secondChild = document.querySelector('ul > li:nth-child(2)');
const position = getPosition(secondChild); // 2
alert(text)
confirm(text)
prompt(text, default)
alert('The Force will be with you. Always.');
const kerdes = confirm('Judge me by my size, do you?');
const target = prompt(`
You would prefer another target?
A military target?
Then name the system!
`, 'Dantooine');
console.log(
`${target} is too remote to make an effective demonstration!`
);
document
getElementById(id)
getElementsByName(name)
document
/elem
getElementsByTagName(tagName)
getElementsByClassName(className)
querySelector(css_selector)
querySelectorAll(css_selector)
className
tulajdonságclass
attribútum szöveges értéke<div class="human hero">Aragorn</div>
const div = document.querySelector('div')
div.className // 'human hero'
div.className = 'human king'
<!-- keretrendszer betöltése -->
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.4.0/jasmine.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.4.0/jasmine.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.4.0/jasmine-html.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.4.0/boot.min.js"></script>
<!-- az alkalmazás és teszt betöltése -->
<script src="app.js"></script>
<script src="app.test.js"></script>
// app.test.js
describe('factorial', () => {
it('0! should be 1', () => {
expect(factorial(0)).toBe(1);
})
})
describe('factorial', () => {
it('0! should be 1', function () {
expect(factorial(0)).toBe(1);
});
it('1! should be 1', function () {
expect(factorial(1)).toBe(1);
});
it('5! should be 120', function () {
expect(factorial(5)).toBe(120);
});
});
describe('factorial', () => {
/* ... */
it('5! should be 120', function () {
expect(factorial(5)).toBe(1200);
});
});
document.querySelector(css-selector)
elem.addEventListener('click', onClick)