Med HTML5 og CSS3 fikk nettlesere en rekke fantastiske teknologier: 3D-grafikk , stikkontakter, tråder og mer. Med disse kan webapplikasjoner utnytte noen av de mest sofistikerte egenskapene til datamaskiner og operativsystemer de brukes på. Nettleseren tilbyr en robust allsidig økosystem for applikasjonsutvikling, noe som fremgår av den nylige økningen av mange kraftige webapplikasjoner som vi ikke kan leve uten. Noe som fortsatt mangler er skjønnheten i HTML-tekstkommentarer og dekorasjon. Hva er tekstdekorasjon? Squiggly understreker, robuste høydepunkter og bølgete streik er noen av tingene som nettlesere ikke gir innfødt støtte til. Dette kan høres mer forseggjort ut enn nyttig, men muligheten for JavaScript-utviklere å produsere disse stilene kan vise seg å være nyttige i aspekter som e-læringsressurser og nettbaserte eboklesere. Videre kan dette bidra til å forbedre brukeropplevelsen i webapplikasjoner som dreier seg om naturlige designprinsipper. I det minste er det morsomt å bygge et slikt verktøy og gir innsikt i de mange særegenheter i en nettleser.
Utviklere har funnet mange løsninger på begrensningen av nettleseren. Mange av disse løsningene innebærer bruk av CSS på mindre intuitive måter, da noen bruker bilder i ':: etter' pseudoelementene. Dette fungerer, men det er ofte vanskelig å opprettholde mange bilder for hvert stil-fargepar. Denne artikkelen tar en titt på anatomien til et JavaScript-bibliotek som prøver å løse dette problemet elegant.
Biblioteket er åpen kildekode, og er tilgjengelig på GitHub: Tekstkommentar
Under utviklingen av dette biblioteket ble det lagt særlig vekt på å sikre kompatibilitet med de mest populære nettleserne (inkludert IE 9+). Imidlertid, i motsetning til hvordan de fleste løser dette problemet, stoler ikke biblioteket på spesifikt obskure CSS-triks; eller verre, spesiell Unicode-symboler . I stedet bruker den SVG for å oppnå mye bedre, renere tekstdekorasjoner.
I utgangspunktet implementerer biblioteket en 'klasse' for kommentator som kan brukes til automatisk å lage DIV-elementer, plassere dem under tekster som skal kommenteres, og fylle bakgrunnen med SVG-bilder. Flere DIV kan kombineres for å tilpasse dekorasjonene ytterligere. Tilnærmingen er kompatibel med flere nettlesere, gir fleksibilitet i forhold til plassering av dekorative elementer, og tillater enklere utvidelse med tilpassede maler.
Biblioteket er utviklet ved hjelp av Google Closure Tools fordi det er modulært og kryssleser, noe som hjelper til med å produsere kompakt og rask JavaScript-kode uten ekstra avhengighet.
Biblioteket er designet som en samling av JavaScript-'klasser', og eksponerer alle nødvendige funksjoner for brukeren gjennom 'klasse' -kommentaren:
Her er en kort oversikt over tilgjengelige funksjoner:
annotateDocument - kommenterer elementer som er merket med en 'data-merknad' attributt.
understrek - understreker element
highlight - highlights element
streik - slår element
underlineSelected - understreker valgt tekst
highlightSelected - markerer valgt tekst
strikeSelected - treffer valgt tekst
unannotateElement - fjerner merknader fra element
getTemplates - returnerer ordbok med merkemaler
setUnderlineOptions - angir innstillinger for understreket kommentator
setHighlightOptions - angir innstillinger for markeringsnotatøren
setStrikeOptions - angir innstillinger for streikannotator
Annotatorklassen har tre forekomster av AnnotatorImpl-klassen for hver kommentarfunksjon: understrek, fremhev og streik.
tvs.Annotator = function() { this.underliner_ = new tvs.AnnotatorImpl( 'underliner', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.underlinePositioner); this.highlighter_ = new tvs.AnnotatorImpl( 'highlighter', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.highlightPositioner, {opacity: 0.45}); this.striker_ = new tvs.AnnotatorImpl( 'striker', tvs.Annotator.getTemplates(), tvs.AnnotatorCore.strikePositioner); };
AnnotatorImpl-forekomster opprettes med forskjellige ID-er og posisjonshjelperobjekter. Bestått ID blir brukt senere i CSS-klassenavn og interne feltnavn, noe som krever at ID-er er unike. Også en referanse til en liste over kjente maler sendes (kan endres senere).
Hvert posisjonsobjekt er en implementering av IPposisjonsgrensesnitt som kun har 'getPosition' -metoden og ser ut som følger:
/** * Underline positioner * @implements {tvs.IPositioner} */ tvs.AnnotatorCore.underlinePositioner = /** @type {!tvs.IPositioner} */ ({ /** * @param {Object} elementRect * @param {number} annotationHeight * @return {{left: number, top: number, width: number, height: number}} */ getPosition: function(elementRect, annotationHeight) { return { width: elementRect.width, height: annotationHeight, left: elementRect.left, top: elementRect.bottom - (elementRect.height * 0.1) }; } });
Dette gjør at hver mal kan brukes med understreking, utheving eller markering av tekst. Når en kommentar blir brukt på et element, får du begrensningsboksen for elementet ved å kalle 'getElementRects' som vist nedenfor:
var rects = elemOrEv.getClientRects();
Denne metoden returnerer en samling rektangler som indikerer avgrensningsrektanglene for hver boks i en klient. Etter å ha passert hver rekt til betongposisjoner, får vi destinasjonsgrenser.
Som nevnt tidligere, er det bare ett sett med maler som brukes til alle slags SVG-tekstkommentarer. Hver mal består av maldeler. En maldel er en enhet som representerer delens innhold, malbredde og tegningsmodus.
Innhold er et sett med SVG-elementer representert som en streng. Siden dette innholdet ikke har en rot-SVG-node der visningsportens bredde og høyde (i piksler) er angitt, godtar malens delkonstruktør dem som parametere. Du kan for eksempel spesifisere størrelsen på en visningsport som 100px x 100px og tegne en linje til (50, 50) og (25, 25). Etter at merknaden er brukt, vil alle svg-elementene bli riktig størrelse til ønsket størrelse. Innholdsverdien kan bruke strengen “{0}” som erstattes med fargen valgt av brukeren.
Følgende SVG gjengir en diagonal linje. Vi bruker dette som en av delene i et eksempel på en kommentarstil som snart følger:
var t = new tvs.Template(new tvs.SvgTemplatePart( '' + '', 20, 20, 'repeat' ))
Malbredde er en streng som kan være “*”, “høyde” eller noe annet:
“*” Angir bredden på alle elementene med en stjerne som er lik hverandre
“Høyde” angir bredden som er lik høyden på merkelementet
Alt annet som er angitt her, blir direkte satt til CSS bredde og min breddeegenskaper.
Tegnemodus er en streng som kan være enten 'gjenta' eller 'strekke'. Som verdiene indikerer, gjentar du innholdet mens du setter det til “gjenta”, mens innstillingen strekkes på “strekk”.
Her er et eksempel på hva vi kan oppnå ved å konfigurere disse tre parametrene:
Tekstkommentarene i eksemplet ovenfor inneholder fire deler. Den første delen er den diagonale linjen, med malbredden satt til 'høyde' og tegningsmodus satt til 'gjenta'. Den andre delen har malbredden satt til “*” og tegningsmodus satt til “gjenta”. Den tredje delen er satt til '15px' bred og tegnes i 'gjenta' -modus. Til slutt er den siste delens bredde satt til '*' og tegningsmodus er satt til 'strekk'.
Når disse breddene blir evaluert, tar den første delen 5 piksler (lik høyden på merkelementet), den tredje delen tar 15 piksler (som sett), og den gjenværende plassen er likt delt mellom andre og fjerde del.
Når den samme teksten er uthevet ved hjelp av samme mal, får vi dette:
Som du kan se er høyden på merkelementet større, og det samme er bredden på den første delen (siden malbredden for den delen er satt til 'høyde'). Naturligvis forble tredjedelens bredde uendret fra forrige eksempel.
Å bruke en streik-effekt på den samme teksten med samme mal gir et resultat som ligner på det første. Den eneste forskjellen er plasseringen der merkelementene er plassert:
Selv om disse tekstkommentarene virker komplekse (slik de ser ut, med fire forskjellige deler), bruker de alle veldig enkle SVG-elementer. Som et ekstra eksempel krever det å gjøre en squiggly linje en enkelt del, med følgende enkle SVG-innhold:
tvs.AnnotatorDictionary.svgTemplates['brush'] = new tvs.Template(new tvs.SvgTemplatePart( svgContent, 50, 50, '*', 'stretch' ));
Når disse malene evalueres, endres størrelsen på innholdet og '{0}' erstattes automatisk med den angitte fargen. Enda mer, å legge til nye maler er så enkelt som å legge dem til et JavaScript-objekt:
Hver kommentar brukes ved å legge til et div-element med absolutt posisjonering på siden:
tvs.SvgTemplatePart.prototype.getBackground = function(color) { var image = tvs.AnnotatorCore.formatString(this.content, [color]); var encodedSVG = goog.crypt.base64.encodeString(image); return 'data:image/svg+xml;base64,' + encodedSVG; };
Div-elementet er fylt ut med en tabell der hver celle som legges til tilsvarer en av delene i malen. Innholdet i hver maldel er lagt til som Base64-kodet data URI, med valgt farge brukt:
var annotator = new tvs.Annotator(); annotator.underlineSelected();
For en bedre brukeropplevelse, spesielt når du prøver å bruke dette JavaScript-biblioteket med redigerbare innholdsområder, er det viktig for tekstkommentatoren å kjenne til grensene for tekst som brukeren for øyeblikket velger. Rangy , et pent JavaScript-bibliotek som omhandler rekkevidde og utvalg, har blitt brukt for å oppnå dette på tvers av nettlesere. Rangy tilbyr et enkelt standardbasert API for å utføre vanlige DOM Range og Selection-oppgaver i alle store nettlesere, og trekker bort de veldig forskjellige implementeringene av denne funksjonaliteten mellom Internet Explorer og opp til DOM-kompatible nettlesere. Det er den eneste avhengigheten av prosjektet.
Når Text Annotator er innebygd, er det veldig enkelt å bruke det:
annotator.unannotateElement(annotatedElement);
Hvert kommenterte element er merket med 'tv-merket-tekst' -klassen, og hvert merkelement har klassen 'tv-merknad-element'. Det er enda enklere å fjerne merknader, en enkel linje:
tvs.AnnotatorImpl = function(id, templates, positioner, options) { // ... this.throttle = new goog.Throttle(goog.bind(this.refreshAllAnnotations, this), 50); tvs.AnnotatorCore.registerForWindowResize( this.id,goog.bind(this.throttle.fire, this.throttle)); }; tvs.AnnotatorImpl.prototype.refreshAllAnnotations = function() { var elems = goog.dom.getElementsByClass(this.getCssClassForAnnotated()); var refFunc = goog.bind(this.refreshAnnotation, this); goog.array.forEach(elems, refFunc); };
Når størrelsen på vinduet er endret, kan det hende at elementene beveger seg rundt, og at de merkede elementene må 'oppdateres'. Dette håndteres av biblioteket. Men; For å redusere påvirkningen på ytelsen, blir oppfordringen til forfriskende kommentarer kommentert:
data-annotate='underline squiggly green'
Ved oppdatering kan merkelementer legges til, endres eller fjernes fra siden etter behov.
For å gjøre det lettere å kommentere statisk tekst på en side, er en enkel dataattributt på containerelementet alt du trenger:
|_+_|
Dette vil kommentere innholdet i elementet med en skikkelig grønn understreking.
Hva mer kan jeg si om denne SVG-tekstopplæringen? Et morsomt, men kraftig verktøy er enkelt implementert. Jeg tror ikke vi vil ha stor nytte av å sikre støtte for Internet Explorer 8, da vi i stedet kan ende opp med å komplisere hele implementeringen. Men med noen forbedringer og litt arbeid i kjernen, kan vi utvide biblioteket for å kunne produsere dekorative grenser for ikke-tekstlige elementer. Videre kan det være en interessant oppgave å implementere en mekanisme for å lagre og senere gjenopprette tilstanden til en kommentars redigerbare innhold.
Foreløpig er mulighetene bare begrenset av fantasien din (og nettleserfunksjonene). Kanskje du vil ha mikroavtrykkstreker, eller graderinger, eller til og med animasjoner. Med Tekstkommentar , du kan.