rsence-pre 2.3.0.16 → 2.3.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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