Script Library: 1238 scripts
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Archive version of: rebol-dom.r ... version: 42 ... inetw3dm 19-Apr-2021

Amendment note: Added: *strip-chars-from() to get-array-obj!() || Publicly available? Yes

REBOL [
    	File: %rebol-dom.r
    	Date: 02-11-2020
    	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
    ]

my-dialect: [
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 styles: "" 
		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: .table: .area: .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 #"^"" = node-name/1 [remove node-name]
			foreach [-char +char] obj-chars: [#"^/" " " 
			"," "" {" : "} {: "} {":"} {: "} {":} {:} {" "} {" } { " } "" 
			"[" "" "]" "" {""} {"} {  "} "" ":" "" { =} {=} {=} " " "'" ""
			][
			replace/all node-name -char +char
			]
]

getnodename: func [node-name][
        DOM: head DOM styles: "" =: :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 [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
		]
		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: form attr-name *value: none 
            do compose/deep [.style[(key)]]
            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 [array-obj! selection [block!]][
            dom: head dom 
            repeat this first selection [
            node-element: first data-node: first dom: next find dom to-word join "." array-obj!]
            if [use-methods and not find node-element " ." ][use-attr-as-methods yes]
            use-methods: off        
]

.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: []
var: func [var-data][node-element: ""
			any [
			attempt [variable: first parse node-element: var-data "=:, "]
			attempt [if equal? block! type? var-data [variable: first node-element: var-data]] 
			attempt [variable: to-string form var-data node-element: ""]
			]
			use*=*to-set-values
			if empty? node-element [if not find node-list variable [append node-list reduce 
			[form variable node-element: any [attempt [do :variable] " "]]]] 
			if not find node-list variable [append node-list reduce [form variable node-element]]
			do get-array-obj!
			attempt [if not find variable "." [do load to-string reduce ["set " #"'" variable ". :array-obj!"]]]
			use-methods: off
]

get-array-obj!: does [reform ["array-obj!: " join variable ":" 
			{func [key [block! word! string!]][
			if not equal? tag! type? node-element [node-element: select node-list } 
			mold form variable {] any [
			if empty? form key [ 
			return any [
			attempt [trim next find/tail node-element first parse node-element ":= ,"]
			next node-element]
			]
			attempt [*value: first this: next find parse strip-chars-from form parse/all node-element {=:} {=;,} *key: form key]  
			attempt [*value: select node-element *key: key] 
			attempt [do head insert next key [node-element join]] 
			attempt [do form key] 
			if not find node-element key []] ;[print [*key "called"]]
			]}
			]
]

arr=: `=: func[value][
			equal: :=  
			either find node-element mold form *value [
			replace node-element mold form *value mold value
			][
			either find node-element {=""} [
			replace node-element {=""} join "=" mold value
			][	
			replace node-element *value value
			]
			]
			 replace/all node-element {""} ""
] 

node-element: *node-name: *name: array-obj!: key: *key: *value: ""

markup-DOM: func [DSL][
		either block! = this-type?: type? DSL [
			either find DSL [rebol-DOM: [{DSL-type="html/block" type="text/html"}]] [DOM: copy/deep DSL]
			[insert DSL [rebol-DOM: [{DSL-type="html/block" type="text/html"}]]
			DOM: copy/deep DSL: load replace/all mold DSL "__" " "
			
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 [cnt: 0
		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 [
			set to-word join *node-name cnt: cnt + 1 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"]
		    ]
		
]

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]
]

{
**************************************************************************************************
An example of how to use the DOM functions follows. The syntax hopefully should be easy to follow being that it
resembles how you would use javascript with the HTML,XML DOM. 

It's just a little bit different, why not just make it the same?

Were not scripting against a DOM, (a Documents  Object Modle) but a DOM, (a Dialect Object Modle) because 
you may not actually know the syntax of the loaded document or data before it's transcode to a DOM from a DSL.

Plus Rebol wont let you too far off the hook in writing code any way you like. Some *op Words and  code/data 
has set types that follow a strict syntax. I think the best way around this is to load as type? string!, reformat 
and parse as type? block!. Maybe.....

These DOM functions should work very close to the HTML DOM functions:

getElementsByTagName .getAttribute .setAttribute 
}


markup-DOM my-dialect
        
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 " ". 
;IE (javascript, json objects/arrays.. lua table/arrays.. associative arrays etc.) 
;even DOM's and rebol data.

;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 

use*=*to-set-values

;variables and there values (node-elements) 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 value to be set as a node-element thats bound to the array-obj! function.

var anObj: = {anObj 100:"a" 2 : "two words" 7="c"}

anObj[2]

anObj[2] `= "a to z"

node-element

use-methods: yes

var app: = document.(getElementByTagName('p)[2]) 

        .style[bgcolor]`="green"
	
	.innerHTML("Lets change this, shall we.")


;call/associate the array-obj! with this variable name
;because the variable name "app" and the node-name "p"
;are not the same.

app: :array-obj!

;the style.obj! is auto created by using the document. function

.style["bgcolor"]

;is the same as calling 

app[bgcolor]

app[.width] `= "curly quew"

app ('bgcolor) `= {'purple'}


;when you need to create a variable to use with an array-obj!

var join {poppy } {100:"a" street : "backside" 7="c"}

;you don't need a set-word! variable. It will always be the first
;word followed by ": =", ": ", or " " found in the value (node-element).
;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. Rebol block! series.

var poppy2: = [poppy2 #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 number keys with the pound sign. "#"

poppy2[street:]`= "old rover rd."

poppy2[#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: :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

;..................................Why put Vars in my code?.................................................;
 
;Vars are array objects that should be used with all data as strings.
;no words, no symbols, no objects, no loading, no parsing,
;and no dependency on outside global functions. 

;If you could use Vars everywhere, i think your code would be
;simpler with less overhead (objects/function/WORDS) to deal with.

;You say too many strings is just as bad. They get stuck in the teeth
;and can gum up your stuff just as bad. Answere: Rebol2 = hash-it!.
;Yea i know, but thats why i like Rebol2.

;Data alone isn't functional at all. your right. We need methods.
;Vars can use it's data as methods to attempt to return it's own
;and other Var node-elements. And i think the good part is your
;forced to write them clear and simple. And they will attempt to 
;work with any caseload. 

;No, really Vars use *any [attempt(try again) on-true return]
;That can save you a lot of coding, but can become tricky too.

var 'try-this 

try-this.[insert (add 50 50) ","]

try-this.[append "beautiful" ""]

try-this.[(print ["hello" "there" your-to-old])]

try-this[100]

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!

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(["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[]

;and then back to Rebol

reb-do 2 * 2