View documentation | View discussion [638 posts] | View script | License |
Download script | History | Other scripts by: inetw3dm |
30-Apr 16:49 UTC
[0.174] 34.067k
[0.174] 34.067k
Archive version of: rebol-dom.r ... version: 48 ... inetw3dm 20-May-2021Amendment note: Updated: getting close. version 0.9 Roadmap: more DOM funcitons, get and set by methods, Var search by index: arr[1] || Publicly available? Yes REBOL [ File: %rebol-dom.r Date: 05-01-2021 Title: "Dialect Object Model" Emai: inetw3.dm@gmail.com author: daniel murrill Purpose: { Use a recodable rebol function to create easy to follow blocks/series as a Dialect Object Model that allow different program languages to work together and viewed as HTML and VID. A parse alternative} ] library: [ author: daniel murrill level: 'intermediate platform: 'all type: Dialect domain: [html vid css json js array] tested-under: 'windows support: none license: none see-also: %Mdlparser.r version: 0.9 ] my-dialect: [ rebol-DOM: [{DSL-type="html/block" type="text/html"}] lua-tbl = {[first] = "fred", [last] = "cougar"} #this-issue [{color: "purple" bgcolor: "orange"}] var anObj = { 100: 'a', 2: 'b', 7: 'c', }; body: [{background-color="blue" text "white"} ] p: [ { "color":"#0000ff", "bgcolor":"yellow", "width" : "399", "height" : "100" "font-styles": "big" } This is an example of an Dialect Oject Model b: [ {color = "Chocolate" bgcolor = "yellow"} that can be written to look like json' html' javascript arrays' css' i: [ {color = "green"} VID' or plain old rebol ] ] if you like. ] hr: [{color="red" bgcolor="yellow"}] div: [ {width="399" bgcolor="orange"} b: [ {color: "purple" bgcolor: "orange"} Maybe it would be easier to write i: [ {color: "green"} MakeDoc.r code but the purpose of this rebol DOM is'] ] ] p: [ {width "399" height= 200 style="color: red; bgcolor: brown; border: 2x2;" } b: [ {color="red"} to read or load as many well known dialects of coding styles as possible and write all of it as a single or seperate legible rebol series that's quickly manipulated' transcoded as html' and viewed as a VID. ] ] ] document.: func [request-as][ DOM: head DOM use*=*to-set-values any [equal? block! type? data-node data-node: node: reduce [to-block data-node]] either equal? tag! type? data-node/1 [node-element: data-node/1 ][ node-element: data-node/1: build-tag to-block first parent-node: data-node ] var .style: = node-element style: :array-obj! .style: :array-obj! return node-element ] return-tag-node: does [=: :equal? any [equal? block! type? data-node data-node: node: reduce [to-block strip-obj-chars-from data-node]] any [equal? tag! type? node-element: data-node/1 attempt [ replace/all node-element [=] [] node-element: data-node/1: build-tag to-block node-element] ] ] .style: [] equal?: := DOM: DSL: html: window: end-tag: "" data-node: parent-node: node: none .body: .hr: .p: .b: .i: .tr: .ul: .li: .area: .table: .td: .button: .input: .div: .font: .span: 0 node-obj: node-element: node-name: *name: use-methods: attr-name: attr-value: none check: func [select-this][return first parse select-this none] strip-chars-from: func [node-name][ foreach char elemt-chars: ["{" "}" "(" ")" {"} "/" "." "[" "]" "," ":" ";" "," "=" ][ replace/all node-name char " " ] ] strip-obj-chars-from: func [node-name][ trim node-name if equal? #"^"" node-name/1 [remove node-name] foreach [-char +char] obj-chars: [#"^/" " " "," "" {" : "} {: "} {":"} {: "} {":} {:} {" "} {" } { " } "" "[" "" "]" "" {""} {"} { "} "" ":" " " { =} {=} {=} " " "'" "" { #} { #","} ][ replace/all node-name -char +char ] ] getnodename: func [node-name][data-node: [""] DOM: head DOM =: :equal? either block! = type? node-name [ insert/only data-node: [] node-name any [attempt [node-element: data-node/1: build-tag data-node/1] node-element: data-node/1] ][ node-name: to block! strip-chars-from form node-name count: any [attempt [count: pick find node-name integer! 1]1] nodename: to-word join "." array-obj!: node-name/1 any [repeat ? count [data-node: first DOM: next node: find DOM nodename] print reduce ["node-name:" mold form node-name/1 "not found"] ] slf*: join node-name/1 count ] if '= = first DOM [data-node: first next DOM] return either tag! = type? data-node/1 [node-element: data-node/1][node-element: data-node] ] setnodename: func [old-name new-name][ any [equal? this-name: check strip-chars-from old-name check node-element getnodename old-name] any [equal? none not find node-element new-name try [ replace node-element to string! this-name new-name replace data-node to-tag join "/" this-name to-tag join "/" new-name] ] ] getattribute: func [attr-name][ attr-value: none do compose/deep [attr-value: array-obj![(attr-name)]] print any [[attr-name attr-value] ["node-attribute:" mold form attr-name "not found"] ] ] setattribute: func [attr-name new-attr][ *key: *value: none do compose/deep [.style[(form attr-name )]] any [ if *value [replace node-element attr-name new-attr] array-obj![repend [" " new-attr {="undefined"}]""] print ["Must get a parent-node with this attribute: " attr-name]] ;get-attributes node-element attempt [set-attributes] ] setattributevalue: func [attr-name attr-value][ any [ if find node-element key: form attr-name [ do compose/deep [.style[(key)] `= (attr-value)]] array-obj![repend [" " attr-name {="}attr-value {"}]""] print ["Must get a parent-node with this attribute: " attr-name] ] ;get-attributes node-element attempt [set-attributes] ] getElementByTagName: func [Tag-Name selection [block!]][ dom: head dom repeat this first selection [ node-element: first data-node: first dom: next find dom to-word join "." Tag-Name] if [use-methods and not find node-element " ."][use-attr-as-methods yes] use-methods: off ] look-deep-for: func [this in-node][ foreach in-child-node in-node [ if find/any mold node-element: in-child-node this [return node-element break] ] ] getElementById: func [my-id][in-child-node: none id: copy join "id*" form my-id =: :equal? foreach in-parent-node dom [ if block! = type? in-parent-node [any [look-deep-for id in-parent-node foreach in-sibling in-parent-node [ if block! = type? in-sibling [look-deep-for id in-sibling ]]]]] ] querySelecter: func [css-Selecter][in-child-node: none id: rejoin [css-Selecter "*="] =: :equal? foreach in-parent-node dom [ if block! = type? in-parent-node [any [look-deep-for id in-parent-node foreach in-sibling in-parent-node [ if block! = type? in-sibling [look-deep-for id in-sibling ]]]]] ] .innerHTML: func [element][ children: copy/part next data-node find/last data-node tag! either equal? tag! type? node-element [ any [empty? element replace data-node children element] ][print "The node-element has no innerHTML"] ] use*=*to-set-values: does [=: func [value][any [value]]] use-attr-as-methods: func [maybe [logic!]][ if maybe [foreach [-char +char][{" } {" .} ".." "."][replace/all node-element -char +char] ] replace node-element " " " ." use-methods: yes ] node-list: [] *!: func [var][set to-word check form node-element none set to-set-word form var :array-obj!] var: func [var-data][node-element: variable: "" node-name: :variable any [ attempt [variable: first parse node-element: var-data "=:, "] attempt [if equal? block! type? var-data [variable: first node-element: var-data]] attempt [variable: var-data node-element: ""] ] use*=*to-set-values variable: to-string variable any [ not empty? node-element any [find node-list variable append node-list reduce [variable node-element: any [attempt [do :variable] " "]]]] any [equal? tag! type? node-element append node-list reduce [form variable node-element]] set to-word variable array-obj!: func [key [block! word! string!]] node: compose/deep copy get-array-obj! attempt [if not find variable "." [do load to-string reduce ["set " #"'" variable ". :array-obj!"]]] use-methods: off ] get-array-obj!: [ if not equal? tag! type? node-element [node-element: select node-list (form variable) ] if inline: find/any node-element { style*=*"} [ replace node-element inline replace inline {"} " "] any [ if empty? form key [ return any [ if equal? tag! type? node-element [node-element] attempt [trim next find/tail node-element first parse node-element ":= ,"] next node-element] ] attempt [*value: select parse strip-obj-chars-from copy node-element "[]{}`:;= " *key: form key] attempt [*value: select node-element *key: key] attempt [do head insert next copy key [node-element join]] attempt [do form key] if not find node-element key [none]] ;[print [*key "called"]] ] arr=: `=: func[attr-value][ any [ attempt [replace node-element *value do reform attr-value] replace node-element form *value form attr-value replace node-element mold form *value mold attr-value ] ] node-element: *node-name: *name: array-obj!: key: *key: *value: "" markup-DOM: func [DSL][ use-methods: string-is-data: no =: :equal? either block! = this-type?: type? DSL [ DOM: copy/deep DSL: load replace/all replace/all mold DSL "__" " " {=""} {="undefined"} any [ find DSL [rebol-DOM: [{DSL-type="html/block" type="text/html"}]] insert DSL [rebol-DOM: [{DSL-type="html/block" type="text/html"}]]] get-data: func [data][ find-end-tag: find data get-word! either find-end-tag [ replace data first find-end-tag to-tag mold to-refinement first find-end-tag ][ insert tail data to-tag join "/" any [*name *node-name] ] repeat in-data data [ if set-word! = type? in-data [*node-name: copy form in-data replace data in-data node-name: to-word join "." *node-name ] if string! = type? in-data [ strip-obj-chars-from in-data insert in-data next reform [node-name " "] child: build-tag to-block in-data foreach [a b][{=" } "={" {" "} "*}" "*" {"}][replace/all child a b] replace data in-data child ] if block! = type? in-data [ get-next in-data ] ] ] get-next: func [in-data][ repeat data in-data [ if set-word! = type? data [*name: copy form data replace in-data data node-name: to-word join "." *name ] if string! = type? data [ strip-obj-chars-from data insert data next reform [node-name " "] child: build-tag to-block data foreach [a b][{=" } "={" {" "} "*}" "*" {"}][replace/all child a b] replace in-data data child ] if block! = type? data [get-data data set to-word *node-name data] ] find-end-tag: find in-data get-word! either find-end-tag[ replace in-data first find-end-tag to-tag mold to-refinement first find-end-tag ][ insert tail in-data to-tag join "/" any [*node-name *name] clear *node-name] ] repeat with-this-data DSL [ if issue! = type? with-this-data [ node-name: to-word join "." *name: copy form with-this-data ] if set-word! = type? with-this-data [ replace DSL with-this-data node-name: to-word join "." *name: copy form with-this-data ] if word! = type? with-this-data [ either '= = with-this-data [string-is-data: yes replace DSL with-this-data "" ][ *name: copy form with-this-data replace DSL with-this-data node-name: to-word join "." with-this-data] replace DSL reduce [node-name node-name] node-name ] if string! = type? with-this-data [ either string-is-data [ replace DSL with-this-data rejoin [node-name " " with-this-data] ][ created-data: copy with-this-data strip-obj-chars-from created-data insert created-data reduce [node-name " "] child: build-tag to-block remove created-data foreach [a b][{=" } "={" {" "} "*}" "*" {"}][replace/all child a b] replace DSL with-this-data child ] string-is-data: no ] if block! = type? with-this-data [ get-data with-this-data ] if get-word! = type? with-this-data [ replace DSL with-this-data to-tag mold to-refinement *name ] ] replace/all dsl "" [] DOM: copy DSL ][ view center-face layout [ backcolor black space 8 across h3 yellow "Need a Dialect Object Model as type! block" return text gray "Your DSL type is: " text red bold form :this-type? return text gray "Some DOM functions will not work properly"] ] ] format-this: func [node-element with-these-chars][ foreach [-char +char] with-these-chars [ replace/all node-element -char +char] do last with-these-chars ] as-js-object!: [ { #} "" {="} {: "} "={" ": {" {""} {"} {" } {", } {", "} {"} [replace node-element " " ": {" replace/all node-element { "} {: "} replace/all node-element "::" ":" replace/all node-element " : " ": " append node-element "}"] ] .as-js-object: does [attempt [format-this node-element as-js-object!]] return-html-dsl: does [ html: copy form any [find head DOM "<body" head DOM] replace/all replace/all html "<." "<" "' " ", " replace/all replace/all html "{" "<" "}" ">" foreach n-name [ ".body " ".hr " ".p " ".b " ".i " ".? " ".tr " ".table " ".td " ".button " ".input " ".div " ".ul " ".li " ".font " ".span " ".img " ".a " ".strong " " ." ".hr " "lua-tbl " ][replace/all html n-name " " ] append replace/all html </body> "" </body> html: any [find html "<body" html] ] markup-DOM my-dialect getElementById 'my-p1 document. getnodename {"div"[1]}getattribute "bgcolor" document. getnodename{("p")[2]} .style[width] `= "block-build" setattributevalue('height) "1000" node-element getattribute "height" setnodename {hr[1]} "listview" node-element document. getnodename{("p")[1]}.style[font-styles] `= "block-build" setattribute('font-styles)"whithouse" setattributevalue('boogies)"green-color" data-node: do to-path [DOM .p .b] document.(data-node).style[color] `= "bluberry" setattribute('i-style) "silly" ; Some examples of selecting keys and values set to variables as an array object. ; good to use with anything that's structured with {} , or "". It also can be used with []. ;IE (javascript, json objects/arrays.. lua table/arrays.. associative arrays etc.) ;even DOM's and rebol data. ;The insert, remove, append, and lookup of a group (a node-element) by way of a Var (variable) ;is done as a data-node and syntactically as an associative array. The associattion of key ;values is done by index in Rebol therefore there is no need for the overhead of objects or ;multi.dim arrays. But the cool part is you can do what ever you like! ;You must use use*=*to-set-values before setting the first variable. ;it will use = to set any value to a variable (a set-word) ;`= this literal equal is used to set values to keys. Feel free to use ;different function symbols for any !op function. use*=*to-set-values ;variables and there values (node-elements) that are'nt tags are sent and fetched from a ;node-list block for demo purposes. They will be appended to the DOM later. ;The variable name and the first word in it's value must be the same in order for ;the variable to be automatically bound to the node-element and array-obj!() function. var hello: = {hello 100:"a" 2: "two words" 7="c"} hello[2] hello[2] `= "a to z" node-element ;insert dots, "." to keys to be used as methods to get and set values. ;the to-methods function not created yet.sorry!.dot. ;use-methods: yes var app: = document.(getElementByTagName('p)[2]).style[bgcolor]`="green" .innerHTML("Lets change this, shall we.") ;You must call/associate the array-obj! with this variable name ;because the variable name "app" and the node-name/TagName "p" ;are not the same. *![app] ;or app: :array-obj! ;the style.obj! is auto created by using the document. function .style["bgcolor"] ;is the same as calling, but without the cell(block) this time. app 'bgcolor ;Write values however. they are handled by the get-array-obj! as any-type. node-element app[.width] `= "curly quew" app ('bgcolor) `= to-string [purple] ;when you need to create a variable to use with an array-obj! poppy: {100:"a" street : "backside" 7="c"} var 'poppy ;local or global hoisting: must move to head. head poppy[] var join {poppy2 } {200:"a" street : "backside" 7="c"} poppy2[] ;you don't need a set-word! variable. It will always be the first ;word followed by ": =", ": ", or " " found in the value (node-element) ;or a set word that has a value. ;you can access it with array-obj![]. But the value will change once ;a new VAR is created and you'll have to select it from the node-list. poppy[street]`="old rover rd." poppy[7] `= "cities" ;VAR values can also be set to an arrayed object. var poppy3: = [poppy3 #100:"a" street: "backside" #7:"c"] ;Even though it's not the best idea to use integers as keys, you can. ;it can encourage mistakes when trying to get by index... poppy2[3] ;But this is Rebol, so we will roll with this... ;You must always start cell number keys with the pound sign. "#" poppy3[street:]`= "old rover rd." poppy3[#7:]`= "cities" ;DOM variables are renamed to start with a dot "." so not to be confused with words. ;this will change in the future. All DOM Var's will be type! set-word!. ;Remember when calling a node-name and using that name as the variable, var .anObj: = getnodename "anobj" ;you dont have to call/associate the array-obj! with this variable name ;but the variable name must began with a dot. IE "." .anobj[7] ;but with var anObj: = getnodename "anobj" ;you do *![anObj] ;or anObj: :array-obj! anobj[7] ;after calling some variable[key]/array-obj![key], you can replace the key and value. replace replace node-element *key 'this-key *value {'some-value'} data-node var 'try-this try-this.[insert (add 50 50) ","] node-element try-this.[append ("new-value")","] try-this[.innerHTML("change me please") ""] ;a roadmap for javascripting with the Dialect Object Model (DOM). ;A quick way to change op! functions between rebol and javascript. js-op!: does [x: :* *: :do console.log: :print var 'use js-do: :js-op!] reb-op!: does [*: :x =: :equal? reb-do: :reb-op!] ;This code... { function welcomeSite() { siteMessage = "Welcome to the..."; console.log(siteMessage); var siteMessage; } welcomeSite(); siteMessage.append("Rebolution") siteMessage } ;Is changed to this code... js-op! 'function! welcomeSite: *{ siteMessage: = "Welcome to the... "; Message-type: "Welcome" do reb-op! alert(siteMessage) console.log(siteMessage); var 'siteMessage; }; ;Hey you can load welcomeSite from a DOM or files with variables, functions, key-values or Rebol code: use[welcomeSite()]; ;to use the welcomeSite Message-type in your code. js-do *{ var say-hi-to: = Message-type console.log(reduce ["This is a message to" say-hi-to "you."]); } siteMessage.[append("Rebolution.")#"^/"] siteMessage.[print] var first-obj: = {first-obj: first-name: "Brigsby" last-name: "Backfort"} var second-obj: = {second-obj: first-name: "Krystal" last-name: "Frontbunker"} first-obj[last-name]`="FortBack" first-obj[] second-obj[last-name]`="Bunkerfront" second-obj[] Var contacts: = {Bestfriend: "[{"first": "Besty", "last": "Bestest", "number": 777-9211}]"} Bestfriend[first] *![contacts] contacts[first] ;Does Var persist if not destroyed? YES. first-obj[] ;and then back to Rebol reb-do 2 * 2 ;Create a DOM from a nested javascript object DSL, search and update. ;A return-js-object-dsl() function will return the new js-object. ;Mold blocks and load strings to do quick formating like remove all ",". markup-DOM load replace/all {data: [ fullName: "James Zhan", address: { city: "Shenzhen", state: { name: "Guangdone", abbr: "CN"" }, country: { local-name: "Guangdone", abbr: "CN" id: "jazzy" }, }, hobbies: ["coding", "reading"], projects: [ { name: "form2json", language: "javascript", popular: true }, { name: "peony", language: "ruby" } ] ] } "," "" getElementById("jazzy").as-js-object var here: dom/.data/.projects/1 *![here] here[name]`="funkacopics" format-this node-element as-js-object! node-element dom/.data/.address ;And a cool but very simple trick in Rebol. For non-rebolers ;this IS code and data mixed together. First it's ALL string data. var num: {num: a: 1 b: 2 c: 3} ;Rember, the *num value is a string, not an object. amount: num[a]`= [amount '+ 15] ;And the new *formed() value is a [string: "1" word: '+ integer: 15] ;The DO() function binds each piece to the interpreter, and voila! num[a] Notes
|