More Documentation Web NavigationCallback etc.

Windows specific forum
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

More Documentation Web NavigationCallback etc.

Post by Rescator »

Some more info is needed on this in the manual,
especially regarding urls/GET (like when FORM's are used)
as I seem to recall that there is a url/string limit?

Likewise when passing text to the webgadget, the manual need to point this out to avoid future "bug" posts about text getting cutoff and so on.

I'm sure the PB Team can find out what limitations are in their code (none?),
but when it comes to the ATL/ActiveX/IE stuff there probably is a few undocumented ones at worst knowing Microsoft.

(something tells me the Webgadget is going to get very popular in the ext few months ;))
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

http://support.microsoft.com/kb/208427
Maximum URL length is 2,083 characters in Internet Explorer
If you are using the GET method, you are limited to a maximum of 2,048 characters, minus the number of characters in the actual path.
*pokes PB Team* any chance of POST support for the webgadget as 2KB is not that much for certain FORM uses like a HTML GUI based app.
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

Why do you need POST support when you can write into the gadget whatever code you want ?
quidquid Latine dictum sit altum videtur
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

.. because imagine typing more than 2KB worth of text into a <TEXTAREA> using GET to return that to the PB program will cut off the text due to the length limit of IE urls/GETs. POST has no such limits.

Unless I missed something and there is another way to retrive the full text of a form's input field using the new webgadget functions?
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Hmm, unfortunately I can't see a way to do this with the current functions (or I'm blind). :(

The callback would have to be updated to do something like this:

Code: Select all

  Procedure NavigationCallback(Gadget, Url$, Text$)
    ;Text$ is empty unless a POST is performed.
    ;
    ; Return #True to allow this navigation or #False to deny it.
    ;
    ProcedureReturn #True
  EndProcedure
ricardo
Addict
Addict
Posts: 2438
Joined: Fri Apr 25, 2003 7:06 pm
Location: Argentina

Post by ricardo »

Rescator wrote: Unless I missed something and there is another way to retrive the full text of a form's input field using the new webgadget functions?
GET and POST are server side things, noy related to the browser itself.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Yes and no! In the case of the WebGadget and the new functions added in PB 4.10, only thing lacking from a fully useable hTML based GUI app is intercepting POST forms. (GET forms work as they are now, only limited by IE's URL length which is around 2048 bytes)

For example, the Windows Help and other interfaces in XP and Vista actually uses a form of WebGadget for it's user interfaces.
Another big plus for a HTML based GUI is rapid development. (you could just add the input fields and buttons etc, and have it work almost at once, and worry about "prettying it up" with CSS etc later)
ricardo
Addict
Addict
Posts: 2438
Joined: Fri Apr 25, 2003 7:06 pm
Location: Argentina

Post by ricardo »

But then its not a POST nor GET, you can use javascript (and javascript can perfectly interact with PB) to retreive the content of the form.

There are several javascript codes to verify the content of a form and then you can do whatever you want in PB.

I know the big possibilities of using DHTML and specialy AJAX as a GUI, personally i develope 2 finished applications using that way and its very nice.
ricardo
Addict
Addict
Posts: 2438
Joined: Fri Apr 25, 2003 7:06 pm
Location: Argentina

Post by ricardo »

This code is maybe dirty (i just put together different things as demostration not as a real example) but shows that you can get the form values easily without the need to navigate.

Code: Select all

DataSection 

IID_IHTMLDocument: ; {626FC520-A41E-11CF-A731-00A0C9082637} 
Data.l $626FC520 
Data.w $A41E, $11CF 
Data.b $A7, $31, $00, $A0, $C9, $08, $26, $37 
    
IID_NULL: ; {00000000-0000-0000-0000-000000000000} 
Data.l $00000000 
Data.w $0000, $0000 
Data.b $00, $00, $00, $00, $00, $00, $00, $00        

EndDataSection 

Procedure MakeBSTR(String$) 
   Unicode$ = Space(Len(String$)*2+2) 
   MultiByteToWideChar_(#CP_ACP, 0, @String$, -1, @Unicode$, Len(String$)*2+2) 
   ProcedureReturn SysAllocString_(@Unicode$) 
EndProcedure 

Procedure.s ReadBSTR(bstr) 
   length = WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, 0, 0, 0, 0) 
   Text$ = Space(length) 
   WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, @Text$, length, 0, 0)    
   ProcedureReturn Text$ 
EndProcedure 

Procedure.s StringFromVARIANT(*var.VARIANT) 
   
   If VariantChangeType_(*var, *var, $2, #VT_BSTR) = #S_OK 
      Result$ = ReadBSTR(*var\bstrVal) 
      SysFreeString_(*var\bstrVal) 
   Else 
      Result$ = "ERROR : Cannot convert VARIANT to String!" 
   EndIf 
   
   ProcedureReturn Result$ 
EndProcedure 

Procedure.s GetJSVariable(Gadget, Name$) ;obtiene variables js
   Result$ = "ERROR" 
   
   Browser.IWebBrowser2 = GetWindowLong_(GadgetID(Gadget), #GWL_USERDATA) 
   If Browser\get_Document(@DocumentDispatch.IDispatch) = #S_OK 
      If DocumentDispatch\QueryInterface(?IID_IHTMLDocument, @Document.IHTMLDocument) = #S_OK 
         If Document\get_Script(@Script.IDispatch) = #S_OK 
            
            bstr_name = MakeBSTR(Name$) 
            Result = Script\GetIDsOfNames(?IID_NULL, @bstr_name, 1, 0, @dispID.l) 
            If Result = #S_OK 
               
               params.DISPPARAMS\cArgs = 0 
               params\cNamedArgs = 0        
               
               Result = Script\Invoke(dispID, ?IID_NULL, 0, #DISPATCH_PROPERTYGET, @params, @varResult.VARIANT, 0, 0) 
               If Result = #S_OK 
                  Result$ = StringFromVARIANT(@varResult) 
               Else 
                  Message$ = Space(3000) 
                  FormatMessage_(#FORMAT_MESSAGE_IGNORE_INSERTS|#FORMAT_MESSAGE_FROM_SYSTEM, 0, Result, 0, @Message$, 3000, 0)          
                  Result$ = "ERROR: Invoke() "+Message$            
               EndIf 
               
            Else 
               Message$ = Space(3000) 
               FormatMessage_(#FORMAT_MESSAGE_IGNORE_INSERTS|#FORMAT_MESSAGE_FROM_SYSTEM, 0, Result, 0, @Message$, 3000, 0)          
               ;Result$ = "ERROR: GetIDsOfNames() "+Message$          
               
            EndIf 
            SysFreeString_(bstr_name) 
            
            Script\Release() 
         EndIf 
         Document\Release() 
      EndIf 
      DocumentDispatch\Release() 
   EndIf 
   
   ProcedureReturn Result$ 
EndProcedure 

Procedure ResizeWebWindow()
  ResizeGadget(10, #PB_Ignore, #PB_Ignore, WindowWidth(0), WindowHeight(0)-52)
  ResizeGadget(4, #PB_Ignore, #PB_Ignore, WindowWidth(0)-185, #PB_Ignore)
  ResizeGadget(5, WindowWidth(0)-25, #PB_Ignore, #PB_Ignore, #PB_Ignore)
  ResizeGadget(6, #PB_Ignore, #PB_Ignore, WindowWidth(0), #PB_Ignore)
EndProcedure

Procedure NavigationCallback(Gadget, Url$)
  Debug "Navigating to: " + Url$
  
  ; stop evil MS pages from being viewed :D
  If FindString(Url$, "microsoft", 1) = 0
    ProcedureReturn #True
  Else
    MessageRequester("PureBasic MiniBrowser v1.0", "No evil MS pages please ;)")
    ProcedureReturn #False
  EndIf
EndProcedure

Procedure.s RunJSFunction(Gadget, Function$, Arguments$, Separator$) ;corre funciones js
   Result$ = "ERROR" 
   
   Browser.IWebBrowser2 = GetWindowLong_(GadgetID(Gadget), #GWL_USERDATA) 
   If Browser\get_Document(@DocumentDispatch.IDispatch) = #S_OK 
      If DocumentDispatch\QueryInterface(?IID_IHTMLDocument, @Document.IHTMLDocument) = #S_OK 
         If Document\get_Script(@Script.IDispatch) = #S_OK 
            
            bstr_command = MakeBSTR(Function$) 
            Result = Script\GetIDsOfNames(?IID_NULL, @bstr_command, 1, 0, @dispID.l) 
            If Result = #S_OK 
               
               ; parse the arguments          
               ; 
               If Trim(Arguments$) = "" 
                  Count = 0 
                  *Arguments = 0 
               Else            
                  Count = CountString(Arguments$, Separator$)+1 
                  *Arguments = AllocateMemory(SizeOf(VARIANT)*Count)        
                  *Arg.VARIANT = *Arguments 
                  
                  For i = 1 To Count            
                     *Arg\vt = #VT_BSTR 
                     *Arg\bstrVal = MakeBSTR(StringField(Arguments$, i, Separator$)) 
                     *Arg + SizeOf(VARIANT) 
                  Next i 
               EndIf 
               
               params.DISPPARAMS\cArgs = Count 
               params\cNamedArgs = 0 
               params\rgvarg = *Arguments 
               
               Result = Script\Invoke(dispID, ?IID_NULL, 0, #DISPATCH_METHOD, @params, @varResult.VARIANT, 0, 0) 
               If Result = #S_OK 
                  Result$ = StringFromVARIANT(@varResult) 
               Else 
                  Message$ = Space(3000) 
                  FormatMessage_(#FORMAT_MESSAGE_IGNORE_INSERTS|#FORMAT_MESSAGE_FROM_SYSTEM, 0, Result, 0, @Message$, 3000, 0)          
                  Result$ = "ERROR: Invoke() "+Message$            
               EndIf 
               
               If *Arguments 
                  *Arg.VARIANT = *Arguments 
                  For i = 1 To Count 
                     SysFreeString_(*Arg\bstrVal) 
                     *Arg + SizeOf(VARIANT) 
                  Next i          
                  FreeMemory(*Arguments) 
               EndIf 
               
            Else 
               Message$ = Space(3000) 
               FormatMessage_(#FORMAT_MESSAGE_IGNORE_INSERTS|#FORMAT_MESSAGE_FROM_SYSTEM, 0, Result, 0, @Message$, 3000, 0)          
               Result$ = "ERROR: GetIDsOfNames() "+Message$          
               
            EndIf 
            SysFreeString_(bstr_command) 
            
            Script\Release() 
         EndIf 
         Document\Release() 
      EndIf 
      DocumentDispatch\Release() 
   EndIf 
   
   ProcedureReturn Result$ 
EndProcedure 

HTMLPage$ = "<script type='text/javascript'>"
HTMLPage$+ "var result;"
HTMLPage$+ "function Clean(){ result=''};"
HTMLPage$+ "function isEmpty(elem, helperMsg){"
HTMLPage$+ "	if(elem.value.length == 0){"
;HTMLPage$+ "		alert(helperMsg);"
HTMLPage$+ "		elem.focus();"
HTMLPage$+ "		return true;"
HTMLPage$+ "	}else{"
;HTMLPage$+ "	alert(elem.value);"
HTMLPage$+ "	result = elem.value;"
HTMLPage$+ "	}"
HTMLPage$+ "	return false;"
HTMLPage$+ "}"
HTMLPage$+ "</script>"
HTMLPage$+ "<form>"
HTMLPage$+ "Required Field: <input type='text' value='hello' id='req1'/>"
HTMLPage$+ "<input type='button' "
HTMLPage$+ "	onclick=" + Chr(34) + "isEmpty(document.getElementById('req1'), 'Please Enter a Value')" + Chr(34)
HTMLPage$+ "	value='Check Field' />"
HTMLPage$+ "</form>"


If OpenWindow(0, 100, 200, 500, 300, "PureBasic MiniBrowser v1.0", #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)

  CreateStatusBar(0, WindowID(0))
    StatusBarText(0, 0, "Welcome to the world's smallest Browser ! :)", 0)
      
  CreateGadgetList(WindowID(0))
    ButtonGadget(1,   0, 0, 50, 25, "Back")
    ButtonGadget(2,  50, 0, 50, 25, "Next")
    ButtonGadget(3, 100, 0, 50, 25, "Stop")
  
    StringGadget(4, 155, 5, 0, 20, "http://www.google.com")
    
    ButtonGadget(5, 0, 0, 25, 25, "Go")
    
    Frame3DGadget(6, 0, 29, 0, 2, "", 2) ; Nice little separator
  
    If WebGadget(10, 0, 34, 0, 0, "about:" + HTMLPage$) = 0 : MessageRequester("Error", "ATL.dll Not found", 0) : End : EndIf
    
    SetGadgetAttribute(10, #PB_Web_BlockPopups, 1)    ; disable popup windows
    SetGadgetAttribute(10, #PB_Web_BlockPopupMenu, 1) ; disable popup menu 
    SetGadgetAttribute(10, #PB_Web_NavigationCallback, @NavigationCallback()) ; set navigation callback

  AddKeyboardShortcut(0, #PB_Shortcut_Return, 0)
  
  ResizeWebWindow()

  ;SetGadgetItemText(10,#PB_Web_HtmlCode,HTMLPage$) 

  Repeat
    Event = WaitWindowEvent()
    
    ;Find if some JS variable has any value
    JSVar$ = GetJSVariable(10,"result")
    If JSVar$ And JSVar$ <> "ERROR"
      RunJSFunction(10,"Clean","","")
      Debug "Javascript variable value: " + JSVar$
    EndIf
      
    Select Event
      Case #PB_Event_Gadget
      
        Select EventGadget()
          Case 1
            SetGadgetState(10, #PB_Web_Back)

          Case 2
            SetGadgetState(10, #PB_Web_Forward)           
          
          Case 3
            SetGadgetState(10, #PB_Web_Stop)
          
          Case 5
            SetGadgetText(10, GetGadgetText(4))
            
          Case 10 
            Select EventType()
              Case #PB_EventType_TitleChange
                Title$ = GetGadgetItemText(10, #PB_Web_PageTitle)
                If Title$ = ""
                  SetWindowTitle(0, "PureBasic MiniBrowser v1.0")
                Else
                  SetWindowTitle(0, Title$ + " - PureBasic MiniBrowser v1.0")
                EndIf
              
              Case #PB_EventType_StatusChange
                StatusBarText(0, 0, GetGadgetItemText(10, #PB_Web_StatusMessage), 0)
                
              Case #PB_EventType_PopupWindow
                MessageRequester("PureBasic MiniBrowser v1.0", "A popup window was blocked!")
                            
              Case #PB_EventType_DownloadStart
                Debug "Download starting"
               
              Case #PB_EventType_DownloadProgress
                Debug "Progress: "+Str(GetGadgetAttribute(10, #PB_Web_Progress))+" of " + Str(GetGadgetAttribute(10, #PB_Web_ProgressMax))
              
              Case #PB_EventType_DownloadEnd              
                Debug "Download ended"
                
              Case #PB_EventType_PopupMenu
                MessageRequester("PureBasic MiniBrowser v1.0", "No popup menu available!")
              
              Default
                Debug "unknown event"
                
            EndSelect            
            
        EndSelect      
      
      Case #PB_Event_Menu ; We only have one shortcut      
        If GetActiveGadget() = 4 ; Check if the return was pressed inside the string
          SetGadgetText(10, GetGadgetText(4))
        EndIf

      Case #PB_Event_SizeWindow
        ResizeWebWindow()
      
    EndSelect
      
  Until Event = #PB_Event_CloseWindow
   
EndIf
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

ricardo wrote:But then its not a POST nor GET
Actually it is, despite not being sent to a server you still have to specify method="get" or method="post" as the WebGadget (due to wrapping IE) behaves just like a browser. Alternatively if you like you can call it url data and non-url data but that is just more confusing.
This code is maybe dirty (i just put together different things as demostration not as a real example) but shows that you can get the form values easily without the need to navigate.
Thanks, but could you post this in Tips and Tricks instead as the bugs forum gets cleaned out now and again and it'd be a shame to loose that example.

But to the issue of javascript, I see that you fetch the data directly which is nice since there is no data length issues, but it's almost as easy to fetch the form data as well isn't it?

Maybe the PB team should add a function to readt/write to javascript variables instead? That would be much more powerfull and actually act as a sort of native PB/AJAX which would be even more powerfull.

I see one issue with your example though, how do you get around url limit with the javascript? a 2K script may be too little at times right?
Then again, one do not live generate a javascript normally so :)

But to get back to the topic, I wish there was a way (implemented into the current set or added to) fetch larger than 2KB of text from a FORM in a webgadget.

Freak, Fred, any chance of adding something similar to what Ricardo showed? A GetJSVariable() ?

(I assume a SetJSVariable() would be too much work or not possible?)
ricardo
Addict
Addict
Posts: 2438
Joined: Fri Apr 25, 2003 7:06 pm
Location: Argentina

Post by ricardo »

Rescator wrote:
ricardo wrote:But then its not a POST nor GET
Actually it is, despite not being sent to a server you still have to specify method="get" or method="post"
In the example i post there is no GET or POST specify.
Thanks, but could you post this in Tips and Tricks instead as the bugs forum gets cleaned out now and again and it'd be a shame to loose that example.
The code i post is just a combination of posts already in the forum (not mines). You may use the search function and will find more about.
ricardo
Addict
Addict
Posts: 2438
Joined: Fri Apr 25, 2003 7:06 pm
Location: Argentina

Post by ricardo »

Rescator wrote: Freak, Fred, any chance of adding something similar to what Ricardo showed? A GetJSVariable() ?
What i showed is Freak's, i just put the example for you, but is Freak's

http://www.purebasic.fr/english/viewtop ... +getscript

Freak has shared a lot of wonderfull webgadget related stuff here in the forums
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

There will be no native functions for communication with JavaScript,
as it is not possible on Linux. As for the POST stuff, i will have to check that
on the other OS first as well.
quidquid Latine dictum sit altum videtur
Post Reply