Seite 1 von 1

Javascript erweitern

Verfasst: 12.03.2013 14:48
von TroaX
Halli Hallo,

Bin beim Stöbern nach umsetzbaren Techniken auf diesen Thread im englischen Board gestoßen: http://www.purebasic.fr/english/viewtopic.php?t=16968

Kurz zuammengefasst:
Zugriff auf Javascript-Funktionen getestet: Geht und geil!
Zugriff auf Javascript-Variablen lesend getestet: Geht und genial!
Zugriff auf Javascript-Variablen schreibend getestet: Geht und mega!

Nur eines würde ich gerne auch haben. Zugriff von Javascript auf FB-Funktionalitäten, um ein Runtime-Environment für HTML und Javascript Anwendungen zu basteln. Ich werde es erstmal nur für Windows umsetzen, da die Codes im oben genannten Threads die WinAPI verwenden. Ich zerbreche mir jetzt seit 2 Tagen den Kopf darüber und habe bisher nur einen möglichen Ansatz gefunden. Den Navigation-Callback dafür nutzen. Schematisch würde das so aussehen (ich habe noch keinen Code geschrieben, da ich noch im Konzept bin. Mir ist nur die Machbarkeit wichtig):
  • Es wird über window.location eine Navigation ausgelöst. Bei der JS-Funktion wird dann die URL mit den Daten übergeben. Das würde so aussehen: func: //console/ new/ print? text=HalloWelt&weitererparameter=nene
  • Das Navigation-Callback kann ja als Eventhandler angesehen werden. Die Location-URL wird so über tragen und mit den bekannten Funktionen in PB zerlegt werden. Damit nicht versehentlich fieser Code aus dem Internet auf dem Rechner landet soll die Navigation auf die klassischen Protokolle unterbunden werden. Das Protokoll func soll dann auf die selbst geschriebene Console-API zugreifen, eine neue (new) Konsole öffnen und den Text aus dem Parameter text ausgeben.
  • Bei großen Inhalten für die Parameter kann man den direkten Zugriff auf die JS-Variablen nehmen und den Namen der Variable als String in den Parametern übertragen. Das gleiche gilt für den Rückgabewert. Wenn man aber die Funktions-Aufrufe per eigner JS-API regelt, kann man das in der Programmierung mit JS und der API unterbinden.
  • Das aufrufen von JS-Funktionen seitens PB ist zudem eine Möglichkeit, einen in JS definierten PB-Aufruf zu vervollständigen, in dem man die Verarbeitung des Rückgabewertes anstößt.
Sooo in der Theorie klingt da gut und in der Praxis wird es auch gehen. Meine Frage an der Stelle. Gibt es eine elegantere Art als das Navigation-Callback oder geht es wirklich nur so? Denn man müsste ja im Grunde vom Webgadget ja auch ein Event bekommen können, wenn eine nicht deklarierte Funktion aufgerufen wird und dessen Namen und Parameter selbst verarbeiten kann. Hat damit jemand Erfahrung oder sollte ich das wirklich mit dem Calback umsetzen?

Danke für Antworten.
MFG TroaX :-)

Re: Javascript erweitern

Verfasst: 12.03.2013 15:41
von Kiffi
hier mal ein Ansatz mit COMate. Hiermit kannst Du Werte setzen
und auslesen sowie auf Ereignisse reagieren. Vielleicht kannst Du
damit was anfangen.

Code: Alles auswählen

IncludePath "[DeinPfadZu]\COMatePLUS\"
XIncludeFile "comateplus.pbi"
IncludePath ""

Enumeration
	#frmMain
	#StringGadget1
	#StringGadget2
	#StringGadget3
	#cmdWriteValues
	#cmdReadValues
	#Webgadget
EndEnumeration

EnableExplicit

Procedure.s GetExampleHtml()
	
	Protected HTML.s
	
	HTML + "<html>"
	HTML + "<body scroll='no'>"
	HTML + "<h1>Ich bin HTML</h1>"
	HTML + "<input type='textbox' id='textbox1' value='tb1' /><br />"
	HTML + "<input type='textbox' id='textbox2' value='tb2' /><br />"
	HTML + "<input type='textbox' id='textbox3' value='tb3' /><br />"
	HTML + "</body>"
	HTML + "</html>"
	
	ProcedureReturn HTML
	
EndProcedure

Procedure SetHtmlElementValue(gadget, HtmlElementId.s, Value.s)
	
	Protected myCOMateObject.COMateObject
	
	myCOMateObject = COMate_WrapCOMObject(GetWindowLong_(GadgetID(gadget), #GWL_USERDATA))
	
	If myCOMateObject 
		Value = ReplaceString(Value, "'", "$0027")
		myCOMateObject\SetProperty("document\getElementById('" + HtmlElementId + "')\value='" + Value + "'")
		If COMate_GetLastErrorCode() : Debug COMate_GetLastErrorDescription() : EndIf
		myCOMateObject\Release()
	EndIf
	
EndProcedure

Procedure.s GetHtmlElementValue(gadget, HtmlElementId.s)
	
	Protected myCOMateObject.COMateObject
	Protected ReturnValue.s
	
	myCOMateObject = COMate_WrapCOMObject(GetWindowLong_(GadgetID(gadget), #GWL_USERDATA))
	
	If myCOMateObject 
		ReturnValue = myCOMateObject\GetStringProperty("document\getElementById('" + HtmlElementId + "')\value")
		If COMate_GetLastErrorCode() : Debug COMate_GetLastErrorDescription() : EndIf
		myCOMateObject\Release()
	EndIf
	
	ProcedureReturn ReturnValue
  
EndProcedure

Procedure textbox1_Events(Object.COMateObject, eventName$, parameterCount, *result.VARIANT) 
	Debug "textbox1-Event: " + eventName$
EndProcedure
Procedure textbox2_Events(Object.COMateObject, eventName$, parameterCount, *result.VARIANT) 
	Debug "textbox2-Event: " + eventName$
EndProcedure
Procedure textbox3_Events(Object.COMateObject, eventName$, parameterCount, *result.VARIANT) 
	Debug "textbox3-Event: " + eventName$
EndProcedure

Procedure.i AddEventProcedure(Gadget, ObjectID.s, EventProcedure) 
	Protected browser.COMateObject
	Protected element.COMateObject
	Protected result
	browser = COMate_WrapCOMObject(GetWindowLong_(GadgetID(Gadget), #GWL_USERDATA)) 
	If browser 
		element = browser\GetObjectProperty("document\getElementById('" + ObjectID + "')")
		If element
			element\SetEventHandler(#COMate_CatchAllEvents, EventProcedure, #COMate_VariantReturn)
			element\Release()
		Else
			Debug "ObjectID '" + ObjectID + "' not found"
		EndIf
		browser\Release()
	EndIf 
	ProcedureReturn result
EndProcedure 

OpenWindow(#frmMain, 0, 0, 800, 600, "WebGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

StringGadget(#StringGadget1, 10, 15, 200, 20, "TB1")
StringGadget(#StringGadget2, 10, 40, 200, 20, "TB2")
StringGadget(#StringGadget3, 10, 65, 200, 20, "TB3")

ButtonGadget(#cmdWriteValues, 10,  90, 200, 30, "Formularfelder füllen")
ButtonGadget(#cmdReadValues,  10, 140, 200, 30, "Formularfelder auslesen")

WebGadget(#Webgadget, 215, 15, 575, 580, "")

SetGadgetItemText(#Webgadget, #PB_Web_HtmlCode, GetExampleHtml())

Repeat 
	
	Select WaitWindowEvent()
			
		Case #PB_Event_Gadget
			
			Select EventGadget()
					
				Case #Webgadget
					
					Select EventType()
						Case #PB_EventType_DownloadEnd
							AddEventProcedure(#Webgadget, "textbox1", @textbox1_Events())
							AddEventProcedure(#Webgadget, "textbox2", @textbox2_Events())
							AddEventProcedure(#Webgadget, "textbox3", @textbox3_Events())
					EndSelect
					
				Case #cmdWriteValues
					SetHtmlElementValue(#Webgadget, "textbox1", GetGadgetText(#StringGadget1))
					SetHtmlElementValue(#Webgadget, "textbox2", GetGadgetText(#StringGadget2))
					SetHtmlElementValue(#Webgadget, "textbox3", GetGadgetText(#StringGadget3))
					
				Case #cmdReadValues
					Debug "Textbox1: " + GetHtmlElementValue(#Webgadget, "textbox1")
					Debug "Textbox2: " + GetHtmlElementValue(#Webgadget, "textbox2")
					Debug "Textbox3: " + GetHtmlElementValue(#Webgadget, "textbox3")
					
			EndSelect
			
		Case #PB_Event_CloseWindow
			Break
			
	EndSelect
	
ForEver
Grüße ... Kiffi

Re: Javascript erweitern

Verfasst: 12.03.2013 16:08
von TroaX
COMate ist wirklich genial. Habe mir das eben mal grob angesehen. Danke für den Tipp. Mal schauen, ob sich das damit machen lässt. Sieht aber gut aus :-)

Re: Javascript erweitern

Verfasst: 12.03.2013 17:18
von TroaX
Hmmm also ich wurschtel mich jetzt mit Google durch die Begriffe COM bzw. Component Object Model sowie ActiveX. Aber irgendwie komm ich nicht dahinter, wie ich damit Javascript erweitern kann. Ich kann zwar neue Objekte für die Verwendung in HTML Code definieren und auch deren Attribute und Proberties auslesen bzw. schreiben. Aber wirklich eigene Funktionalität kann ich damit wohl nicht implementieren. Oder ich bin zu blöd dazu oder zu blind, um es zu finden. Weiß jemand nen Tipp?

Re: Javascript erweitern

Verfasst: 12.03.2013 17:56
von Kiffi
vielleicht kannst Du ExecuteJavaScript() in Demo_ExecuteJavaScriptInWebGadget.pb
im Ordner 'Basic demos' von COMate gebrauchen?

Grüße ... Kiffi

Re: Javascript erweitern

Verfasst: 12.03.2013 18:22
von TroaX
Neee das führt Javascript direkt im WebGadget aus. Das macht ja die oben im Link angewendete Methode ja auch. Der Unterschied ist, das hier dem Javascript der Code direkt zur Ausführung in das Script gedropped werden kann. Die Methode unter dem Link hingegen spricht nur eine Javascript-Funktion, die im JS-Code implementiert wurde an. Im Grunde aber ist es der gleiche Weg. Ich will es aber umgekehrt haben. So das wenn man in JS folgende Anweisung schreibt PB das dann ausführt:

Code: Alles auswählen

result = PBApi.Console.OpenPrint("Hallo Welt");
Auf diesen Funktionsaufruf muss das Webgadget ja irgendwie reagieren, weil es diese Funktion ja nicht gibt. Und ich dachte das könnte man Abfragen. Dann müsste natürlich auch das Element den Namen des Objects sowie der Unterobjekte, die Methoden sowie die Eigenschaften und deren Werten übergeben. Und ich denke mir jetzt mal, das es so wie ich mir vorstelle nicht mit COMate möglich ist. Und so wie es aussieht kann ich ActiveX nur global erweitern und ich denke auch, das unser Webgadget genauso wie im .NET sich über die Internetoptionen mitkonfigurieren lässt. Und somit würde ich ja auch meine JS-Funktionen wegen der globalen Struktur auch dem IE zur Verfügung stellen. Und das wollte ich eigentlich nicht unbedingt.

Ich denke einfach, das aus Sicherheitsgründen die Javascript-Funktionalität in den einzelnen Engines gekapselt ist und deswegen nur vom Programm ausgehende Anfragen stattfinden können. Umgekehrt wäre es ja auch irgendwo fatal, wenn jemand die JS-API aus dem Inet ansprechen kann. Ich werde es denke ich mal über das Navigation-Callback machen.Das ist die sicherste und stabilste Möglichkeit, auch wenn vielleicht nicht die schönste :-D

Aber vielleicht kennt ja jemand noch ne andere Möglichkeit, auch wenn die Hoffnung langsam schwindet :-D

Re: Javascript erweitern

Verfasst: 15.04.2014 09:08
von TroaX
So dieser Thread von mir ist zwar schon etwas älter. Der Wunsch dieses umsetzen zu können bbesitze ich aber immer noch und habe einen Weg im .NET gefunden. Unter folgendem Link steht genauestens, was ich machen möchte. Genau so hatte ich mir das gedacht:
http://www.codeproject.com/Articles/353 ... ation#cvfj

Wenn ich es dort richtig gelesen habe, soll es auch dort über COM gehen. Die Frage ist nur, wie ich innerhalb des Webgadget's die Rechte passend zuweise (FULLTRUST) und wie ich die Prozeduren als JS-Funktionenen über COM in das Webgadget einbinde. Ich denke COMMate hilft da bestimmt weiter. Ich finde nur keinen passenden Ansatz. Jemand eine Idee? :)