; MaterialSB - A MaterializeCSS wrapper for SpiderBasic ; ; This library replaces SpiderBasic's default UI with MaterializeCSS components. ; Components are designed to closely match their Materialize equivalents. ; ; Usage: ; IncludeFile "MaterialSB/MaterialSB.sbi" ; MaterialSB::Download(@MyCallback()) ; ; For documentation, see: https://materializeweb.com/ DeclareModule MaterialSB ;{ Initialization Declare Download(*callback) Declare AutoInit() Declare Init(Element, Options) ;} ;{ Parent Management Declare CloseCurrentParent(depth = 1) Declare GetCurrentParent() Declare SetCurrentParent(Parent) ;} ;{ HTML Helpers Declare.s Paragraph(Text.s, Color.s = "") Declare.s Paragraph_ex(Text.s, Class.s = "", Style.s = "") Declare.s Header(Text.s, Level, Color.s = "") Declare.s Header_ex(Text.s, Level, Class.s = "", Style.s = "") Declare Append(Content.s, Parent = #Null) Declare.s Link(Text.s, *Callback, Color.s = "") Declare.s Link_ex(Text.s, *Callback, Class.s = "", Style.s = "") ;} ;{ Element Manipulation Declare SetAttribute(Element, Attribute.s, Value.s) Declare SetClass(Element, Class.s) Declare SetContent(Element, Content.s) Declare AddClass(Element, Class.s) Declare AddContent(Element, Content.s) Declare GetValue(Element) Declare SetValue(Element, Value.s) ;} ;{ Theme Declare GetDarkThemeState() Declare SetDarkTheme(State) ;} ;{ Style Constants #Class_Hide_On_Small_Only = "hide-on-small-only" #Class_Hide_On_Small_And_Down = "hide-on-small-and-down" #Class_Hide_On_Med_And_Down = "hide-on-med-and-down" #Class_Hide_On_Med_And_Up = "hide-on-med-and-up" #Class_Hide_On_Med_Only = "hide-on-med-only" #Class_Hide_On_Large_Only = "hide-on-large-only" #Class_Show_On_Large = "show-on-large" #Class_Show_On_Medium = "show-on-medium" #Class_Show_On_Small = "show-on-small" #Class_Show_On_Medium_And_Up = "show-on-medium-and-up" #Class_Show_On_Medium_And_Down = "show-on-medium-and-down" #Class_Pulse = "pulse" #Class_Centered = "center-align" #Class_LeftAlign = "left-align" #Class_RightAlign = "right-align" ;} ;{ Color Constants ; Base colors #Color_Red = "red" #Color_Pink = "pink" #Color_Purple = "purple" #Color_DeepPurple = "deep-purple" #Color_Indigo = "indigo" #Color_Blue = "blue" #Color_LightBlue = "light-blue" #Color_Cyan = "cyan" #Color_Teal = "teal" #Color_Green = "green" #Color_LightGreen = "light-green" #Color_Lime = "lime" #Color_Yellow = "yellow" #Color_Amber = "amber" #Color_Orange = "orange" #Color_DeepOrange = "deep-orange" #Color_Brown = "brown" #Color_Grey = "grey" #Color_BlueGrey = "blue-grey" #Color_Black = "black" #Color_White = "white" #Color_Transparent = "transparent" ; Color modifiers (append to base color) #Color_Lighten_5 = " lighten-5" #Color_Lighten_4 = " lighten-4" #Color_Lighten_3 = " lighten-3" #Color_Lighten_2 = " lighten-2" #Color_Lighten_1 = " lighten-1" #Color_Darken_1 = " darken-1" #Color_Darken_2 = " darken-2" #Color_Darken_3 = " darken-3" #Color_Darken_4 = " darken-4" #Color_Accent_1 = " accent-1" #Color_Accent_2 = " accent-2" #Color_Accent_3 = " accent-3" #Color_Accent_4 = " accent-4" #Color_Text = "-text" ;} ;{ Navbar EnumerationBinary NavbarFlags #Navbar_Default = 0 #Navbar_Align_Right = 1 #Navbar_Align_Center #Navbar_Bottom #Navbar_Shadow1 #Navbar_Shadow2 #Navbar_Shadow3 #Navbar_Container EndEnumeration Declare Navbar(Flags = #Navbar_Default) Declare NavbarAddLogo(Text.s, ImagePath.s = "", Link.s = "", Flags = #Navbar_Default, Parent = #Null) Declare NavbarAddLink(Text.s, Link.s, Parent = #Null) Declare NavbarAddSidenavTrigger(SidenavID.s, Parent = #Null) ;} ;{ Sidenav EnumerationBinary SidenavFlags #Sidenav_Default = 0 #Sidenav_Fixed = 1 #Sidenav_Right #Sidenav_CloseOnClick EndEnumeration Declare Sidenav(Flags = #Sidenav_Default) Declare SidenavAddLink(Text.s, Link.s, Icon.s = "", Parent = #Null) Declare SidenavAddDivider(Parent = #Null) Declare SidenavAddSubheader(Text.s, Parent = #Null) Declare SidenavAddUserView(Name.s, Email.s, AvatarPath.s = "", BackgroundPath.s = "", Parent = #Null) ;} ;{ Grid EnumerationBinary GridFlags #Grid_Default = 0 #Grid_Container = 1 EndEnumeration Declare Row(Flags = #Grid_Default, Parent = #Null) Declare Col(S, M = 0, L = 0, XL = 0, Flags = #Grid_Default, Parent = #Null) ;} ;{ Media EnumerationBinary MediaFlags #Media_Default = 0 #Media_Responsive = 1 #Media_Circle #Media_Controls EndEnumeration Declare Image(Source.s, Alt.s = "", Flags = #Media_Default, Parent = #Null) Declare Video(Source.s, Type.s = "video/mp4", Flags = #Media_Default, Parent = #Null) Declare YoutubeVideo(Source.s, Flags = #Media_Default, Parent = #Null) ;} ;{ Table EnumerationBinary TableFlags #Table_Default = 0 #Table_Striped = 1 #Table_Highlight #Table_Centered #Table_Responsive EndEnumeration Declare Table(Title.s, Flags = #Table_Default, Parent = #Null) Declare TableAddColumn(Title.s, Table) Declare TableAddItem(Text.s, Table) Declare TableSetText(Text.s, Item, ColumnIndex) ;} ;{ Button EnumerationBinary ButtonFlags #Button_Default = 0 #Button_Tonal = 1 #Button_Outlined #Button_Elevated #Button_Text #Button_Floating #Button_Large #Button_Small #Button_IconLeft #Button_Disabled EndEnumeration Declare Button(Text.s, *Callback, Flags = #Button_Default, Parent = #Null) Declare ButtonSetCallback(Button, *Callback) ;} ;{ Card EnumerationBinary CardFlags #Card_Default = 0 #Card_Panel = 1 #Card_Small #Card_Medium #Card_Large #Card_Horizontal EndEnumeration Declare Card(Text.s = "", Flags = #Card_Default, Parent = #Null) Declare CardImage(Source.s, Parent = #Null) Declare CardContent(Parent = #Null) Declare CardTitle(Text.s, Parent = #Null) Declare CardAction(Parent = #Null) ;} ;{ Carousel EnumerationBinary CarouselFlags #Carousel_Default = 0 #Carousel_Slider = 1 EndEnumeration Declare Carousel(Flags = #Carousel_Default, Parent = #Null) Declare CarouselAddItem(Carousel, ImageSource.s, Link.s) ;} ;{ Tabs EnumerationBinary TabFlags #Tab_Default = 0 #Tab_Disabled = 1 EndEnumeration Declare Tab(Flags = #Tab_Default, Parent = #Null) Declare TabAddItem(Title.s, Tab, ID.s, Flags = #Tab_Default) ;} ;{ Modal EnumerationBinary ModalFlags #Modal_Default = 0 #Modal_FixedFooter = 1 #Modal_BottomSheet #Modal_Dismissible EndEnumeration Declare Modal(Flags = #Modal_Default) Declare ModalHeader(Text.s, Parent = #Null) Declare ModalContent(Parent = #Null) Declare ModalFooter(Parent = #Null) Declare ModalOpen(ModalElement) Declare ModalClose(ModalElement) ;} ;{ Toast EnumerationBinary ToastFlags #Toast_Default = 0 #Toast_Rounded = 1 EndEnumeration Declare Toast(Text.s, Duration = 4000, Flags = #Toast_Default, Color.s = "") Declare ToastDismissAll() ;} ;{ Forms EnumerationBinary InputFlags #Input_Default = 0 #Input_Outlined = 1 #Input_Password #Input_Email #Input_Number #Input_Tel #Input_Url #Input_Date #Input_Time #Input_Disabled #Input_Readonly EndEnumeration EnumerationBinary TextareaFlags #Textarea_Default = 0 #Textarea_Outlined = 1 #Textarea_Disabled #Textarea_Readonly EndEnumeration EnumerationBinary CheckboxFlags #Checkbox_Default = 0 #Checkbox_Filled = 1 #Checkbox_Checked #Checkbox_Disabled EndEnumeration EnumerationBinary RadioFlags #Radio_Default = 0 #Radio_WithGap = 1 #Radio_Checked #Radio_Disabled EndEnumeration EnumerationBinary SwitchFlags #Switch_Default = 0 #Switch_Checked = 1 #Switch_Disabled EndEnumeration EnumerationBinary SelectFlags #Dropdown_Default = 0 #Dropdown_Outlined = 1 #Dropdown_Multiple #Dropdown_Disabled EndEnumeration EnumerationBinary RangeFlags #Range_Default = 0 #Range_Disabled = 1 EndEnumeration Declare TextInput(Label.s = "", Placeholder.s = "", Flags = #Input_Default, Parent = #Null) Declare Textarea(Label.s = "", Placeholder.s = "", Flags = #Textarea_Default, Parent = #Null) Declare Checkbox(Label.s, Flags = #Checkbox_Default, Parent = #Null) Declare Radio(Name.s, Label.s, Flags = #Radio_Default, Parent = #Null) Declare Switch(LabelOff.s, LabelOn.s, Flags = #Switch_Default, Parent = #Null) Declare Dropdown(Label.s = "", Flags = #Dropdown_Default, Parent = #Null) Declare DropdownAddOption(Text.s, Value.s, DropdownElement, Selected = #False) Declare Range(Min = 0, Max = 100, Value = 50, Flags = #Range_Default, Parent = #Null) Declare InputSetCallback(InputElement, *Callback) ;} EndDeclareModule Module MaterialSB EnableExplicit ;{ Private Variables Global download_callback Global current_parent Global current_navbar Global current_sidenav Global current_modal Global dropdown_menu_index = 0 Global input_id_counter = 0 Global NewList parent_list() ;} ;{ Private Macros Macro CheckParent() If Parent = #Null If current_parent = #Null !materialsb$g_current_parent = document.body.firstElementChild; EndIf Parent = current_parent EndIf EndMacro Macro PushParent() AddElement(parent_list()) parent_list() = current_parent EndMacro ;} ;{ Private Declarations Declare Handler_Download(url.s, success) ;} ;=========================================================================== ; Initialization ;=========================================================================== Procedure Download(*callback) download_callback = *callback LoadScript("LocalFiles/CSS/materialize.min.css", @Handler_Download(), #PB_Script_CSS) EndProcedure Procedure AutoInit() !M.AutoInit(); EndProcedure Procedure Init(Element, Options) Protected check !v_check = v_element.matches(".carousel"); If check !M.Carousel.init(v_element, v_options); ProcedureReturn #True EndIf !v_check = v_element.matches("select"); If check !M.FormSelect.init(v_element, v_options); ProcedureReturn #True EndIf !v_check = v_element.matches(".sidenav"); If check !M.Sidenav.init(v_element, v_options); ProcedureReturn #True EndIf !v_check = v_element.matches(".modal"); If check !M.Modal.init(v_element, v_options); ProcedureReturn #True EndIf ProcedureReturn #False EndProcedure ;=========================================================================== ; Parent Management ;=========================================================================== Procedure CloseCurrentParent(depth = 1) While depth > 0 And ListSize(parent_list()) current_parent = parent_list() DeleteElement(parent_list()) depth - 1 Wend ProcedureReturn current_parent EndProcedure Procedure GetCurrentParent() ProcedureReturn current_parent EndProcedure Procedure SetCurrentParent(Parent) PushParent() current_parent = Parent ProcedureReturn current_parent EndProcedure ;=========================================================================== ; HTML Helpers ;=========================================================================== Procedure.s Paragraph(Text.s, Color.s = "") Protected Result.s, Count = CountString(Text, ~"\n") + 1, i If Color = "" Result = "

" Else Result = ~"

" EndIf Result + StringField(Text, 1, ~"\n") For i = 2 To Count Result + "
" + StringField(Text, i, ~"\n") Next ProcedureReturn Result + "

" EndProcedure Procedure.s Paragraph_ex(Text.s, Class.s = "", Style.s = "") Protected Result.s = " "" Result + ~" class=\"" + Class + ~"\"" EndIf If Style <> "" Result + ~" style=\"" + Style + ~"\"" EndIf Result + ">" Result + StringField(Text, 1, ~"\n") For i = 2 To Count Result + "
" + StringField(Text, i, ~"\n") Next ProcedureReturn Result + "

" EndProcedure Procedure.s Header(Text.s, Level, Color.s = "") Protected Result.s = " "" Result + ~" class=\"" + Color + ~"-text\"" EndIf ProcedureReturn Result + ">" + Text + "" EndProcedure Procedure.s Header_ex(Text.s, Level, Class.s = "", Style.s = "") Protected Result.s = " "" Result + ~" class=\"" + Class + ~"\"" EndIf If Style <> "" Result + ~" style=\"" + Style + ~"\"" EndIf ProcedureReturn Result + ">" + Text + "" EndProcedure Procedure Append(Content.s, Parent = #Null) CheckParent() !v_parent.innerHTML += v_content; EndProcedure Procedure.s Link(Text.s, *Callback, Color.s = "") Protected Result.s, Callback.s, Pos If Color <> "" Color = ~" class=\"" + Color + ~"-text\"" EndIf If *Callback = #Null Result = ~"" Else ; A very hacky approach to to approach native SB behavior: we need to get the name of the function out of the callback ! v_callback = String(p_callback); Pos = FindString(Callback, "(") - 10 Callback = Mid(Callback, 10, Pos) Result = ~"" EndIf Result + Text + "" ProcedureReturn Result EndProcedure Procedure.s Link_ex(Text.s, *Callback, Class.s = "", Style.s = "") Protected Result.s = ~" "" Result + ~" class=\"" + Class + ~"\"" EndIf If Style <> "" Result + ~" style=\"" + Style + ~"\"" EndIf If *Callback <> #Null ; A very hacky approach to approach native SB behavior: we need to get the name of the function out of the callback ! v_callback = String(p_callback); Pos = FindString(Callback, "(") - 10 Callback = Mid(Callback, 10, Pos) Result + ~" onclick=\"" + Callback + ~"()\"" EndIf Result + ">" + Text + "" ProcedureReturn Result EndProcedure ;=========================================================================== ; Element Manipulation ;=========================================================================== Procedure SetAttribute(Element, Attribute.s, Value.s) !v_element.setAttribute(v_attribute, v_value); EndProcedure Procedure SetClass(Element, Class.s) !v_element.className = v_class; EndProcedure Procedure SetContent(Element, Content.s) !v_element.innerHTML = v_content; EndProcedure Procedure AddClass(Element, Class.s) Protected Count = CountString(Class, " ") + 1, i, ClassName.s For i = 1 To Count ClassName = StringField(Class, i, " ") !v_element.classList.add(v_classname); Next EndProcedure Procedure AddContent(Element, Content.s) !v_element.insertAdjacentHTML('beforeend', v_content); EndProcedure Procedure GetValue(Element) Protected Result !v_result = v_element.value; ProcedureReturn Result EndProcedure Procedure SetValue(Element, Value.s) !v_element.value = v_value; EndProcedure ;=========================================================================== ; Theme ;=========================================================================== Procedure GetDarkThemeState() Protected theme.s !v_theme = document.documentElement.getAttribute("theme"); ProcedureReturn Bool(theme = "dark") EndProcedure Procedure SetDarkTheme(State) If Bool(State) <> GetDarkThemeState() If State !document.documentElement.setAttribute("theme", "dark"); Else !document.documentElement.setAttribute("theme", "light"); EndIf EndIf EndProcedure ;=========================================================================== ; Navbar ;=========================================================================== Procedure Navbar(Flags = #Navbar_Default) Protected Wrapper !materialsb$g_current_navbar = document.createElement('nav'); If Flags & #Navbar_Bottom !materialsb$g_current_navbar.style.position = "absolute"; !materialsb$g_current_navbar.style.bottom = "0"; EndIf If Flags & #Navbar_Shadow1 !materialsb$g_current_navbar.classList.add("z-depth-1"); ElseIf Flags & #Navbar_Shadow2 !materialsb$g_current_navbar.classList.add("z-depth-2"); ElseIf Flags & #Navbar_Shadow3 !materialsb$g_current_navbar.classList.add("z-depth-5"); EndIf !v_wrapper = document.createElement('div'); !v_wrapper.className = "nav-wrapper"; If Flags & #Navbar_Container !v_wrapper.classList.add("container"); EndIf !materialsb$g_current_navbar.append(v_wrapper); !document.body.prepend(materialsb$g_current_navbar); ProcedureReturn Wrapper EndProcedure Procedure NavbarAddLogo(Text.s, ImagePath.s = "", Link.s = "", Flags = #Navbar_Default, Parent = #Null) Protected Logo If Parent = #Null !v_parent = materialsb$g_current_navbar.firstElementChild; Else !v_parent = v_parent.firstElementChild; EndIf If ImagePath <> "" !v_text = '' + v_text + ''; EndIf If Link = "" !v_parent.innerHTML += ''; Else !v_parent.innerHTML += ''; EndIf !v_logo = v_parent.lastElementChild; If Flags & #Navbar_Align_Center !v_logo.classList.add("center"); ElseIf Flags & #Navbar_Align_Right !v_logo.classList.add("right"); ; Remove right alignment from any existing UL elements !for (const child of v_parent.children) { ! if (child.tagName === 'UL') child.classList.remove("right"); !} EndIf ProcedureReturn Logo EndProcedure Procedure NavbarAddLink(Text.s, Link.s, Parent = #Null) Protected LinkElement If Parent = #Null !v_parent = materialsb$g_current_navbar.firstElementChild; EndIf ; Find existing list elements !var _list = null, _dropdown = null; !for (const child of v_parent.children) { ! if (child.tagName === 'UL' && child.classList.contains("hide-on-med-and-down")) _list = child; ! if (child.tagName === 'UL' && child.classList.contains("dropdown-content")) _dropdown = child; !} ; Create lists if this is the first link !if (_list === null) { ! var _rightLogo = false; ! for (const child of v_parent.children) { ! if (child.tagName === 'A' && child.classList.contains("right")) { _rightLogo = true; break; } ! } ! var _menuId = 'materialsb_dropdown' + materialsb$g_dropdown_menu_index; ! v_parent.innerHTML += ''; ! if (_rightLogo) { ! v_parent.innerHTML += ''; ! v_parent.innerHTML += ''; ! } else { ! v_parent.innerHTML += ''; ! v_parent.innerHTML += ''; ! } ! v_linkelement = v_parent.lastElementChild.lastElementChild; !} else { ! _list.innerHTML += '
  • ' + v_text + '
  • '; ! _dropdown.innerHTML += '
  • ' + v_text + '
  • '; ! v_linkelement = _list.lastElementChild; !} dropdown_menu_index + 1 ProcedureReturn LinkElement EndProcedure Procedure NavbarAddSidenavTrigger(SidenavID.s, Parent = #Null) Protected Trigger If Parent = #Null !v_parent = materialsb$g_current_navbar.firstElementChild; EndIf !v_trigger = document.createElement('a'); !v_trigger.href = "#"; !v_trigger.setAttribute('data-target', v_sidenavid); !v_trigger.className = "sidenav-trigger"; !v_trigger.innerHTML = 'menu'; !v_parent.prepend(v_trigger); ProcedureReturn Trigger EndProcedure ;=========================================================================== ; Sidenav ;=========================================================================== Procedure Sidenav(Flags = #Sidenav_Default) !materialsb$g_current_sidenav = document.createElement('ul'); !materialsb$g_current_sidenav.className = "sidenav"; If Flags & #Sidenav_Fixed !materialsb$g_current_sidenav.classList.add("sidenav-fixed"); EndIf ; Sidenav must be added to body, not inside navbar !document.body.append(materialsb$g_current_sidenav); ProcedureReturn current_sidenav EndProcedure Procedure SidenavAddLink(Text.s, Link.s, Icon.s = "", Parent = #Null) Protected Result If Parent = #Null !v_parent = materialsb$g_current_sidenav; EndIf !v_result = document.createElement('li'); If Icon <> "" !v_result.innerHTML = '' + v_icon + '' + v_text + ''; Else !v_result.innerHTML = '' + v_text + ''; EndIf !v_parent.append(v_result); ProcedureReturn Result EndProcedure Procedure SidenavAddDivider(Parent = #Null) Protected Result If Parent = #Null !v_parent = materialsb$g_current_sidenav; EndIf !v_result = document.createElement('li'); !v_result.innerHTML = '
    '; !v_parent.append(v_result); ProcedureReturn Result EndProcedure Procedure SidenavAddSubheader(Text.s, Parent = #Null) Protected Result If Parent = #Null !v_parent = materialsb$g_current_sidenav; EndIf !v_result = document.createElement('li'); !v_result.innerHTML = '' + v_text + ''; !v_parent.append(v_result); ProcedureReturn Result EndProcedure Procedure SidenavAddUserView(Name.s, Email.s, AvatarPath.s = "", BackgroundPath.s = "", Parent = #Null) Protected Result If Parent = #Null !v_parent = materialsb$g_current_sidenav; EndIf !v_result = document.createElement('li'); !var _userView = document.createElement('div'); !_userView.className = "user-view"; ; Background If BackgroundPath <> "" !var _bg = document.createElement('div'); !_bg.className = "background"; !_bg.innerHTML = ''; !_userView.append(_bg); EndIf ; Avatar If AvatarPath <> "" !var _avatar = document.createElement('a'); !_avatar.href = "#user"; !_avatar.innerHTML = ''; !_userView.append(_avatar); EndIf ; Name If Name <> "" !var _name = document.createElement('a'); !_name.href = "#name"; !_name.innerHTML = '' + v_name + ''; !_userView.append(_name); EndIf ; Email If Email <> "" !var _email = document.createElement('a'); !_email.href = "#email"; !_email.innerHTML = '' + v_email + ''; !_userView.append(_email); EndIf !v_result.append(_userView); !v_parent.append(v_result); ProcedureReturn Result EndProcedure ;=========================================================================== ; Grid ;=========================================================================== Procedure Row(Flags = #Grid_Default, Parent = #Null) CheckParent() PushParent() !materialsb$g_current_parent = document.createElement('div'); !materialsb$g_current_parent.className = "row"; If Flags & #Grid_Container !materialsb$g_current_parent.classList.add("container"); EndIf !v_parent.append(materialsb$g_current_parent); ProcedureReturn current_parent EndProcedure Procedure Col(S, M = 0, L = 0, XL = 0, Flags = #Grid_Default, Parent = #Null) CheckParent() PushParent() !materialsb$g_current_parent = document.createElement('div'); !materialsb$g_current_parent.className = "col s" + v_s; If M !materialsb$g_current_parent.classList.add("m" + v_m); EndIf If L !materialsb$g_current_parent.classList.add("l" + v_l); EndIf If XL !materialsb$g_current_parent.classList.add("xl" + v_xl); EndIf If Flags & #Grid_Container !materialsb$g_current_parent.classList.add("container"); EndIf !v_parent.append(materialsb$g_current_parent); ProcedureReturn current_parent EndProcedure ;=========================================================================== ; Media ;=========================================================================== Procedure Image(Source.s, Alt.s = "", Flags = #Media_Default, Parent = #Null) Protected Result CheckParent() !v_result = document.createElement('img'); !v_result.src = v_source; !v_result.alt = v_alt; If Flags & #Media_Circle !v_result.classList.add("circle"); EndIf If Flags & #Media_Responsive !v_result.classList.add("responsive-img"); EndIf !v_parent.append(v_result); ProcedureReturn Result EndProcedure Procedure Video(Source.s, Type.s = "video/mp4", Flags = #Media_Default, Parent = #Null) Protected Result CheckParent() !v_result = document.createElement('video'); !v_result.innerHTML = ''; If Flags & #Media_Controls !v_result.controls = true; EndIf If Flags & #Media_Responsive !v_result.classList.add("responsive-video"); EndIf !v_parent.append(v_result); ProcedureReturn Result EndProcedure Procedure YoutubeVideo(Source.s, Flags = #Media_Default, Parent = #Null) Protected Result CheckParent() !v_result = document.createElement('div'); If Flags & #Media_Responsive !v_result.classList.add("video-container"); EndIf !v_result.innerHTML = ''; !v_parent.append(v_result); ProcedureReturn Result EndProcedure ;=========================================================================== ; Table ;=========================================================================== Procedure Table(Title.s, Flags = #Table_Default, Parent = #Null) Protected Result CheckParent() !v_result = document.createElement('table'); !var _thead = document.createElement('thead'); !var _tr = document.createElement('tr'); !var _th = document.createElement('th'); !_th.innerHTML = v_title; !var _tbody = document.createElement('tbody'); If Flags & #Table_Striped !v_result.classList.add("striped"); EndIf If Flags & #Table_Highlight !v_result.classList.add("highlight"); EndIf If Flags & #Table_Centered !v_result.classList.add("centered"); EndIf If Flags & #Table_Responsive !v_result.classList.add("responsive-table"); EndIf !_tr.append(_th); !_thead.append(_tr); !v_result.append(_thead); !v_result.append(_tbody); !v_parent.append(v_result); ProcedureReturn Result EndProcedure Procedure TableAddColumn(Title.s, Table) Protected Result !v_result = document.createElement('th'); !v_result.innerHTML = v_title; !v_table.firstChild.firstChild.append(v_result); ProcedureReturn Result EndProcedure Procedure TableAddItem(Text.s, Table) Protected Result, Count, i, ColumnText.s !v_result = document.createElement('tr'); !v_count = Math.min(v_table.firstChild.firstChild.childElementCount, v_text.split('\n').length); For i = 1 To Count ColumnText = StringField(Text, i, Chr(10)) !var _td = document.createElement('td'); !_td.innerHTML = v_columntext; !v_result.append(_td); Next !v_table.lastChild.append(v_result); ProcedureReturn Result EndProcedure Procedure TableSetText(Text.s, Item, ColumnIndex) Protected Count !v_count = v_item.childElementCount; While Count < (ColumnIndex + 1) !v_item.append(document.createElement('td')); Count + 1 Wend !v_item.children[v_columnindex].innerHTML = v_text; EndProcedure ;=========================================================================== ; Button ;=========================================================================== Procedure Button(Text.s, *Callback, Flags = #Button_Default, Parent = #Null) Protected Result CheckParent() !v_result = document.createElement('a'); !v_result.innerHTML = v_text; !v_result.tabIndex = 0; ; Button size Select #True Case Bool(Flags & #Button_Floating) !v_result.classList.add("btn-floating"); Case Bool(Flags & #Button_Large) !v_result.classList.add("btn-large"); Case Bool(Flags & #Button_Small) !v_result.classList.add("btn-small"); Default !v_result.classList.add("btn"); EndSelect ; Button variant Select #True Case Bool(Flags & #Button_Tonal) !v_result.classList.add("tonal"); Case Bool(Flags & #Button_Outlined) !v_result.classList.add("outlined"); Case Bool(Flags & #Button_Elevated) !v_result.classList.add("elevated"); Case Bool(Flags & #Button_Text) !v_result.classList.add("text"); Default !v_result.classList.add("filled"); EndSelect If Flags & #Button_Disabled !v_result.classList.add("disabled"); EndIf If *Callback <> #Null !v_result.addEventListener('click', p_callback); EndIf ; add a 5 pixels margin around every buttons. !v_result.style.margin = '5px'; !v_parent.append(v_result); ProcedureReturn Result EndProcedure Procedure ButtonSetCallback(Button, *Callback) !v_button.addEventListener('click', p_callback); EndProcedure ;=========================================================================== ; Card ;=========================================================================== Procedure Card(Text.s = "", Flags = #Card_Default, Parent = #Null) CheckParent() PushParent() !materialsb$g_current_parent = document.createElement('div'); If Flags & #Card_Panel !materialsb$g_current_parent.classList.add("card-panel"); Else !materialsb$g_current_parent.classList.add("card"); EndIf If Flags & #Card_Small !materialsb$g_current_parent.classList.add("small"); EndIf If Flags & #Card_Medium !materialsb$g_current_parent.classList.add("medium"); EndIf If Flags & #Card_Large !materialsb$g_current_parent.classList.add("large"); EndIf If Flags & #Card_Horizontal !materialsb$g_current_parent.classList.add("horizontal"); EndIf If Text <> "" !materialsb$g_current_parent.innerHTML = v_text; EndIf !v_parent.append(materialsb$g_current_parent); ProcedureReturn current_parent EndProcedure Procedure CardImage(Source.s, Parent = #Null) Protected Result CheckParent() !v_result = document.createElement('div'); !v_result.className = "card-image"; !v_result.innerHTML = ''; !v_parent.append(v_result); ProcedureReturn Result EndProcedure Procedure CardContent(Parent = #Null) CheckParent() PushParent() !materialsb$g_current_parent = document.createElement('div'); !materialsb$g_current_parent.className = "card-content"; !v_parent.append(materialsb$g_current_parent); ProcedureReturn current_parent EndProcedure Procedure CardTitle(Text.s, Parent = #Null) Protected Result CheckParent() !v_result = document.createElement('span'); !v_result.className = "card-title"; !v_result.innerHTML = v_text; !v_parent.append(v_result); ProcedureReturn Result EndProcedure Procedure CardAction(Parent = #Null) CheckParent() PushParent() !materialsb$g_current_parent = document.createElement('div'); !materialsb$g_current_parent.className = "card-action"; !v_parent.append(materialsb$g_current_parent); ProcedureReturn current_parent EndProcedure ;=========================================================================== ; Carousel ;=========================================================================== Procedure Carousel(Flags = #Carousel_Default, Parent = #Null) Protected Result CheckParent() !v_result = document.createElement('div'); !v_result.className = "carousel"; If Flags & #Carousel_Slider !v_result.classList.add("carousel-slider"); EndIf !v_parent.append(v_result); ProcedureReturn Result EndProcedure Procedure CarouselAddItem(Carousel, ImageSource.s, Link.s) Protected Result !v_result = document.createElement('a'); !v_result.className = "carousel-item"; !v_result.href = v_link; !v_result.innerHTML = ''; !v_carousel.append(v_result); ProcedureReturn Result EndProcedure ;=========================================================================== ; Tabs ;=========================================================================== Procedure Tab(Flags = #Tab_Default, Parent = #Null) Protected Result CheckParent() !v_result = document.createElement('ul'); !v_result.className = "tabs"; !v_parent.append(v_result); ProcedureReturn Result EndProcedure Procedure TabAddItem(Title.s, Tab, ID.s, Flags = #Tab_Default) Protected Result !v_result = document.createElement('li'); !v_result.className = "tab"; !v_result.innerHTML = '' + v_title + ''; If Flags & #Tab_Disabled !v_result.classList.add("disabled"); EndIf !v_tab.append(v_result); ProcedureReturn Result EndProcedure ;=========================================================================== ; Modal ;=========================================================================== Procedure Modal(Flags = #Modal_Default) Protected Result, ID.s !v_result = document.createElement('div'); !v_result.className = "modal"; ; MaterializeCSS 2.1.1+ uses the Popover API !v_result.setAttribute('popover', ''); If Flags & #Modal_FixedFooter !v_result.classList.add("modal-fixed-footer"); EndIf If Flags & #Modal_BottomSheet !v_result.classList.add("bottom-sheet"); EndIf ; Modal must be added directly to body, outside of main content !document.body.appendChild(v_result); ; Store reference for ModalContent/ModalFooter !materialsb$g_current_modal = v_result; ProcedureReturn Result EndProcedure Procedure ModalHeader(Text.s, Parent = #Null) Protected Result If Parent = #Null !v_parent = materialsb$g_current_modal; EndIf !v_result = document.createElement('div'); !v_result.className = "modal-header"; !v_result.innerHTML = v_text; !v_parent.appendChild(v_result); ProcedureReturn Result EndProcedure Procedure ModalContent(Parent = #Null) Protected Result If Parent = #Null !v_parent = materialsb$g_current_modal; EndIf !v_result = document.createElement('div'); !v_result.className = "modal-content"; !v_parent.appendChild(v_result); ; Set as current parent for adding content PushParent() current_parent = Result ProcedureReturn Result EndProcedure Procedure ModalFooter(Parent = #Null) Protected Result If Parent = #Null !v_parent = materialsb$g_current_modal; EndIf !v_result = document.createElement('div'); !v_result.className = "modal-footer"; !v_parent.appendChild(v_result); ; Set as current parent for adding buttons PushParent() current_parent = Result ProcedureReturn Result EndProcedure Procedure ModalOpen(ModalElement) !v_modalelement.showPopover(); EndProcedure Procedure ModalClose(ModalElement) !v_modalelement.hidePopover(); EndProcedure ;=========================================================================== ; Toast ;=========================================================================== Procedure Toast(Text.s, Duration = 4000, Flags = #Toast_Default, Color.s = "") Protected Classes.s = "" If Flags & #Toast_Rounded Classes = "rounded" EndIf ; Add color class if specified If Color <> "" If Classes <> "" Classes + " " EndIf Classes + Color EndIf ; toast changed in 2.1.1 See: github.com/materializecss/materialize/issues/604 !new M.Toast({ ! text: v_text, ! classes: v_classes, ! displayLength: v_duration !}); EndProcedure Procedure ToastDismissAll() !M.Toast.dismissAll(); EndProcedure ;=========================================================================== ; Forms ;=========================================================================== Procedure TextInput(Label.s = "", Placeholder.s = "", Flags = #Input_Default, Parent = #Null) Protected Result, InputType.s = "text" CheckParent() ; Determine input type from flags If Flags & #Input_Password InputType = "password" ElseIf Flags & #Input_Email InputType = "email" ElseIf Flags & #Input_Number InputType = "number" ElseIf Flags & #Input_Tel InputType = "tel" ElseIf Flags & #Input_Url InputType = "url" ElseIf Flags & #Input_Date InputType = "date" ElseIf Flags & #Input_Time InputType = "time" EndIf ; Create wrapper div !var _wrapper = document.createElement('div'); !_wrapper.className = "input-field"; If Flags & #Input_Outlined !_wrapper.classList.add("outlined"); EndIf ; Create input element !v_result = document.createElement('input'); !v_result.type = v_inputtype; If Placeholder <> "" !v_result.placeholder = v_placeholder; EndIf If Flags & #Input_Disabled !v_result.disabled = true; EndIf If Flags & #Input_Readonly !v_result.readOnly = true; EndIf !_wrapper.append(v_result); ; Create label if provided If Label <> "" !var _label = document.createElement('label'); ; !_label.htmlFor = v_id; !_label.innerHTML = v_label; !_wrapper.append(_label); EndIf !v_parent.append(_wrapper); ProcedureReturn Result EndProcedure Procedure Textarea(Label.s = "", Placeholder.s = "", Flags = #Textarea_Default, Parent = #Null) Protected Result CheckParent() ; Create wrapper div !var _wrapper = document.createElement('div'); !_wrapper.className = "input-field"; If Flags & #Textarea_Outlined !_wrapper.classList.add("outlined"); EndIf ; Create textarea element !v_result = document.createElement('textarea'); !v_result.className = "materialsb-textarea"; If Placeholder <> "" !v_result.placeholder = v_placeholder; EndIf If Flags & #Textarea_Disabled !v_result.disabled = true; EndIf If Flags & #Textarea_Readonly !v_result.readOnly = true; EndIf !_wrapper.append(v_result); ; Create label if provided If Label <> "" ; !var _label = document.createElement('label'); ; !_label.htmlFor = v_id; ; !_label.innerHTML = v_label; ; !_wrapper.append(_label); EndIf !v_parent.append(_wrapper); ProcedureReturn Result EndProcedure Procedure Checkbox(Label.s, Flags = #Checkbox_Default, Parent = #Null) Protected Result CheckParent() ; Create label wrapper (MaterialSB structure) !var _label = document.createElement('label'); ; Create checkbox input !v_result = document.createElement('input'); !v_result.type = "checkbox"; If Flags & #Checkbox_Filled !v_result.classList.add("filled-in"); EndIf If Flags & #Checkbox_Checked !v_result.checked = true; EndIf If Flags & #Checkbox_Disabled !v_result.disabled = true; EndIf !_label.append(v_result); ; Create span for label text !var _span = document.createElement('span'); !_span.innerHTML = v_label; !_label.append(_span); ; Wrap in p for proper spacing !var _p = document.createElement('p'); !_p.append(_label); !v_parent.append(_p); ProcedureReturn Result EndProcedure Procedure Radio(Name.s, Label.s, Flags = #Radio_Default, Parent = #Null) Protected Result CheckParent() ; Create label wrapper !var _label = document.createElement('label'); ; Create radio input !v_result = document.createElement('input'); !v_result.type = "radio"; !v_result.name = v_name; If Flags & #Radio_WithGap !v_result.classList.add("with-gap"); EndIf If Flags & #Radio_Checked !v_result.checked = true; EndIf If Flags & #Radio_Disabled !v_result.disabled = true; EndIf !_label.append(v_result); ; Create span for label text !var _span = document.createElement('span'); !_span.innerHTML = v_label; !_label.append(_span); ; Wrap in p for proper spacing !var _p = document.createElement('p'); !_p.append(_label); !v_parent.append(_p); ProcedureReturn Result EndProcedure Procedure Switch(LabelOff.s, LabelOn.s, Flags = #Switch_Default, Parent = #Null) Protected Result CheckParent() ; Create switch wrapper !var _wrapper = document.createElement('div'); !_wrapper.className = "switch"; ; Create label !var _label = document.createElement('label'); !_label.innerHTML = v_labeloff; ; Create checkbox input !v_result = document.createElement('input'); !v_result.type = "checkbox"; If Flags & #Switch_Checked !v_result.checked = true; EndIf If Flags & #Switch_Disabled !v_result.disabled = true; EndIf !_label.append(v_result); ; Create lever span !var _lever = document.createElement('span'); !_lever.className = "lever"; !_label.append(_lever); ; Add "on" label text !_label.innerHTML += v_labelon; !_wrapper.append(_label); !v_parent.append(_wrapper); ProcedureReturn Result EndProcedure Procedure Dropdown(Label.s = "", Flags = #Dropdown_Default, Parent = #Null) Protected Result CheckParent() ; Create wrapper div !var _wrapper = document.createElement('div'); !_wrapper.className = "input-field"; If Flags & #Dropdown_Outlined !_wrapper.classList.add("outlined"); EndIf ; Create select element !v_result = document.createElement('select'); If Flags & #Dropdown_Multiple !v_result.multiple = true; EndIf If Flags & #Dropdown_Disabled !v_result.disabled = true; EndIf !_wrapper.append(v_result); ; Create label if provided If Label <> "" !var _label = document.createElement('label'); !_label.innerHTML = v_label; !_wrapper.append(_label); EndIf !v_parent.append(_wrapper); ProcedureReturn Result EndProcedure Procedure DropdownAddOption(Text.s, Value.s, SelectElement, Selected = #False) Protected Result !v_result = document.createElement('option'); !v_result.value = v_value; !v_result.innerHTML = v_text; If Selected !v_result.selected = true; EndIf !v_selectelement.append(v_result); ProcedureReturn Result EndProcedure Procedure Range(Min = 0, Max = 100, Value = 50, Flags = #Range_Default, Parent = #Null) Protected Result CheckParent() ; Create wrapper !var _wrapper = document.createElement('p'); !_wrapper.className = "range-field"; ; Create range input !v_result = document.createElement('input'); !v_result.type = "range"; !v_result.min = v_min; !v_result.max = v_max; !v_result.value = v_value; If Flags & #Range_Disabled !v_result.disabled = true; EndIf !_wrapper.append(v_result); !v_parent.append(_wrapper); ProcedureReturn Result EndProcedure Procedure InputSetCallback(InputElement, *Callback) !v_inputelement.addEventListener('input', p_callback); EndProcedure ;=========================================================================== ; Private Procedures ;=========================================================================== Procedure Handler_Download(url.s, success) If success Select url Case "LocalFiles/CSS/materialize.min.css" LoadScript("LocalFiles/CSS/material-icons.css", @Handler_Download(), #PB_Script_CSS) Case "LocalFiles/CSS/material-icons.css" LoadScript("LocalFiles/JS/materialize.min.js", @Handler_Download(), #PB_Script_JavaScript) Case "LocalFiles/JS/materialize.min.js" ; Remove SpiderBasic's default styles !$('link[href="/spiderbasic/libraries/javascript/dojo/themes/flat/flat.css"]').remove(); !$('link[href="/spiderbasic/libraries/javascript/dojo/dgrid/css/dgrid.css"]').remove(); !$('link[href="/spiderbasic/libraries/javascript/themes/flat/window.css"]').remove(); !document.body.removeAttribute('id'); !document.body.removeAttribute('class'); !document.body.removeAttribute('oncontextmenu'); !document.body.removeAttribute('onload'); ; Initialize SetDarkTheme(#True) !document.body.style.minHeight = '100vh'; ; Create main container !materialsb$g_current_parent = document.createElement('main'); !document.body.append(materialsb$g_current_parent); ; Remove SB's scroll event ! $(document).off('scroll'); ; Call user callback !materialsb$g_download_callback(1); EndSelect Else !materialsb$g_download_callback(0); EndIf EndProcedure EndModule ; IDE Options = SpiderBasic 3.10 (Windows - x86) ; CursorPosition = 516 ; Folding = IACAAAAAAAAAAAAg ; iOSAppOrientation = 0 ; AndroidAppCode = 0 ; AndroidAppOrientation = 0 ; EnableXP ; DPIAware ; CompileSourceDirectory