social_stream-presence 0.6.2 → 0.6.3

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.
@@ -2,4 +2,6 @@
2
2
  //= require strophe
3
3
  //= require jquery.tools.tooltip
4
4
  //= require jquery.ui.chatbox
5
+ //= require jquery.flexselect
6
+ //= require liquidmetal
5
7
  //= require_tree .
@@ -136,7 +136,8 @@ var awayTimer;
136
136
  var timer;
137
137
  var reconnectTimer;
138
138
  var disconnectionFlag = true;
139
- var afterNewConnectionFlagFlag = false;
139
+ var afterNewConnectionFlag = false;
140
+ var afterFirstConnectionFlag = true;
140
141
  var requestContacts=false;
141
142
  var cyclesToRefresh = (refreshMinTime/timerPeriod);
142
143
 
@@ -219,8 +220,6 @@ function onConnect(status) {
219
220
 
220
221
  awayTimer = setInterval("awayTimerFunction()", awayTimerPeriod);
221
222
  timer = setInterval("timerFunction()", timerPeriod);
222
-
223
- hideAllNotifications();
224
223
  }
225
224
 
226
225
  updateChatWindow();
@@ -285,6 +284,8 @@ function onMessage(msg) {
285
284
  ///////
286
285
  function onPresence(presence) {
287
286
 
287
+ log(presence)
288
+
288
289
  //Check presence stanza type
289
290
  ptype = $(presence).attr('type');
290
291
 
@@ -332,8 +333,8 @@ function processUnavailablePresenceStanza(presence){
332
333
 
333
334
  if (slug != user_slug) {
334
335
  if (getConnectionBoxFromSlug(slug)!=null){
335
- hideConnectionBoxFromSlug(slug)
336
- showChatNotificationForSlug(slug,$(getConnectionBoxFromSlug(slug)).attr("name") + " is offline");
336
+ hideConnectionBoxFromSlug(slug);
337
+ showOfflineChatNotificationForSlug(slug);
337
338
  updateConnectedUsersOfMainChatBox();
338
339
  }
339
340
  }
@@ -1,6 +1,5 @@
1
1
  @import "colors";
2
2
 
3
-
4
3
  /* Chatbox style sheet */
5
4
 
6
5
  .ui-widget-content{
@@ -208,7 +207,10 @@ input.connectChatButton{
208
207
  padding: 2px 0 2px 0px;
209
208
  }
210
209
 
211
-
210
+ p.zero_users_connected {
211
+ text-align: center;
212
+ margin-top: 10px;
213
+ }
212
214
 
213
215
 
214
216
  /* Tooltip */
@@ -223,6 +225,7 @@ input.connectChatButton{
223
225
  color: white;
224
226
  background:transparent url(black_arrow3.png);
225
227
  text-align: center;
228
+ z-index: 10;
226
229
  }
227
230
 
228
231
 
@@ -283,7 +286,7 @@ input.connectChatButton{
283
286
  width:auto;
284
287
  min-width:170px;
285
288
  list-style:none;
286
- z-index: 1;
289
+ z-index: 2;
287
290
  }
288
291
 
289
292
  .dropdown span.value {
@@ -350,3 +353,40 @@ a.chatLink:link, a.chatLink:visited {
350
353
  a.chatImageLink:link, a.chatImageLink:visited {
351
354
  color: $main-color;
352
355
  }
356
+
357
+
358
+
359
+
360
+ /* Chosen stylesheet */
361
+
362
+ div.allContacts {
363
+ width: 100px;
364
+ display: block;
365
+ }
366
+
367
+ #search_chat_contact_flexselect {
368
+ background: url('btn/search_icon.png') 5px 50% no-repeat $secondary-color;
369
+ padding: 0 0px 0 0px;
370
+ font-size: 11px;
371
+ color: $main-color;
372
+ border: solid 1px $input-border-color;
373
+ height: 25px;
374
+ width: 122px;
375
+ padding: 0 3px 0 22px;
376
+ margin-bottom: 1px;
377
+ }
378
+
379
+ #search_chat_contact_flexselect_dropdown {
380
+ background: $secondary-color;
381
+ }
382
+
383
+ #search_chat_contact_flexselect_dropdown li {
384
+ background: $secondary-color;
385
+ font-size: 11px;
386
+ color: $main-color;
387
+ }
388
+
389
+ #search_chat_contact_flexselect_dropdown li:hover {
390
+ background: $separation-color;
391
+ }
392
+
@@ -1,4 +1,5 @@
1
1
  /*
2
2
  *= require jquery.ui.chatbox
3
+ *= require flexselect
3
4
  *= require_tree .
4
5
  */
@@ -1,7 +1,8 @@
1
1
  module XmppHelper
2
2
 
3
3
  def getChatContacts
4
- connected_users = []
4
+ connected_users = []
5
+ all_users = []
5
6
 
6
7
  #Get bidirectional contacts
7
8
  contacts = current_user.contact_actors(:type=>:user)
@@ -12,9 +13,10 @@ module XmppHelper
12
13
  if contact.user.connected
13
14
  connected_users << contact.user
14
15
  end
16
+ all_users << contact.user
15
17
  end
16
18
 
17
- return connected_users
19
+ return [connected_users,all_users]
18
20
  end
19
21
 
20
22
  end
@@ -1,44 +1,57 @@
1
- <div>
2
-
3
- <div class="block">
4
- <div class="header">
5
- <%=image_tag("btn/btn_friend.png", :class => "header_icon")%>
6
- <div class="header_text">
7
- <%=t('chat.title')%>
8
- </div>
9
- </div>
10
-
11
- <div id="status" class="dropdown">
12
- <dt><a href=""><span><%=t('chat.status.choose')%></span></a></dt>
13
- <dd>
14
- <ul id="statusList">
15
- <li><a id="available" href="#" class="option"><img class="flag" src="<%=image_path("status/available.png")%>" alt=""/> <%=t('chat.status.available')%> <span class="value">available</span></a></li>
16
- <li><a id="away" href="#" class="option"><img class="flag" src="<%=image_path("status/away.png")%>" alt=""/> <%=t('chat.status.away')%> <span class="value">away</span></a></li>
17
- <li><a id="dnd" href="#" class="option"><img class="flag" src="<%=image_path("status/dnd.png")%>" alt=""/> <%=t('chat.status.dnd')%> <span class="value">dnd</span></a></li>
18
- <li><a id="offline" href="#" class="option"><img class="flag" src="<%=image_path("status/offline.png")%>" alt=""/> <%=t('chat.status.offline')%> <span class="value">offline</span></a></li>
19
- </ul>
20
- </dd>
21
- </div>
22
-
23
- </div>
1
+ <div>
2
+ <div class="block">
3
+ <div class="header">
4
+ <%=image_tag("btn/btn_friend.png", :class => "header_icon")%>
5
+ <div class="header_text">
6
+ <%=t('chat.title')%>
7
+ </div>
8
+ </div>
9
+
10
+ <div id="status" class="dropdown">
11
+ <dt><a href=""><span><%=t('chat.status.choose')%></span></a></dt>
12
+ <dd>
13
+ <ul id="statusList">
14
+ <li><a id="available" href="#" class="option"><img class="flag" src="<%=image_path("status/available.png")%>" alt=""/> <%=t('chat.status.available')%> <span class="value">available</span></a></li>
15
+ <li><a id="away" href="#" class="option"><img class="flag" src="<%=image_path("status/away.png")%>" alt=""/> <%=t('chat.status.away')%> <span class="value">away</span></a></li>
16
+ <li><a id="dnd" href="#" class="option"><img class="flag" src="<%=image_path("status/dnd.png")%>" alt=""/> <%=t('chat.status.dnd')%> <span class="value">dnd</span></a></li>
17
+ <li><a id="offline" href="#" class="option"><img class="flag" src="<%=image_path("status/offline.png")%>" alt=""/> <%=t('chat.status.offline')%> <span class="value">offline</span></a></li>
18
+ </ul>
19
+ </dd>
20
+ </div>
21
+
22
+ </div>
24
23
 
25
- <% @contacts = getChatContacts %>
24
+ <% @contacts = getChatContacts %>
25
+ <% @online_contacts = @contacts[0] %>
26
+ <% @all_contacts = @contacts[1] %>
27
+
28
+ <div class="allContacts">
29
+ <select data-placeholder="Search Contact" id="search_chat_contact" class="flexselect">
30
+ <option value=""></option>
31
+ <% unless @all_contacts.empty? %>
32
+ <%@all_contacts.each do |contact| %>
33
+ <option value="<%=contact.slug%>"><%=contact.name%></option>
34
+ <% end %>
35
+ <% else %>
36
+ <option value="ZERO_CONTACTS"> <%=t('chat.zerocontacts')%></option>
37
+ <% end %>
38
+ </select>
39
+ </div>
26
40
 
27
- <div class="users_connected">
28
- <% unless @contacts.empty? %>
29
- <%@contacts.each do |contact| %>
30
- <div class="user_presence" name='<%=contact.name%>' slug='<%=contact.slug%>'>
31
- <a title='<%=contact.name%>' class="presence_user_link" width="28">
32
- <%=image_tag(contact.logo.url, :alt => contact.name , :size => "28x28")%>
33
- <% if contact.user.status %>
34
- <%=image_tag("status/" + contact.user.status + ".png", :class => "presence_status") %></a>
35
- <% end %>
36
- </a>
37
- </div>
38
- <%end%>
39
- <% end %>
40
- </div>
41
-
42
- </div>
43
-
44
-
41
+ <div class="users_connected">
42
+ <% if @online_contacts.empty? %>
43
+ <p class="zero_users_connected"> <%=t('chat.zerousers')%> </p>
44
+ <% else %>
45
+ <%@online_contacts.each do |contact| %>
46
+ <div class="user_presence" name='<%=contact.name%>' slug='<%=contact.slug%>'>
47
+ <a title='<%=contact.name%>' class="presence_user_link" width="28">
48
+ <%=image_tag(contact.logo.url, :alt => contact.name , :size => "28x28")%>
49
+ <% if contact.user.status %>
50
+ <%=image_tag("status/" + contact.user.status + ".png", :class => "presence_status") %></a>
51
+ <% end %>
52
+ </a>
53
+ </div>
54
+ <%end%>
55
+ <% end %>
56
+ </div>
57
+ </div>
@@ -6,6 +6,8 @@ en:
6
6
  unableconnect: "Chat Out of Service"
7
7
  title: "Chat"
8
8
  password: "Password"
9
+ zerousers: "No users connected"
10
+ zerocontacts: "No contacts found"
9
11
  status:
10
12
  choose: "Choose status"
11
13
  available: "Available"
@@ -17,4 +19,5 @@ en:
17
19
  checkbox: "Enable or disable Social Stream Chat"
18
20
  update: "Update Settings"
19
21
  notify:
20
- offline: "You are offline"
22
+ offline: "You are offline"
23
+ guestOffline: "is offline"
@@ -6,6 +6,8 @@ es:
6
6
  unableconnect: "Chat Fuera de servicio"
7
7
  title: "Chat"
8
8
  password: "Contraseña"
9
+ zerousers: "No hay contactos conectados"
10
+ zerocontacts: "No se encontró ningún contacto"
9
11
  status:
10
12
  choose: "Establecer estado"
11
13
  available: "Disponible"
@@ -18,4 +20,4 @@ es:
18
20
  update: "Guardar configuración"
19
21
  notify:
20
22
  offline: "Desconectado"
21
-
23
+ guestOffline: "está desconectado"
@@ -1,6 +1,6 @@
1
1
  class AddStatusColumnToUser < ActiveRecord::Migration
2
2
  def self.up
3
- add_column :users, :status, :string, :default => "chat"
3
+ add_column :users, :status, :string, :default => "available"
4
4
  end
5
5
 
6
6
  def self.down
@@ -1,5 +1,5 @@
1
1
  module Socialstream
2
2
  module Presence
3
- VERSION = "0.6.2"
3
+ VERSION = "0.6.3"
4
4
  end
5
5
  end
@@ -0,0 +1,265 @@
1
+ /**
2
+ * flexselect: a jQuery plugin, version: 0.3 (2011-12-17)
3
+ * @requires jQuery v1.3 or later
4
+ *
5
+ * FlexSelect is a jQuery plugin that makes it easy to convert a select box into
6
+ * a Quicksilver-style, autocompleting, flex matching selection tool.
7
+ *
8
+ * For usage and examples, visit:
9
+ * http://rmm5t.github.com/jquery-flexselect/
10
+ *
11
+ * Licensed under the MIT:
12
+ * http://www.opensource.org/licenses/mit-license.php
13
+ *
14
+ * Copyright (c) 2009-2012, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
15
+ */
16
+ (function($) {
17
+ $.flexselect = function(select, options) { this.init(select, options); };
18
+
19
+ $.extend($.flexselect.prototype, {
20
+ settings: {
21
+ allowMismatch: false,
22
+ selectedClass: "flexselect_selected",
23
+ dropdownClass: "flexselect_dropdown",
24
+ inputIdTransform: function(id) { return id + "_flexselect"; },
25
+ inputNameTransform: function(name) { return; },
26
+ dropdownIdTransform: function(id) { return id + "_flexselect_dropdown"; }
27
+ },
28
+ select: null,
29
+ input: null,
30
+ hidden: null,
31
+ dropdown: null,
32
+ dropdownList: null,
33
+ cache: [],
34
+ results: [],
35
+ lastAbbreviation: null,
36
+ abbreviationBeforeFocus: null,
37
+ selectedIndex: 0,
38
+ picked: false,
39
+ dropdownMouseover: false, // Workaround for poor IE behaviors
40
+
41
+ init: function(select, options) {
42
+ this.settings = $.extend({}, this.settings, options);
43
+ this.select = $(select);
44
+ this.preloadCache();
45
+ this.renderControls();
46
+ this.wire();
47
+ },
48
+
49
+ preloadCache: function() {
50
+ this.cache = this.select.children("option").map(function() {
51
+ return { name: $.trim($(this).text()), value: $(this).val(), score: 0.0 };
52
+ });
53
+ },
54
+
55
+ renderControls: function() {
56
+ var selected = this.select.children("option:selected");
57
+
58
+ this.hidden = $("<input type='hidden'/>").attr({
59
+ id: this.select.attr("id"),
60
+ name: this.select.attr("name")
61
+ }).val(selected.val());
62
+
63
+ this.input = $("<input type='text' autocomplete='off' />").attr({
64
+ id: this.settings.inputIdTransform(this.select.attr("id")),
65
+ name: this.settings.inputNameTransform(this.select.attr("name")),
66
+ accesskey: this.select.attr("accesskey"),
67
+ tabindex: this.select.attr("tabindex"),
68
+ style: this.select.attr("style")
69
+ }).addClass(this.select.attr("class")).val($.trim(selected.text()));
70
+
71
+ this.dropdown = $("<div></div>").attr({
72
+ id: this.settings.dropdownIdTransform(this.select.attr("id"))
73
+ }).addClass(this.settings.dropdownClass);
74
+ this.dropdownList = $("<ul></ul>");
75
+ this.dropdown.append(this.dropdownList);
76
+
77
+ this.select.after(this.input).after(this.hidden).remove();
78
+ $("body").append(this.dropdown);
79
+ },
80
+
81
+ wire: function() {
82
+ var self = this;
83
+
84
+ this.input.click(function() {
85
+ self.lastAbbreviation = null;
86
+ self.focus();
87
+ });
88
+
89
+ this.input.mouseup(function(event) {
90
+ // This is so Safari selection actually occurs.
91
+ event.preventDefault();
92
+ });
93
+
94
+ this.input.focus(function() {
95
+ self.abbreviationBeforeFocus = self.input.val();
96
+ self.input.select();
97
+ if (!self.picked) self.filterResults();
98
+ });
99
+
100
+ this.input.blur(function() {
101
+ if (!self.dropdownMouseover) {
102
+ self.hide();
103
+ if (!self.settings.allowMismatch && !self.picked) self.reset();
104
+ }
105
+ });
106
+
107
+ this.dropdownList.mouseover(function (event) {
108
+ if (event.target.tagName == "LI") {
109
+ var rows = self.dropdown.find("li");
110
+ self.markSelected(rows.index($(event.target)));
111
+ }
112
+ });
113
+ this.dropdownList.mouseleave(function () {
114
+ self.markSelected(-1);
115
+ });
116
+ this.dropdownList.mouseup(function (event) {
117
+ self.pickSelected();
118
+ self.focusAndHide();
119
+ });
120
+ this.dropdown.mouseover(function (event) {
121
+ self.dropdownMouseover = true;
122
+ });
123
+ this.dropdown.mouseleave(function (event) {
124
+ self.dropdownMouseover = false;
125
+ });
126
+ this.dropdown.mousedown(function (event) {
127
+ event.preventDefault();
128
+ });
129
+
130
+ this.input.keyup(function(event) {
131
+ switch (event.keyCode) {
132
+ case 13: // return
133
+ event.preventDefault();
134
+ self.pickSelected();
135
+ self.focusAndHide();
136
+ break;
137
+ case 27: // esc
138
+ event.preventDefault();
139
+ self.reset();
140
+ self.focusAndHide();
141
+ break;
142
+ default:
143
+ self.filterResults();
144
+ break;
145
+ }
146
+ });
147
+
148
+ this.input.keydown(function(event) {
149
+ switch (event.keyCode) {
150
+ case 9: // tab
151
+ self.pickSelected();
152
+ self.hide();
153
+ break;
154
+ case 33: // pgup
155
+ event.preventDefault();
156
+ self.markFirst();
157
+ break;
158
+ case 34: // pgedown
159
+ event.preventDefault();
160
+ self.markLast();
161
+ break;
162
+ case 38: // up
163
+ event.preventDefault();
164
+ self.moveSelected(-1);
165
+ break;
166
+ case 40: // down
167
+ event.preventDefault();
168
+ self.moveSelected(1);
169
+ break;
170
+ case 13: // return
171
+ case 27: // esc
172
+ event.preventDefault();
173
+ event.stopPropagation();
174
+ break;
175
+ }
176
+ });
177
+ },
178
+
179
+ filterResults: function() {
180
+ var abbreviation = this.input.val();
181
+ if (abbreviation == this.lastAbbreviation) return;
182
+
183
+ var results = [];
184
+ $.each(this.cache, function() {
185
+ this.score = LiquidMetal.score(this.name, abbreviation);
186
+ if (this.score > 0.0) results.push(this);
187
+ });
188
+ this.results = results;
189
+
190
+ this.sortResults();
191
+ this.renderDropdown();
192
+ this.markFirst();
193
+ this.lastAbbreviation = abbreviation;
194
+ this.picked = false;
195
+ },
196
+
197
+ sortResults: function() {
198
+ this.results.sort(function(a, b) { return b.score - a.score; });
199
+ },
200
+
201
+ renderDropdown: function() {
202
+ var dropdownBorderWidth = this.dropdown.outerWidth() - this.dropdown.innerWidth();
203
+ var inputOffset = this.input.offset();
204
+ this.dropdown.css({
205
+ width: (this.input.outerWidth() - dropdownBorderWidth) + "px",
206
+ top: (inputOffset.top + this.input.outerHeight()) + "px",
207
+ left: inputOffset.left + "px"
208
+ });
209
+
210
+ var list = this.dropdownList.html("");
211
+ $.each(this.results, function() {
212
+ // list.append($("<li/>").html(this.name + " <small>[" + Math.round(this.score*100)/100 + "]</small>"));
213
+ list.append($("<li/>").html(this.name));
214
+ });
215
+ this.dropdown.show();
216
+ },
217
+
218
+ markSelected: function(n) {
219
+ if (n > this.results.length) return;
220
+
221
+ var rows = this.dropdown.find("li");
222
+ rows.removeClass(this.settings.selectedClass);
223
+ this.selectedIndex = n;
224
+
225
+ if (n >= 0) $(rows[n]).addClass(this.settings.selectedClass);
226
+ },
227
+
228
+ pickSelected: function() {
229
+ var selected = this.results[this.selectedIndex];
230
+ if (selected) {
231
+ //this.input.val(selected.name);
232
+ //this.picked = true;
233
+ if(typeof changeSelectContactValue == "function"){
234
+ changeSelectContactValue(selected.name,selected.value);
235
+ }
236
+ this.hidden.val(selected.value);
237
+ } else if (this.settings.allowMismatch) {
238
+ this.hidden.val("");
239
+ } else {
240
+ this.reset();
241
+ }
242
+ this.input.val("");
243
+ },
244
+
245
+ hide: function() {
246
+ this.dropdown.hide();
247
+ this.lastAbbreviation = null;
248
+ },
249
+
250
+ moveSelected: function(n) { this.markSelected(this.selectedIndex+n); },
251
+ markFirst: function() { this.markSelected(0); },
252
+ markLast: function() { this.markSelected(this.results.length - 1); },
253
+ reset: function() { this.input.val(this.abbreviationBeforeFocus); },
254
+ focus: function() { this.input.focus(); },
255
+ focusAndHide: function() { this.hide(); //this.focus();
256
+ }
257
+ });
258
+
259
+ $.fn.flexselect = function(options) {
260
+ this.each(function() {
261
+ if (this.tagName == "SELECT") new $.flexselect(this, options);
262
+ });
263
+ return this;
264
+ };
265
+ })(jQuery);