rsence-pre 2.3.0.16 → 2.3.0.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/VERSION +1 -1
  2. data/conf/default_conf.yaml +53 -200
  3. data/js/chat/chat_panel/chat_panel.coffee +120 -0
  4. data/js/chat/speech_bubble/speech_bubble.coffee +56 -0
  5. data/js/chat/speech_bubble/themes/default/speech_bubble.css +84 -0
  6. data/js/chat/speech_bubble/themes/default/speech_bubble.html +7 -0
  7. data/js/chat/speech_bubble/themes/default/user_anon.png +0 -0
  8. data/js/comm/sessionwatcher/sessionwatcher.js +1 -1
  9. data/js/comm/values/values.js +2 -34
  10. data/js/controls/numerictextcontrol/numerictextcontrol.coffee +109 -0
  11. data/js/controls/onoffbutton/onoffbutton.coffee +44 -0
  12. data/js/controls/onoffbutton/themes/default/onoffbutton.css +50 -0
  13. data/js/controls/onoffbutton/themes/default/onoffbutton.html +10 -0
  14. data/js/controls/textcontrol/textcontrol.coffee +291 -0
  15. data/js/core/class/class.js +1 -1
  16. data/js/core/elem/elem.coffee +83 -1
  17. data/js/core/util/util_methods/util_methods.coffee +103 -0
  18. data/js/datetime/calendar/calendar.coffee +3 -0
  19. data/js/datetime/calendar_pulldown/calendar_pulldown.coffee +62 -0
  20. data/js/datetime/calendar_pulldown/themes/default/calendar_pulldown.css +16 -0
  21. data/js/datetime/calendar_pulldown/themes/default/calendar_pulldown.html +1 -0
  22. data/js/datetime/calendar_pulldown/themes/default/calendar_pulldown.png +0 -0
  23. data/js/datetime/datepicker/datepicker.coffee +59 -0
  24. data/js/datetime/datetimepicker/datetimepicker.coffee +7 -0
  25. data/js/datetime/datetimepicker/datetimepicker.js +2 -2
  26. data/js/datetime/momentjs/momentjs.js +1400 -0
  27. data/js/datetime/timepicker/timepicker.coffee +7 -0
  28. data/js/foundation/application/application.js +1 -1
  29. data/js/foundation/control/valueaction/valueaction.js +8 -1
  30. data/js/foundation/control/valueresponder/valueresponder.js +1 -1
  31. data/js/foundation/view/morphanimation/morphanimation.js +9 -3
  32. data/js/foundation/view/view.js +43 -33
  33. data/js/views/scrollview/scrollview.js +10 -0
  34. data/lib/rsence/default_config.rb +10 -6
  35. data/plugins/client_pkg/lib/client_pkg_build.rb +2 -2
  36. metadata +22 -4
  37. data/js/controls/textcontrol/textcontrol.js +0 -420
@@ -0,0 +1,109 @@
1
+ #### = Description
2
+ ## HNumericTextControl is an extension of HTextControl that
3
+ ## validates the input as a number. It supports value ranges.
4
+ ##
5
+ ## If you need decimal numbers (floating-point), pass the
6
+ ## decimalNumber: true option to the constructor.
7
+ ####
8
+ HNumericTextControl = HTextControl.extend
9
+
10
+ defaultEvents:
11
+ mouseWheel: true
12
+ textEnter: true
13
+ contextMenu: true
14
+ keyDown: true
15
+
16
+ controlDefaults: HTextControl.prototype.controlDefaults.extend
17
+ numberIncrement: 1
18
+ decimalNumber: false
19
+ decimalPlaces: -1
20
+ decimalSeparator: '.'
21
+ withStepper: false
22
+
23
+ ## Uses the mouseWheel event to step up/down the value.
24
+ mouseWheel: (_delta)->
25
+ _value = @value
26
+ if _delta < 0
27
+ _value = _value-@options.numberIncrement
28
+ else
29
+ _value = _value+@options.numberIncrement
30
+ _value = @validateNumber(_value)
31
+ @setValue( _value )
32
+
33
+ keyDown: (_key)->
34
+ if _key == Event.KEY_UP
35
+ @mouseWheel(1)
36
+ return true
37
+ else if _key == Event.KEY_DOWN
38
+ @mouseWheel(-1)
39
+ return true
40
+ false
41
+
42
+ _numbers: ['0','1','2','3','4','5','6','7','8','9']
43
+ validateNumber: (_value)->
44
+ if @options.decimalNumber
45
+ _value = parseFloat(_value)
46
+ if @options.decimalPlaces != -1
47
+ _decPlaces = Math.pow(10,@options.decimalPlaces)
48
+ _value = Math.round(_value*_decPlaces)/_decPlaces
49
+ else
50
+ _value = parseInt( _value, 10 )
51
+ if isNaN( _value )
52
+ _value = @value
53
+ if _value > @maxValue
54
+ _value = @maxValue
55
+ else if _value < @minValue
56
+ _value = @minValue
57
+ _value
58
+
59
+ fieldToValue: (_unFilteredValue)->
60
+ _value = ''
61
+ for _chr, i in _unFilteredValue.split('')
62
+ if _chr == '.' or _chr == @options.decimalSeparator
63
+ _value += '.'
64
+ continue
65
+ if _chr == '-' and i == 0
66
+ _value += '-'
67
+ continue unless ~@_numbers.indexOf(_chr)
68
+ _value += _chr
69
+ @validateNumber( _value )
70
+ valueToField: (_value)->
71
+ _value = @validateNumber(_value)
72
+ if @options.decimalNumber and @options.decimalPlaces != -1
73
+ if _value - Math.round(_value) == 0
74
+ _value = _value+@options.decimalSeparator
75
+ for n in [0...@options.decimalPlaces]
76
+ _value += '0'
77
+ else
78
+ _value = _value.toString().replace('.',@options.decimalSeparator)
79
+ _value
80
+
81
+ refreshValue: ->
82
+ @base()
83
+ @stepper.setValue(@value) if @stepper?
84
+
85
+ ### = Description
86
+ ## Extends the validateText method to ensure the
87
+ ## input is a number.
88
+ ###
89
+ validateText: (_value)-> _value
90
+
91
+ drawSubviews: ->
92
+ @base()
93
+ @setStyleOfPart('value','textAlign','right')
94
+ if @options.withStepper
95
+ @setStyleOfPart('label','right','14px')
96
+ _top = Math.round((@rect.height-22)/2)
97
+ @stepper = HStepper.extend(
98
+ refreshValue: ->
99
+ @base()
100
+ @parent.setValue(@value)
101
+ ).new( [null,_top,14,24,0,null], @,
102
+ value: @value
103
+ valueObj: @valueObj
104
+ minValue: @minValue
105
+ maxValue: @maxValue
106
+ stepSize: @options.numberIncrement
107
+ enabled: @enabled
108
+ )
109
+ @stepper.bringToFront()
@@ -0,0 +1,44 @@
1
+ HOnOffButton = HCheckbox.extend
2
+ componentName: 'onoffbutton'
3
+ defaultEvents:
4
+ click: true
5
+ controlDefaults: HControlDefaults.extend
6
+ label: 'ON'
7
+ labelOff: 'OFF'
8
+ constructor: (_ctrl)->
9
+ if @label instanceof Array
10
+ @labelOff = @label[1]
11
+ @label = @label[0]
12
+ _ctrl.labelOff = @labelOff
13
+ markupElemNames: [ 'label', 'offlabel', 'control', 'onvalue', 'offvalue' ]
14
+ refreshLabel: ->
15
+ @base()
16
+ @refreshLabelOff()
17
+ setLabel: (_arr)->
18
+ if _arr instanceof Array
19
+ _label = _arr[0]
20
+ @setLabelOff( _arr[1] )
21
+ else
22
+ _label = _arr
23
+ @setMarkupOfPart('label',_label)
24
+ setLabelOff: (_label)->
25
+ @offLabel = _label
26
+ @refreshLabelOff()
27
+ refreshLabelOff: ->
28
+ @setMarkupOfPart( 'offlabel', @labelOff )
29
+ refreshValue: ->
30
+ if @value != false
31
+ @setStyleOfPart( 'offvalue', 'display', 'none' )
32
+ if @value != true
33
+ @setStyleOfPart( 'onvalue', 'display', 'none' )
34
+ if @value == false
35
+ @setStyleOfPart( 'offvalue', 'display', 'block' )
36
+ if @value == true
37
+ @setStyleOfPart( 'onvalue', 'display', 'block' )
38
+ click: (x,y)->
39
+ hw = @rect.width*0.5
40
+ x = x-@pageX()
41
+ if x < hw
42
+ @setValue(true)
43
+ else
44
+ @setValue(false)
@@ -0,0 +1,50 @@
1
+ .onoffbutton_label,
2
+ .onoffbutton_label_off {
3
+ position: absolute;
4
+ top: 2px; height: 20px; line-height: 20px;
5
+ text-align: center; vertical-align: middle;
6
+ font-family: Arial, sans-serif;
7
+ font-size: 12px; font-weight: bold;
8
+ color: #333;
9
+ }
10
+ .onoffbutton_label {
11
+ left: 6px; right: 50%;
12
+ }
13
+ .onoffbutton_label_off {
14
+ right: 6px; left: 50%;
15
+ }
16
+ .disabled > .button_control > .onoffbutton_label,
17
+ .disabled > .button_control > .onoffbutton_label_off {
18
+ color: #999;
19
+ }
20
+ .enabled > .button_control:hover > .onoffbutton_label,
21
+ .enabled > .button_control:active > .onoffbutton_label_off {
22
+ color: #000;
23
+ }
24
+ .enabled > .button_control:active > .onoffbutton_label,
25
+ .enabled > .button_control:active > .onoffbutton_label_off {
26
+ color: #000;
27
+ }
28
+ .onoffbutton_on,
29
+ .onoffbutton_off {
30
+ position: absolute;
31
+ display: none;
32
+ top: 1px; height: 20px;
33
+ opacity: 0.6;
34
+ }
35
+ .onoffbutton_off {
36
+ left: 50%; right: 1px;
37
+ background-color: #660000;
38
+ border-bottom-right-radius: 3px;
39
+ border-top-right-radius: 3px;
40
+ }
41
+ .onoffbutton_on {
42
+ right: 50%; left: 1px;
43
+ background-color: #006600;
44
+ border-bottom-left-radius: 3px;
45
+ border-top-left-radius: 3px;
46
+ }
47
+ .disabled > .button_control > .onoffbutton_off,
48
+ .disabled > .button_control > .onoffbutton_on {
49
+ opacity: 0.3;
50
+ }
@@ -0,0 +1,10 @@
1
+ <div class="button_control" id="control#{_ID}">
2
+ <div class="button_edge_left"></div>
3
+ <div class="button_center"></div>
4
+ <div class="button_edge_right"></div>
5
+ <div class="onoffbutton_on" id="onvalue#{_ID}"></div>
6
+ <div class="onoffbutton_off" id="offvalue#{_ID}"></div>
7
+ <div class="onoffbutton_label" id="label#{_ID}">#{this.label}</div>
8
+ <div class="onoffbutton_label_off" id="offlabel#{_ID}">#{this.offLabel}</div>
9
+ <div class="button_antiselect"></div>
10
+ </div>
@@ -0,0 +1,291 @@
1
+ #### = Description
2
+ ## HTextControl is a control unit that represents an editable input
3
+ ## line of text. Commonly, textcontrol is used as a single text field in
4
+ ## the request forms. HTextControl view or theme can be changed; the
5
+ ## default_theme is used by default.
6
+ ##
7
+ ## = Instance variables
8
+ ## +type+:: '[HTextControl]'
9
+ ## +value+:: The string that is currently held by this object.
10
+ ####
11
+ HTextControl = HControl.extend
12
+
13
+ componentName: 'textcontrol'
14
+
15
+ # allows text selection
16
+ textSelectable: true
17
+
18
+ defaultEvents:
19
+ textEnter: true
20
+ contextMenu: true
21
+
22
+ controlDefaults: HControlDefaults.extend
23
+ labelStyle:
24
+ textIndent: 0
25
+ fontSize: '10px'
26
+ color: '#666'
27
+ refreshAfter: 1
28
+ refreshOnBlur: true
29
+ refreshOnInput: true
30
+ refreshOnIdle: true
31
+ focusOnCreate: false
32
+
33
+ ## This flag is true, when the text input field has focus.
34
+ hasTextFocus: false
35
+
36
+ ### = Description
37
+ ## The contextMenu event for text input components is not prevented by default.
38
+ ###
39
+ contextMenu: -> true
40
+
41
+ ### = Description
42
+ ## The refreshLabel method sets the title property of the text
43
+ ## field, essentially creating a tooltip using the label.
44
+ ###
45
+ refreshLabel: ->
46
+ return unless @label
47
+ if @markupElemIds? and @markupElemIds.label?
48
+ @setAttrOfPart( 'label', 'title', @label )
49
+ else
50
+ return
51
+ if @_labelView?
52
+ @_labelView.setLabel( @label )
53
+ else
54
+ @_labelView = HLabel.new( [ 2, 2, 2000, 28 ], @,
55
+ label: @label
56
+ style: @options.labelStyle
57
+ )
58
+ _labelWidth = @_labelView.stringWidth( @label, null, @_labelView.markupElemIds.value )+4
59
+ @_labelView.rect.setWidth( _labelWidth )
60
+ @_labelView.drawRect()
61
+ if @componentName == 'textarea'
62
+ @setStyleOfPart('value','textIndent',_labelWidth+'px')
63
+ else
64
+ @setStyleOfPart('label','left',_labelWidth+'px')
65
+
66
+ drawSubviews: ->
67
+ ELEM.setStyle(@elemId,'overflow','visible')
68
+ @base()
69
+ if @options.focusOnCreate
70
+ @getInputElement().focus()
71
+ @setSelectionRange( @value.length, @value.length ) if @typeChr(@value) == 's'
72
+
73
+ lostActiveStatus: ->
74
+ if @markupElemIds? && @markupElemIds.value?
75
+ ELEM.get( @markupElemIds.value ).blur()
76
+ @textBlur()
77
+
78
+ setStyle: (_name, _value, _cacheOverride)->
79
+ @base(_name, _value, _cacheOverride)
80
+ return unless @markupElemIds? && @markupElemIds.value?
81
+ @setStyleOfPart('value', _name, _value, _cacheOverride)
82
+
83
+ setEnabled: (_flag)->
84
+ @base(_flag)
85
+ if @markupElemIds? and @markupElemIds.value?
86
+ ELEM.get(@markupElemIds.value).disabled = !@enabled
87
+
88
+ _clipboardEventTimer: null
89
+ _getChangeEventFn: ->
90
+ _this = @
91
+ return (e)->
92
+ clearTimeout( _this._clipboardEventTimer ) if _this._clipboardEventTimer
93
+ _this._clipboardEventTimer = setTimeout( ( -> _this.clipboardEvent() ), 200 )
94
+ return true
95
+ _changedFieldValue: (_value1,_value2)-> _value1 != _value2
96
+ _updateValueFromField: ->
97
+ _validatedValue = @validateText( @getTextFieldValue() )
98
+ if @_changedFieldValue( _validatedValue, @value )
99
+ @setValue( _validatedValue )
100
+
101
+ clipboardEvent: ->
102
+ @_updateValueFromField()
103
+ clearTimeout( @_clipboardEventTimer )
104
+ @_clipboardEventTimer = null
105
+
106
+ _changeEventFn: null
107
+ _clearChangeEventFn: ->
108
+ if @_changeEventFn
109
+ Event.stopObserving( ELEM.get(@markupElemIds.value), 'paste', @_changeEventFn )
110
+ Event.stopObserving( ELEM.get(@markupElemIds.value), 'cut', @_changeEventFn )
111
+ @_changeEventFn = null
112
+
113
+ _setChangeEventFn: ->
114
+ @_clearChangeEventFn() if @_changeEventFn
115
+ @_changeEventFn = @_getChangeEventFn()
116
+ Event.observe( ELEM.get(@markupElemIds.value), 'paste', @_changeEventFn )
117
+ Event.observe( ELEM.get(@markupElemIds.value), 'cut', @_changeEventFn )
118
+
119
+ ### = Description
120
+ ## Special event for text entry components.
121
+ ## Called when the input field gains focus.
122
+ ##
123
+ ###
124
+ textFocus: ->
125
+ EVENT.changeActiveControl( @ )
126
+ @hasTextFocus = true
127
+ @_setChangeEventFn()
128
+ true
129
+
130
+ ### = Description
131
+ ## Special event for text entry components.
132
+ ## Called when the input field loses focus.
133
+ ###
134
+ textBlur: ->
135
+ @hasTextFocus = false
136
+ @_clearChangeEventFn()
137
+ if @options.refreshOnBlur
138
+ @_updateValueFromField()
139
+ @refreshValue()
140
+ true
141
+
142
+ idle: ->
143
+ @refreshAfter() if @hasTextFocus and @options.refreshOnIdle and @options.refreshOnInput
144
+
145
+ refreshValue: ->
146
+ @setTextFieldValue( @value )
147
+
148
+ ### = Description
149
+ ## Placeholder method for validation of the value.
150
+ ##
151
+ ###
152
+ validateText: (_value)->
153
+ @fieldToValue(_value)
154
+
155
+ ### = Description
156
+ ## Returns the input element or null, if no input element created (yet).
157
+ ###
158
+ getInputElement: ->
159
+ return ELEM.get( @markupElemIds.value ) if @markupElemIds and @markupElemIds.value
160
+ null
161
+
162
+ ### = Description
163
+ ## Returns the value of the input element.
164
+ ###
165
+ getTextFieldValue: ->
166
+ _inputElement = @getInputElement()
167
+ if _inputElement?
168
+ return _inputElement.value
169
+ else
170
+ return ''
171
+
172
+ valueToField: (_value)-> _value
173
+ fieldToValue: (_value)-> _value
174
+
175
+ ### = Description
176
+ ## Sets the value of the input element.
177
+ ##
178
+ ## = Parameters
179
+ ## +_value+:: The value to set.
180
+ ###
181
+ setTextFieldValue: (_value)->
182
+ _inputElement = @getInputElement()
183
+ return unless _inputElement?
184
+ [ _selectionStart, _selectionEnd ] = @getSelectionRange()
185
+ _value = @valueToField(_value)
186
+ _inputElement.value = _value if _inputElement.value != _value.toString()
187
+ @setSelectionRange( _selectionStart, _selectionEnd )
188
+
189
+ # returns a random number prefixed and suffixed with '---'
190
+ _randomMarker: -> '---'+Math.round((1+Math.random())*10000)+'---'
191
+
192
+ die: ->
193
+ @getInputElement().blur() if @hasTextFocus
194
+ clearTimeout(@_refreshTimer) if @_refreshTimer
195
+ @_refreshTimer = null
196
+ @_clearChangeEventFn()
197
+ @base()
198
+
199
+ ### = Description
200
+ ## Returns the selection (or text cursor position) of the input element
201
+ ## as an +Array+ like +[ startOffset, endOffset ]+.
202
+ ###
203
+ getSelectionRange: ->
204
+ _inputElement = @getInputElement()
205
+ if _inputElement == null or @hasTextFocus == false
206
+ _rangeArr = [ 0, 0 ]
207
+ ## Internet Explorer:
208
+ else if document.selection
209
+ # create a range object
210
+ _range = document.selection.createRange()
211
+ # original range text
212
+ _rangeText = _range.text
213
+ _rangeLength = _rangeText.length
214
+ # make a copy of the text and replace \r\n with \n
215
+ _origValue = _inputElement.value.replace(/\r\n/g, "\n")
216
+ # create random marker to replace the text with
217
+ _marker = @_randomMarker()
218
+ # re-generate marker if it's found in the text.
219
+ _marker = @_randomMarker() until ~_origValue.indexOf( _marker )
220
+ _markerLength = _marker.length
221
+ # temporarily set the text of the selection to the unique marker
222
+ _range.text = _marker
223
+ _markerValue = _inputElement.value.replace(/\r\n/g, "\n")
224
+ _range.text = _rangeText
225
+ _markerIndex = _markerValue.indexOf( _marker )
226
+ _rangeArr = [ _markerIndex, _markerIndex + _rangeLength ]
227
+ ## Other browsers
228
+ else if _inputElement.selectionStart
229
+ _rangeArr = [ _inputElement.selectionStart, _inputElement.selectionEnd ]
230
+ ## No support:
231
+ else
232
+ _rangeArr = [ 0, 0 ]
233
+ return _rangeArr
234
+
235
+ _refreshTimer: null
236
+ _lastFieldValue: null
237
+ refreshAfter: ->
238
+ _fieldValue = @getTextFieldValue()
239
+ if @_lastFieldValue == null or _fieldValue != @_lastFieldValue
240
+ @_lastFieldValue = _fieldValue
241
+ if @_refreshTimer
242
+ clearTimeout( @_refreshTimer )
243
+ @_refreshTimer = null
244
+ if @options.refreshAfter and @options.refreshAfter > 0
245
+ _this = @
246
+ @_refreshTimer = setTimeout( (->
247
+ _this._updateValueFromField()
248
+ ), @options.refreshAfter*1000 )
249
+ else
250
+ @_updateValueFromField()
251
+ # @setValue( @validateText( @getTextFieldValue() ) )
252
+ # @refreshValue()
253
+
254
+ ### = Description
255
+ ## Sets the selection (or text cursor position) of the input element.
256
+ ##
257
+ ## = Parameters
258
+ ## +_selectionStart+:: The start of the selection (or an Array containing
259
+ ## both start and end offset, see below).
260
+ ## +_selectionEnd+:: The end offset of the selection.
261
+ ##
262
+ ## = Note
263
+ ## - +_selectionStart+ can also be given as an +Array+
264
+ ## like +[ startOffset, endOffset ]+.
265
+ ## - If the +_selectionEnd+ is omitted, no selection is made; the text
266
+ ## cursor is positioned at the startOffset instead.
267
+ ###
268
+ setSelectionRange: ( _selectionStart, _selectionEnd )->
269
+ if @typeChr( _selectionStart ) == 'a'
270
+ _selectionEnd = _selectionStart[1];
271
+ _selectionStart = _selectionStart[0];
272
+ unless _selectionEnd?
273
+ _selectionEnd = _selectionStart
274
+ _inputElement = @getInputElement()
275
+ return if _inputElement == null or @hasTextFocus == false
276
+ # Internet Explorer
277
+ if _inputElement.createTextRange
278
+ _range = _inputElement.createTextRange()
279
+ _range.move( 'character', _selectionStart, _selectionEnd )
280
+ _range.select()
281
+ # Other browsers:
282
+ else if _inputElement.selectionStart
283
+ _inputElement.setSelectionRange( _selectionStart, _selectionEnd )
284
+
285
+ ### = Description
286
+ ## Receives the +textEnter+ event to update the value
287
+ ## based on what's (potentially) entered in the text input field.
288
+ ###
289
+ textEnter: ->
290
+ @refreshAfter() if @options.refreshOnInput
291
+ return false
@@ -96,7 +96,7 @@ HClass.prototype = {
96
96
  _returnValue = _method.apply(this, arguments);
97
97
  }
98
98
  catch(e){
99
- !this.isProduction && console.warn("An exception occurred while calling base: ",this._exceptionProperties(e)," object: ",_ancestor);
99
+ !this.isProduction && console.warn("An exception occurred while calling base: ",HClass.prototype._exceptionProperties(e)," object: ",_ancestor);
100
100
  _returnValue = null;
101
101
  }
102
102
  // then because event this function can be called from child method
@@ -21,6 +21,9 @@ BROWSER_TYPE =
21
21
  firefox2: false
22
22
  firefox3: false
23
23
  firefox4: false # version 4 or newer
24
+ ios: false
25
+ iphone: false # also true for iPod touch
26
+ ipad: false
24
27
 
25
28
  ###
26
29
  The DOM Element abstraction engine
@@ -796,7 +799,80 @@ ELEM = HClass.extend
796
799
  else
797
800
  @_runCmd( @_domLoadQueue.shift() )
798
801
  null
799
-
802
+
803
+ ###
804
+ Returns an array of key, value style string pair containing the gradient style supported by the current browser.
805
+
806
+ The format of the colorSteps Object with the following items:
807
+ Key Description
808
+ start Default background color in a valid hexadecimal color format, also the start color
809
+ end Default gradient end color for dumber browsers
810
+ type Currently only 'linearTopBottom' is supported
811
+ steps An Array containing color, percent (number without suffix) pairs, like [ 10, '#fff']
812
+ ###
813
+ _standardGradientSteps: (_startColor,_stepsIn,_endColor)->
814
+ _steps = [ "#{_startColor} 0%" ]
815
+ if _stepsIn.length != 0
816
+ for _step in _stepsIn
817
+ _steps.push "#{_step[1]} #{_step[0]}%"
818
+ _steps.push "#{_endColor} 100%"
819
+ return _steps
820
+ _linearGradientStyle: (_gradient)->
821
+ # IE6-8
822
+ if BROWSER_TYPE.ie and not BROWSER_TYPE.ie9 and not BROWSER_TYPE.ie10
823
+ _key = 'filter'
824
+ _value = "progid:DXImageTransform.Microsoft.gradient( startColorstr='#{_gradient.start}', endColorstr='#{_gradient.end}',GradientType=0 )"
825
+ # IE9
826
+ else if BROWSER_TYPE.ie9 or BROWSER_TYPE.ie10
827
+ # IE9 SVG, needs conditional override of 'filter' to 'none'
828
+ # Also static white-shaded svg, needs a svg source to base64 utility
829
+ _key = 'background'
830
+ _svg = '<?xml version="1.0" ?>'
831
+ _svg += '<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">'
832
+ _svg += '<linearGradient id="gradientie9" gradientUnits="userSpaceOnUse" x1="0%" y1="0%" x2="0%" y2="100%">'
833
+ _svg += """<stop offset="0%" stop-color="##{_gradient.start}" />"""
834
+ for _step in _gradient.steps
835
+ _svg += """<stop offset="#{_step[0]}%" stop-color="##{_step[1]}" />"""
836
+ _svg += """<stop offset="100%" stop-color="##{_gradient.end}" />"""
837
+ _svg += _svgSteps.join('')
838
+ _svg += '</linearGradient>'
839
+ _svg += '<rect x="0" y="0" width="1" height="1" fill="url(#gradientie9)" />'
840
+ _svg += '</svg>'
841
+ _svg64 = @sha.str2Base64(_svg)
842
+ _value = "url(data:image/svg+xml;base64,#{_svg64})"
843
+ else if BROWSER_TYPE.ie10
844
+ _key = 'background'
845
+ _steps = @_standardGradientSteps(_gradient.start,_gradient.steps,_gradient.end).join(',')
846
+ _value = "-ms-linear-gradient(top, #{_steps})"
847
+ # Firefox 3.6 and newer
848
+ else if BROWSER_TYPE.firefox4 or BROWSER_TYPE.firefox3
849
+ _key = 'background'
850
+ _steps = @_standardGradientSteps(_gradient.start,_gradient.steps,_gradient.end).join(', ')
851
+ _value = "-moz-linear-gradient(top, #{_steps})"
852
+ # Chrome and Safari
853
+ else if BROWSER_TYPE.safari or BROWSER_TYPE.chrome
854
+ _key = 'background'
855
+ # Chrome10+,Safari5.1+
856
+ _steps = @_standardGradientSteps(_gradient.start,_gradient.steps,_gradient.end).join(',')
857
+ _value = "-webkit-linear-gradient(top, #{_steps})"
858
+ # Chrome,Safari4+ (unsupported)
859
+ # -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(9%,#efefef), color-stop(91%,#e0e0e0), color-stop(100%,#efefef))
860
+ # Opera 11.10+
861
+ else if BROWSER_TYPE.opera
862
+ _key = 'background'
863
+ _steps = @_standardGradientSteps(_gradient.start,_gradient.steps,_gradient.end).join(',')
864
+ _value = "-o-linear-gradient(top, )"
865
+ else
866
+ # Old browsers
867
+ _key = 'background'
868
+ _value = _gradient.start
869
+ # W3C standard:
870
+ # _steps = @_standardGradientSteps(_gradient.start,_gradient.steps,_gradient.end).join(',')
871
+ # _value = "linear-gradient(to bottom, #{_steps})"
872
+ return [ _key, _value ]
873
+ _linearGradientCSS: (_gradient)->
874
+ @_linearGradientStyle(_gradient).join(': ')+';'
875
+
800
876
  ###
801
877
  Does browser version checks and starts the document loaded check poll
802
878
  ###
@@ -816,6 +892,7 @@ ELEM = HClass.extend
816
892
  _browserType.ie9 = !!~_ua.indexOf('MSIE 9')
817
893
  _browserType.ie10 = !!~_ua.indexOf('MSIE 10')
818
894
  unless _browserType.ie9
895
+ @sha = SHA.new(8) # SHA1 needed for IE9/10 SVG base64 encoding
819
896
  _browserType.ie9 = _browserType.ie10 # IE 10 is treated like IE 9
820
897
  _browserType.mac = !!~_ua.indexOf('Macintosh')
821
898
  _browserType.win = !!~_ua.indexOf('Windows')
@@ -823,6 +900,11 @@ ELEM = HClass.extend
823
900
  _browserType.firefox2 = !!~_ua.indexOf('Firefox/2.')
824
901
  _browserType.firefox3 = !!~_ua.indexOf('Firefox/3.')
825
902
  _browserType.firefox4 = _browserType.firefox and not _browserType.firefox2 and not _browserType.firefox3
903
+ _iPhone = !!~_ua.indexOf('iPhone') or !!~_ua.indexOf('iPod')
904
+ _iPad = !!~_ua.indexOf('iPad')
905
+ _browserType.ios = _iPhone or _iPad
906
+ _browserType.iphone = _iPhone
907
+ _browserType.ipad = _iPad
826
908
  @_domWaiter()
827
909
  null
828
910