Opprett et redigeringssystem på stedet

Å gjøre brukere klikke gjennom flere sider bare for å redigere et felt er så 1999. I denne opplæringen lærer du hvordan du oppretter et redigeringssystem på stedet som finnes på populære nettsteder, for eksempel Flickr.


Et ord fra forfatteren

Med all buzz rundt Web 2.0 er brukervennlighet nå mye viktigere enn noensinne. Å kunne redigere noe innhold uten å måtte gå til en annen side, er noe mange brukere virkelig ønsker. Mange store navn bruker allerede dette mønsteret til stor effekt. Hvis du har brukt Flickr, har du sannsynligvis sett dette i aksjon.

Jeg tror en demo er verdt tusen ord. Hit demoen og prøv det selv.

I dag skal vi se på hvordan du implementerer dette med, du gjettet det riktig, vårt favoritt JavaScript-bibliotek, jQuery. Interessert? La oss komme i gang med en gang!

Designmål

Før vi begynner å se på hvordan å implementere funksjonaliteten, er det noen tanker om målene og de resulterende beslutningene.

  • Vi må la brukeren redigere innholdet uten å forlate siden. Dette er en gitt.
  • Dette bør enten fungere som helhet eller mislykkes som helhet. Når JS er deaktivert, ønsker vi ikke å løpe inn i rare quirks.
  • Brukeren bør vite at innholdet kan redigeres. En subtil blå bakgrunnsendring bør trekke brukerens oppmerksomhet til dette.
  • Når du arbeider med hvordan du utløser redigeringen, er det noen alternativer. Vi kan enten la brukeren redigere på normalt klikk eller dobbeltklikk. Jeg har valgt dobbeltklikk siden tilfeldige dobbeltklikk forekommer i mindre grad enn tilfeldige klikk. Bytte det handler bare om å endre parameteren i bindingshendelsen.
  • En måte for brukeren å lagre eller kaste bort endringene.
  • Lagre eller redigere hendelser kan utløses på to måter. Tastatur hendelser eller mus hendelser. Jeg valgte mus hendelser siden tastatur hendelser mangler spesifisitet.
  • Med hensyn til mus hendelser, kan du bruke enten tradisjonelle knapper eller vanlige lenker. Jeg valgte koblinger uten spesiell grunn.
  • Brukeren skal kunne gjenoppta redigering, selv om han klikker utenfor inngangsruten eller forlater siden og kommer tilbake.
  • I tillegg skal brukeren kunne redigere så mange felt som mulig samtidig.

Nå som vi har kartlagt våre behov, kan vi nå gå videre til hvordan vi skal gjøre dette.

Handlingsplan

Vi må nå kartlegge hva som må gjøres i en bestemt rekkefølge.

Trinn 1: Vi må legge til en klasse av redigerbar til hvert element som trenger denne funksjonaliteten.

Steg 2: Vi må neste gang legge til hovers til hvert redigerbart element for å gjøre oppmerksom på at innholdet i innholdet er redigerbart. Vi legger til og fjerner svømmerne ved hjelp av JavaScript i stedet for CSS. Dette gjøres hovedsakelig for enheter eller nettlesere med JavaScript deaktivert. Vi ønsker ikke å sende dem feil visuelle tegn.

Trinn 3: Når et redigerbart element dobbeltklikkes, må vi bytte ut innholdet og erstatte det med en tekstboks med den gamle teksten i den.

Trinn 4a: Når brukeren vil lagre endringene, kopierer du inntastens verdi til overordnet elementet og fjerner inntastingsboksen.

Trinn 4b: Eller når brukeren vil forkaste endringene, erstatt det gamle innholdet og fjern inntastingsboksen.

Dette er de grunnleggende trinnene i å skape denne funksjonaliteten. Selvfølgelig er det få andre små ting, men jeg skal forklare dem når vi går.

Core Markup

HTML-oppslaget på demo-siden ser ut som det.

    In-place redigeringssystem - av Siddharth for NetTuts      

In-place redigering

av Siddharth for de nydelige folkene på Net Tuts

Elementer med en klasse av redigerbar er, vel, redigerbar. Hvis du ikke har lagt merke til, alle elementer som inneholder redigerbar klassen får en blå bakgrunn på hover for å indikere denne evnen.

Dobbeltklikk for å redigere innholdet. Bruk de dynamisk opprettede koblingene for å lagre eller kaste bort endringene. Du kan åpne så mange felt for å redigere som du vil uten noen hikke.

Jeg

  • er Siddharth
  • elsker å jobbe med nettet
  • er en frilanser
  • skriv for Net Tuts
  • kan bli funnet på www.ssiddharth.com
  • vil aldri la deg ned eller gi deg opp :)

Ting å gjøre denne uken

  • Få design godkjenning fra Deacon
  • Send en faktura til Albert
  • Start arbeidet med Dwights prosjekt
  • Snakk med Sara om nye ideer
  • Sjekk Seths nettsted for gjengivelse av feil
  • Møt med Clintson for å diskutere prosjektet

Som du ser, ignorerer kjeleplaten, har vi to uordnede lister. Hver li elementet har en klasse av redigerbar å betegne at innholdet kan redigeres.

Vi har også inkludert jQuery-biblioteket og vår egen skriptfil.

CSS Styling

 kropp font-family: "Lucida Grande", "Verdana", sans-serif; skriftstørrelse: 12px;  en farge: # 000;  a: svever tekst-dekorasjon: ingen;  p margin: 30px 0 10px 0;  h1 skriftstørrelse: 30px; polstring: 0; margin: 0;  h2 font-size: 20px;  #container width: 820px; margin-left: auto; margin-høyre: auto; polstring: 50px 0 0 0;  .editHover background-color: # E8F3FF;  .editBox width: 326px; Min høyde: 20px; polstring: 10px 15px; bakgrunnsfarge: #fff; grense: 2px solid # E8F3FF;  ul listestil: none;  li bredde: 330px; Min høyde: 20px; polstring: 10px 15px; margin: 5px;  li.noPad padding: 0; bredde: 360px;  skjema bredde: 100%;  .btnSave, .btnCancel polstring: 6px 30px 6px 75px;  .block float: left; margin: 20px 0; 

Ikke noe spesielt her. Bare en haug med kode for layout og styling.

Vær spesielt oppmerksom på editHover og noPad klasser. Vi bruker dem litt.

JavaScript-implementering

Nå som vi har et solid rammeverk og noen grunnleggende styling på plass, kan vi begynne å kode opp den nødvendige funksjonaliteten. Legg merke til at vi utnytter jQuery mye. Spesielt trenger vi minst versjon 1.3 eller høyere. Noe mindre og det vil ikke fungere.

Legge til svømmer

Som nevnt tidligere, må vi legge til en subtil blå bakgrunn til redigerbare objekter for å indikere at de kan redigeres. Vi har allerede opprettet editHover klasse for å ta vare på dette.

 $ ("redigerbar"). hover (funksjon () $ (dette) .addClass ("editHover");, funksjon () $ (dette) .removeClass ("editHover"););

Denne lille brikken tar vare på det for oss. Vi bruker jQuery's sveve metode for å legge til editHover klasse når elementet er svevet på og fjern det når det ikke er det. Vi bruker dette å referere til det spesifikke elementet som er svevet over. Hvis vi hadde brukt .redigerbar Som selgeren i stedet vil hvert element få klassen lagt til den. Så vi bruker dette å målrette bare elementet vi trenger.

Bytte ut elementene

Først må vi sørge for at vår kode blir utført når målelementet er dobbeltklikket. Så vi hekker først handleren for denne hendelsen først.

 $ ("redigerbar"). bind ("dblclick", replaceHTML);

Vi legger til replaceHTML funksjon til Dobbeltklikk hendelsen i forhold til redigerbar element med den ene liner. Nå kan vi fortsette å bytte ut elementene.

 funksjon erstatteHTML () oldText = $ (dette) .html () .replace (/ "/ g," ""); $ (dette) .html ("") .html ("
Lagre endringer Kast bort endringer ");

La oss gå over kodebiten vår med liten bit.

Jeg definerer funksjonaliteten i en egen navngitt funksjon i stedet for en anonym funksjon av en bestemt grunn: Jeg bruker denne funksjonen mer enn en gang. Deretter lagrer vi innholdet i elementet til fremtidig bruk ved hjelp av jQuery's html metode og erstatte alle sitater siden det knuser opp vår produksjon nedover linjen.

Nå som innholdet vårt er trygt lagret for senere bruk, kan vi bytte ut elementene. Først tømmer vi ut li element ved å sende inn en tom streng til html metode. Deretter legger vi inn standard HTML for en innmatingsboks. Vi legger til noen klasser til det for styling. Enda viktigere, vi satte det verdi Tilordne den opprinnelige teksten som inneholder elementet som er lagret i oldText. Vi legger også til et par koblinger for å ta vare på å lagre og kaste bort endringene. Vi har også lagt klasser til dem slik at de kan målrettes enkelt og for styling.

Som alltid bruker vi dette å målrette elementet som utløste hendelsen.

Holde redigeringene

 $ (".btnSave"). live ("klikk", funksjon () newText = $ (dette) .siblings ("form") .children (".BoxBox") .val (). erstatte (/ "/ g , "" "); $ (dette) .parent () .html (newText););

Først opp, la meg introdusere jQuery's bo metode. Du har sikkert ikke sett så mye før, så jeg gir en rask introduksjon.

Du kan ikke koble håndtere til hendelser utløst av elementer som ikke engang er til stede i DOM når siden og JavaScript ble lastet. Hvis du bruker normale hendelsesbindende funksjoner, vil det mislykkes på grunn av den ovennevnte grunnen. De bo Metoden tar seg av det.

Det binder håndtere til hendelser uavhengig av når elementet ble opprettet. For mer om dette, kan du gå gjennom de offisielle dokumentene.

Lar oss se på koden vår nå. Vi binder først koden i vår anonyme funksjon til klikk begivenhet. Innenfor funksjonen lagrer vi først teksten i innboksboksen. Dette kan være litt vanskelig fordi inntastingsboksen ikke har en ID. Så vi ser først etter formelementet som skjer for å være søsken og deretter krysse gjennom for å finne inngangselementet. Vi kopierer deretter verdien sin etter å ha erstattet alle sitatene det kan inneholde.

Deretter får vi koblingene foreldreelementet, li element og erstatt HTML-innholdet med teksten vi kopierte i forrige trinn.

Denne blokken kunne enkelt blitt opprettet som en liner, men jeg valgte å splitte den til 2 linjer for å lese om det.

Kast bort endringene

 $ (".btnDiscard"). live ("klikk", funksjon () $ (dette) .parent () .html (oldText););

Dette er like enkelt som det ser ut. Siden brukeren ikke vil beholde noen av endringene. Vi erstatter bare HTML-innholdet til foreldreelementet med den opprinnelige teksten vi kopierte tidligere til oldText variabel.

Med dette er kjernen i vårt arbeid gjort. Vi trenger bare å gjøre et par endringer for å sikre at ting ikke bryter når brukeren gjør uventede ting.

Binding og losning

Hvis du har testet koden vår på dette tidspunktet, vil du sannsynligvis ende opp med denne funksjonaliteten som bryter feil: Når en bruker dobbeltklikker i den resulterende innskriftsboksen, er den nå fylt med HTML-innholdet i redigeringssystemet. Prøv det selv. Med hvert dobbeltklikk gjenspeiler verdien av innboksfeltet ved å legge til en annen gjeng med tekst til den. Dette problemet vil trolig være mye verre hvis du har valgt klikk som utløserhendelse.

For å rette opp dette, må vi knytte hendelsesbehandleren til det bestemte elementet alene og bind dem igjen så snart brukeren klikker enten lagre eller kaste bort. La oss implementere det nå.

Våre tidligere kodeblokker må nå redigeres slik:

 funksjon erstatteHTML () // Kode $ (dette) .html ("") // Tidligere skjemainnsettingskode .unbind ('dblclick', replaceHTML); 

Vi fjerner håndterer for elementet som utløste hendelsen. Resten av elementene med redigerbar klassen har fortsatt sine håndtere intakt og vil svare på hendelser.

 $ (".btnSave"). live ("klikk", funksjon () // Tidligere kode $ (dette) .parent () .html (newText) .bind ("dblclick", replaceHTML););
 $ (".btnDiscard"). live ("klikk", funksjon () $ (dette) .parent () .html (oldText) .bind ("dblclick", replaceHTML););

Deretter legger vi disse håndtererene tilbake på tross av om brukeren velger å redigere dem eller ikke. Hvis vi ikke legger til igjen disse, kan feltene bare redigeres én gang. Den andre gangen de dobbeltklikkes, er håndtererne ikke lenger knyttet til hendelsene. Vi utbedrer dette ved å hekte håndtererne tilbake til hendelsene.

Et par tweaks

Denne siste koden er bare for å spore opp utseendet på vår effekt. Hvis du har lagt merke til, li har litt polstring på plass for å få teksten til å se bedre ut. Men når teksten er strippet ut og erstattet av en tekstboks, blir resultatet galt og bryter effekten. Vi vil at tekstboksen skal ta opp akkurat samme plass som den opprinnelige teksten tok. Med dette i tankene legger vi til en noPad klasse til elementet når det har blitt dobbeltklikket og fjernet igjen når brukeren lagrer eller kasserer redigeringen.

 funksjon erstatteHTML () // Kode $ (dette) .addClass ("noPad") .html ("") // Tidligere kode

Vi fjerner håndterer for elementet som utløste hendelsen. Resten av elementene med redigerbar klassen har fortsatt sine håndtere intakt og vil svare på hendelser.

 $ (".btnSave"). live ("klikk", funksjon () // Tidligere kode $ (dette) .parent () .removeClass ("noPad") // Tidligere kode);
 $ (".btnDiscard"). live ("klikk", funksjon () $ (dette) .parent () .removeClass ("noPad") // Tidligere kode);

Den komplette koden

Slik ser den komplette koden ut:

 $ (dokument) .ready (funksjon () var oldText, newText; $ ("editable"). hover (funksjon () $ (dette) .addClass ("editHover");, funksjon () $ dette) .removeClass ("editHover");); $ ("redigerbar") bind ("dblclick", erstatteHTML); $ (".btnSave"). $ (dette) .siblings ("form") .children (". editBox") .val (). erstatte (/ "/ g," ""); $ (dette) .parent () .html (newText). removeClass ("noPad") .bind ("dblclick", replaceHTML);); $ (".btnDiscard"). live ("klikk", funksjon () $ (dette) .parent () .html (oldText) .removeClass ("noPad") .bind ("dblclick", replaceHTML);); funksjon erstatteHTML () oldText = $ (dette) .html () .replace (/ "/ g," ""); $ dette) .addClass ("noPad") .html ("") .html ("
Lagre endringer .unbind ('dblclick', replaceHTML); );

Ikke verst. Femti odd linjer for å legge til litt spiffy ny funksjonalitet.

Tar det ett skritt videre: Backend

For å ikke gjøre det for lenge, har jeg satt fast på å skape klientens sidefunksjonalitet alene. Hvis du vil implementere denne funksjonaliteten i dine egne prosjekter, antok det implicit at du trenger et back-end-system for å lagre disse endringene, og enda viktigere, vil du trenge en AJAX-forespørsel for å gjøre denne anropet asynkront.

Legge til denne funksjonaliteten bør være en cinch, men gjør et notat om dette. Koden ovenfor ble opprettet for å illustrere dette mønsteret og ikke for bruk i produksjon. Så jeg har abstained fra å legge til flere ID-attributt til elementene og navnegenskapene til tekstbokser. I produksjonskoden legger du til alle dem slik at tekstboksenes navnattributt kan settes på en meningsfull måte, og på den måten kan bakenden gjenkjenne hvilket datatype som skal oppdateres.

For å legge til en AJAX-forespørsel, må vår lagringshåndterer oppdateres til slik:

 $ (".btnSave"). live ("klikk", funksjon () newText = $ (dette) .siblings ("form") .children (".BoxBox") .val (). erstatte (/ "/ g , "" "); $ .ajax (type:" POST ", url:" handler.php ", data: newText, suksess: funksjon (msg) // Noen kode her for å gjenspeile en vellykket redigering;) ; $ (dette) .parent () .html (newText) .removeClass ("noPad") .bind ("dblclick", replaceHTML););

Husk at for backendingen å gjøre noen følelse av hva du sender til det, trenger du ytterligere data sammen med den oppdaterte teksten, slik at appen vet hvilke data som skal redigeres. Du kan enkelt sende inn mer enn ett stykke data til skriptet hvis du trenger det.

Konklusjon

Og der har du det hvordan du legger til en brukervennlig funksjonalitet for prosjektene dine. Forhåpentligvis har du funnet denne opplæringen interessant, og dette har vært nyttig for deg. Du er velkommen til å bruke denne koden på andre steder i prosjektene dine og chime her hvis du har problemer.

Spørsmål? Hyggelige ting å si? Kritikk? Treff kommentar delen og la meg en kommentar. Glad koding!

  • Følg oss på Twitter, eller abonner på Nettuts + RSS-feed for flere daglige webutviklinger og artikler.