adhearsion 0.7.6 → 0.7.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.version +1 -1
  2. data/CHANGELOG +43 -25
  3. data/Rakefile +0 -5
  4. data/TODO +51 -2
  5. data/ahn +2 -1
  6. data/apps/default/Rakefile +16 -7
  7. data/apps/default/config/adhearsion.yml +22 -1
  8. data/apps/default/config/helpers/manager_proxy.yml +1 -0
  9. data/apps/default/config/helpers/micromenus/images/arrow-off.gif +0 -0
  10. data/apps/default/config/helpers/micromenus/images/arrow-on.gif +0 -0
  11. data/apps/default/config/helpers/micromenus/images/error.gif +0 -0
  12. data/apps/default/config/helpers/micromenus/images/folder-off.gif +0 -0
  13. data/apps/default/config/helpers/micromenus/images/folder-on.gif +0 -0
  14. data/apps/default/config/helpers/micromenus/images/folder.png +0 -0
  15. data/apps/default/config/helpers/micromenus/images/ggbridge.jpg +0 -0
  16. data/apps/default/config/helpers/micromenus/images/green.png +0 -0
  17. data/apps/default/config/helpers/micromenus/images/microbrowser.bg.gif +0 -0
  18. data/apps/default/config/helpers/micromenus/images/red.png +0 -0
  19. data/apps/default/config/helpers/micromenus/images/url-off.gif +0 -0
  20. data/apps/default/config/helpers/micromenus/images/url-on.gif +0 -0
  21. data/apps/default/config/helpers/micromenus/images/yellow.png +0 -0
  22. data/apps/default/config/helpers/micromenus/javascripts/animation.js +1341 -0
  23. data/apps/default/config/helpers/micromenus/javascripts/carousel.js +1238 -0
  24. data/apps/default/config/helpers/micromenus/javascripts/columnav.js +306 -0
  25. data/apps/default/config/helpers/micromenus/javascripts/connection.js +965 -0
  26. data/apps/default/config/helpers/micromenus/javascripts/container.js +4727 -0
  27. data/apps/default/config/helpers/micromenus/javascripts/container_core.js +2915 -0
  28. data/apps/default/config/helpers/micromenus/javascripts/dom.js +892 -0
  29. data/apps/default/config/helpers/micromenus/javascripts/dragdrop.js +2921 -907
  30. data/apps/default/config/helpers/micromenus/javascripts/event.js +1771 -0
  31. data/apps/default/config/helpers/micromenus/javascripts/yahoo.js +433 -0
  32. data/apps/default/config/helpers/micromenus/stylesheets/carousel.css +78 -0
  33. data/apps/default/config/helpers/micromenus/stylesheets/columnav.css +135 -0
  34. data/apps/default/config/helpers/micromenus/stylesheets/microbrowsers.css +42 -0
  35. data/apps/default/config/helpers/multi_messenger.yml +5 -1
  36. data/apps/default/config/migration.rb +10 -0
  37. data/apps/default/extensions.rb +1 -1
  38. data/apps/default/helpers/factorial.alien.c +3 -3
  39. data/apps/default/helpers/lookup.rb +2 -1
  40. data/apps/default/helpers/manager_proxy.rb +67 -15
  41. data/apps/default/helpers/micromenus.rb +173 -31
  42. data/apps/default/helpers/multi_messenger.rb +20 -3
  43. data/lib/adhearsion.rb +218 -88
  44. data/lib/constants.rb +1 -0
  45. data/lib/core_extensions.rb +15 -9
  46. data/lib/phone_number.rb +85 -0
  47. data/lib/rami.rb +3 -2
  48. data/lib/servlet_container.rb +47 -24
  49. data/lib/sexy_migrations.rb +70 -0
  50. data/test/asterisk_module_test.rb +9 -9
  51. data/test/specs/numerical_string_spec.rb +53 -0
  52. metadata +31 -11
  53. data/apps/default/config/helpers/micromenus/javascripts/builder.js +0 -131
  54. data/apps/default/config/helpers/micromenus/javascripts/controls.js +0 -834
  55. data/apps/default/config/helpers/micromenus/javascripts/effects.js +0 -956
  56. data/apps/default/config/helpers/micromenus/javascripts/prototype.js +0 -2319
  57. data/apps/default/config/helpers/micromenus/javascripts/scriptaculous.js +0 -51
  58. data/apps/default/config/helpers/micromenus/javascripts/slider.js +0 -278
  59. data/apps/default/config/helpers/micromenus/javascripts/unittest.js +0 -557
  60. data/apps/default/config/helpers/micromenus/stylesheets/firefox.css +0 -10
  61. data/apps/default/config/helpers/micromenus/stylesheets/firefox.xul.css +0 -44
@@ -0,0 +1,135 @@
1
+ /*
2
+ * Copyright (c) 2007, David A. Lindquist (stringify.com)
3
+ * Some Rights Reserved
4
+ *
5
+ * This code is licensed under the Creative Commons Attribution 2.5 License
6
+ * (http://creativecommons.org/licenses/by/2.5/). Please maintain the above
7
+ * license and copyright statements when using this code.
8
+ *
9
+ * $Id: columnav.css 476 2007-02-20 23:43:22Z david $
10
+ */
11
+
12
+ /* DO NOT CHANGE ANYTHING IN THIS SECTION
13
+
14
+ Styles below override defaults in carousel.css and govern fundamental layout
15
+ and behavior.
16
+
17
+ ------------------------------------------------------------------------------*/
18
+
19
+ .carousel-component {
20
+ background: transparent;
21
+ color: black;
22
+ overflow: auto !important;
23
+ padding: 0;
24
+ }
25
+
26
+ .carousel-component ul.carousel-list li {
27
+ color: black;
28
+ font-family: inherit;
29
+ font-size: 1em;
30
+ text-align: left;
31
+ }
32
+
33
+ .carousel-component ul.carousel-list li div {
34
+ overflow: auto;
35
+ overflow-y: scroll;
36
+ position: relative;
37
+ }
38
+
39
+ .carousel-component ul.carousel-list li a {
40
+ display: block;
41
+ overflow-x: hidden;
42
+ position: relative;
43
+ }
44
+
45
+ .carousel-component ul.carousel-list li a span {
46
+ display: block;
47
+ position: relative;
48
+ }
49
+
50
+
51
+ /* CUSTOMIZE ANYTHING IN THIS SECTION
52
+
53
+ Styles below can be changed to customize colors, margins, padding, fonts,
54
+ etc., as well as the icons that appear before each item. At minimum, set the
55
+ width of .carousel-component and its list items, and the height of the div
56
+ it contains.
57
+
58
+ ------------------------------------------------------------------------------*/
59
+
60
+ .carousel-component {
61
+ }
62
+
63
+ .carousel-component ul.carousel-list li {
64
+ width: 348px;
65
+ }
66
+
67
+ .carousel-component ul.carousel-list li div {
68
+ height: 348px;
69
+ }
70
+
71
+ .carousel-component ul.carousel-list li a {
72
+ color: black;
73
+ cursor: default;
74
+ font-family: 'Lucida Grande', Helvetica, Arial, sans-serif;
75
+ font-size: 12px;
76
+ margin: 0 1px;
77
+ padding: 2px;
78
+ text-decoration: none;
79
+ }
80
+
81
+ .carousel-component ul.carousel-list li a.columnav-has-menu {
82
+ background-image: url(../images/arrow-off.gif);
83
+ background-position: right center;
84
+ background-repeat: no-repeat;
85
+ }
86
+
87
+ .carousel-component ul.carousel-list li a.columnav-active {
88
+ background-color: #3875d7;
89
+ }
90
+
91
+ /* IE6 cannot grok element selectors with chained class names */
92
+ html>body .carousel-component ul.carousel-list li a.columnav-has-menu.columnav-active {
93
+ background-image: url(../images/arrow-on.gif);
94
+ }
95
+
96
+ .carousel-component ul.carousel-list li a.columnav-error span {
97
+ background-image: url(../images/error.gif);
98
+ color: red;
99
+ }
100
+
101
+ .carousel-component ul.carousel-list li a span {
102
+ background-repeat: no-repeat;
103
+ background-position: 0px center;
104
+ margin-right: 14px;
105
+ padding-left: 20px;
106
+ }
107
+
108
+ .carousel-component ul.carousel-list li a.columnav-active span {
109
+ color: white;
110
+ }
111
+
112
+ .carousel-component ul.carousel-list li a.columnav-has-menu span {
113
+ background-image: url(../images/folder-off.gif);
114
+ }
115
+
116
+ /* IE6 cannot grok element selectors with chained class names */
117
+ html>body .carousel-component ul.carousel-list li a.columnav-has-menu.columnav-active span {
118
+ background-image: url(../images/folder-on.gif);
119
+ }
120
+
121
+ .prevButton { }
122
+ .prevButton a {
123
+ color: black;
124
+ font-family: 'Lucida Grande', Helvetica, Arial;
125
+ font-size: 10px;
126
+ line-height: 22px;
127
+ position: relative;
128
+ text-align: center;
129
+ text-decoration: none;
130
+ }
131
+
132
+ .prevButton a:hover {
133
+ background-color: #3875d7;
134
+ color: white;
135
+ }
@@ -0,0 +1,42 @@
1
+ body {
2
+ background: url(/images/ggbridge.jpg) top left no-repeat; }
3
+
4
+ div.microbrowser {
5
+ background: url(/images/microbrowser.bg.gif) top left no-repeat;}
6
+ div.microbrowser .hd {}
7
+ div.microbrowser .ft {
8
+ display: none; }
9
+ div.microbrowser h1 {
10
+ color: white;
11
+ text-shadow: black 0px 0px 5px;
12
+ margin: 0; padding: 6px 0;
13
+ text-align: center;
14
+ font-size: 20px; }
15
+
16
+ .yui-panel {
17
+ width: 400px;}
18
+
19
+ .yui-panel .hd {
20
+ padding:0;
21
+ border:none;
22
+ color:#000;
23
+ height:44px;
24
+ margin-left:33px;
25
+ margin-right:33px;
26
+ text-align:center;
27
+ overflow:visible; }
28
+
29
+ .yui-panel .hd .tl {
30
+ width:30px;
31
+ height:22px;
32
+ top: 4px;
33
+ left:10px;
34
+ position:absolute; }
35
+
36
+ .yui-panel .hd .tr {
37
+ width:30px;
38
+ height:22px;
39
+ line-height: 22px;
40
+ top:6px;
41
+ left:315px;
42
+ position:absolute; }
@@ -2,4 +2,8 @@
2
2
  # be any Jabber/XMPP account.
3
3
  username: test@adhearsion.com
4
4
  password: password
5
- enabled: false
5
+ enabled: false
6
+
7
+ # Specify whether incoming subscription requests should
8
+ # be automatically accepted.
9
+ accept_subscriptions: false
@@ -47,3 +47,13 @@ class CreateGroups < ActiveRecord::Migration
47
47
  drop_table :groups
48
48
  end
49
49
  end
50
+
51
+
52
+ CreateUsers.up
53
+ CreateGroups.up
54
+
55
+ ### If you'd like to create any initial users, do it here by
56
+ ### requiring your database.rb file and performing your logic.
57
+ #
58
+ # require 'config/database.rb'
59
+ # User.create :name => "Jay Phillips", :extension => 123
@@ -7,7 +7,7 @@
7
7
  # your extensions.conf file for Adhearsion as so:
8
8
  #
9
9
  # [internal]
10
- # exten => _X.,1,AGI(agi://192.168.1.3)
10
+ # exten => _.,1,AGI(agi://192.168.1.3)
11
11
  #
12
12
  # then, when Adhearsion receives that call, it sees it came from
13
13
  # the "internal" context and invokes this.
@@ -24,9 +24,9 @@
24
24
  */
25
25
 
26
26
  int fast_factorial(int input) {
27
- int sum = 0, count = 1;
27
+ int prod = 1, count = 1;
28
28
  while(count <= input) {
29
- sum += count++;
29
+ prod *= count++;
30
30
  }
31
- return sum;
31
+ return prod;
32
32
  }
@@ -15,7 +15,8 @@ def lookup number
15
15
  if (results = doc.at "#results_single_listing") then
16
16
  # This div's h3 contains the name of the caller
17
17
  hash[:first_name], hash[:last_name] = results.at('h3').inner_html.split(/,\s*/).reverse
18
-
18
+ hash[:name] = hash[:first_name] + " " + hash[:last_name]
19
+
19
20
  # Now we just need the rest of the information contained in p's.
20
21
  meta = results/'p'
21
22
  meta.pop # Discard the useless p element
@@ -38,23 +38,75 @@ class PBX
38
38
  @@sip_users[:users]
39
39
  end
40
40
 
41
- def self.originate hash
42
- # This is an ugly hack to use until RAI's AMI work is ported in.
43
- h = {}
44
- h['Application'] = hash.delete :app
45
- hash.each { |k,v| h[k.to_s.titleize] = v }
46
- @@rami_client.originate h
47
- end
41
+ class << self
42
+
43
+ # An introduction connects two endpoints together. The first argument is
44
+ # the first person the PBX will call. When she's picked up, Asterisk will
45
+ # play ringing while the second person is being dialed.
46
+ #
47
+ # The first argument is the person called first. Pass this as a canonical
48
+ # IAX2/server/user type argument. Destination takes the same format, but
49
+ # comma-separated Dial() arguments can be optionally passed after the
50
+ # technology.
51
+ #
52
+ # TODO: Provide an example when this works.
53
+ def introduce src, dst, hash={}
54
+ cid = hash.delete(:callerid) || hash.delete(:cid)
55
+ options = hash.delete(:options) || hash.delete(:opts)
56
+ dst << "|" << options if options
57
+ call_and_exec src, "Dial", dst, cid
58
+ end
59
+
60
+ def call_and_exec channel, app, args=nil, callerid=nil
61
+ args = { :channel => channel
62
+ :application => app }
63
+ args[:data] = args if args
64
+ args[:callerid] = callerid if callerid
65
+ originate args
66
+ end
67
+
68
+ def overhear their_channel, your_channel
69
+
70
+ end
71
+
72
+
73
+ def call chan, code=nil, &block
74
+ raise "Cannot provide both a String and a block!" if code && block_given?
75
+ ip = 'localhost' # TODO: How to get this?!
76
+ originate :application => "AGI",
77
+ :data => "agi://#{ip}/?call_id=",
78
+ :channel => chan
79
+
80
+ # TODO: Initiate an origination that comes back
81
+ # into Adhearsion and runs either a certain block
82
+ # of code or eval()s a String of dialplan code.
83
+ end
84
+
85
+ def originate hash
86
+ # This is an ugly hack to use until RAI's AMI work is ported in.
87
+ h = {}
88
+ h['Application'] = hash.delete :app
89
+ hash.each { |k,v| h[k.to_s.titleize] = v }
90
+ @@rami_client.originate h
91
+ end
48
92
 
49
- def self.record hash={}, &block
50
- # TODO: Implement me!
51
- raise NotImplementedError
93
+ def record hash={}, &block
94
+ # TODO: Implement me!
95
+ raise NotImplementedError
52
96
 
53
- # defaults = {:file => "#{String.random(5)}", :folder => nil,
54
- # :channel => Thread.current[:VARS]['channel'], :format => 'wav', :mix => '1'}
55
- # defaults = defaults.merge hash
56
- # PBX.rami_client.... # TODO
97
+ # defaults = {:file => "#{String.random(5)}", :folder => nil,
98
+ # :channel => Thread.current[:VARS]['channel'], :format => 'wav', :mix => '1'}
99
+ # defaults = defaults.merge hash
100
+ # PBX.rami_client.... # TODO
101
+ end
102
+
103
+ # private
104
+ # CALL_BLOCK_CACHE = {}
105
+ # def handle_call_specifically expiration=3.minutes.from_now, &block
106
+ # # Find a random, unused id
107
+ # while CALL_BLOCK_CACHE[id = rand(1_073_741_823)]; end # 1073741823 is the Fixnum max
108
+ # CALL_BLOCK_CACHE[id] = [expiration, block]
109
+ # end
57
110
  end
58
111
 
59
-
60
112
  end
@@ -51,8 +51,8 @@ class MicromenusServlet < WEBrick::HTTPServlet::AbstractServlet
51
51
 
52
52
  if route.empty?
53
53
  start "Error" do
54
- build_text "Bad URL!"
55
- build_text "Must point to a micromenu!"
54
+ build_text "Whoops!"
55
+ build_text "You forgot to include the target Micromenu in the URL path!"
56
56
  end
57
57
  return
58
58
  end
@@ -63,9 +63,10 @@ class MicromenusServlet < WEBrick::HTTPServlet::AbstractServlet
63
63
  load_menu filename
64
64
  until route.empty?
65
65
  segment = route.shift
66
- broken = segment.match(/^([\w_.]+);?(\d*)$/)
67
- segment, id = broken[1], broken[2]
68
- id = nil if id.empty?
66
+ broken = segment.match(/^([\w_.]+)(;(\d*))?$/)
67
+
68
+ segment, id = broken[1], broken[3]
69
+ id = nil if id && id.empty?
69
70
 
70
71
  matches = @config.select do |x|
71
72
  x[:type] == :menu && x[:text].nameify == segment
@@ -111,13 +112,12 @@ class MicromenusServlet < WEBrick::HTTPServlet::AbstractServlet
111
112
  end
112
113
  end
113
114
  end
114
-
115
115
  def load_menu filename
116
116
  @config.clear
117
117
  file = File.join('config','helpers', 'micromenus', filename + '.rb')
118
118
  unless File.readable? file
119
- item "Bad URL!"
120
- item "File inexistent!"
119
+ item "Target Micromenu doesn't exist!"
120
+ item "Did you input the URL correctly?"
121
121
  else
122
122
  eval File.read(File.join('config','helpers', 'micromenus', filename + '.rb'))
123
123
  end
@@ -131,8 +131,49 @@ class MicromenusServlet < WEBrick::HTTPServlet::AbstractServlet
131
131
  ((url[-1] == ?/) ? url : url + "/") + pages * '/'
132
132
  end
133
133
  end
134
-
135
134
  def get_refresh() @refresh end
135
+
136
+
137
+ module AjaxResponse
138
+
139
+ def content_type() "application/xml" end
140
+
141
+ def start name='', &block
142
+ @xml.ul do
143
+ yield
144
+ end
145
+ end
146
+
147
+ def build_menu str, uri, request
148
+ #build_menu item[:text], item[:uri], request
149
+ #request.flatten! if request.is_a? Array
150
+ @xml.li do
151
+ @xml.a str, :href => join_url('ajax', request, uri), :rel => 'ajax'
152
+ end
153
+ end
154
+
155
+ def build_text str
156
+ @xml.li { @xml.span str }
157
+ end
158
+
159
+ def build_prompt
160
+
161
+ end
162
+
163
+ def build_image filename, hash=nil
164
+ @xml.img :src => "/images/#{filename}"
165
+ end
166
+
167
+ def build_header str
168
+ @xml.li { @xml.h1 str }
169
+ end
170
+
171
+ def build_call number, name=number
172
+ @xml.a name, :href => "javascript:dial(#{number})"
173
+ @xml.br
174
+ end
175
+ end
176
+
136
177
 
137
178
  module PolycomPhone
138
179
 
@@ -176,7 +217,7 @@ class MicromenusServlet < WEBrick::HTTPServlet::AbstractServlet
176
217
  @xml.br
177
218
  end
178
219
  end
179
-
220
+
180
221
  module XulUi
181
222
 
182
223
  include PolycomPhone
@@ -220,29 +261,122 @@ class MicromenusServlet < WEBrick::HTTPServlet::AbstractServlet
220
261
  end
221
262
 
222
263
  end
223
-
224
-
225
- module FirefoxUi
264
+ module ModernUi
265
+
266
+ CSSs = %w"carousel columnav microbrowsers"
267
+ JAVASCRIPTS = %w"yahoo event dom animation connection container dragdrop carousel columnav"
268
+ INIT = %{
269
+ try { document.execCommand('BackgroundImageCache', false, true); } catch(e) {}
270
+ function init() {
271
+ var cn_cfg = { prevElement: 'columnav-prev', source: document.getElementById('main') };
272
+ var cn = new YAHOO.extension.ColumNav('columnav', cn_cfg);
273
+
274
+ YAHOO.namespace("example.container");
275
+
276
+ YAHOO.example.container.panel1 = new YAHOO.widget.Panel("unique", { width:"350px", visible:true, draggable:true, close:true } );
277
+ YAHOO.example.container.panel1.render();
278
+
279
+ /*
280
+ YAHOO.example.container.panel2 = new YAHOO.widget.Panel("panel2", { width:"300px", visible:true, draggable:true, close:true } );
281
+ YAHOO.example.container.panel2.setHeader("Panel #2 from Script");
282
+ YAHOO.example.container.panel2.setBody("This is a dynamically generated Panel.");
283
+ YAHOO.example.container.panel2.setFooter("End of Panel #2");
284
+ YAHOO.example.container.panel2.render(document.body);
285
+ */
286
+
287
+ YAHOO.util.Event.addListener("show1", "click", YAHOO.example.container.panel1.show, YAHOO.example.container.panel1, true);
288
+ YAHOO.util.Event.addListener("hide1", "click", YAHOO.example.container.panel1.hide, YAHOO.example.container.panel1, true);
289
+
290
+ /*
291
+ YAHOO.util.Event.addListener("show2", "click", YAHOO.example.container.panel2.show, YAHOO.example.container.panel2, true);
292
+ YAHOO.util.Event.addListener("hide2", "click", YAHOO.example.container.panel2.hide, YAHOO.example.container.panel2, true);
293
+ */
294
+ }
295
+ YAHOO.util.Event.addListener(window, 'load', init);
296
+
297
+ }
298
+
299
+ def content_type() "text/html" end
226
300
 
227
- include PolycomPhone
228
-
229
301
  def start name='', &block
230
302
  @xml.html do
231
303
  @xml.head do
232
304
  @xml.title name
233
- @xml.link :rel => 'stylesheet', :media => 'all', :href => '/stylesheets/firefox.css'
305
+ CSSs.each { |css| @xml.link :rel => 'stylesheet', :type => 'text/css', :href => "/stylesheets/#{css}.css"}
306
+
307
+ JAVASCRIPTS.each { |script| @xml.script :type => 'text/javascript', :src => "/javascripts/#{script}.js" do end }
308
+ @xml.script INIT, :type => 'text/javascript'
234
309
  end
235
310
  @xml.body do
236
- yield
311
+
312
+ @xml.div :id => "unique", :class => 'microbrowser' do
313
+
314
+ @xml.div :class => "hd" do
315
+ @xml.div :class => "tl" do
316
+ @xml.div :class => 'prevButton' do
317
+ @xml.a "Back", :href => "javascript:void(0)", :id => "columnav-prev"
318
+ end
319
+ end
320
+ @xml.h1 name
321
+ @xml.div :class => 'tr' do
322
+ @xml.span "Close", :class => "container-close"
323
+ end
324
+ end
325
+
326
+ @xml.div :class => 'bd' do
327
+ @xml.div :id => 'columnav', :class => "carousel-component" do
328
+ @xml.div :class => "carousel-clip-region" do
329
+ @xml.ul :class => "carousel-list" do end
330
+ end
331
+ end
332
+
333
+ @xml.ul :id => 'main', :style => 'display:none' do
334
+ yield
335
+ # @xml << %{
336
+ # <li><a href="/viewaddressbook">View Address book again</a>
337
+ # <ul><li>
338
+ # <a href="http://google.com">Jicksta.com</a>
339
+ # </li></ul></li>
340
+ # <li><a href='#'>Linking to Somewhere</a></li>
341
+ # <li><strong>Not</strong> linking to somewhere</li>
342
+ # }
343
+ end
344
+ end
345
+
346
+ @xml.div :class => "ft" do
347
+ @xml.hr
348
+ end
349
+
350
+ end
237
351
  end
238
352
  end
239
353
  end
354
+
355
+ def build_menu str, uri, request
356
+ #build_menu item[:text], item[:uri], request
357
+ #request.flatten! if request.is_a? Array
358
+ @xml.li { @xml.a str, :rel => 'ajax', :href => join_url('ajax', request, uri) }
359
+ end
360
+
361
+ def build_text str
362
+ @xml.li { @xml.span str }
363
+ end
364
+
365
+ def build_prompt
366
+
367
+ end
368
+
369
+ def build_image filename, hash=nil
370
+ @xml.li { @xml.img :src => "/images/#{filename}" }
371
+ end
372
+
373
+ def build_header str
374
+ @xml.li { @xml.h1 str }
375
+ end
376
+
240
377
  def build_call number, name=number
241
- # The tel:// UI doesn't do Firefox much good. Mexuar, maybe?
242
- @xml.a name, :href => "tel://#{number}"
243
- @xml.br
378
+ @xml.li { @xml.a name, :href => "javascript:call(#{number})" }
244
379
  end
245
-
246
380
  end
247
381
 
248
382
 
@@ -253,11 +387,9 @@ class MicromenusServlet < WEBrick::HTTPServlet::AbstractServlet
253
387
  name += '.bmp' unless name.index ?.
254
388
  @config << {:type => :image, :text => name}
255
389
  end
256
-
257
- def refresh_every time
390
+ def refresh_every time
258
391
  @refresh = time
259
392
  end
260
-
261
393
  def heading str
262
394
  @config << {:type => :heading, :text => str}
263
395
  end
@@ -302,8 +434,7 @@ class MicromenusServlet < WEBrick::HTTPServlet::AbstractServlet
302
434
  end
303
435
 
304
436
  USER_AGENT_MAP = {
305
- "Polycom" => MicromenuGenerator::PolycomPhone,
306
- "Firefox" => MicromenuGenerator::XulUi#FirefoxUi
437
+ "Polycom" => MicromenuGenerator::PolycomPhone
307
438
  }
308
439
 
309
440
  def do_GET(request, response)
@@ -311,6 +442,13 @@ class MicromenusServlet < WEBrick::HTTPServlet::AbstractServlet
311
442
  log "Request from: " + request['User-Agent']
312
443
 
313
444
  route = request.path[1..-1].split '/'
445
+ handler = nil
446
+
447
+ if route.first == 'ajax'
448
+ handler = MicromenuGenerator::AjaxResponse
449
+ route.shift
450
+ end
451
+
314
452
  if route.first == 'images'
315
453
  file = File.join(%w(config helpers micromenus images), route[1..-1])
316
454
  # TODO: Handle missing files
@@ -321,17 +459,21 @@ class MicromenusServlet < WEBrick::HTTPServlet::AbstractServlet
321
459
  file = File.join %w(config helpers micromenus stylesheets), route[1..-1]
322
460
  response.content_type = 'text/css'
323
461
  response.body = File.read file
462
+ elsif route.first == 'javascripts'
463
+ file = File.join %w(config helpers micromenus javascripts), route[1..-1]
464
+ response.content_type = 'text/javascript'
465
+ response.body = File.read file
324
466
  else
325
- mg = MicromenuGenerator.new request, resolve_brand(request['User-Agent']), StringIO.new
467
+ mg = MicromenuGenerator.new request, handler || resolve_brand(request['User-Agent']), StringIO.new
326
468
  response.content_type = mg.content_type
327
469
  response['Expires'] = 2
328
470
 
329
471
  mg.process route
330
472
 
331
473
  refresh = mg.get_refresh
332
- response['Refresh'] = refresh if refresh
474
+ response['Refresh'] = refresh if refresh
333
475
 
334
- response.body = mg.io.string
476
+ response.body = mg.io.string
335
477
  end
336
478
  end
337
479
 
@@ -339,12 +481,12 @@ class MicromenusServlet < WEBrick::HTTPServlet::AbstractServlet
339
481
  USER_AGENT_MAP.each do |k,v|
340
482
  return v if useragent.index k
341
483
  end
342
- MicromenuGenerator::PolycomPhone # Polycom's the default since it's XHTML
484
+ MicromenuGenerator::ModernUi # Default to Class A browser
343
485
  end
344
486
  end
345
487
 
346
488
  $MICROMENUS_SERVER = Thread.new do
347
- micromenu_server = WEBrick::HTTPServer.new :Port => ($HELPERS.micromenus.port || 1337)
489
+ micromenu_server = WEBrick::HTTPServer.new :Port => ($HELPERS['micromenus']['port'] || 1337)
348
490
 
349
491
  micromenu_server.mount '/', MicromenusServlet
350
492
  $HUTDOWN.hook {