Sang med Sinatra The Recall App

Velkommen til Track 2 of Singing med Sinatra. I del ett har vi gjennomgått ruter, hvordan å jobbe med URI-parametere, arbeider med skjemaer, og hvordan Sinatra skiller ruter med HTTP-metoden de ble forespurt av. I dag skal vi utvide vår kunnskap om Sinatra ved å bygge en liten database-drevet app, "Recall", for å ta notater / lage en gjøremålsliste.

Vi skal bruke en SQLite-database for å lagre notatene, og vi vil bruke DataMapper RubyGem til å kommunisere med databasen. Kjør følgende inne i et skall for å installere de relevante Gems:

perle installasjon sqlite3 datamapper dm-sqlite-adapter

Avhengig av hvordan du har RubyGems satt opp på systemet, må du kanskje prefiks perle installasjon med sudo.


The Warm-Up

La oss hoppe rett inn ved å opprette en ny katalog for prosjektet, og opprette applikasjonsfilen, recall.rb. Start det ved å kreve de relevante perlene:

krever 'rubygems' krever 'sinatra' krever 'datamapper'

Merk: Hvis du kjører Ruby 1.9 (som du burde være), kan du slippe "required" rubygems-linjen, da Ruby automatisk laster RubyGems uansett.

Og sett opp databasen med følgende:

DataMapper :: oppsett (: standard, "sqlite3: // # Dir.pwd /recall.db") klasse Ta med DataMapper :: Ressursegenskap: id, Seriell eiendom: innhold, Tekst,: required => sann eiendom: fullfør, boolsk,: required => true,: default => falsk egenskap: created_at, DateTime-egenskap: updated_at, DateTime-slutt DataMapper.finalize.auto_upgrade!

På den første linjen oppretter vi en ny SQLite3-database i gjeldende katalog, oppkalt recall.db. Nedenfor oppretter vi faktisk et notatbord i databasen.

Mens vi ringer klassen 'Notat', vil DataMapper opprette tabellen som 'Notater'. Dette er i tråd med en konvensjon som Ruby on Rails og andre rammer og ORM-moduler følger.

Inne i klassen setter vi opp databaseskjemaet. Tabellen 'Notater' har 5 felt. en id felt som vil være et heltall primærnøkkel og automatisk inkrementering (dette er hva seriell betyr). EN innhold felt som inneholder tekst, en boolsk fullstendig felt og to datetime felt, created_at og updated_at.

Den aller siste linjen instruerer DataMapper til å automatisk oppdatere databasen for å inneholde tabellene og feltene vi har angitt, og å gjøre det igjen hvis vi gjør noen endringer i skjemaet.


Hjemmesiden

La oss nå lage vår hjemmeside:

På toppen er et skjema for å legge til et nytt notat, og under er det alle notatene i databasen. For å komme i gang legger du til følgende i programfilen, recall.rb:

få '/' do @notes = Note.all: .order =>: id.desc @title = 'Alle notater' erb: hjemme ende

Viktig notat: Fjern prikken ('.') i :.rekkefølge. (WordPress forstyrrer kodesamplesen.)

På den andre linjen ser du hvordan vi henter alle notatene fra databasen. Hvis du har brukt ActiveRecord (ORM brukt i Rails) før, vil DataMapper syntaks føle seg veldig kjent. Notatene er tildelt til @notes instansvariabel. Det er viktig å bruke forekomstvariabler (det er variabler som begynner med en @) slik at de vil være tilgjengelige fra visningsfilen.

Vi satte @tittel instansvariabel, og last inn visninger / home.erb se fil gjennom ERB-parseren.

Opprett visninger / home.erb se fil og start den av med følgende:

<% # display notes %>

Vi har en enkel form som POSTer til hjemmesiden ('/'), og under det er noe ERB-kode som fungerer som plassholder for nå.


oppsett

HTML-standardpartiet blant dere kan ha lidd et mindre slag etter at vi har sett at vår hjemmevisefil inneholder ingen doktype eller andre HTML-koder. Vel, det er en grunn til det. Lage en layout.erb filen i din visninger / katalog som inneholder følgende:

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

Minnes

fordi du er for opptatt av å huske

<%= yield %>

En app for Nettuts+.

De to interessante delene her er linjer 5 og 18. På linje 5 ser du den første bruken av <%=? %> ERB-koder. <%= er forskjellig fra det vanlige <% som det skriver ut hva som er inni. Så her viser vi hva som er i @tittel instansvariabel etterfulgt av | Minnes for sidens </code> stikkord.</p> <p>På linje 18 er <code><%= yield %></code>. Sinatra vil vise dette <code>layout.erb</code> fil på alle ruter. Og det faktiske innholdet for den ruten vil bli satt inn hvor som helst <code>utbytte</code> er. <code>utbytte</code> er et begrep som i hovedsak betyr "Stopp her, sett inn hva som venter, fortsett deretter på".</p> <p>Start serveren med <code>shotgun recall.rb</code> i skallet, og ta en titt på hjemmesiden i nettleseren. Du bør se innhold fra layoutfilen, og skjemaet fra selve <code>home.erb</code> utsikt.</p> <img src="//accentsconagua.com/img/images_26_3/singing-with-sinatra-the-recall-app_2.png"> <hr> <h2>CSS</h2> <p>I layoutfilen inkluderte vi to CSS-filer. Sinatra kan laste statiske filer (f.eks. CSS, JS, bilder etc.) fra en navngitt mappe <code>offentlig/</code> i rotkatalogen. Så lag den katalogen, og inne i det to filer: <code>reset.css</code> og <code>style.css</code>. Tilbakestillingen inneholder tilbakestilling av HTML5 Boilerplate CSS:</p> <pre>/ * HTML5? Boilerplate style.css inneholder en tilbakestilling, font normalisering og noen basestiler. Kreditt er igjen hvor kreditt skyldes. mye inspirasjon ble tatt fra disse prosjektene: yui.yahooapis.com/2.8.1/build/base/base.css camendesign.com/design/ praegnanz.de/weblog/htmlcssjs-kickstart * / / * html5doctor.com Tilbakestill stilark ( Eric Meyer Reset Reloaded + HTML5 baseline) v1.6.1 2010-09-17 | Forfattere: Eric Meyer og Richard Clark html5doctor.com/html-5-reset-stylesheet/ * / html, kropp, div, span, objekt, iframe, h1, h2, h3, h4, h5, h6, p, blokk , abbr, adresse, sitere, kode, del, dfn, em, img, ins, kbd, q, samp, liten, sterk, sub, sup, var, b, jeg, dl, dt, dd, ol, ul, li Feltformat, Form, Etikett, Legende, Tabell, Tekst, Tbody, Tfoot, Thead, Tr, Th, td, artikkel, til side, lerret, detaljer, figcaption, figur, footer, header, hgroup, meny, nav, del, sammendrag , tid, markere, lyd, video margin: 0; padding: 0; kant: 0; font-size: 100%; skrifttype: arve; vertical-align: baseline; artikkel, til side, detaljer, figcaption, figur, footer, header, hgroup, meny, nav, del display: block; blockquote, q quotes: none; blockquote: før, blockquote: etter, q: før, q: etter innhold: "; innhold: ingen; inn bakgrunnsfarger: # ff9; farge: # 000; tekstdekorasjon: ingen; merk -farge: # ff9; farge: # 000; skrifttype-stil: kursiv; skrifttype-vekt: fet; del tekst-dekorasjon: linje igjennom; abbr [tittel], dfn [title] border-bottom: 1px punktert; markør: hjelp; tabell grensekollaps: kollaps; grenseavstand: 0; hr display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; input, velg vertical-align: middle; / * END RESET CSS * / / * font normalisering inspirert av fra YUI Library's fonts.css: developer.yahoo.com/yui/ * / body font : 13px / 1,231 sans-serif; * skriftstørrelse: liten; / * hack beholdt for å bevare spesifisitet * / velg, inntast, textarea, knapp font: 99% sans-serif; / * normaliser monospace dimensjonering * no. wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome * / pre, kode, kbd, samp font-familien: monospace, sans-serif; / * * minimal b ase stiler * / kropp, velg, skriv inn, textarea / * # 444 ser bedre ut enn svart: twitter.com/H_FJ/statuses/11800719859 * / color: # 444; / * angi basen font her, for å søke jevnt * / / * font-familie: Georgia, serif; * / / * overskrifter (h1, h2, etc) har ingen standard skriftstørrelse eller margin. definer dem selv. * / h1, h2, h3, h4, h5, h6 font-weight: bold; / * Tving alltid en rullefelt i ikke-IE: * / html overflow-y: scroll; / * tilgjengelig fokusbehandling: people.opera.com/patrickl/experiments/keyboard/test * / a: svever, a: aktiv disposisjon: ingen; a, a: aktiv, a: besøkt farge: # 607890; a: svever farge: # 036; ul, ol margin-left: 2em; ol liste-stil-type: desimal; / * Fjern marginer for navigasjonslister * / nav ul, nav li margin: 0; list-style: none; liste-stil-bilde: ingen; liten skriftstørrelse: 85%; sterk, th font-weight: bold; td vertikaljustering: topp; / * sett under, sup uten å påvirke linjehøyde: gist.github.com/413930 * / sub, sup font-size: 75%; linjehøyde: 0; stilling: relativ; sup topp: -0.5em; sub bunn: -0.25em; pre / * www.pathf.com/blogs/2008/05/formatting-quoted-code-in-blog-posts-css21-white-space-pre-wrap/ * / white-space: pre; hvitrom: pre-wrap; hvitrom: pre-line; ord-wrap: break-word; polstring: 15px; textarea overflow: auto; / * www.sitepoint.com/blogs/2010/08/20/ie-remove-textarea-scrollbars/ * / .ie6 legend, .ie7 legend margin-left: -7px; / * thnx ivannikolic! * / / * juster avkrysningsbokser, radioer, tekstinnganger med deres etikett av: Thierry Koblentz tjkdesign.com/ez-css/css/base.css * / input [type = "radio"] vertikaljustering: tekstbunn; input [type = "avkrysningsboks"] vertikaljustering: bunn; .ie7 input [type = "avkrysningsboks"] vertikaljustering: basislinje; .6 inngang vertikaljustering: tekstbunn; / * hånd markør på klikkbare inngangselementer * / label, input [type = "knapp"], input [type = "submit"], input [type = "bilde"], knapp markør: pointer; / * webkit-nettlesere legger til en 2px-margin utenfor krom av formelementer * / knapp, input, velg tekstarea margin: 0; / * farger for form validitet * / input: gyldig, textarea: gyldig input: ugyldig, textarea: ugyldig grense-radius: 1px; -moz-box-shadow: 0px 0px 5px rød; -webkit-boks-skygge: 0px 0px 5px rød; boks-skygge: 0px 0px 5px rød; .no-boxshadow input: ugyldig, .no-boxshadow textarea: ugyldig bakgrunnsfarge: # f0dddd; / * Disse valgdeklarasjonene må være separate. Ingen tekstskygge: twitter.com/miketaylr/status/12228805301 Også: hot pink. * / :: - moz-valg bakgrunn: # FF5E99; farge: #fff; tekstskygge: ingen; :: valg bakgrunn: # FF5E99; farge: #fff; tekstskygge: ingen; / * j.mp/webkit-tap-highlight-color * / a: link -webkit-tap-highlight-color: # FF5E99; / * Gjør knapper bra i IE: www.viget.com/inspire/styling-the-button-element-in-internet-explorer/ * / button width: auto; overløp: synlig; / * bikubisk resizing for ikke-innfødte IMG: code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ * / .ie7 img -ms-interpolation-modus: bicubic; </pre> <p>Og <code>style.css</code> inneholder noen grunnleggende styling for å få appen til å se pen ut:</p> <pre>kropp margin: 35px auto; bredde: 640px; header text-align: center; margin: 0 0 20px; header h1 display: inline; skriftstørrelse: 32px; header h1 a: link, header h1 a: besøkt farge: # 444; tekst-dekorasjon: ingen; header h2 font-size: 16px; font-style: kursiv; farge: # 999; #main margin: 0 0 20px; #add margin: 0 0 20px; #add textarea høyde: 30px; bredde: 510px; polstring: 10px; grense: 1px solid #ddd; # legg inn høyde: 50px; bredde: 100px; margin: -50px 0 0; grense: 1px solid #ddd; bakgrunn: hvit; #edit textarea høyde: 30px; bredde: 480px; polstring: 10px; grense: 1px solid #ddd; #edit input [type = submit] høyde: 50px; bredde: 100px; margin: -50px 0 0; grense: 1px solid #ddd; bakgrunn: hvit; #edit input [type = avkrysningsboks] høyde: 50px; bredde: 20px; artikkel grense: 1px solid #eee; border-top: none; polstring: 15px 10px; artikkel: first-of-type border: 1px solid #eee; artikkel: nth-barn (jevn) bakgrunn: #fafafa; article.complete bakgrunn: # fedae3; artikkelstreng font-size: 0.8em; p margin: 0 0 5px; .meta font-size: 0.8em; font-style: kursiv; farge: # 888; .links font-size: 1.8em; linjehøyde: 0.8em; flyte: høyre; margin: -10px 0 0; .links en display: block; tekst-dekorasjon: ingen; </pre> <p>Oppdater siden i nettleseren din, og alt skal være mer stilert. Ikke bekymre deg for dette CSS for mye; det bare gjør ting ser litt finere ut!</p> <img src="//accentsconagua.com/img/images_26_3/singing-with-sinatra-the-recall-app_3.png"> <hr> <h2>Legge til en notat i databasen</h2> <p>Akkurat nå hvis du prøver å sende inn skjemaet på hjemmesiden, kommer du til å få en rutefeil. La oss lage POST-ruten for hjemmesiden nå:</p> <pre>post '/' gjør n = Note.new n.content = params [: innhold] n.created_at = Time.now n.updated_at = Time.now n.save omadressering '/' ende</pre> <p>Så når en postforespørsel blir gjort på hjemmesiden, oppretter vi et nytt Objekt-objekt i <code>n</code> (takket være DataMapper ORM, <code>Note.new</code> representerer en ny rad i <code>notater</code> tabell i databasen). De <code>innhold</code> feltet er satt til de innsendte dataene fra textarea og <code>created_at</code> og <code>updated_at</code> datetime felt er satt til gjeldende tidsstempel.</p> <p>Det nye notatet lagres deretter, og brukeren viderekobles tilbake til hjemmesiden der det nye notatet vil bli vist.</p> <hr> <h2>Viser notatene</h2> <p>Så vi har lagt til et nytt notat, men vi kan ikke se det på hjemmesiden ennå, siden vi ikke har skrevet koden for den. Inne i <code>visninger / home.erb</code> vis fil, erstatt <code><%# display notes %></code> linje med:</p> <pre><% @notes.each do |note| %> <article <%= 'class="complete"' if note.complete %>> <p> <%= note.content %> <span>"> [Rediger]</span> </p> <p> / Komplett ">? </p> <p>laget: <%= note.created_at %></p> </article> <% end %></pre> <p>På første linje begynner vi en løkke gjennom hver av <code>@notes</code> (Alternativt kunne vi ha skrevet <code>for notat i @notes</code>, men å bruke en blokk, som vi er her, er en bedre praksis). På linje 2, gir vi <code><article></code> en klasse av <code>fullstendig</code> hvis nåværende notat er satt til <code>fullstendig</code>. Resten skal være ganske rett frem.</p> <hr> <h2>Redigerer en notat</h2> <p>Så vi kan legge til og vise notater. Nå trenger vi bare muligheten til å redigere og slette dem.</p> <p>Du har kanskje lagt merke til det i vår <code>home.erb</code> se vi satt en <code>[redigere]</code> lenke for hvert notat til det som egentlig er <code>/: Id</code>, så la oss lage den ruten nå:</p> <pre>få '/: id' do @note = Note.get params [: id] @title = "Rediger notat ## params [: id]" erb: rediger slutt</pre> <p>Vi henter det forespurte notatet fra databasen ved hjelp av den oppgitte IDen, sett opp en <code>@tittel</code> variabel, og last inn <code>visninger / edit.erb</code> se fil gjennom ERB-parseren.</p> <p>Skriv inn følgende for <code>visninger / edit.erb</code> utsikt:</p> <pre><% if @note %> <form action="/<%= @note.id %>"metode =" 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>/ Delete "> Slett</p> <% else %> <p>Merk ikke funnet.</p> <% end %></pre> <p>Dette er en ganske enkel visning. Et skjema som peker tilbake til gjeldende side, en tekstarea som inneholder innholdet i notatet og en avkrysningsboks som blir sjekket hvis notatet er satt til <code>fullstendig</code>.</p> <p>Men se på den tredje linjen. Mystisk. For å forklare dette, trenger vi å spore litt.</p> <h3>RESTful tjenester</h3> <p>Du har hørt om de to begrepene GET og POST.</p> <ul> <li> <strong>FÅ: </strong>Den vanligste. Det er vanligvis for å be om en side, og kan bokmerkes.</li> <li> <strong>POST: </strong> Brukes til å sende inn data og kan ikke bokmerkes.</li> </ul> <p>Men GET og POST er ikke de eneste "HTTP-verbene" - det er to flere du bør vite om: PUT og DELETE.</p> <p>Teknisk sett bør POST bare brukes til å skape noe - for eksempel å lage en ny kommentar i din fantastiske nye webapp, for eksempel.</p> <p>PUT er verbet for å endre noe. Og SLETT, du gjettet det, er for å slette noe.</p> <p>Å ha disse fire verbene er en fin måte å skille en app opp. Det er logisk. Dessverre støtter nettlesere ikke faktisk PUT eller DELETE forespørsler, og derfor har du sannsynligvis aldri hørt om dem før.</p> <p>Så, å komme tilbake på sporet her, hvis vi vil logisk dele opp appen vår (som Sinatra oppfordrer), må vi fake disse PUT og SLETT forespørsler. Du ser vårt skjema <code>handling</code> er satt til <code>post</code>. Den gjemte <code>_metode</code> inputfelt som vi har satt til <code>sette</code> På den tredje linjen lar Sinatra falle denne PUT-forespørselen, mens den faktisk bruker en POST. Rails, blant annet rammer, gjør ting på samme måte.</p> <hr> <h2>La oss sette</h2> <p>Nå har vi faked vår PUT-forespørsel, vi kan lage en rute for det:</p> <pre>sett '/: id' gjør n = Note.get params [: id] n.content = params [: innhold] n.complete = params [: fullført]? 1: 0 n.updated_at = Time.now n.save omadressering '/' slutt</pre> <p>Det er alt ganske enkelt. Vi får det relevante notatet ved hjelp av ID-en i URI, angi feltene til de nye verdiene, lagre og viderekoble hjemmet. Legg merke til hvordan på den fjerde linjen bruker vi en ternær operatør til å sette <code>n.complete</code> til <code>1</code> hvis <code>parametere [: komplett]</code> eksisterer, eller <code>0</code> ellers. Dette skyldes at verdien av en avkrysningsboks kun sendes inn med et skjema hvis det er sjekket, så vi bare sjekker for eksistensen av det.</p> <hr> <h2>Slette en notat</h2> <p>I vår <code>edit.erb</code> se, vi la til en "Slett" -kobling til det som egentlig er banen <code>/: Id / slette</code>. Legg dette til din søknadsfil:</p> <pre>få '/: id / delete' gjør @note = Note.get params [: id] @title = "Bekreft sletting av notat ## params [: id]" erb: slett slutt</pre> <p>På denne siden får vi bekreftelse fra brukeren at de faktisk vil slette dette notatet. Opprett visningsfilen på <code>visninger / delete.erb</code> med følgende:</p> <pre><% if @note %> <p>Er du sikker på at du vil slette følgende notat: <em>"<%= @note.content %>"</em>?</p> <form action="/<%= @note.id %>"metode =" post "> <input type="hidden" name="_method" value="delete"> <input type="submit" value="Yes, Delete It!"> "> Avbryt </form> <% else %> <p>Merk ikke funnet.</p> <% end %></pre> <p>Legg merke til at akkurat som hvordan vi fakket en PUT-forespørsel ved å sette en skjult <code>_metode</code> inntastingsfelt, feiler vi nå en DELETE forespørsel.</p> <hr> <h2>DELETE ruten</h2> <p>Jeg er sikker på at du får tak i dette nå. Slett ruten er:</p> <pre>slett '/: id' gjør n = Note.get params [: id] n.destroy viderekobling '/' slutt</pre> <p>Prøv det! Du bør nå kunne se, legge til, redigere og fjerne notater. Det er bare en ting til? </p> <hr> <h2>Merking av en kommentar som "fullført"</h2> <p>Akkurat nå hvis du vil sette et notat som <code>fullstendig</code> du må gå inn i redigeringsvisningen og merk av i boksen på den siden. La oss gjøre prosessen litt enklere.</p> <p>Tilbake da vi opprettet hovedsiden, inkluderte vi en <code>/: Id / komplett</code> lenke på hver notat. La oss lage den ruten nå, som bare vil sette et notat som komplett (eller ufullstendig hvis det allerede var satt til å fullføre):</p> <pre>få '/: id / complete' gjør n = Note.get params [: id] n.complete = n.complete? 0: 1 # flip it n.updated_at = Time.now n.save omadressering '/' slutt</pre> <hr> <h2>Konklusjon</h2> <p>Du og Sinatra trekker av en crackin 'duet! Du har veldig raskt skrevet en enkel webapp som utfører alle CRUD-operasjonene du forventer en app å gjøre. Den er skrevet i super-sexy-ren Ruby-kode, og er skilt i sine logiske deler.</p> <p>I den siste delen av Singing med Sinatra, Encore, forbedrer vi feilhåndtering, sikrer appen fra XSS og lager et RSS-feed for notatene..</p> <p><strong>Merk:</strong> Du kan bla gjennom de endelige prosjektfilene for denne opplæringen på 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">Kode</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">Sang med 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">Sang med 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="/">no.accentsconagua.com</a><div class="h-block-a"></div></div> <div class="footer-text"> Interessant informasjon og nyttige tips om programmering. Nettstedutvikling, webdesign og webutvikling. Photoshop opplæringsprogrammer. Opprettelse av dataspill og mobile applikasjoner. Bli en profesjonell programmerer fra grunnen av. </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="Søke..."> <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>