Parcourir la source

added xml namespace extension

A Silk instance will use its xml namespace as namespace for new elements created through the DNU mechanism.
Example:
  svg := Silk newElement: 'svg' xmlns: 'http://www.w3.org/2000/svg'. "this creates a new svg element in its proper namespace"
  svg CIRCLE: {'cx' -> 60. 'cy' -> 25. 'r' -> 10}.   "This creates a svg circle, not a html circle"

The current behavior is not affected, this is just a new optional feature.
Christian Haider il y a 4 ans
Parent
commit
ea1ecbef93
1 fichiers modifiés avec 64 ajouts et 15 suppressions
  1. 64 15
      src/Silk.st

+ 64 - 15
src/Silk.st

@@ -51,16 +51,28 @@ Taken all this together, one can do pretty neat constructs:
 adds `<p id="mission">We are the champions.</p>` into `aSilk`
 and returns the Silk-wrapped `<p>` with insertion cursor at the end.!
 
-!Silk methodsFor: 'writing'!
+!Silk methodsFor: 'accessing'!
+
+namespace
+	"<String>
+	XML namespace for elements: html.
+	The default for all virtual Silk tag messages"
+	
+	^self element namespaceURI
+! !
+
+!Silk methodsFor: 'error handling'!
 
 doesNotUnderstand: aMessage
 	"`aSilk DIV` creates a div element and inserts it.
 	`aSilk DIV: anObject` creates a div element, inserts it
 	and puts contents in it"
-	(self class tryMakeDnuElement: aMessage)
+	(self class tryMakeDnuElement: aMessage in: self)
 		ifNil: [ ^ super doesNotUnderstand: aMessage ]
 		ifNotNil: [ :newElement | self << newElement. ^ newElement ]
-!
+! !
+
+!Silk methodsFor: 'writing'!
 
 nextPut: anObject
 	"Double-dispatches anObject via renderOnSilk: message.
@@ -71,11 +83,57 @@ nextPut: anObject
 		ifNil: [ super nextPut: anObject ]
 ! !
 
+!Silk class methodsFor: 'accessing'!
+
+htmlNamespace
+	"<String>
+	XML namespace for HTML elements.
+	The default for all virtual Silk tag messages"
+	
+	^'http://www.w3.org/1999/xhtml'
+!
+
+namespace
+	"<String>
+	XML namespace for elements: html.
+	The default for all virtual Silk tag messages"
+	
+	^self htmlNamespace
+! !
+
+!Silk class methodsFor: 'error handling'!
+
+doesNotUnderstand: aMessage
+	"`Silk DIV` creates a div element.
+	`Silk DIV: anObject` creates a div element and puts contents in it"
+	^ (self tryMakeDnuElement: aMessage in: self)
+		ifNil: [ super doesNotUnderstand: aMessage ]
+! !
+
 !Silk class methodsFor: 'instance creation'!
 
-tryMakeDnuElement: aMessage
+newElement: aString in: aSilk
+	"<Silk>
+	creates a new element in the same xml namespace as aSilk.
+	When aSilk is the class Silk, the default behavior applies (html namespace for new elements)"
+	
+	aSilk namespace = self htmlNamespace ifTrue: [
+		^self newElement: aString].
+	"actually, the lines above are not needed if you want to use the namespaced method always"
+	^self newElement: aString xmlns: aSilk namespace
+!
+
+tryMakeDnuElement: aMessage in: aSilk
 	"`DIV` creates a div element.
-	`DIV: anObject` creates a div element and puts contents in it"
+	`DIV: anObject` creates a div element and puts contents in it.
+	When aSilk is an instance and not the class Silk, 
+	and the instance has an xml namespace other than the default #html,
+	Then that namespace is used for the new element.
+	You can do:
+		svg := Silk newElement: 'svg' xmlns: 'http://www.w3.org/2000/svg'.
+		svg CIRCLE: {'cx' -> 60. 'cy' -> 25. 'r' -> 10}.
+	This creates a svg circle, not a html circle."
+	
 	| selector newElement useArg |
 	selector := aMessage selector.
 	selector asUppercase = selector
@@ -85,20 +143,11 @@ tryMakeDnuElement: aMessage
 		ifFalse: [ useArg := false ].
 	(selector includes: ':')
 		ifTrue: [ ^ nil ].
-	newElement := self newElement: selector asLowercase.
+	newElement := self newElement: selector asLowercase in: aSilk.
 	useArg ifTrue: [ newElement << aMessage arguments first ].
 	^ newElement
 ! !
 
-!Silk class methodsFor: 'message handling'!
-
-doesNotUnderstand: aMessage
-	"`Silk DIV` creates a div element.
-	`Silk DIV: anObject` creates a div element and puts contents in it"
-	^ (self tryMakeDnuElement: aMessage)
-		ifNil: [ super doesNotUnderstand: aMessage ]
-! !
-
 !Association methodsFor: '*Silk'!
 
 renderOnSilk: aSilk