AppMenu for browser apps

Share your advanced knowledge/code with the community.
User avatar
Danilo
Posts: 51
Joined: Wed Feb 26, 2014 7:11 am

AppMenu for browser apps

Post by Danilo »

Hi guys, today I wrote a small app-menu for use in the browser:

Image

Code: Select all

;
; by Danilo, 2020/01/06
;
; 2020/01/07 Added status bar, by Danilo
;
Prototype MenuButtonClicked(id.s)

Procedure.i CreateAppStatusbar(id.s)
    Protected content.s
    ! var elem = document.getElementById(v_id);
    ! if(elem != null) elem.parentNode.removeChild(elem);
    ! var bar = document.createElement("div")
    ! bar.id = v_id;
    ! bar.style.cssText = "position:fixed; bottom:0; left:0; z-index: 499; width:100%; background-color:#222; color:#888; font-size:16px; padding: 5px";
    ! var txt = document.createElement("div");
    ! txt.id = v_id+"_txt";
    ! txt.innerText = "|";
    ! bar.appendChild( txt );
    ! document.getElementsByTagName('body')[0].appendChild(bar);
    ProcedureReturn #True
EndProcedure

Procedure SetAppStatusbarText(id.s, text.s)
    ! var elem = document.getElementById(v_id+"_txt");
    ! if(elem != null) elem.innerText = v_text;
EndProcedure

Procedure.i CreateAppMenu(id.s)
    ! var elem = document.getElementById(v_id);
    ! if(elem != null) elem.parentNode.removeChild(elem);
    ! var bar = document.createElement("div")
    ! bar.id = v_id;
    ! bar.style.cssText = "position:fixed; top:0; left:0; z-index: 499; width:100%; background-color:#222;";
    ! document.getElementsByTagName('body')[0].appendChild(bar);
    ProcedureReturn #True
EndProcedure

Procedure AddMenuButton(menuId.s,id.s,title.s)
    ! var elem    = document.getElementById(v_menuid);
    ! var btndiv  = document.createElement("div");
    ! btndiv.style.cssText = "float:left; overflow:hidden;";
    ! var btn     = document.createElement("button");
    ! btndiv.appendChild( btn );
    ! var subMenu = document.createElement("div");
    ! subMenu.id  = v_id+"_subMenu";
    ! subMenu.style.cssText = "display: none; position: absolute; min-width: 150px; z-index: 500; box-shadow: 0px 18px 26px 0px rgba(0,0,0,0.8); };";
    ! btn.appendChild( document.createTextNode(v_title) );
    ! btndiv.appendChild( subMenu );
    ! btn.id               = v_id;
    ! btn.style.cssText    = "";
    ! btn.style.fontSize   = '16px';    btn.style.backgroundColor = 'inherit';
    ! btn.style.color      = '#ccc';    btn.style.border     = 'none';
    ! btn.style.margin     = '0';       btn.style.padding    = '10px 10px';
    ! btn.style.cursor     = 'pointer'; btn.style.outline    = 'none';
    ! btn.onmouseover      = function() { this.style.backgroundColor = '#888';
    !                                     document.getElementById(v_id+"_subMenu").style.display = 'block'; };
    ! btn.onmouseout       = function() { this.style.backgroundColor = '#222';
    !                                     document.getElementById(v_id+"_subMenu").style.display = 'none'; };
    ! if(elem != null) elem.appendChild(btndiv);
EndProcedure

Procedure AddMenuEntry(buttonID.s, title.s, value, callback.MenuButtonClicked=0)
    ! var elem    = document.getElementById(v_buttonid+"_subMenu");
    ! if(elem!=null) {
    !   var btn = document.createElement("a");
    !   btn.appendChild( document.createTextNode(v_title) );
    !   btn.id = v_buttonid+"-"+v_title;
    !   btn.value = v_value;
    !   btn.display = 'block';
    !   btn.style.cssText = "float:none; text-decoration:none; display: block; text-align: left;";
    !   btn.style.fontSize   = '16px';    btn.style.background = '#222';
    !   btn.style.color      = '#ccc';    btn.style.border     = 'none';
    !   btn.style.margin     = '0';       btn.style.padding    = '6px 10px';
    !   btn.style.cursor     = 'pointer'; btn.style.outline    = 0;
    !   btn.onmouseover      = function() { this.style.backgroundColor = '#888'; document.getElementById(v_buttonid+"_subMenu").style.display = 'block'; };
    !   btn.onmouseout       = function() { this.style.backgroundColor = '#222'; document.getElementById(v_buttonid+"_subMenu").style.display = 'none'; };
    !   btn.onclick          = function() { var b = document.getElementById(v_buttonid+"_subMenu"); b.style.display = 'none'; if(v_callback!=0) v_callback(this.value); };
    !   elem.appendChild(btn);
    ! }
EndProcedure

Procedure AddMenuDivider(buttonID.s)
    ! var elem    = document.getElementById(v_buttonid+"_subMenu");
    ! if(elem!=null){
    !   var hr = document.createElement("hr");
    !   hr.display = 'block';
    !   hr.style.cssText = "display: block; padding: 0; margin:0; border-width:0.5px; border-style: solid; border-color: #888; ";
    !   hr.style.backgroundColor = '#222';
    !   hr.onmouseover      = function() { this.style.backgroundColor = '#888'; document.getElementById(v_buttonid+"_subMenu").style.display = 'block'; };
    !   hr.onmouseout       = function() { this.style.backgroundColor = '#222'; document.getElementById(v_buttonid+"_subMenu").style.display = 'none'; };
    !   elem.appendChild(hr);
    ! }
EndProcedure


;--[ CREATE APP MENU ]----------------------------------


Procedure OnMenuBtnClicked(id)
    ;! alert('menu button clicked: '+v_id);
    ;! console.log('AppMenuEvent. ID: '+v_id);
    AddGadgetItem(2,-1,"AppMenuEvent. ID = '"+id+"'")
EndProcedure

If CreateAppMenu("myMenu")
    ; Create the menu
    AddMenuButton("myMenu","myFileMenu"    ,"File")
    AddMenuButton("myMenu","myEditMenu"    ,"Edit")
    AddMenuButton("myMenu","myCompilerMenu","Compiler")
    AddMenuButton("myMenu","myDebuggerMenu","Debugger")
    AddMenuButton("myMenu","myToolsMenu"   ,"Tools")
    AddMenuButton("myMenu","myHelpMenu"    ,"Help")
    
    ; Add entries to file menu
    AddMenuEntry("myFileMenu", "New"                    ,  101 ,@OnMenuBtnClicked())
    AddMenuEntry("myFileMenu", "Open"                   ,  102 ,@OnMenuBtnClicked())
    AddMenuEntry("myFileMenu", "Save"                   ,  103 ,@OnMenuBtnClicked())
    AddMenuEntry("myFileMenu", "Save As..."             ,  104 ,@OnMenuBtnClicked())
    AddMenuEntry("myFileMenu", "Save All"               ,  105 ,@OnMenuBtnClicked())
    AddMenuEntry("myFileMenu", "Reload"                 ,  106 ,@OnMenuBtnClicked())
    AddMenuEntry("myFileMenu", "Close"                  ,  107 ,@OnMenuBtnClicked())
    AddMenuEntry("myFileMenu", "Close All"              ,  108 ,@OnMenuBtnClicked())
    
    ; Add entries to edit menu
    AddMenuEntry("myEditMenu", "Undo"                   ,  201 ,@OnMenuBtnClicked())
    AddMenuEntry("myEditMenu", "Redo"                   ,  202 ,@OnMenuBtnClicked())
    AddMenuDivider("myEditMenu")
    AddMenuEntry("myEditMenu", "Cut"                    ,  203 ,@OnMenuBtnClicked())
    AddMenuEntry("myEditMenu", "Copy"                   ,  204 ,@OnMenuBtnClicked())
    AddMenuEntry("myEditMenu", "Paste"                  ,  205 ,@OnMenuBtnClicked())
    AddMenuDivider("myEditMenu")
    AddMenuEntry("myEditMenu", "Insert comments"        ,  206 ,@OnMenuBtnClicked())
    AddMenuEntry("myEditMenu", "Remove comments"        ,  207 ,@OnMenuBtnClicked())
    AddMenuEntry("myEditMenu", "Format indentation"     ,  208 ,@OnMenuBtnClicked())
    AddMenuDivider("myEditMenu")
    AddMenuEntry("myEditMenu", "Select All"             ,  209 ,@OnMenuBtnClicked())
    AddMenuDivider("myEditMenu")
    AddMenuEntry("myEditMenu", "Find/Replace"           ,  210 ,@OnMenuBtnClicked())
    AddMenuEntry("myEditMenu", "Find Next"              ,  211 ,@OnMenuBtnClicked())
    AddMenuEntry("myEditMenu", "Find Previous"          ,  212 ,@OnMenuBtnClicked())
    AddMenuEntry("myEditMenu", "Find in files..."       ,  213 ,@OnMenuBtnClicked())
    
    ; Add entries to compiler menu
    AddMenuEntry("myCompilerMenu", "Compile/Run"        ,  301 ,@OnMenuBtnClicked())
    
    ; Add entries to debugger menu
    AddMenuEntry("myDebuggerMenu", "Debug"              ,  401 ,@OnMenuBtnClicked())
    
    ; Add entries to tools menu
    AddMenuEntry("myToolsMenu", "File Viewer"           ,  501 ,@OnMenuBtnClicked())
    AddMenuEntry("myToolsMenu", "Structure Viewer"      ,  502 ,@OnMenuBtnClicked())
    AddMenuEntry("myToolsMenu", "Variable Viewer"       ,  503 ,@OnMenuBtnClicked())
    AddMenuEntry("myToolsMenu", "Compare Files/Folders" ,  504 ,@OnMenuBtnClicked())
    AddMenuEntry("myToolsMenu", "Procedure Browser"     ,  505 ,@OnMenuBtnClicked())
    AddMenuEntry("myToolsMenu", "Issue Browser"         ,  506 ,@OnMenuBtnClicked())
    AddMenuEntry("myToolsMenu", "Project Panel"         ,  507 ,@OnMenuBtnClicked())
    AddMenuEntry("myToolsMenu", "Templates"             ,  508 ,@OnMenuBtnClicked())
    AddMenuEntry("myToolsMenu", "Explorer"              ,  509 ,@OnMenuBtnClicked())
    AddMenuEntry("myToolsMenu", "Color Picker"          ,  510 ,@OnMenuBtnClicked())
    AddMenuEntry("myToolsMenu", "Character Table"       ,  511 ,@OnMenuBtnClicked())
    AddMenuDivider("myToolsMenu")
    AddMenuEntry("myToolsMenu", "Configure Tools"       ,  512 ,@OnMenuBtnClicked())
    
    ; Add entries to debugger menu
    AddMenuEntry("myHelpMenu" , "Help (F1)"             ,  601 ,@OnMenuBtnClicked())
EndIf


;--[ CREATE STATUS BAR ]----------------------------------


CreateAppStatusbar("myStatusbar")
SetAppStatusbarText("myStatusbar", "App ready.")


;--[ CREATE SPIDERBASIC APP ]----------------------------------


Procedure CloseWindowEvent()
  AddGadgetItem(2,-1,"Closing window: " + EventWindow())
  CloseWindow(EventWindow()) ; Close the specific window
EndProcedure

Procedure Button1Pressed()
    AddGadgetItem(2,-1,"Button 1 pressed.")
EndProcedure

OpenWindow(0,0,0,0,0,"",#PB_Window_Background):SetWindowColor(0,RGB(200,200,200))
  ButtonGadget(1,10,50,150,25,"Button 1")
  ListViewGadget(2,10,90,300,450)

OpenWindow(1, 400, 90, 320, 200, "Window 0 - Resizable", #PB_Window_SizeGadget)
OpenWindow(2, 400,400, 320, 200, "Window 1")
OpenWindow(3, 800, 90, 320, 200, "Window 2")

BindGadgetEvent(1,@Button1Pressed())
BindEvent(#PB_Event_CloseWindow, @CloseWindowEvent())

AddGadgetItem(2,-1,"Ready.")
Last edited by Danilo on Tue Jan 07, 2020 5:59 am, edited 1 time in total.
cya,
...Danilo
User avatar
Danilo
Posts: 51
Joined: Wed Feb 26, 2014 7:11 am

Re: AppMenu for browser apps

Post by Danilo »

Added statusbar.
cya,
...Danilo
Dirk Geppert
Posts: 282
Joined: Fri Sep 22, 2017 7:02 am

Re: AppMenu for browser apps

Post by Dirk Geppert »

Cool stuff! Thx Danilo.

I tested it also on a smartphone. Unfortunately there is a problem with the Safari browser when using the landscape mode and going to full screen. Then you can only click the button, but not the AppMenu.

cya Dirk
User avatar
Danilo
Posts: 51
Joined: Wed Feb 26, 2014 7:11 am

Re: AppMenu for browser apps

Post by Danilo »

Dirk Geppert wrote:I tested it also on a smartphone. Unfortunately there is a problem with the Safari browser when using the landscape mode and going to full screen. Then you can only click the button, but not the AppMenu.
I see. Looks like mobile Safari does not like clicks at the very top of the screen.

It actually works if you don't touch the screen at the very top.
If you hit the menu buttons at the bottom, it works. :D

You can make it work better for mobile landscape mode by adding a margin to the top of the screen.
I tested with 10 pixels and it worked, 15 pixels was perfect.

I added the top-margin in the AddMenuButton() procedure at line 53:

Old line:

Code: Select all

    ! btn.style.margin     = '0';       btn.style.padding    = '10px 10px';
New line:

Code: Select all

    ! btn.style.margin     = '15px 0 0 0';       btn.style.padding    = '10px 10px';
If you would like to make the menu buttons larger, you could increase the font size at line 51,
or increase btn.style.padding at line 53.

Here is a screenshot with added top-margin on iPhone:
Image
cya,
...Danilo
Dirk Geppert
Posts: 282
Joined: Fri Sep 22, 2017 7:02 am

Re: AppMenu for browser apps

Post by Dirk Geppert »

Yeah, thx. That seems to mitigate the problem. However, with a margin at 15px, you still have to tap very close to the bottom of the appbar, to get an reaction.
May we have to use some meta tags in the header, to make the page behave more like an app.

In the chat you had shown new fancy gui elements. Especially the ToggleCheckbox would interest me.
Do you plan to post the tip on how to restyle it?
Post Reply