update vers grond
This commit is contained in:
@@ -1,87 +0,0 @@
|
||||
main {
|
||||
position: absolute;
|
||||
top: 2rem;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
.loader {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.loader {
|
||||
margin: 6rem 0 0;
|
||||
}
|
||||
.error {
|
||||
color: #FFFAAA;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
label {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
label span {
|
||||
text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
|
||||
}
|
||||
input {
|
||||
margin: 1rem 0 0;
|
||||
font-size: 1.6rem;
|
||||
font-weight: 300;
|
||||
padding: 0.8rem 1rem;
|
||||
color: white;
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
transition: all 0.3s;
|
||||
box-shadow: 1px 1px 2px rgba(0,0,0, 0.3);
|
||||
-moz-appearance:none;
|
||||
-webkit-appearance:none;
|
||||
outline: none;
|
||||
}
|
||||
input:focus {
|
||||
border: 1px solid transparent;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: 1rem 0 2rem;
|
||||
}
|
||||
ul li {
|
||||
padding: 0.6rem 1rem;
|
||||
margin: 1px 0;
|
||||
line-height: 1.4rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
align-content: space-between;
|
||||
text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
box-shadow: 0 0 2px rgba(0,0,0, 0.3);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
ul li:hover,
|
||||
ul li:active,
|
||||
ul li:focus {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
ul li a {
|
||||
margin: 0 0.6rem 0 0;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
ul li span {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial;
|
||||
font-weight: 300;
|
||||
background-size: cover;
|
||||
background-attachment: fixed;
|
||||
background-image: -webkit-radial-gradient(ellipse farthest-corner at top, #661141, #000000);
|
||||
background-image: radial-gradient(ellipse farthest-corner at top, #661141, #000000);
|
||||
color: white;
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
|
||||
<svg width="44" height="44" viewBox="0 0 44 44" xmlns="http://www.w3.org/2000/svg" stroke="#fff">
|
||||
<g fill="none" fill-rule="evenodd" stroke-width="2">
|
||||
<circle cx="22" cy="22" r="1">
|
||||
<animate attributeName="r" begin="0s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite"/>
|
||||
<animate attributeName="stroke-opacity" begin="0s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
<circle cx="22" cy="22" r="1">
|
||||
<animate attributeName="r" begin="-0.9s" dur="1.8s" values="1; 20" calcMode="spline" keyTimes="0; 1" keySplines="0.165, 0.84, 0.44, 1" repeatCount="indefinite"/>
|
||||
<animate attributeName="stroke-opacity" begin="-0.9s" dur="1.8s" values="1; 0" calcMode="spline" keyTimes="0; 1" keySplines="0.3, 0.61, 0.355, 1" repeatCount="indefinite"/>
|
||||
</circle>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -1,28 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="initial-scale=1,witdh=device-width">
|
||||
<link rel="stylesheet" type="text/css" href="./css/style.css">
|
||||
<title>Riot todo</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="stylesheet" href="todo.css">
|
||||
<script src="todo.riot" type="riot"></script>
|
||||
<script src="https://unpkg.com/riot@9.1.3/riot+compiler.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- vue html -->
|
||||
<main>
|
||||
<label>
|
||||
<span>Search a movie</span>
|
||||
<input type="input" placeholder="28 Days Later..">
|
||||
</label>
|
||||
|
||||
<div class="loader">
|
||||
<img src="./img/puff.svg">
|
||||
</div>
|
||||
|
||||
<p class="error"></p>
|
||||
<div id="list-movies">
|
||||
</div>
|
||||
</main>
|
||||
<todo />
|
||||
<script>
|
||||
riot.compile().then(() => {
|
||||
riot.mount('todo', {
|
||||
title: 'I want to behave!',
|
||||
items: [
|
||||
{ title: 'Avoid excessive caffeine', done: false },
|
||||
{ title: 'Be less provocative', done: true },
|
||||
{ title: 'Be nice to people', done: true }
|
||||
]
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
<script type="module" src="./js/app.js"></script>
|
||||
</html>
|
||||
</html>
|
@@ -1,7 +0,0 @@
|
||||
import model from './model'
|
||||
import Controller from './controller'
|
||||
import View from './view'
|
||||
|
||||
const view = new View()
|
||||
const app = new Controller(view,model)
|
||||
|
@@ -1,45 +0,0 @@
|
||||
class Controller {
|
||||
constructor(view,model){
|
||||
this.view = view
|
||||
this.model = model
|
||||
|
||||
this.loading = false
|
||||
this.lastSearch = null
|
||||
this.error = null
|
||||
this.results = []
|
||||
|
||||
this.view.setLoading(false)
|
||||
this.view.bindSearch(this.search.bind(this))
|
||||
}
|
||||
reset() {
|
||||
this.loading = false
|
||||
this.error = null
|
||||
this.results = []
|
||||
}
|
||||
|
||||
async search(searchMovie) {
|
||||
try {
|
||||
this.reset();
|
||||
this.loading = true;
|
||||
this.view.setLoading(true);
|
||||
|
||||
const movies = await this.model.getMovies(searchMovie);
|
||||
|
||||
if (movies && movies.length > 0) {
|
||||
this.results = movies;
|
||||
} else {
|
||||
this.error = "No movies found.";
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error occurred during search:', error);
|
||||
this.error = "An error occurred during search.";
|
||||
} finally {
|
||||
this.loading = false;
|
||||
this.view.setLoading(false);
|
||||
this.view.renderResults(this.results, this.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Controller
|
||||
|
@@ -1,12 +0,0 @@
|
||||
// Returns a function, that, as long as it continues to be invoked, will not
|
||||
// be triggered. The function will be called after it stops being called for
|
||||
// N milliseconds.
|
||||
function debounce(fn, wait) {
|
||||
let timeout
|
||||
|
||||
return (...args) => {
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(() => fn(...args), wait)
|
||||
}
|
||||
}
|
||||
export default debounce
|
@@ -1,23 +0,0 @@
|
||||
let apiKey = 'a776e2df'
|
||||
|
||||
let model = {
|
||||
getMovies(search){
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(`http://www.omdbapi.com/?apikey=${apiKey}&s=${search}`)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
resolve(data.Search);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('There was a problem with the fetch operation:', error);}
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default model
|
@@ -1,54 +0,0 @@
|
||||
import debounce from "./helpers.js"
|
||||
|
||||
class View {
|
||||
constructor(){
|
||||
this.listMovies = document.querySelector("#list-movies")
|
||||
this.inputSearch = document.querySelector("input")
|
||||
this.loader = document.querySelector(".loader")
|
||||
this.message = document.querySelector("p.error")
|
||||
}
|
||||
|
||||
_getInput(){
|
||||
return this.inputSearch.value
|
||||
}
|
||||
|
||||
setLoading(loading){
|
||||
if (loading)
|
||||
this.loader.style.display = "block"
|
||||
else
|
||||
this.loader.style.display = "none"
|
||||
}
|
||||
|
||||
renderMessage(error){
|
||||
this.message.style.display = "block"
|
||||
this.message.textContent = error
|
||||
}
|
||||
|
||||
renderList(movies){
|
||||
let ul = document.createElement("ul")
|
||||
movies.forEach((movie)=>{
|
||||
let li = document.createElement("li")
|
||||
let a = document.createElement("a")
|
||||
let span = document.createElement("span")
|
||||
a.href = `http://www.imdb.com/title/${movie.imdbID}`
|
||||
a.target="_blank"
|
||||
a.textContent = movie.Title
|
||||
span.textContent = movie.Year
|
||||
|
||||
|
||||
li.appendChild(a)
|
||||
li.appendChild(span)
|
||||
ul.appendChild(li)
|
||||
})
|
||||
|
||||
this.listMovies.replaceChildren(ul)
|
||||
}
|
||||
|
||||
bindSearch(handler){
|
||||
this.inputSearch.addEventListener("input",debounce((e)=>{
|
||||
handler(this._getInput())
|
||||
},500))
|
||||
}
|
||||
}
|
||||
|
||||
export default View
|
75
DEV4.1/tp4/ex1/todo.css
Normal file
75
DEV4.1/tp4/ex1/todo.css
Normal file
@@ -0,0 +1,75 @@
|
||||
|
||||
body {
|
||||
font-family: 'myriad pro', sans-serif;
|
||||
font-size: 20px;
|
||||
border: 0;
|
||||
}
|
||||
todo {
|
||||
display: block;
|
||||
max-width: 600px;
|
||||
margin: 5% auto;
|
||||
}
|
||||
form input {
|
||||
font-size: 85%;
|
||||
padding: .4em;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 2px;
|
||||
}
|
||||
button {
|
||||
background-color: #1FADC5;
|
||||
border: 1px solid rgba(0,0,0,.2);
|
||||
font-size: 75%;
|
||||
color: #fff;
|
||||
padding: .4em 1.2em;
|
||||
border-radius: 2em;
|
||||
cursor: pointer;
|
||||
margin: 0 .23em;
|
||||
outline: none;
|
||||
}
|
||||
button[disabled] {
|
||||
background-color: #ddd;
|
||||
color: #aaa;
|
||||
}
|
||||
ul {
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
list-style-type: none;
|
||||
padding: .2em 0;
|
||||
}
|
||||
.completed {
|
||||
text-decoration: line-through;
|
||||
color: #ccc;
|
||||
}
|
||||
label {
|
||||
cursor: pointer;
|
||||
}
|
||||
.filters {
|
||||
margin-top: 10px;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
/* position: absolute;*/
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
.filters li {
|
||||
display: inline;
|
||||
}
|
||||
.filters li a {
|
||||
color: inherit;
|
||||
/* margin: 3px;*/
|
||||
margin-right:10px;
|
||||
padding: 3px 7px;
|
||||
text-decoration: none;
|
||||
font-size : 0.75em;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.filters li a:hover {
|
||||
border-color: rgba(175, 47, 47, 0.1);
|
||||
}
|
||||
|
||||
.filters li a.selected {
|
||||
border-color: rgba(175, 47, 47, 0.2);
|
||||
}
|
||||
|
70
DEV4.1/tp4/ex1/todo.riot
Normal file
70
DEV4.1/tp4/ex1/todo.riot
Normal file
@@ -0,0 +1,70 @@
|
||||
<todo>
|
||||
<h3>{ props.title }</h3>
|
||||
<ul>
|
||||
<li each={ item in state.items }>
|
||||
<label class={ item.done ? 'completed' : null }>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={ item.done }
|
||||
onclick={ () => toggle(item) } />
|
||||
{ item.title }
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
<form onsubmit={ add }>
|
||||
<input oninput={ edit } />
|
||||
<button disabled={ !state.text }>
|
||||
Addddd #{ state.items.length + 1 }
|
||||
</button>
|
||||
<button disabled={ this.state.items.some(item => !item.done) } onclick={ clear }>Clear done</button>
|
||||
<ul class="filters">
|
||||
<li> <a href="#">All</a></li>
|
||||
<li> <a href="#">Active</a></li>
|
||||
<li> <a href="#">Done</a></li>
|
||||
</ul>
|
||||
</form>
|
||||
<script>
|
||||
export default function todos(){
|
||||
return {
|
||||
onBeforeMount(props, state) {
|
||||
// initial state
|
||||
this.state = {
|
||||
items: props.items,
|
||||
text: ''
|
||||
}
|
||||
},
|
||||
edit(e) {
|
||||
// update only the text state
|
||||
this.update({
|
||||
text: e.target.value
|
||||
})
|
||||
},
|
||||
clear(e) {
|
||||
this.update({
|
||||
items: this.state.items.filter(item => !item.done)
|
||||
})
|
||||
this.update()
|
||||
},
|
||||
add(e) {
|
||||
e.preventDefault()
|
||||
|
||||
if (this.state.text) {
|
||||
this.update({
|
||||
items: [
|
||||
...this.state.items,
|
||||
// add a new item
|
||||
{title: this.state.text}
|
||||
],
|
||||
text: ''
|
||||
})
|
||||
}
|
||||
},
|
||||
toggle(item) {
|
||||
item.done = !item.done
|
||||
// trigger a component update
|
||||
this.update()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</todo>
|
Reference in New Issue
Block a user