|
| 1 | +VERSION 1.0 CLASS |
| 2 | +BEGIN |
| 3 | + MultiUse = -1 'True |
| 4 | +END |
| 5 | +Attribute VB_Name = "stdHTML" |
| 6 | +Attribute VB_GlobalNameSpace = False |
| 7 | +Attribute VB_Creatable = False |
| 8 | +Attribute VB_PredeclaredId = True |
| 9 | +Attribute VB_Exposed = False |
| 10 | + |
| 11 | + |
| 12 | +Private Enum EElementType |
| 13 | + ENone |
| 14 | + EElement |
| 15 | + ELiteral |
| 16 | +End Enum |
| 17 | +Private Type TElement |
| 18 | + TagName As String |
| 19 | + Attributes As Variant() |
| 20 | + Children As stdHTML() |
| 21 | + isSelfClosing As Boolean |
| 22 | +End Type |
| 23 | +Private Type TLiteral |
| 24 | + content as string |
| 25 | +End Type |
| 26 | + |
| 27 | +Private Type TThis |
| 28 | + ElementType As EElementType |
| 29 | + Element as TElement |
| 30 | + Literal as TLiteral |
| 31 | +End Type |
| 32 | +Private This As TThis |
| 33 | + |
| 34 | +'Creates a new stdHTML object. This is the main entry point for creating HTML document objects. |
| 35 | +Public Function Create() as stdHTML |
| 36 | + set Create = New stdHTML |
| 37 | + Call Create.protInit("html", Array()) |
| 38 | +End Function |
| 39 | + |
| 40 | +' Creates a new stdHTML object with the specified tag name and attributes, and adds it to the current element. |
| 41 | +'@param tagName - Name of the tag to create |
| 42 | +'@param attributes - Attributes to add to the tag |
| 43 | +'@param isSelfClosing - Whether the tag is self-closing |
| 44 | +Public Function CreateChild(ByVal tagName as string, ByVal attributes as variant, optional byval isSelfClosing as Boolean = false) as stdHTML |
| 45 | + set CreateChild = new stdHTML |
| 46 | + Call CreateChild.protInit(tagName, attributes, isSelfClosing) |
| 47 | + |
| 48 | + 'Theoretically someone could call this function on a literal element, or the predeclared stdHTML object. |
| 49 | + If this.ElementType = EElementType.EElement Then |
| 50 | + Dim iUB as long: iUB = UBound(This.Element.Children) |
| 51 | + ReDim Preserve This.Element.Children(iUB + 1) |
| 52 | + Set This.Element.Children(iUB + 1) = CreateChild |
| 53 | + else |
| 54 | + Err.Raise vbObjectError + 1, "Cannot add child to a non-element context." |
| 55 | + End if |
| 56 | +End Function |
| 57 | + |
| 58 | +'Creates a literal element and adds it to the current element. |
| 59 | +'@param text - Text to add |
| 60 | +Public Sub CreateLiteral(ByVal text as string) |
| 61 | + Dim newLit as stdHTML: set newLit = new stdHTML |
| 62 | + Call newLit.protInitLiteral(text) |
| 63 | + |
| 64 | + 'Theoretically someone could call this function on a literal element, or the predeclared stdHTML object. |
| 65 | + If this.ElementType = EElementType.EElement Then |
| 66 | + Dim iUB as long: iUB = UBound(This.Element.Children) |
| 67 | + ReDim Preserve This.Element.Children(iUB + 1) |
| 68 | + Set This.Element.Children(iUB + 1) = newLit |
| 69 | + else |
| 70 | + Err.Raise vbObjectError + 1, "Cannot add literal to a non-element context." |
| 71 | + End If |
| 72 | +End Sub |
| 73 | + |
| 74 | + |
| 75 | +'Initialise an element object. |
| 76 | +'@param tagName - Name of the tag to create |
| 77 | +'@param attributes - Attributes to add to the tag |
| 78 | +'@param isSelfClosing - Whether the tag is self-closing |
| 79 | +Public Sub protInitElement(tagName as string, attributes as variant, isSelfClosing as Boolean) |
| 80 | + This.ElementType = EElementType.EElement |
| 81 | + This.Element.TagName = tagName |
| 82 | + This.Element.Attributes = attributes |
| 83 | + This.Element.isSelfClosing = isSelfClosing |
| 84 | +End Sub |
| 85 | + |
| 86 | +'Initialise a literal object. |
| 87 | +'@param content - Content of the literal element |
| 88 | +Public Sub protInitLiteral(content as string) |
| 89 | + This.ElementType = EElementType.ELiteral |
| 90 | + This.Literal.content = content |
| 91 | +End Sub |
| 92 | + |
| 93 | + |
| 94 | + |
| 95 | +Public Property Get TagName() as string |
| 96 | + Select Case this.ElementType |
| 97 | + Case EElementType.EElement |
| 98 | + TagName = This.Element.TagName |
| 99 | + Case EElementType.ELiteral |
| 100 | + TagName = "" |
| 101 | + case else |
| 102 | + Err.Raise vbObjectError + 1, "Invalid element type." |
| 103 | + End Select |
| 104 | +End Property |
| 105 | + |
| 106 | +Public Property Get Attr(name as string) as variant |
| 107 | + Dim i as Long |
| 108 | + For i = 0 to UBound(This.Element.Attributes) step 2 |
| 109 | + if This.Element.Attributes(i) = name then |
| 110 | + Attr = This.Element.Attributes(i + 1) |
| 111 | + exit for |
| 112 | + end if |
| 113 | + next i |
| 114 | + Attr = Empty 'If the attribute doesn't exist, return empty |
| 115 | +End Property |
| 116 | +Public Property Let Attr(name as string, value as variant) |
| 117 | + Dim i as Long |
| 118 | + For i = 0 to UBound(This.Element.Attributes) step 2 |
| 119 | + if This.Element.Attributes(i) = name then |
| 120 | + This.Element.Attributes(i + 1) = value |
| 121 | + Exit Property |
| 122 | + end if |
| 123 | + next i |
| 124 | + |
| 125 | + 'If the attribute doesn't exist, add it |
| 126 | + Dim iUB as Long: iUB = UBound(This.Element.Attributes) |
| 127 | + ReDim Preserve This.Element.Attributes(iUB + 2) |
| 128 | + This.Element.Attributes(iUB + 1) = name |
| 129 | + This.Element.Attributes(iUB + 2) = value |
| 130 | +End Property |
| 131 | + |
| 132 | + |
| 133 | +Public Property Get Id() as string |
| 134 | + ID = Attr("id") |
| 135 | +End Property |
| 136 | +Public Property Let ID(value As String) |
| 137 | + Attr("id") = value |
| 138 | +End Property |
| 139 | + |
| 140 | +Public Property Get Title() as string |
| 141 | + Title = Attr("title") |
| 142 | +End Property |
| 143 | +Public Property Let Title(value As String) |
| 144 | + Attr("title") = value |
| 145 | +End Property |
| 146 | + |
| 147 | +Public Property Get Children() As stdHTML() |
| 148 | + If this.ElementType <> EElementType.EElement then Err.Raise vbObjectError + 1, "Cannot get children of a non-element context." |
| 149 | + Children = This.Element.Children |
| 150 | +End Property |
| 151 | + |
| 152 | +'Adds the specified classes to the element |
| 153 | +'@param classes - Classes to add |
| 154 | +Public Sub AddClasses(ParamArray classes() as string) |
| 155 | + If this.ElementType <> EElementType.EElement then Err.Raise vbObjectError + 1, "Cannot add classes to a non-element context." |
| 156 | + |
| 157 | + Dim classes as string: classes = Attr("class") |
| 158 | + If isEmpty(classes) then |
| 159 | + Attr("class") = Join(classes, " ") |
| 160 | + Else |
| 161 | + Dim newClass as variant |
| 162 | + For each newClass in classes |
| 163 | + If InStr(1, classes, newClass, vbTextCompare) = 0 then |
| 164 | + classes = classes & " " & newClass |
| 165 | + end if |
| 166 | + next |
| 167 | + Attr("class") = classes |
| 168 | + end if |
| 169 | +End Sub |
| 170 | + |
| 171 | +'Removes the specified classes from the element |
| 172 | +'@param classes - Classes to remove |
| 173 | +Public Sub RemoveClasses(ParamArray classes() as string) |
| 174 | + If this.ElementType <> EElementType.EElement then Err.Raise vbObjectError + 1, "Cannot remove classes from a non-element context." |
| 175 | + |
| 176 | + Dim classes as string: classes = Attr("class") |
| 177 | + If not isEmpty(classes) then |
| 178 | + Dim remClass as variant |
| 179 | + For each remClass in classes |
| 180 | + If InStr(1, classes, remClass, vbTextCompare) <> 0 then |
| 181 | + classes = Replace(classes, newClass, "") |
| 182 | + end if |
| 183 | + next |
| 184 | + |
| 185 | + Attr("class") = Replace(classes, " ", " ") |
| 186 | + end if |
| 187 | +End Sub |
| 188 | + |
| 189 | +'Obtain the HTML string representation of the element. |
| 190 | +'@param indent - Indentation string to use for nested elements |
| 191 | +Public Function ToString(Optional indent As String = "") As String |
| 192 | + select case this.ElementType |
| 193 | + case EElementType.EElement |
| 194 | + Dim output As String: output = indent & "<" & this.Element.TagName |
| 195 | + |
| 196 | + Dim i As Long |
| 197 | + For i = 0 To UBound(this.Element.Attributes) Step 2 |
| 198 | + output = output & " " & this.Element.Attributes(i) & serializeAttribute(this.Element.Attributes(i + 1)) |
| 199 | + Next i |
| 200 | + |
| 201 | + If this.Element.isSelfClosing Then |
| 202 | + output = output & " />" |
| 203 | + Else |
| 204 | + output = output & ">" |
| 205 | + |
| 206 | + Dim child As stdHTML |
| 207 | + For Each child In this.Element.Children |
| 208 | + output = output & vbCrLf & child.ToString(indent & " ") |
| 209 | + Next child |
| 210 | + |
| 211 | + output = output & vbCrLf & indent & "</" & this.Element.TagName & ">" |
| 212 | + End If |
| 213 | + |
| 214 | + ToString = output |
| 215 | + case EElementType.ELiteral |
| 216 | + ToString = this.Literal.content |
| 217 | + end Select |
| 218 | +End Function |
| 219 | + |
| 220 | +'Serializes an attribute to a string |
| 221 | +'@param attr - Attribute to serialize |
| 222 | +'@returns Serialized attribute |
| 223 | +Private Function serializeAttribute(ByRef attr as Variant) as string |
| 224 | + select case varType(attr) |
| 225 | + case vbNull |
| 226 | + serializeAttribute = "" |
| 227 | + case vbString |
| 228 | + serializeAttribute = "='" & attr & "'" |
| 229 | + case vbBoolean |
| 230 | + serializeAttribute = "=" & IIf(attr, "true", "false") |
| 231 | + case vbLong, vbInteger |
| 232 | + serializeAttribute = "=" & CStr(attr) |
| 233 | + case vbDouble, vbSingle |
| 234 | + serializeAttribute = "=" & CStr(attr) |
| 235 | + case vbDate |
| 236 | + serializeAttribute = "='" & format(attr, "yyyy-mm-dd") & "'" |
| 237 | + case vbCurrency |
| 238 | + serializeAttribute = "=" & CStr(attr) |
| 239 | + case vbByte |
| 240 | + serializeAttribute = "=" & CStr(attr) |
| 241 | + case else |
| 242 | + Err.Raise vbObjectError + 2, "Unsupported attribute type: " & VarType(attr) & ". For: " & attr |
| 243 | + end select |
| 244 | +End Function |
0 commit comments