29. november 2012 - 17:05Der er
31 kommentarer og 1 løsning
Overføre data fra en HTMLside til en anden (fast) HTMLside .
HEJ,
Lige en definition:
EN HTMLside er en side skrevet i HTML, som vises på en lokal Webbrowser og ALDRIG har noget med en
WEBSide at gøre. WEBSider er sider fra det store Cyberspace...
Men de er begge skrevet i HTML.
Jeg har et projekt, som meget kort fortalt går ud på at Delphi 7 (D7)danner N (antallet er pt. ikke afklaret) HTML-sider baseret på databaser styret (genereret og manipuleret) af D7. Altså D7 viser en forside hvor bruger vælger et link. D7 genererer nu en HTML-side (baseret på databaser omkring denne side, manipulerer de enkelte tags (<input type = tekst .., <textarea value ="" .., <selectbokse, checkbokse etc.) til korrekt datavisning og viser siden i en Twebbrowser.
På de sider HVOR det er muligt at ændre værdier taster bruger disse ændringer ind (trykker SAVE) eller vælger at lukke siden. Inden HTML-siden endelig lukkes (fanges af et SUBMIT-script) skal jeg have disse data gemt.
TWebbrowseren (TWB) i Delphi har (af en eller anden grund IKKE implementeret en BEFORE_CLOSE_HTML_PAGE-event, hvilket betyder at der skal laves en aller helhest masse kunstgreb for at gemme disse rettelser. TWB første event er BEFORENAVIGATE2 (og når denne kommer er aktuelle HTMLside lukket for tilgang (tro mig JEG HAR PRØVET! ). Da var det jeg kom til at tænke på følgende:
Når jeg bruger POP-UP er det muligt at overføre data fr POP-UPen til den kaldende HTML-side (om det er en WEB-side er underordnet)
og dette kunne bruges ved at ændringer fra den AKTUELT VISENDE HTML-side overføres til HOVEDSIDEN (<form = mainside>) (som aldrig vil forsvinde (jo ved programlukning)) og alligevel har kontakten til D7 og databaserne)
Så det jeg har brug for er et script, som kan overføre een (eller mange) data fra en variabel HTML-side en en FAST -HTMLside, hvor de så bliver håndteret.
I .net kan jeg sætte et direktiv, så jeg kan scripte mellem dokumentet i webbrowser kontrollen og .net-app'en. Det mener jeg også, du kan gøre i Delphi 7.
I så fald er det blot at lave en knap i dokumentet, som kalder en funktion i din 'Delphi-skal' - som igen opdaterer databaserne
Skal jeg fra Webbrowser (wb1) til Delphi (dvs. før siden effektivt lukkes af wb1.Goback; ) må jeg over et afskyeligt COM-interface, som begge sprog kan kommunikere med (JavaScript og Delphi). Dette COM-interface skal have en MONIKER og ... og ..... (en masse andre extemt komplicerede begreber) ... (behøver jeg at sige mere ) .
Havde jeg dette COM-interface ville jeg bruge dette og ikke en (noget mere (relativt)) usikker metode som JavaScript overførsel mellem siderne.
Når jeg tænker på denne løsning med JSc. er det også fordi projektet skal være færdig inden jeg bliver total senil og at det ikke skal/kan være guldrandet hele vejen igennem (at foretrække men praktisk umuligt!) (ps: konen påstår humoristisk at jeg er pre-senil - dvs. godt på vej)... hehe
Hvis jeg havde adgang til "gemmedata" fra den enkelte sider er det ikke noget problem at putte dem ind hvor de hører hjemme. I førnævnte D7 - "NAVIGATE2-event" er muligheden for gemme - men ingen data. Hvis HTML-siden var tilgængelig kunne jeg med d7 kode hente hver eneste value fra hvert eneste TAG og gemme den i rigtig database. Men det er ønsketænkning, da siden er "dø".
JA, selvfølgelig er en HTML-side en side skrevet i HTML (uanset hvordan jeg eller en anden vender og drejer det begreb / ord). Vi kan ikke være mere enige.
MEN
for at lægge vægt på at disse sider KUN SKAL VISES LOKALT i en LOKAL BROWSER har jeg valgt at lave denne "lidt" kunstige opdeling (forkert eller ikke). Disse sider, dersom de vises på en browser på en "rigtig" webbrowser (hvad det så end er !), vil da være på gale veje. At de vil kunne vises er så en hel anden sag. !
Ret beset er hele webbrowser kontrollen vel i udgangspunktet et 'afskyeligt COM-interface' =)
Nu er jeg langt fra at vide ret meget om Delphi, men at kalde JS fra Delphi, kan jeg umiddelbart se, er ret ligetil. Det må også være muligt 'den anden vej'.
Som sagt er det ganske let i .net - hvad enten jeg skriver VB eller C#. Jeg er ret sikker på, det også kan lade sig gøre i Delphi =)
AT kalde JS-scripts fra D7 er ganske let. Faktisk har jeg et par stykker kørende og de fungerer perfekt. Henter det de skal gøre og gør det hurtigt og perfekt.
Men den anden vej: en JavaScript genereret lokal (dvs. i html-siden) og som kan kommunikere fra JavaScript og ind i Delphi er, som jeg har læst det, ikke en nem opgave.
Jeg har nærlæst samme artikel (Peter Johnson // DelphiDabbler.com) inden du sendte linket (tak for det uanset, det viser vi tænker lidt parallelt) og det er det jeg baserer mine udtalelser på. Men da Peter Johnson (som ved mere om dette end jeg) måtte udvikle dette over 3-5 år (fremgår af artiklen), må jeg finde en løsning som er rimelig kortsigtet. Den forkromede løsning har jeg simpelt hen ikke tid til. Den må vente til version 37.5 (eller hvad det nu måtte være).
Jeg har skrevet artiklen (p1 -> p6) ud og vil bruge den som godnatlæsning de næste mange uger....
Har også søgt på nettet, i Twebbrowser dokumentationen, men hidtil har jeg ikke fundet noget brugbart. Ærgerligt.
En mulig løsning (testet og fundet virksom, men langsom) kunne være at bruge en SUBMIT løsning til en url med en lokaladresse a la <a href ="#slutt">AFSLUT / TILBAGE (etc) </A> a la følgende: <form name='webside1' action="#slutt method="post" > og længere nede kommer SUBMIT-knappen.
Denne 'URL' fanges af Browserens BeforeNavigate2 Event, men lukker adgangen til innerHTML -koden. Imidlertid er browseren stadig loaded med HTML-siden og da kan jeg lave en sløjfe hvor jeg med Delphicall (og JS) kan hente VAR1 , var2, var3 fra hjemmesiden osv.
A la: For N := 0 to Antal_relevante_tags_på hjemmesiden -1 DO BEGIN Var := ReadVAR(formNavn, ElementTag.Value); array(N) := var; END; gemme disse data i et Array . Derefter udføre WB1.Goback (returnere fra hjemmesiden) og så pakke data ud fra Array'et og lægge ind i de relevante databasser under d7 kontrol.
I SUBMIT har du også mulighed for at benytte POSTdata, af en eller anden (tredie ?) årsag virker dette HELLER ikke i kommunikationen til D7. Jeg får "??????????????t" som returværdi (15 * ? + 1 t) uanset hvad jeg poster af data fra hjememsiden. (selv med HTTPencodning / HTTPdekodning). Har prøvet med flere sider og variabel antal poster.
Kristian
Så der er vel ingen anden vej end at bide i det sure ævle og komme i gang med Peter Johnson (suk og atter suk (og fan(censur)ns og hel(censur)de og helhest og ...... ))...
Nu ved jeg ikke, hvor meget data, der er tale om, men hvis det kan indeholdes i en GET-forespørgesel, kunne du prøve at køre sådan én. Så kunne jeg forestille mig, du på BeforeNavigate2 kunne nå at aflæse browserens window objekts Location - og der finde query-strengen(?) Efterfølgende kunne du så sende brugeren tilbage.
Som jeg forstår det, er det ikke noget problem at hæfte en Delphi event handler på et HTML element ved hjælp af IHTMLDocument2. Kan du ikke bare lave en knap med en Delphi handler, som indsamler data i HTML siden, når knappen klikkes?
Du kan også sætte en onsubmit handler på formen. Den fyres af, inden formen submittes - hvilket i øvrigt kun sker, hvis handleren ikke returnerer false (undefined eller true lader formen submitte).
Det betyder, du har tid til at lade handler'en indsamle data, inden formens submit sender brugeren tilbage til hoveddokumentet. Skulle der være et fejludfyldt felt, kunne du jo lade handler'en returnere false og give brugeren en besked. Så bliver siden stående
"Hvis siden alligevel submittes til Delphi til sidst" >> Det, tror jeg ikke, er tilfældet. En submit er et kald til et dokument. Jeg tror ikke, du får fat i Delphi ved submit af en form i en webbrowser kontrol
Jeg kan på html-siden sagtens lave en <form // SUBMIT </form> funktion. Klikker jeg denne får jeg 15 ? og eet t (???????????????t) retur som postdata. Uanset om jeg bruger en form med een VARIABEL (en <input tag id='test' navn='test' value='test' size = ..... >, EEN form med 2 VAR's (<input id=test2 etc) , en form med 3 variable (<input id='test3' etc) får jeg mine (faste / var jeg ved at sige) 15 ? og t. Postdata er konstant uanset om antal variable i formen. Så det med et hidden felt er ikke brugbart. Et SUBMIT-kald/klik vil virke som en "alm." <a href .. funktion. den kan fanges (læs videre nedenfor)
<OLEBOLE>
du skriver:
"Som jeg forstår det, er det ikke noget problem at hæfte en Delphi event handler på et HTML element ved hjælp af IHTMLDocument2. Kan du ikke bare lave en knap med en Delphi handler, som indsamler data i HTML siden, når knappen klikkes?"
På d7 mainformen, som er bygget op som en standard IEBROWSER (wb) (side-frem, side-tilbage, home, print etc). er de fleste af funktionerne styret af d7. Altså SIDE-TILBAGE er inaktiv hvis du er på MAINSIDE ("læs menuen"). Klikker du kunder, vises KUNDER som htmlside (omend ikke færdig) og SIDE-TALBAGE bliver AKTIV og SIDE-FREM deaktiveres. KLIK Side-tilbage deaktiverer og aktiverer SIDE-FREM (som på en alm. browser).
Nu er jeg inde på siden INDSTILLINGER. Retter start_faktura_nummer" fra 1 til 1000 (det er faktisk ulovligt hvis det er eksisterende fakturaer mellem 1 og 1000) . det skal der senere tages hånd om. Det nye nummer f. eks. 555.
Nå vil jeg gerne have det gemt i d7-basen. Bruger jeg en HTML kontrol ( SUBMIT, LINK (<a href =... )) fanges siden af Webbrowserens BeforeNavigate2 event, men denne lukker på en eller anden måde adgangen til BROWSER.innerHTML. prøver jeg de "pæne " og officielle metoder får jeg bare ERRORS som svar = "INGEN ADGANG", "Objektet eksisterer ikke " eller noget lignende. Men HTML-siden er stadig i browseren. Adgang via Webbrowswer (komponenten) er tilsyneladende udelukket. Men bruger jeg et kunstgreb og går ind via BROWSERKODEN som OBJECT kan jeg hente hele browser.Innerhtml . Problemet her er bare, at rettelserne ikke kommer med tilbage.... (Fan(censur)es..) det er kun den org. indlagte side jeg kan hente (og den har jeg jo i forvejen).
Hvis jeg derimod bruger den d7-genererede SIDE-TILBAGE button kan jeg hente alt fra html-siden, både direkte via Wb1-komponentens interfaces/funktioner eller med JavaScript funktioner (styret fra D7). Når jeg så til slut fyrer kommndoen Webbrowser.Goback; (= webbrowser side-tilbage), og da hopper WB glad og fro tilbage til udgangssiden. Men da har jeg jo også overgivet programkontrollen til D7 og herfra har jeg ALDIG oplevet problemer. det er den modsatte vej som giver prblmr.
har brugt nogen timer sammen med Peter Johnson (PJ).
Jeg tror det kan lykkes. Har været ud og gøre vejene usikre det meste af dagen (indkøb - fy for en helhest hvor er der dog mange mennesker med exact samme ide... (jeg må lære at tænke anderledes ! ) ), så den ide (altså PJ ide'en ) vil jeg arbejde videre med. (hehe)
Jeg forstår stadig ikke, hvorfor du ikke knytter en Delphi handler-funktion på en HTML-knap - og lader funktionen hente de ønskede data i HTML-siden. Såvidt jeg forstår, kan du med Delphi navigere i HTML-sidens DOM - hente/sætte properties fra/på DOM-elementer - og lægge event handlers på DOM-elementer.
Altså kan du knytte en Delphi funktion til click event'en på en HTML-knap i webbrowseren. Når knappen klikes, kaldes funktionen i din 'Delphi skal'. Funktionen traverserer herefter de relevante dele af sidens DOM og henter værdier fra felterne. Har jeg forstået den del af Delphi korrekt, mener jeg, det må være ret ligetil.
Det handler for mig ikke om, hvad du gør, men hvad du kan gøre for at få løst problemet =)
Det eneste, du skal bruge, er felterne og en knap: 'Gem'. Brugeren udfylder felterne og klikker på knappen. Knappen kalder en Delphi funktion via en event handler. Funktionen i Delphi henter alle felters værdier ... Voilà! =)
Vi har nu i adskillige indlæg kredset om det reelle problem:
Nemlig at JAvascriptet på en HTMLSide skal starte et DELPHI-EVENT (enten via en indbygget EVENT-handler (som BeforeNavigate2) eller en, som jeg / en anden må lave selv.
Problemet er, at for at få mine data med (altså ændringer i HTML-sidens selectbokse, Input mv.) må disse være læsbare på en eller anden måde når dette HTML-side JavaScript affyres (tryk på knap tryk på et link etc).
Jeg har søgt nettet op og ned, kryds og tværs (en hel dag faktisk) på at finde en metode (bedre kode), som kunne dette. Det eneste rigtig brugbare og som kunne "tilbyde en løsning" var det indlæg som du også fandt omkring Peter Johnson // Delphidabbler .
Når BeforeNavigate2 eventen fyrer bliver al tilgang til siden på en aller anden måde lukket (som tidligere nævnt). Tilgangen til Wb1-komponenten sker netop via IHTMLDocument2 parameteren,
DOC := WB1 AS IHTMLDocument2; SBody := DOC.Body; // body refererer til sidens <BODY>..</BODY>
Det her accepteres af D7, men går jeg bare lidt videre (prøver at accesse Sbody (eks: Var := Sbody.innerHTML ; (var skulle have hele HTMLKOden fra <BODY .. .. til sidste </BODY> ) men kommer ud med ACCESS not possible... fordi tilgangen er lukket // siden er under nedlukning
Det samme sker ved <SUBMIT> // Form løsningen udover at jeg får totalt ulæsbare POSTDATA . <a href='url' fanges men giver mig samme muligheder (læs: Umuligheder) fordi den fanges af BeforeNavigate2 hvor HTML-siden er lukket ... osv.. osv ... osv... Ditto for <a href ='link'
Kort sagt jeg kører ind i en dårlig cirkel.
Tilsyneladende er den eneste brugbare metode at jeg må fange HTML-submit / HREF - eventen og overgive kontrollen til d7 FØR siden lukkes af BEF.NAV2. Noget PJ også påpeger i sine artikler. Eller rent ud sagt ignorere/ glemme Retur muligheder på HTML-siden og "KUN " benytte D7 browserens returmuligheder. Den fungerer nemlig perfekt (og kan behandle læste data ).
Noget du påpeger i #17.
(Men skippe Retur på en HTML-side - jeg vil græde snot """"" ...)
Lav en HTML-side helt uden et FORM element. Den skal kun indeholde INPUT elementer - evt. i lidt P, SPAN og DIV - men ingen FORM! Derudover skal der være en knap - ikke en submitknap ... bare en knap!
Nu har du en event handler på en HTML-knap. Når knappen klikkes, kaldes en Delphi funktion - og intet andet. Delphi funktionen samler de nødvendige data i HTML dokumentet ved hjælp af DOM. Når data er indsamlet og behandlet, loades en anden side i browserkontrollen.
Formålet med knappen og handler'en er blot at give Delphi besked om, hvornår brugeren er færdig og data derfor kan hentes.
Jeg har aldrig rodet med Delphi, og nu er ikke tidspunktet, hvor jeg begynder. Jeg er dog ikke i tvivl om, at hvis jeg installerede Delphi 7 ville jeg kunne have et virkende eksempel klar på under en halv time. Jeg kan ikke med min allerbedste vilje se problemet =)
Jeg er oprigtig ked af at vi snakker i ring, og at vi i større eller mindre grad misforstår hinanden. Det er IKKE min mening endsige mit ønske.
Men:
Laver jeg en HTML-side med lidt INPUTS, lidt P +/- DIV og andre TAGS og en KNAP. KLIKKER JEG PÅ DENNE KNAP SKER DER INTET. ABSOLUT INTET. Assigner jeg et JAVASCRIPT, som starter en DELPHI-routine (via COM interfacet, som den eneste mulighed) kan jeg fange alle data fra browseren. Og det er det du foreslår, hvis jeg ellers har forstået dig ret.
MEN Det at lave dette Javascript er ikke bare ....
Javascriptet skal kommunikere med et EXTERNAL COM server object, som indeholder interfaces for HTML-knap rutinen. Denne overgiver kontrollen til EXTERENAL COM server objectet, som igen overgiver kontrollen til den relevante DELPHI rutine - og retur. (Kan sammenlignes med en TOLK som oversætter fra engelsk til swahili - og tilbage.)
Og det er det jeg faktisk er i gang med at løse, men det er ikke en nem opgave.
Jeg skal ikke lægge hovedet på blokken om der er andre metoder som kan løse dette nemmere, det er der sikkert, men jeg har ikke umiddelbart kendskab til hvordan.
(bruger ikke .Net (bevidst!) eller andre avancerede net-teknologier, dels fordi D7 ikke supporter dem ordentligt og dels fordi jeg ikke kender .NET godt nok )
Jeg må have set mig blind på problemet. Løsningen var så enkel og ligefrem at selv en 5 årig (SUPER-programmør !) kunne se den, men mig ( = gamle fjols !!) ...
Løsningen er at lægge en ny Class ind i den eksisterende Class og dermed udvide funktionaliteten. Denne Class skal fange webbrowser click (også de "uautoriserede") og tage en aktion på dette klik. Finder den en TAG under klikket som
vClick := (Wb1.document as IHTMLDocument2).activeElement; id = vClick.Id; tag = vClick.Tag; osv
finder den Id, Tag Og class'en UNDER delphi Control. Resten er bare at teste om det er en Button (den rigtige naturligvis) , og så gemme data.
JUBIII !!!!
Hvis du stadig ikke samler point vil jeg tildele dem til mig selv.
Men UANSET tak fordi du åbnede "det gamle halvblinde fjols's blinde øje ".
Læg lige dit aktuelle projekt til side et øjeblik og se, om du kan få [url=https://groups.google.com/forum/?fromgroups#!msg/borland.public.delphi.oleautomation/J19HHVwZq7c/zngs5eCZfaUJ]dette eksempel[/b] til at virke.
Brug en helt simpel HTML-side med et enkelt link. Det vigtige er, at proceduren MyEvent bliver fyret af, når linket klikkes. Sørg for, at der ikke sker sideskift ved at sætte et hashmark (#) som href. Når det virker, kan du kopiere koden over i dit eget projekt og lade MyEvent indamle data fra HTML-elementerne.
I stedet for ShowMessage kalder du med Document.getElementsByTagName("input"), som returnerer en NodeList collection. Den kan du så traversere og hente hvert elements value
Kristian, det er mig, der takker! For s*t*n, det kan være frustrende, ikke at kunne se dig i øjnene og pege på din skærm - og sige "Hold nu k*ft og hør efter, hvad det er, jeg siger". Jeg kunne jo se, løsningen lå lige under næsen på dig :D
Kanon fedt, at du fandt løsningen. Somme tider står mediet lidt i vejen for forståelsen. Kloge hoveder påstår, at kun 10-20% af vores face-to-face kommunikation er verbal - så det er vel egentlig ikke så mærkeligt.
Jeg kender problemstillingen. Har osse arbejdet som IT-lærer på en produktionsskole.
Og om alder tror jeg nok at jeg er ældst (ikke en konkurrence!) men jeg ville blive SMIIIIDT ud af arbejdsmarkedet om 4 år, hvis de da ikke allerede havde gjort det. Invalidepensionist - helgarderet, kun 5 discus prolabser (een plejer at være nok ) !
Gammel (JO da) E-ingeniør fra Odense Teknikum (1889) øh 1989 (så gammel er jeg altså heller ikke ! hehe) men fandt hurtigt softwaren fremfor hardwaren... PASCAL indtil delphi/windows kom.
Bruger uddannelsen mest for sjov nu til at hjælpe unge mennesker (eksperten dk) med deres hardware problemer.
Sjovt ... jeg gik på DIA (svagstrøm) - mens, der var noget, der hed sådan - i første halvdel af 70'erne (1970'erne ... høhø). Aldersprisen må dog trods alt være din *o)
Havde det været NOBEL- prisen havde jeg været mere tilfreds (hehe), men sådan er det nu engang. Men i mit tilfælde siger jeg AGE BEFORE BEAUTY .. (til stor moro for konen!)
Men jeg lukker nu. Så må vi mødes igen når der er andre opgaver til fælles benefice...
Tak for hjælpen / sludderen / alt indtil næste gang.
PS: Denne løsning løser også mit problem med overføre HTML til en fast (anden) HTML-side (altså der hvor jeg skal overføre en farve fra en ColorPicker til en <input text box) så det problem lukker jeg om en uge, så har de andre med/mod-spillere en mulighed for at give input.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.