social_stream 0.19.2 → 0.19.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/.travis.yml +1 -1
  2. data/README.rdoc +1 -1
  3. data/base/app/assets/stylesheets/cheesecake.css.scss +43 -12
  4. data/base/app/controllers/contacts_controller.rb +1 -1
  5. data/base/app/models/activity.rb +4 -1
  6. data/base/app/models/actor.rb +2 -14
  7. data/base/app/models/relation.rb +2 -4
  8. data/base/app/models/relation/single.rb +2 -7
  9. data/base/app/models/tie.rb +2 -1
  10. data/base/app/views/activities/_new.html.erb +1 -1
  11. data/base/app/views/cheesecake/_cheesecake.html.erb +170 -105
  12. data/base/app/views/cheesecake/_index.html.erb +45 -47
  13. data/base/app/views/cheesecake/_sector_form.html.erb +1 -0
  14. data/base/app/views/toolbar/_home.html.erb +1 -1
  15. data/base/config/locales/en.yml +2 -0
  16. data/base/config/locales/es.yml +2 -0
  17. data/base/config/locales/rails.es.yml +192 -0
  18. data/base/db/migrate/20110912074426_add_reject_relation.rb +2 -2
  19. data/base/db/migrate/20120201185454_singleton_single_relations.rb +46 -0
  20. data/base/lib/social_stream/base/version.rb +1 -1
  21. data/base/lib/tasks/db/populate.rake +1 -1
  22. data/base/spec/controllers/posts_controller_spec.rb +2 -2
  23. data/base/spec/factories/activity.rb +1 -1
  24. data/base/spec/factories/post.rb +1 -1
  25. data/base/spec/factories/tie.rb +3 -3
  26. data/base/spec/models/activity_authorization_spec.rb +3 -3
  27. data/base/spec/support/db.rb +3 -1
  28. data/documents/app/assets/images/48/{word.png → doc.png} +0 -0
  29. data/documents/app/assets/images/48/{excel.png → xls.png} +0 -0
  30. data/documents/lib/social_stream/documents/version.rb +1 -1
  31. data/documents/social_stream-documents.gemspec +1 -1
  32. data/documents/spec/factories/document.rb +1 -1
  33. data/documents/spec/factories/picture.rb +1 -1
  34. data/documents/spec/support/db.rb +3 -3
  35. data/events/app/views/events/_sidebar_calendar.html.erb +5 -5
  36. data/events/lib/social_stream/events/version.rb +1 -1
  37. data/events/social_stream-events.gemspec +1 -1
  38. data/lib/social_stream/version.rb +1 -1
  39. data/linkser/db/migrate/20120202104549_add_links_foreign_key.rb +9 -0
  40. data/presence/app/assets/javascripts/chat_interface_manager.js.erb +167 -177
  41. data/presence/app/assets/javascripts/chat_persistence.js +194 -0
  42. data/presence/app/assets/javascripts/chat_utilities.js +15 -0
  43. data/presence/app/assets/javascripts/chat_window_manager.js +57 -1
  44. data/presence/app/assets/javascripts/xmpp_client_management.js.erb +191 -143
  45. data/presence/app/assets/stylesheets/chat.css.scss +4 -5
  46. data/presence/app/views/chat/_contacts.html.erb +2 -5
  47. data/presence/app/views/chat/_index.html.erb +46 -32
  48. data/presence/app/views/chat/_off.html.erb +2 -2
  49. data/presence/config/routes.rb +1 -1
  50. data/presence/lib/social_stream/presence/version.rb +1 -1
  51. data/presence/vendor/assets/javascripts/jquery.ui.chatbox.js +14 -11
  52. data/social_stream.gemspec +4 -4
  53. data/spec/support/db.rb +4 -4
  54. metadata +37 -32
data/.travis.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  rvm:
2
2
  - 1.8.7
3
3
  - 1.9.2
4
- - ree
4
+ - 1.9.3
5
5
  env:
6
6
  - DB=mysql
7
7
  - DB=postgres
data/README.rdoc CHANGED
@@ -32,7 +32,7 @@ add your own activities easily.
32
32
 
33
33
  Add to your Gemfile:
34
34
 
35
- gem 'social_stream'
35
+ gem 'social_stream', '>= 0.19.0'
36
36
 
37
37
  and run:
38
38
 
@@ -13,6 +13,24 @@
13
13
  float: left;
14
14
  position: relative;
15
15
  }
16
+ #sector_form {
17
+ float: left;
18
+ position: relative;
19
+ width: 0px;
20
+ padding: 0px;
21
+ margin: 0px;
22
+ overflow: hidden;
23
+ height: 450px;
24
+ }
25
+ #contacts_explorer {
26
+ float: right;
27
+ position: relative;
28
+ width: 300px;
29
+ padding: 0px;
30
+ margin: 0px;
31
+ overflow: hidden;
32
+ height: 450px;
33
+ }
16
34
  #contacts_filter {
17
35
  width: 290px;
18
36
  height: 45px;
@@ -49,14 +67,14 @@
49
67
 
50
68
  #contacts_grid {
51
69
  width: 300px;
52
- height: 336px;
70
+ height: 340px;
53
71
  overflow: hidden;
54
72
  position: relative;
55
73
  float: left;
56
74
  }
57
75
  #contacts_grid_available {
58
76
  width: 300px;
59
- height: 336px;
77
+ height: 308px;
60
78
  position: relative;
61
79
  float: left;
62
80
  overflow: auto;
@@ -71,13 +89,14 @@
71
89
  text-align: center;
72
90
  vertical-align: middle;
73
91
  background-color: $fill-color;
92
+ z-index: 2000;
74
93
  }
75
94
  #contacts_save {
76
95
  width: 130px;
77
96
  padding-right: 5px;
78
97
  height: 30px;
79
98
  text-align: right;
80
- float: right;
99
+ float: left;
81
100
  margin-right: 20px;
82
101
  }
83
102
  #contacts_save_form {
@@ -96,7 +115,7 @@
96
115
  #contacts_changes_button {
97
116
  width: 130px;
98
117
  height: 25px;
99
- float: right;
118
+ float: left;
100
119
  margin-top: 10px;
101
120
  cursor: pointer;
102
121
  }
@@ -163,7 +182,7 @@
163
182
  width: 48px;
164
183
  height: 48px;
165
184
  float: left;
166
- margin: 4px;
185
+ padding: 4px;
167
186
  opacity: 0.8;
168
187
  }
169
188
  #contacts_grid .actor img {
@@ -172,7 +191,9 @@
172
191
  }
173
192
  #contacts_grid .actor.focused {
174
193
  opacity: 1;
175
-
194
+ padding: 3px;
195
+ background: $secondary-color;
196
+ border: 1px solid $main-color;
176
197
  }
177
198
  #contacts_grid .actor.focused img {
178
199
 
@@ -183,14 +204,18 @@
183
204
  width: 24px;
184
205
  height: 24px;
185
206
  float: left;
186
- margin: 2px 2px 0px 2px;
207
+ padding: 2px 2px 0px 2px;
208
+ background-color: $fill-color;
187
209
  }
188
210
  #contacts_grid_selected .actor img {
189
211
  width: 24px;
190
212
  height: 24px;
191
213
  }
192
- #contacts_grid_selected.focused .actor {
193
-
214
+ #contacts_grid_selected .actor.focused {
215
+ opacity: 1;
216
+ background: $header-notification-color;
217
+ padding: 2px 2px 2px 2px;
218
+ border: 0px;
194
219
  }
195
220
  #contacts_grid_selected .actor.focused img {
196
221
 
@@ -198,10 +223,16 @@
198
223
  #contacts_grid_selected {
199
224
  width: 280px;
200
225
  min-height: 28px;
201
- background-color: $fill-color;
226
+ background-color: $secondary-color;
202
227
  border: 1px solid $main-color;
203
- display: none;
204
- padding-bottom: 2px;
228
+ padding: 0px;
229
+ margin-bottom: 2px;
230
+ }
231
+ #contacts_grid_selected_hint {
232
+ padding-top: 5px;
233
+ margin: auto;
234
+ height: 11px;
235
+ text-align: center;
205
236
  }
206
237
  .cheesecake_actor_tipsy.tipsy {
207
238
  padding-top: 2px;
@@ -34,7 +34,7 @@ class ContactsController < ApplicationController
34
34
  end
35
35
 
36
36
  def destroy
37
- @contact.relation_ids = [current_subject.relation_reject.id]
37
+ @contact.relation_ids = [Relation::Reject.instance.id]
38
38
 
39
39
  respond_to do |format|
40
40
  format.js
@@ -228,7 +228,10 @@ class Activity < ActiveRecord::Base
228
228
 
229
229
  rels = Relation.normalize(relation_ids)
230
230
 
231
- own_rels = rels.select{ |r| r.actor_id == channel.author_id }
231
+ own_rels = rels.select{ |r| r.actor_id == channel.author_id }
232
+ # Consider Relation::Single as own_relations
233
+ own_rels += rels.select{ |r| r.is_a?(Relation::Single) }
234
+
232
235
  foreign_rels = rels - own_rels
233
236
 
234
237
  # Only posting to own relations or allowed to post to foreign relations
@@ -205,16 +205,6 @@ class Actor < ActiveRecord::Base
205
205
  relations.joins(:relation_permissions => :permission).where('permissions.action' => 'notify')
206
206
  end
207
207
 
208
- # The {Relation::Public} for this {Actor}
209
- def relation_public
210
- Relation::Public.of(self)
211
- end
212
-
213
- # The {Relation::Reject} for this {Actor}
214
- def relation_reject
215
- Relation::Reject.of(self)
216
- end
217
-
218
208
  # All the {Actor Actors} this one has ties with:
219
209
  #
220
210
  # actor.contact_actors #=> array of actors that sent and receive ties from actor
@@ -381,7 +371,7 @@ class Actor < ActiveRecord::Base
381
371
  #
382
372
  def activity_relations(subject, options = {})
383
373
  if Actor.normalize(subject) == self
384
- return relation_customs + Array.wrap(relation_public)
374
+ return relation_customs + Array.wrap(Relation::Public.instance)
385
375
  else
386
376
  Array.new
387
377
  end
@@ -507,7 +497,7 @@ class Actor < ActiveRecord::Base
507
497
  id
508
498
  a = Activity.new :verb => "like",
509
499
  :channel => channel,
510
- :relation_ids => Array(subject.relation_public.id)
500
+ :relation_ids => Array(Relation::Public.instance.id)
511
501
 
512
502
  a.activity_objects << activity_object
513
503
 
@@ -534,8 +524,6 @@ class Actor < ActiveRecord::Base
534
524
  # After create callback
535
525
  def create_initial_relations
536
526
  Relation::Custom.defaults_for(self)
537
- Relation::Public.default_for(self)
538
- Relation::Reject.default_for(self)
539
527
  end
540
528
 
541
529
  # After create callback
@@ -55,8 +55,6 @@ class Relation < ActiveRecord::Base
55
55
  has_many :audiences, :dependent => :destroy
56
56
  has_many :activities, :through => :audiences
57
57
 
58
- validates_presence_of :actor_id
59
-
60
58
  scope :actor, lambda { |a|
61
59
  where(:actor_id => Actor.normalize_id(a))
62
60
  }
@@ -125,12 +123,12 @@ class Relation < ActiveRecord::Base
125
123
 
126
124
  conds =
127
125
  Permission.arel_table[:action].eq(action).and(Permission.arel_table[:object].eq(object))
128
-
129
- # Relation::Public permissions cannot be customized yet
126
+ # Relation::Public permissions cannot be customized and should not depend on the subject
130
127
  if action == 'read' && object == 'activity' && (options[:public].nil? || options[:public])
131
128
  conds = conds.or(Relation.arel_table[:type].eq('Relation::Public'))
132
129
  end
133
130
 
131
+
134
132
  # Add in condition
135
133
  if ! options[:in].nil?
136
134
  conds = conds.and(Relation.arel_table[:id].in(Relation.normalize_id(Array(options[:in]))))
@@ -5,13 +5,8 @@
5
5
  #
6
6
  class Relation::Single < Relation
7
7
  class << self
8
- def default_for(actor)
9
- create! :actor => actor
10
- end
11
-
12
- # The {Relation::Public} belonging to actor
13
- def of(actor)
14
- actor(actor).first
8
+ def instance
9
+ first || create!
15
10
  end
16
11
  end
17
12
 
@@ -141,7 +141,8 @@ class Tie < ActiveRecord::Base
141
141
 
142
142
  def relation_belongs_to_sender
143
143
  errors.add(:relation, "must belong to sender") unless
144
- contact.sender_id == relation.actor_id
144
+ relation.is_a?(Relation::Single) ||
145
+ contact.sender_id == relation.actor_id
145
146
  end
146
147
  end
147
148
 
@@ -25,7 +25,7 @@
25
25
  <div id="securities">
26
26
  <% if current_subject == receiver %>
27
27
  <%= javascript_tag do %>
28
- var relation_public = <%= receiver.relation_public.id %>;
28
+ var relation_public = <%= Relation::Public.instance.id %>;
29
29
  var public_selected = false;
30
30
  var relation_options = <%= escape_javascript(current_subject.activity_relations(receiver).sort.map{ |r| r.id }.to_json) %>;
31
31
  var relation_public_pos = 0;
@@ -5,121 +5,186 @@ $(function(){
5
5
  width: 440,
6
6
  height: 440
7
7
  },
8
- grid: {
8
+ grid: {
9
9
  id: "contacts_grid",
10
- divIdPrefix: "actor_"
10
+ divIdPrefix: "actor_",
11
+ maxOpacity: 0.8
11
12
  },
12
- rMax : 200,
13
- center: {x : 220, y : 220}
14
- };
15
- cheesecakeData.sectors = <%= raw(current_subject.cheesecake_json) %>.sectors;
16
- var cheese = new socialCheesecake.Cheesecake(cheesecakeData);
17
- cheese.syncSectorFocusCallbacks = true;
18
- cheese.onSectorFocusBegin = function(cheesecake,callback){
19
- $("#contacts_grid_available").fadeOut("fast", callback);
20
- };
21
- cheese.onSectorFocusEnd = function(cheesecake){
22
- console.log("end"); $("#contacts_grid_available").fadeIn("fast");
23
- };
24
- $("#contacts_filter_input").keyup(function(){
25
- cheese.searchEngine.filter($("#contacts_filter_input").val());
26
- //TODO: Make users unfiltered visible again
27
- });
28
- cheese.onChange = function(cheesecake){
29
- var initial = cheesecake.getInitialState();
30
- var changes = cheesecake.getChanges();
31
- if((changes.actors)&&(changes.actors.length==0)&&(changes.sectors)&&(changes.sectors.length==0)&&(changes.subsectors)&&(changes.subsectors.length==0)){
32
- $("#contacts_changes_button").hide();
33
- $("#contacts_save").hide();
34
- }else{
35
- $("#contacts_changes_button").show();
36
- $("#contacts_save").show();
37
- var total = 0;
38
- if(changes.actors)
39
- total += changes.actors.length;
40
- if(changes.sectors)
41
- total += changes.sectors.length;
42
- if(changes.subsectors)
43
- total += changes.subsectors.length;
44
- $("#contacts_changes_button_total").html(total);
13
+ colors : {
14
+ normalSector : {
15
+ background : "#DEEFF8",
16
+ border : "#1F4A75",
17
+ font : "#1F4A75",
18
+ click : "#BDC7D8",
19
+ mouseover : "#D4E4EA",
20
+ mouseup : "#DEEFF8",
21
+ mouseout : "#DEEFF8"
22
+ },
23
+ extraSector : {
24
+ background : "#879EB5",
25
+ border : "#1F4A75",
26
+ font : "#1F4A75",
27
+ click : "#97AEC5",
28
+ mouseover : "#97AEC5",
29
+ mouseup : "#879EB5",
30
+ mouseout : "#879EB5"
45
31
  }
46
- var changes_html = "";
47
- var actors = changes.actors;
48
- $("#contacts_save_changes").val(JSON.stringify(changes));
49
- for(var i in actors){
50
- actor = actors[i];
51
- if(actor.justAdded){
52
- var new_subsectors = actor.subsectors;
53
- var new_subsectors_string = "";
54
- for(var i in new_subsectors){
55
- if(i > 0) new_subsectors_string += ", ";
56
- new_subsectors_string += cheesecake.getSubsectorById(new_subsectors[i]).label;
57
- }
58
- changes_html += "<div class=\"change_added\">" + actor.name + " has been removed from " + old_subsectors_string + "</div>";
59
- }else if(actor.subsectors.length==0){
60
- var old_subsectors = [];
61
- var old_subsectors_string = "";
62
- for(var i in initial.actors){
63
- if(actor.id==initial.actors[i].id){
64
- old_subsectors = initial.actors[i].subsectors;
65
- break;
66
- }
67
- }
68
- for(var i in old_subsectors){
69
- if(i > 0) old_subsectors_string += ", ";
70
- old_subsectors_string += cheesecake.getSubsectorById(old_subsectors[i]).label;
32
+ },
33
+ rMax : 200,
34
+ center: {x : 220, y : 220}
35
+ };
36
+ cheesecakeData.sectors = <%= raw(current_subject.cheesecake_json) %>.sectors;
37
+ var cheese = new socialCheesecake.Cheesecake(cheesecakeData);
38
+ cheese.syncSectorFocusCallbacks = false;
39
+ cheese.onSectorFocusBegin = function(cheesecake,callback){
40
+ if(cheese.highlightedSector.auxiliar){
41
+ $("#contacts_explorer").animate({width: 0},500,function(){
42
+ $("#contacts_explorer").hide();
43
+ });
44
+ setTimeout(function(){
45
+ $("#sector_form").show();
46
+ $("#sector_form").animate({width: 300},500);
47
+ },100);
48
+ }else{
49
+ $("#contacts_grid_available").fadeOut("fast", callback);
50
+ }
51
+ };
52
+ cheese.onSectorFocusEnd = function(cheesecake){
53
+ if(cheese.highlightedSector.auxiliar){
54
+
55
+ }else{
56
+ $("#contacts_grid_available").fadeIn("fast");
57
+ }
58
+ };
59
+ cheese.onSectorUnfocusBegin = function(cheesecake,callback){
60
+ if(cheese.highlightedSector.auxiliar){
61
+
62
+ }else{
63
+ $("#contacts_grid_available").fadeOut("fast", callback);
64
+ }
65
+ };
66
+ cheese.onSectorUnfocusEnd = function(cheesecake){
67
+ if(cheese.highlightedSector.auxiliar){
68
+ $("#sector_form").animate({width: 0},500,function(){
69
+ $("#sector_form").hide();
70
+ });
71
+ setTimeout(function(){
72
+ $("#contacts_explorer").show();
73
+ $("#contacts_explorer").animate({width: 300},500);
74
+ },100);
75
+ }else{
76
+ $("#contacts_grid_available").fadeIn("fast");
77
+ }
78
+ };
79
+ $("#contacts_filter_input").keyup(function(){
80
+ cheese.searchEngine.filter($("#contacts_filter_input").val());
81
+ //TODO: Make users unfiltered visible again
82
+ });
83
+ cheese.onChange = function(cheesecake){
84
+ var initial = cheesecake.getInitialState();
85
+ var changes = cheesecake.getChanges();
86
+ if((changes.actors)&&(changes.actors.length==0)&&(changes.sectors)&&(changes.sectors.length==0)&&(changes.subsectors)&&(changes.subsectors.length==0)){
87
+ $("#contacts_changes_button").hide();
88
+ $("#contacts_save").hide();
89
+ }else{
90
+ $("#contacts_changes_button").show();
91
+ $("#contacts_save").show();
92
+ var total = 0;
93
+ if(changes.actors)
94
+ total += changes.actors.length;
95
+ if(changes.sectors)
96
+ total += changes.sectors.length;
97
+ if(changes.subsectors)
98
+ total += changes.subsectors.length;
99
+ $("#contacts_changes_button_total").html(total);
100
+ }
101
+ var changes_html = "";
102
+ var actors = changes.actors;
103
+ $("#contacts_save_changes").val(JSON.stringify(changes));
104
+ for(var i in actors){
105
+ actor = actors[i];
106
+ if(actor.justAdded){
107
+ var new_subsectors = actor.subsectors;
108
+ var new_subsectors_string = "";
109
+ for(var i in new_subsectors){
110
+ if(i > 0) new_subsectors_string += ", ";
111
+ new_subsectors_string += cheesecake.getSubsectorById(new_subsectors[i]).label;
112
+ }
113
+ changes_html += "<div class=\"change_added\">" + actor.name + " has been removed from " + old_subsectors_string + "</div>";
114
+ }else if(actor.subsectors.length==0){
115
+ var old_subsectors = [];
116
+ var old_subsectors_string = "";
117
+ for(var i in initial.actors){
118
+ if(actor.id==initial.actors[i].id){
119
+ old_subsectors = initial.actors[i].subsectors;
120
+ break;
71
121
  }
72
- changes_html += "<div class=\"change_deleted\">" + actor.name + " has been removed from " + old_subsectors_string + "</div>";
73
- }else{
74
- var old_subsectors = [];
75
- var new_subsectors = actor.subsectors;
76
- var left_subsectors = "";
77
- var joined_subsectors = "";
78
- for(var i in initial.actors){
79
- if(actor.id==initial.actors[i].id){
80
- old_subsectors = initial.actors[i].subsectors;
81
- break;
82
- }
122
+ }
123
+ for(var i in old_subsectors){
124
+ if(i > 0) old_subsectors_string += ", ";
125
+ old_subsectors_string += cheesecake.getSubsectorById(old_subsectors[i]).label;
126
+ }
127
+ changes_html += "<div class=\"change_deleted\">" + actor.name + " has been removed from " + old_subsectors_string + "</div>";
128
+ }else{
129
+ var old_subsectors = [];
130
+ var new_subsectors = actor.subsectors;
131
+ var left_subsectors = "";
132
+ var joined_subsectors = "";
133
+ for(var i in initial.actors){
134
+ if(actor.id==initial.actors[i].id){
135
+ old_subsectors = initial.actors[i].subsectors;
136
+ break;
83
137
  }
84
- for(var i in old_subsectors){
85
- if(new_subsectors.indexOf(old_subsectors[i])==-1){
86
- if(left_subsectors.length!=0){
87
- left_subsectors += ", ";
88
- }
89
- left_subsectors += cheesecake.getSubsectorById(old_subsectors[i]).label;
138
+ }
139
+ for(var i in old_subsectors){
140
+ if(new_subsectors.indexOf(old_subsectors[i])==-1){
141
+ if(left_subsectors.length!=0){
142
+ left_subsectors += ", ";
90
143
  }
144
+ left_subsectors += cheesecake.getSubsectorById(old_subsectors[i]).label;
91
145
  }
92
- for(var i in new_subsectors){
93
- if(old_subsectors.indexOf(new_subsectors[i])==-1){
94
- if(joined_subsectors.length!=0){
95
- joined_subsectors += ", ";
96
- }
97
- joined_subsectors += cheesecake.getSubsectorById(new_subsectors[i]).label;
146
+ }
147
+ for(var i in new_subsectors){
148
+ if(old_subsectors.indexOf(new_subsectors[i])==-1){
149
+ if(joined_subsectors.length!=0){
150
+ joined_subsectors += ", ";
98
151
  }
152
+ joined_subsectors += cheesecake.getSubsectorById(new_subsectors[i]).label;
99
153
  }
100
- if((joined_subsectors.length!=0)&&(left_subsectors.length!=0)){
101
- changes_html += "<div class=\"change_modified\">" + actor.name + " has been removed from " + left_subsectors + " and added to " + joined_subsectors + "</div>";
102
- }else if(joined_subsectors.length!=0){
103
- changes_html += "<div class=\"change_added\">" + actor.name + " has been added to " + joined_subsectors + "</div>";
104
- }else{
105
- changes_html += "<div class=\"change_deleted\">" + actor.name + " has been removed from " + left_subsectors + "</div>";
106
- }
154
+ }
155
+ if((joined_subsectors.length!=0)&&(left_subsectors.length!=0)){
156
+ changes_html += "<div class=\"change_modified\">" + actor.name + " has been removed from " + left_subsectors + " and added to " + joined_subsectors + "</div>";
157
+ }else if(joined_subsectors.length!=0){
158
+ changes_html += "<div class=\"change_added\">" + actor.name + " has been added to " + joined_subsectors + "</div>";
159
+ }else{
160
+ changes_html += "<div class=\"change_deleted\">" + actor.name + " has been removed from " + left_subsectors + "</div>";
107
161
  }
108
162
  }
109
- $("#contacts_changes_details").html(changes_html);
110
163
  }
111
- $('#contacts_changes_button').tipsy({
112
- delayIn: 0,
113
- delayOut: 0,
114
- gravity: 'se',
115
- opacity: 1,
116
- trigger: 'manual',
117
- className: 'contacts_changes_tipsy_menu',
118
- html: true,
119
- hoverable: true,
120
- title: function(){
121
- return $('#contacts_changes').html();
122
- }
123
- });
124
- $("#contacts_save_changes").val(JSON.stringify(cheese.getChanges()));
164
+ $("#contacts_changes_details").html(changes_html);
165
+ }
166
+ $('#contacts_changes_button').tipsy({
167
+ delayIn: 0,
168
+ delayOut: 0,
169
+ gravity: 'se',
170
+ opacity: 1,
171
+ trigger: 'manual',
172
+ className: 'contacts_changes_tipsy_menu',
173
+ html: true,
174
+ hoverable: true,
175
+ title: function(){
176
+ return $('#contacts_changes').html();
177
+ }
178
+ });
179
+ $("#contacts_save_changes").val(JSON.stringify(cheese.getChanges()));
180
+ $("#contacts_save_form").off("submit.disable");
181
+ $("#contacts_save_form").on("submit.disable",function(){
182
+
183
+ if($(".contacts_changes_tipsy_menu").length != 0){
184
+ $("#contacts_changes_button").tipsy("hide");
185
+ }
186
+ $("#contacts_grid_saving").show();
187
+ cheese.disable();
188
+ $("#contacts_save_button").val("<%= t('cheesecake.changes.saving') %>").attr("disabled","true");
189
+ });
125
190
  });