UNPKG

9.22 kBtext/coffeescriptView Raw
1# Hack for IE 8 not allowing to add properties to text nodes
2# So, we'll use <span> instead of text nodes
3
4USE_SPAN_INSTEAD_OF_TEXT_NODES = false
5try
6 testTxtNode = document.createTextNode('')
7 testTxtNode.testProperty = ''
8catch Error
9 USE_SPAN_INSTEAD_OF_TEXT_NODES = true
10
11K = window.K
12
13class K.NateHtmlDom
14 @ON_CLICK_EVENT_BLOCKER: () ->
15 event = arguments[0] || window.event
16 rv = (event.button != 0)
17 event.returnValue = rv
18 return rv
19
20 constructor: (parentOrElem) ->
21 @children = []
22 @nateParent = null
23 @elem = null
24 # if there is parentOrElem, check the type of it
25 if parentOrElem?
26 if parentOrElem instanceof K.NateHtmlDom
27 @nateParent = parentOrElem
28 throw 'Nate parent is not properly handled in constructor yet !'
29 else if K.Elem.isElem(parentOrElem) or K.Elem.isText(parentOrElem)
30 if parentOrElem.nate?
31 throw 'Cannot create 2nd Nate object for same elem! The element you provided as elem for Nate is already a elem for different nate object'
32 else
33 # first, attach @ (this Nate object) to element
34 @attachNateToElem(parentOrElem)
35 # then, check if DOM parent is Nate object - if yes, tell it about me
36 if parentOrElem.parentNode? and parentOrElem.parentNode.nate?
37 parentOrElem.parentNode.nate.addNateChild @
38 else
39 throw 'parentOrElem should be Nate object or html-element'
40 else
41 throw 'parentOrElem should be Nate object or html-element - cannot be null'
42
43 deleteAllChildren: () ->
44 # TODO: optimize this
45 while @children.length > 0
46 @children[0].delete()
47
48 delete: () ->
49 #@deleteAllChildren()
50 if @nateParent?
51 @nateParent.removeNateChild(@)
52 else
53 @elem.style.backgroundColor = '#f00000'
54 throw 'Removal from non-nates is NOT supported. You tried to remove [elem:' + @elem + ']'
55
56 addNateChild: (nateChild) ->
57 if nateChild.nateParent?
58 throw 'Moving nate-child between parents not yet supported.'
59
60 nateChild.nateParent = @
61 @children.push(nateChild)
62 if @elem? and nateChild.elem? and (nateChild.elem.parentNode isnt @elem)
63 @elem.appendChild(nateChild.elem)
64
65 removeNateChild: (nateChild) ->
66 if nateChild.nateParent != @
67 throw 'Can\'t remove nateChild from me, as the child claims his parent is another object.'
68
69 K.Array.removeAll(@children, nateChild)
70 if @elem? and nateChild.elem
71 try
72 @elem.removeChild(nateChild.elem)
73 catch err
74 console.log 'Error during removeChild parent is:', @elem, 'child is:', nateChild.elem
75 nateChild.nateParent = null
76
77 newNate: (elem = null) ->
78 return new K.NateHtmlDom(elem)
79
80 newChildFromElement: (elem, text) ->
81 newNate = @newNate(elem)
82 @addNateChild(newNate)
83 if text?
84 newNate.set('innerHTML', text)
85 return newNate
86
87 newTextNode: (text = '') ->
88 if USE_SPAN_INSTEAD_OF_TEXT_NODES
89 return @newSpan(text)
90 else
91 textNode = document.createTextNode(text)
92 return @newChildFromElement(textNode)
93
94 newTxt: (theTxt) ->
95 return @newTextNode(theTxt)
96
97 newSpan: (text = null) ->
98 span = document.createElement('span')
99 return @newChildFromElement(span, text)
100
101 newDiv: (text = null) ->
102 div = document.createElement('div')
103 return @newChildFromElement(div, text)
104
105 newA: (text = null) ->
106 a = document.createElement('a')
107 return @newChildFromElement(a, text)
108
109 newB: (text = null) ->
110 a = document.createElement('b')
111 return @newChildFromElement(a, text)
112
113 newH1: (text = null) ->
114 a = document.createElement('h1')
115 return @newChildFromElement(a, text)
116
117 newH2: (text = null) ->
118 a = document.createElement('h2')
119 return @newChildFromElement(a, text)
120
121 newH3: (text = null) ->
122 a = document.createElement('h3')
123 return @newChildFromElement(a, text)
124
125 newImg: (text = null) ->
126 a = document.createElement('img')
127 return @newChildFromElement(a, text)
128
129 newLabel: (text = null) ->
130 a = document.createElement('label')
131 return @newChildFromElement(a, text)
132
133 newP: (text = null) ->
134 a = document.createElement('p')
135 return @newChildFromElement(a, text)
136
137 newUl: (text = null) ->
138 a = document.createElement('ul')
139 return @newChildFromElement(a, text)
140
141 newLi: (text = null) ->
142 a = document.createElement('Li')
143 return @newChildFromElement(a, text)
144
145 #
146 # HTML Table
147 #
148 newTable: (text = null) ->
149 a = document.createElement('table')
150 return @newChildFromElement(a, text)
151
152 newTBody: (text = null) ->
153 a = document.createElement('tbody')
154 return @newChildFromElement(a, text)
155
156 newTr: (text = null) ->
157 a = document.createElement('tr')
158 return @newChildFromElement(a, text)
159
160 newTd: (text = null) ->
161 a = document.createElement('td')
162 return @newChildFromElement(a, text)
163
164 newTh: (text = null) ->
165 a = document.createElement('th')
166 return @newChildFromElement(a, text)
167
168 #
169 # HTML Inputs
170 #
171 newTextArea: () ->
172 textarea = document.createElement('textarea')
173 return @newChildFromElement(textarea)
174
175 newOption: (text = null) ->
176 option = document.createElement('option')
177 return @newChildFromElement(option, text)
178
179 newSelect: () ->
180 return @newInputSelect()
181
182 newInputCheckbox: () ->
183 input = document.createElement('input')
184 input.type = "checkbox"
185 return @newChildFromElement(input)
186
187 newInputText: () ->
188 input = document.createElement('input')
189 input.type = "text"
190 return @newChildFromElement(input)
191
192 newInputPassword: () ->
193 input = document.createElement('input')
194 input.type = "password"
195 return @newChildFromElement(input)
196
197 newInputRadio: () ->
198 input = document.createElement('input')
199 input.type = "radio"
200 return @newChildFromElement(input)
201
202 newInputSelect: () ->
203 input = document.createElement('select')
204 return @newChildFromElement(input)
205
206 #
207 # SVG, canvas etc.
208 #
209 newCanvas: (text = null) ->
210 a = document.createElement('canvas')
211 return @newChildFromElement(a, text)
212
213 newSvg: () ->
214 a = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
215 return @newChildFromElement(a)
216
217 #
218 # nate methods
219 #
220 attachNateToElem: (elem) ->
221 # avoid registering >1 Nate objects to one elem
222 if elem.nate?
223 throw 'Provided elem already has Nate object'
224
225 # remove from current element is not supported
226 if @elem?
227 throw 'This nate object is already attached to element.'
228
229 # attach this object to elem
230 @elem = elem
231 @elem.nate = @
232 for child in @children
233 throw 'This needs to be updated...'
234 @elem.appendChild(child)
235
236 getElem: () ->
237 return @elem
238
239 get$: () ->
240 return $(@elem)
241
242 setText: (txt) ->
243 @set('innerHTML', txt)
244 return @
245
246 setOnClickEventBlocker: () ->
247 @set('onclick', K.NateHtmlDom.ON_CLICK_EVENT_BLOCKER)
248 return @
249
250 set: (param, value) ->
251 switch param
252 when 'rect'
253 value.applyToHtmlElement(@elem)
254 when 'checked', 'href', 'id', 'innerHTML', 'value', \
255 'selected', 'onclick', 'src', 'rowSpan', 'colSpan'
256 K.updateProperty(@elem, param, value)
257 when 'for' # 'for' in html maps to 'htmlFor' in js
258 K.updateProperty(@elem, 'htmlFor', value)
259 when 'style'
260 K.updateProperty(@elem.style, 'cssText', value)
261 when 'cssText', 'cursor', \
262 'display', 'float', \
263 'height', 'width', 'left', 'top', 'right', 'bottom',\
264 'margin', 'padding', \
265 'overflow', 'overflowX', 'overflowY', \
266 'position', 'visibility', 'zIndex', \
267 'textAlign', 'verticalAlign', \
268 'backgroundColor', 'color', \
269 'border', 'borderCollapse', \
270 'font', 'fontWeight'
271 K.updateProperty(@elem.style, param, value)
272 when 'on'
273 # TODO: handling of other things than 'block'
274 if value
275 @set 'display', 'block'
276 else
277 @set 'display', 'none'
278 when 'class'
279 K.updateProperty(@elem, 'className', value)
280 #@get$().addClass(value)
281 when 'cols', 'name', 'rows', 'wrap'
282 @elem.setAttribute(param, value)
283 else
284 throw 'No handling for given property implemented: ' + param
285 return @
286
287 setData: (key, value) ->
288 @elem.setAttribute('data-' + key, value)
289 return @
290
291 _decodeHtmlEntitiesToPlainText: (html) ->
292 # Example:
293 # input : Median &amp; average
294 # output : Median & average
295 tempDivElement = document.createElement('div')
296 tempDivElement.innerHTML = html
297
298 if tempDivElement.childNodes.length is 0
299 rv = ""
300 else
301 rv = tempDivElement.childNodes[0].nodeValue
302 return rv
303
304 setTitle: (title) ->
305 # We decode title to plain text, because document.title works in different way
306 # than static <title> tag. Browser's side title needs plain, decoded text
307 # instead of html.
308 document.title = @_decodeHtmlEntitiesToPlainText(title)