Cântând cu Sinatra App Applause

Bine ați venit la piesa 2 a Cântării cu Sinatra. În prima parte, am revizuit rutele, cum să lucrăm cu parametrii URI, să lucrăm cu formulare și cum Sinatra diferențiază rutele prin metoda HTTP la care au fost solicitate. Astăzi, vom extinde cunoștințele noastre despre Sinatra construind o aplicație bazată pe baze de date, "Recall", pentru a face note sau a face o listă de sarcini.

Vom folosi o bază de date SQLite pentru a stoca notele și vom folosi DataMapper RubyGem pentru a comunica cu baza de date. Rulați următoarele în interiorul unei cochilii pentru a instala pietrele relevante:

gem instalați sqlite3 datamapper dm-sqlite-adapter

În funcție de modul în care ați instalat RubyGems pe sistemul dvs., este posibil să aveți nevoie să prefixați gem install cu sudo.


Încălzirea

Să mergem direct prin crearea unui nou director pentru proiect și crearea fișierului de aplicație, recall.rb. Începeți-l prin solicitarea pietrelor relevante:

cer "rubygems" necesită "sinatra" necesită "datamapper"

Notă: Dacă rulați Ruby 1.9 (care ar trebui să fie), puteți renunța la linia "requby" rubygems "deoarece Ruby în mod automat încărcă RubyGems oricum.

Și configurați baza de date cu următoarele:

DataMapper :: setup (: default, clasa "sqlite3: // # Dir.pwd /recall.db") Notă include DataMapper :: Resource property: id, Serial property: content, Text: completă, Boolean,: required => true,: default => proprietate falsă: created_at, DateTime property: updated_at, DateTime end DataMapper.finalize.auto_upgrade!

Pe prima linie, configurăm o nouă bază de date SQLite3 în directorul curent, numit recall.db. Mai jos, în baza noastră, de fapt, în baza de date se stabilește o tabelă "Note".

În timp ce sunăm clasa "Notă", DataMapper va crea tabelul ca "Note". Aceasta este în concordanță cu o convenție pe care Ruby on Rails și alte cadre și module ORM urmează.

În cadrul clasei, setăm schema bazei de date. Tabelul "Note" va conține 5 câmpuri. Un id câmp care va fi o cheie primară intreg și auto-incrementare (aceasta este ceea ce înseamnă "Serial"). A conţinut câmp conținând text, un boolean complet câmp și două câmpuri datetime, creat la și updated_at.

Ultimul rând îl instruiește pe DataMapper să actualizeze automat baza de date pentru a conține tabelele și câmpurile pe care le-am setat și să o facem din nou dacă facem orice modificare a schemei.


Pagina de pornire

Acum, să creăm pagina noastră de pornire:

În partea de sus este un formular pentru a adăuga o notă nouă, și mai jos sunt toate notele din baza de date. Pentru a începe, adăugați următoarele în fișierul de aplicații, recall.rb:

obtineti '/' do @notes = Note.all: .order =>: id.desc @title = 'Toate notele' erb: home end

Notă importantă: Scoateți punctul (".') în :.Ordin. (WordPress interferează cu proba de cod.)

Pe a doua linie, vedeți cum preluăm toate notele din baza de date. Dacă ați folosit anterior ActiveRecord (ORM folosit în Rails), sintaxa DataMapper se va simți foarte familiarizată. Notele sunt atribuite funcției @notes variabila de instanta. Este important să utilizați variabilele de instanță (variabilele care încep cu un @), astfel încât acestea să fie accesibile din fișierul de vizualizare.

Am setat @titlu instanță variabilă și încărcați vizualizari / home.erb vizualizați fișierul prin parserul ERB.

Creați vizualizari / home.erb vizualizați fișierul și porniți-l cu următoarele:

<% # display notes %>

Avem un simplu formular care trimite POST-uri către pagina principală ('/'), și de mai jos este un cod ERB care servește ca înlocuitor pentru moment.


aspecte

Lotul de standarde HTML din rândul dvs. poate să fi suferit un accident vascular cerebral minor după ce a văzut că fișierul nostru de vizualizare de origine nu conține nici o etichetă HTML sau doctype. Ei bine, există un motiv pentru asta. Creeaza o layout.erb fișier în dvs. vizualizari / care conține următoarele:

    <%= @title + ' | Recall' %>      

rechemare

pentru că ești prea ocupat să-ți amintești

<%= yield %>

O aplicație pentru Nettuts+.

Cele două părți interesante sunt linii 5 și 18. Pe linia 5 se vede prima utilizare a liniei <%=? %> Etichetele ERB. <%= este diferit de cel obișnuit <% deoarece imprimă ceea ce este înăuntru. Deci, aici afișăm ce este în @titlu instanță variabilă urmată de | rechemare pentru pagina lui </code> etichetă.</p> <p>Pe linia 18 este <code><%= yield %></code>. Sinatra va afișa acest lucru <code>layout.erb</code> fișier pe toate rutele. Conținutul actual pentru acea rută va fi inserat oriunde <code>Randament</code> este. <code>Randament</code> este un termen care în esență înseamnă "opriți aici, introduceți ce așteaptă, apoi continuați".</p> <p>Porniți serverul cu <code>shotgun recall.rb</code> în shell, și să aruncați o privire la pagina de pornire din browser. Ar trebui să vedeți conținutul din fișierul de aspect, iar formularul de la actual <code>home.erb</code> vedere.</p> <img src="//accentsconagua.com/img/images_26_3/singing-with-sinatra-the-recall-app_2.png"> <hr> <h2>CSS</h2> <p>În fișierul de aspect am inclus două fișiere CSS. Sinatra poate încărca fișiere statice (de ex., CSS, JS, imagini etc.) dintr-un folder numit <code>public/</code> în directorul rădăcină. Deci, creați acel director, și în interiorul acestuia două fișiere: <code>reset.css</code> și <code>style.css</code>. Resetarea conține resetarea CSS HTML5 Boilerplate CSS:</p> <pre>/ * HTML5? Boilerplate style.css conține o resetare, normalizarea fontului și unele stiluri de bază. creditul este lăsat în cazul în care creditul este datorat. multă inspirație a fost preluată din aceste proiecte: yui.yahooapis.com/2.8.1/build/base/base.css camendesign.com/design/ praegnanz.de/weblog/htmlcssjs-kickstart * / / * html5doctor.com Resetați foaia de stil ( Rezumatul lui Eric Meyer Reloaded + HTML5) Autori: Eric Meyer & Richard Clark html5doctor.com/html-5-reset-stylesheet/ * / html, corp, div, span, obiect, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre , abbr, adresa, cite, cod, del, dfn, em, img, ins, kbd, samp, mic, puternic, sub, var, b, i, dl, , câmpul, formularul, eticheta, legenda, tabelul, caption, tbody, tfoot, thead, tr, th, td, articol, deoparte, pânză, detalii, figcaption, figura, subsol, antet, hgroup, meniu, nav, , timp, marcă, audio, video margine: 0; padding: 0; de frontieră: 0; font-size: 100%; font: inherit; vertical-align: linia de bază; articol, deoparte, detalii, figcaption, figura, subsol, header, hgroup, meniu, nav, secțiune display: block; blockquote, q citate: none; blockquote: înainte, blockquote: după, q: înainte, q: după content: "; -color: # ff9; culoare: # 000; font-style: italic; font-weight: bold; del text-decoration: line-through; abbr [title], dfn [title] border-bottom: aranjate, cursorul: ajutor; tabel colaps de margine: colaps; spațiere frontieră: 0; hr display: block; padding: 0; intrare, selectați vertical-align: middle; / * END RESET CSS * / / * normalizarea fontului inspirată din fonturile fonturilor.css: developer.yahoo.com/yui/ * / body font : 13px / 1.231 sans-serif; * font-size: small; / * hack păstrat pentru a păstra specificitatea * / select, input, textarea, butonul font: 99% sans-serif; wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome * / pre, code, kbd, samp font-family: monospace, sans-serif; / * * minimal b ase stiluri * / body, selectare, introducere, textarea / * # 444 arata mai bine decat negru: twitter.com/H_FJ/statuses/11800719859 * / color: # 444; / * setați aici fontul de bază pentru a aplica uniform * / / * font-family: Georgia, serif; * / / * anteturile (h1, h2, etc) nu au dimensiune implicită a fontului sau margine. definiți-vă singuri. * / h1, h2, h3, h4, h5, h6 font-greutate: bold; / * forțați întotdeauna o bara de derulare în non-IE: * / html overflow-y: scroll; / * tratament accesibil accesibil: people.opera.com/patrickl/experiments/keyboard/test * / a: hover, a: activ outline: none; a, a: activ, a: vizitat culoare: # 607890; a: hover culoare: # 036; ul, ol margin-stânga: 2em; ol list-style-type: decimal; / * eliminați marginile pentru listele de navigare * / nav ul, nav li margine: 0; list-style: none; listă-stil-imagine: nici unul; mici font-size: 85%; puternic, font-weight: bold; td vertical-align: top; / * set sub, sup fără a afecta înălțimea liniei: gist.github.com/413930 * / sub, sup font-size: 75%; linia-înălțime: 0; poziție: relativă; sup top: -0.5em; sub bottom: -0.25em; pre / * www.pathf.com/blogs/2008/05/formatting-quoted-code-in-blog-posts-css21-white-space-pre-wrap/ * / alb-spațiu: pre; spațiu alb: spațiu prealabil; spațiu alb: pre-linie; cuvânt-wrap: break-cuvânt; padding: 15px; textarea overflow: auto; / * www.sitepoint.com/blogs/2010/08/20/ie-remove-textarea-scrollbars/ * / .6 legenda, .7 legenda margin-left: -7px; / * thnx ivannikolic! * / / * aliniați casetele de selectare, radiourile, intrările de text cu eticheta acestora: Thierry Koblentz tjkdesign.com/ez-css/css/base.css * / input [type = "radio"] vertical-align: text-bottom; introduceți [type = "checkbox"] vertical-align: bottom; .7 intrare [type = "checkbox"] vertical-align: linia de bază; intrare .ie6 vertical-align: text-bottom; / * cursorul de mână pe elementele de intrare clicabile * / etichetă, introduceți [type = "button"], introduceți [type = submit], introduceți [type = "image"], butonul cursor: pointer; / * browserele webkit adaugă o marjă de 2px în afara cromului elementelor de formă * / buton, intrare, selectare, textarea margine: 0; / * culori pentru validitatea formularului * / input: valid, textarea: valid intrare: invalid, textarea: invalid border-radius: 1px; -moz-box-shadow: 0px 0px 5px roșu; -webkit-box-shadow: 0px 0px 5px roșu; box-shadow: 0px 0px 5px roșu; .no-boxshadow de intrare: invalid, .no-boxshadow textarea: invalid background-color: # f0dddd; / * Aceste declarații de selecție trebuie să fie separate. Fără text-shadow: twitter.com/miketaylr/status/12228805301 De asemenea: fierbinte roz. * / :: - moz-selection background: # FF5E99; Culoare: #fff; text-umbra: nici unul; :: selecție background: # FF5E99; Culoare: #fff; text-umbra: nici unul; / * j.mp/webkit-tap-highlight-color * / a: link -webkit-tap-highlight-color: # FF5E99; / * face butoanele să fie frumoase în IE: www.viget.com/inspire/styling-the-button-element-in-internet-explorer/ * / butonul width: auto; overflow: vizibil; / * redimensionarea bicubică pentru dimensiunea IMG non-nativă: code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ * / .ie7 img -ms-interpolare-mod: bicubic; </pre> <p>Și <code>style.css</code> conține un stil de bază pentru a face aplicația să arate destul:</p> <pre>corp margine: 35px auto; lățime: 640px; header text-aliniere: centru; margine: 0 0 20px; header h1 display: inline; font-size: 32px; header h1 a: link, header h1 a: vizitat culoare: # 444; text-decoration: nici unul; antetul h2 font-size: 16px; font-style: italic; culoare: # 999; #main marja: 0 0 20px; #add marja: 0 0 20px; #add textarea height: 30px; lățime: 510px; padding: 10px; frontieră: 1px solid #ddd; #add input height: 50px; lățime: 100px; margine: -50px 0 0; frontieră: 1px solid #ddd; fundal: alb; #edit textarea height: 30px; lățime: 480px; padding: 10px; frontieră: 1px solid #ddd; #edit intrare [type = submit] height: 50px; lățime: 100px; margine: -50px 0 0; frontieră: 1px solid #ddd; fundal: alb; #edit introduceți [tip = casetă de selectare] height: 50px; lățime: 20px; articol border: 1px solid #eee; frontieră: nici una; padding: 15px 10px; articol: prima de tip border: 1px solid #eee; articol: n-copil (echivalent) background: #fafafa; article.complete background: # fedae3; articol span font-size: 0.8em; p margine: 0 0 5px; .meta font-size: 0.8cm; font-style: italic; culoare: # 888; .links font-size: 1.8; înălțimea liniei: 0.8cm; float: dreapta; marja: -10px 0 0; .link un display: block; text-decoration: nici unul; </pre> <p>Reîmprospătați pagina în browser și totul ar trebui să fie mai mult stil. Nu vă faceți griji prea mult despre acest CSS; doar face ca lucrurile să arate puțin mai frumoase!</p> <img src="//accentsconagua.com/img/images_26_3/singing-with-sinatra-the-recall-app_3.png"> <hr> <h2>Adăugarea unei note la baza de date</h2> <p>Chiar dacă încercați să trimiteți formularul pe pagina de pornire, veți obține o eroare de traseu. Să creăm ruta POST pentru pagina de pornire acum:</p> <pre>post '/' do n = Notă.new n.content = params [: conținut] n.created_at = Time.now n.updated_at = Time.now n.save redirect '/' sfârșit</pre> <p>Deci, atunci când o cerere de post este făcută pe pagina de pornire, vom crea un nou obiect Notă în <code>n</code> (datorită ORM-ului DataMapper), <code>Note.new</code> reprezintă un nou rând în <code>notițe</code> tabelul din baza de date). <code>conţinut</code> câmpul este setat la datele trimise de la textarea și <code>creat la</code> și <code>updated_at</code> datetime sunt setate la marca curentă curentă.</p> <p>Noua notă este apoi salvată și utilizatorul redirecționat înapoi la pagina principală unde va fi afișată noua notă.</p> <hr> <h2>Afișarea notelor</h2> <p>Așadar, am adăugat o notă nouă, însă nu o putem vedea pe pagina principală, deoarece nu am scris codul pentru aceasta. În interiorul <code>vizualizari / home.erb</code> vizualizați fișierul, înlocuiți fișierul <code><%# display notes %></code> line cu:</p> <pre><% @notes.each do |note| %> <article <%= 'class="complete"' if note.complete %>> <p> <%= note.content %> <span>„> [Modifică]</span> </p> <p> / Complet ">? </p> <p>Creată: <%= note.created_at %></p> </article> <% end %></pre> <p>În prima linie începem o buclă prin fiecare <code>@notes</code> (în mod alternativ, am fi putut scrie <code>pentru note în @nnnume</code>, dar folosind un bloc, așa cum suntem aici, este o practică mai bună). Pe linia 2, oferim <code><article></code> o clasă de <code>complet</code> dacă nota curentă este setată la <code>complet</code>. Restul ar trebui să fie destul de drept.</p> <hr> <h2>Editarea unei note</h2> <p>Deci, putem adăuga și vedea note. Acum avem nevoie doar de abilitatea de a le edita și șterge.</p> <p>S-ar putea să fi observat asta în noi <code>home.erb</code> vizualizăm un set <code>[Editați | ×]</code> legătură pentru fiecare notă cu ceea ce este esențial <code>/: Id</code>, așa că hai să creăm acel traseu acum:</p> <pre>primi '/: id' do @note = Note.get paramuri [: id] @title = "Editare notă ## params [: id]" erb:</pre> <p>Returnați nota solicitată din baza de date folosind ID-ul furnizat, configurați a <code>@titlu</code> variabile și încărcați <code>vizualizari / edit.erb</code> vizualizați fișierul prin parserul ERB.</p> <p>Introduceți următoarele pentru <code>vizualizari / edit.erb</code> vedere:</p> <pre><% if @note %> <form action="/<%= @note.id %>"method =" post "> <input type="hidden" name="_method" value="put"> <textarea name="content"><%= @note.content %></textarea> <input type="checkbox" name="complete" <%= "checked" if @note.complete %>> <input type="submit"> </form> <p>/ Șterge "> Delete</p> <% else %> <p>Notă nu a fost găsită.</p> <% end %></pre> <p>Aceasta este o viziune destul de simplă. Un formular care indică înapoi la pagina curentă, o textare care conține conținutul notei și o casetă de selectare care se verifică dacă nota este setată la <code>complet</code>.</p> <p>Dar uita-te la a treia linie. Misterios. Pentru a explica acest lucru, trebuie să vedem puțin.</p> <h3>Servicii rapide</h3> <p>Ați auzit de cei doi termeni GET și POST.</p> <ul> <li> <strong>OBȚINE: </strong>Cel mai comun. În general, solicită o pagină și poate fi marcată.</li> <li> <strong>POST: </strong> Folosit pentru trimiterea de date și nu poate fi marcat.</li> </ul> <p>Dar GET și POST nu sunt singurele "verbe HTTP" - mai sunt încă două despre care trebuie să știți: PUT și DELETE.</p> <p>Din punct de vedere tehnic, POST ar trebui să fie folosită numai pentru a crea ceva - cum ar fi crearea unei noi note, de exemplu, în noua dvs. aplicație web minunată.</p> <p>PUT este verbul pentru modificarea ceva. Și DELETE, ai ghicit-o, înseamnă că ai șters ceva.</p> <p>Având aceste patru verbe este o modalitate foarte bună de a separa o aplicație. Este logic. Din păcate, browserele web nu acceptă de fapt solicitări PUT sau DELETE, motiv pentru care probabil că nu ați mai auzit niciodată de acestea înainte.</p> <p>Deci, revenind aici, dacă vrem să împărțim în mod logic aplicația noastră (pe care Sinatra o încurajează), trebuie să falsăm aceste cereri PUT și DELETE. Veți vedea formularul nostru <code>acțiune</code> este setat sa <code>post</code>. Ascunsul <code>_metodă</code> câmpul de introducere pe care l-am setat <code>a pune</code> pe linia a treia permite Sinatra să falsă această cerere PUT, în timp ce utilizează efectiv un POST. Rails, printre alte cadre, fac lucrurile în mod similar.</p> <hr> <h2>Lasă-ne</h2> <p>Acum, ne-am falsificat solicitarea PUT, putem crea un traseu pentru aceasta:</p> <pre>pune '/: id' n n = Note.get paramuri [: id] n.content = params [: conținut] n.complete = params [: complete]? 1: 0 n.updated_at = Time.now n.save redirecționare '/' sfârșit</pre> <p>E destul de simplu. Obțineți nota relevantă folosind ID-ul din URI, setați câmpurile la noile valori, salvați și redirecționați acasă. Observați cum, pe linia a patra, folosim un operator ternar pentru a seta <code>n.complete</code> la <code>1</code> dacă <code>params [: complet]</code> există, sau <code>0</code> in caz contrar. Acest lucru se datorează faptului că valoarea unei casete este trimisă doar cu un formular dacă este bifată, așa că pur și simplu verificăm existența acesteia.</p> <hr> <h2>Ștergerea unei note</h2> <p>În a noastră <code>edit.erb</code> vizualizare, am adăugat o legătură "Ștergeți" la ceea ce este, în esență, calea <code>/: Id / șterge</code>. Adăugați aceasta în fișierul de aplicație:</p> <pre>primiți '/: id / delete' do @note = Note.get paramuri [: id] @title = "Confirmă ștergerea notei ## params [: id]" erb:</pre> <p>În această pagină vom primi confirmarea de la utilizator că ei vor să ștergă această notă. Creați fișierul de vizualizare la <code>vizualizari / delete.erb</code> cu urmatoarele:</p> <pre><% if @note %> <p>Sigur doriți să ștergeți următoarea notă: <em>"<%= @note.content %>"</em>?</p> <form action="/<%= @note.id %>"method =" post "> <input type="hidden" name="_method" value="delete"> <input type="submit" value="Yes, Delete It!"> „> Anulare </form> <% else %> <p>Notă nu a fost găsită.</p> <% end %></pre> <p>Rețineți că, la fel ca modul în care am falsificat o cerere PUT prin setarea unei ascunse <code>_metodă</code> câmpul de introducere, acum ne confruntăm cu o solicitare DELETE.</p> <hr> <h2>Traseul DELETE</h2> <p>Sunt sigură că mai ai de-a face cu asta. Ruta de ștergere este:</p> <pre>ștergeți '/: id' la n = Note.get params [: id] n.destroy redirect '/' sfârșit</pre> <p>Încearcă! Acum ar trebui să puteți vizualiza, adăuga, edita și elimina note. Mai este doar un lucru? </p> <hr> <h2>Marcarea unei note ca fiind "completă"</h2> <p>Chiar acum dacă doriți să setați o notă ca <code>complet</code> trebuie să accesați vizualizarea Editați și să bifați caseta din acea pagină. Să facem acest proces un pic mai simplu.</p> <p>Înapoi când am creat pagina de pornire principală, am inclus a <code>/: Id / complet</code> link pe fiecare notă. Să facem acum acel traseu, care va stabili pur și simplu o notă ca completă (sau incompletă dacă ar fi fost deja finalizată):</p> <pre>primi '/: id / completă' n n = Note.get params [: id] n.complete = n.complete? 0: 1 # flip it n.updated_at = Time.now n.save redirecționare '/' sfârșit</pre> <hr> <h2>Concluzie</h2> <p>Tu și Sinatra trageți un duet de crackin! Ați scris foarte repede o aplicație web simplă care efectuează toate operațiile CRUD pe care le-ați aștepta ca o aplicație să o facă. Este scris în codul Ruby de super-sexy și este separat în părțile sale logice.</p> <p>În ultima parte a Cântării cu Sinatra, Encore, vom îmbunătăți gestionarea erorilor, vom securiza aplicația din XSS și vom crea un flux RSS pentru note.</p> <p><strong>Notă:</strong> Puteți căuta fișierele finale de proiect pentru acest tutorial la GitHub.</p> <div class="rek-block"> <center> <ins class="adsbygoogle" style="display:inline-block;width:580px;height:400px" data-ad-client="ca-pub-3810161443300697" data-ad-slot="9434875811"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> </center> </div> <div class="h-alltags"> <a href="articles/code">Cod</a> </div> </div> </div> </div> </div> <div class="next_posts clearfix"> <div class="n_post"> <div class="next_posts-h1 left_nh1"><a href="/articles/code/singing-with-sinatra.html">Cântând cu Sinatra</a></div> <div class="next_posts-img" style="background-image: url('//accentsconagua.com/img/images_26_3/singing-with-sinatra.jpg');"></div> </div> <div class="n_post"> <div class="next_posts-h1 right_nh1"><a href="/articles/code/singing-with-sinatra-the-encore.html">Cântând cu Sinatra - The Encore</a></div> <div class="next_posts-img" style="background-image: url('//accentsconagua.com/img/images_26_3/singing-with-sinatra-the-encore.jpg');"></div> </div> </div> <footer> <div class="container"> <div class="footer-langs"> <ul class="site-langs-list"> <li><a href="https://www.accentsconagua.com"><i class="flag flag-DE"></i>Deutsch</a></li> <li><a href="https://fr.accentsconagua.com"><i class="flag flag-FR"></i>Français</a></li> <li><a href="https://nl.accentsconagua.com"><i class="flag flag-NL"></i>Nederlands</a></li> <li><a href="https://no.accentsconagua.com"><i class="flag flag-NO"></i>Norsk</a></li> <li><a href="https://sv.accentsconagua.com"><i class="flag flag-SE"></i>Svenska</a></li> <li><a href="https://it.accentsconagua.com"><i class="flag flag-IT"></i>Italiano</a></li> <li><a href="https://es.accentsconagua.com"><i class="flag flag-ES"></i>Español</a></li> <li><a href="https://ro.accentsconagua.com"><i class="flag flag-RO"></i>Românesc</a></li> </ul> </div> <div class="h-block"><a href="/">ro.accentsconagua.com</a><div class="h-block-a"></div></div> <div class="footer-text"> Informații interesante și sfaturi utile privind programarea. Dezvoltarea de site-uri, web design si dezvoltare web. Tutoriale Photoshop. Crearea de jocuri pe calculator și aplicații mobile. Deveniți un programator profesionist de la zero. </div> </div> </footer> <div class="search"> <img class="searchico" src="//accentsconagua.com/img/search.svg" alt=""> </div> <div class="modal"> <div class="modal-content"> <span class="close-button">×</span> <input class="searchmain" type="text" id="search-input" placeholder="Căutare..."> <ul class="searchli" id="results-container"></ul> </div> </div> <link rel="stylesheet" href="css/flags.css"> <link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.css" /> <script src="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.1.0/cookieconsent.min.js"></script> <script> window.addEventListener("load", function(){ window.cookieconsent.initialise({ "palette": { "popup": { "background": "#edeff5", "text": "#838391" }, "button": { "background": "#4b81e8" } }, "theme": "classic", "position": "bottom-right" })}); </script> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <script src="js/scripts.min.js"></script> <script src="js/common.js"></script> <link rel="stylesheet" href="css/fontawesome-all.min.css"> <script> var modal = document.querySelector(".modal"); var trigger = document.querySelector(".search"); var closeButton = document.querySelector(".close-button"); function toggleModal() { modal.classList.toggle("show-modal"); } function windowOnClick(event) { if (event.target === modal) { toggleModal(); } } trigger.addEventListener("click", toggleModal); closeButton.addEventListener("click", toggleModal); window.addEventListener("click", windowOnClick); </script> <script src="https://unpkg.com/simple-jekyll-search@1.5.0/dest/simple-jekyll-search.min.js"></script> <script> SimpleJekyllSearch({ searchInput: document.getElementById('search-input'), resultsContainer: document.getElementById('results-container'), json: '/search.json', searchResultTemplate: '<li><a href="{url}">{title}</a></li>' }) </script> <script src="jquery.unveil2.min.js"></script> <script> $('img').unveil(); </script> </body> </html>